diff --git a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx index 78719a93..6713b9c8 100644 --- a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx +++ b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx @@ -10,7 +10,7 @@ import { Label } from "@/components/ui/label"; import ExternalDraggingevent from "./dragging-events"; import { Calendar } from "@/components/ui/calendar"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Plus } from "lucide-react"; +import { Book, Plus } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { EventContentArg } from "@fullcalendar/core"; import EventModal from "./event-modal"; @@ -25,6 +25,13 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; const wait = () => new Promise((resolve) => setTimeout(resolve, 1000)); interface CalendarViewProps { @@ -103,7 +110,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => { const [selectedEventDate, setSelectedEventDate] = useState(null); const roleId = Number(getCookiesDecrypt("urie")) || 0; const [apiEvents, setApiEvents] = useState([]); - const [loading, setLoading] = useState(false); + const [Isloading, setLoading] = useState(false); const [draggableInitialized, setDraggableInitialized] = useState(false); const t = useTranslations("CalendarApp"); @@ -116,6 +123,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => { const TODAY = dayjs().format("yyyy-MM-dd"); const INITIAL_YEAR = dayjs().format("YYYY"); const INITIAL_MONTH = dayjs().format("M"); + const [open, setOpen] = useState(false); const [selectedYear, setSelectedYear] = useState(new Date()); const [selectedMonth, setSelectedMonth] = useState( @@ -503,13 +511,44 @@ const CalendarView = ({ categories }: CalendarViewProps) => { ); }; + const getModalContent = (type: "terkirim" | "diterima") => ( +
+ {Isloading ? ( +

Loading...

+ ) : ( + + + + + + + + + + + + + + + + + + + +
NoTicket NumberDate and TimeTitleStatus
{"1"}{"MIA - 001"}{"23/01/2025 13:00"}{"Daily Issue 25 Januari 2025 "} + {type === "terkirim" ? "Completed" : "Completed"} +
+ )} +
+ ); + return ( <>
- {roleId == 11 || roleId == 12 ? ( + {roleId == 11 || roleId == 2 || roleId == 12 ? ( + ) : null} + + + + Hasil Pantauan + + {getModalContent("terkirim")} + + +
diff --git a/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx b/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx index 168b9e3f..94bbf18e 100644 --- a/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx +++ b/app/[locale]/(protected)/contributor/agenda-setting/event-modal.tsx @@ -1118,6 +1118,14 @@ const EventModal = ({
+ {detailData && ( +
+ +
+ )} +
-
- ) => - table.getColumn("status")?.setFilterValue(event.target.value) - } - className="max-w-sm " - /> +
+
+ + + + + +
+

Filter

+ {/*

+ Simpan +

*/} +
+ + {categories.length > 0 ? ( + categories.map((category) => ( +
+ handleCheckboxChange(category.id)} + /> + +
+ )) + ) : ( +

+ No categories found. +

+ )} + +
+ handleStatusCheckboxChange(1)} + /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+ handleStatusCheckboxChange(4)} + /> + +
+
+
+
+
+ + + + + + {table + .getAllColumns() + .filter((column) => column.getCanHide()) + .map((column) => { + return ( + + column.toggleVisibility(!!value) + } + > + {column.id} + + ); + })} + + +
diff --git a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx index 0fcfcb37..e5e821d5 100644 --- a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx +++ b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx @@ -91,7 +91,7 @@ const TableAudio = () => { [] ); const [categoryFilter, setCategoryFilter] = React.useState(""); - const [statusFilter, setStatusFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); const [startDate, setStartDate] = React.useState(""); const [endDate, setEndDate] = React.useState(""); const [filterByCreator, setFilterByCreator] = React.useState(""); @@ -131,7 +131,7 @@ const TableAudio = () => { React.useEffect(() => { fetchData(); getCategories(); - }, [categoryFilter, page, limit, search, startDate, endDate]); + }, [categoryFilter, statusFilter, page, limit, search, startDate, endDate]); async function getCategories() { const category = await listEnableCategory("4"); @@ -175,9 +175,7 @@ const TableAudio = () => { isForSelf, !isForSelf, categoryFilter, - statusFilter?.sort().join(",").includes("1") - ? "1,2" - : statusFilter?.sort().join(","), + statusFilter, statusFilter?.sort().join(",").includes("1") ? userLevelId : "", filterByCreator, filterBySource, @@ -214,6 +212,14 @@ const TableAudio = () => { fetchData(); // Panggil ulang data dengan filter baru }; + function handleStatusCheckboxChange(value: any) { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + } + const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { @@ -324,22 +330,54 @@ const TableAudio = () => { /> -
- - ) => - table - .getColumn("statusName") - ?.setFilterValue(event.target.value) - } - className="max-w-sm " + +
+ handleStatusCheckboxChange(1)} /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+ handleStatusCheckboxChange(4)} + /> +
diff --git a/app/[locale]/(protected)/contributor/content/audio/page.tsx b/app/[locale]/(protected)/contributor/content/audio/page.tsx index 90b45070..756b3272 100644 --- a/app/[locale]/(protected)/contributor/content/audio/page.tsx +++ b/app/[locale]/(protected)/contributor/content/audio/page.tsx @@ -13,7 +13,7 @@ const ReactTableAudioPage = () => {
-
+
diff --git a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx index 9c14dfc8..89f465bc 100644 --- a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx +++ b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx @@ -96,7 +96,7 @@ const TableImage = () => { [] ); const [categoryFilter, setCategoryFilter] = React.useState(""); - const [statusFilter, setStatusFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); const [startDate, setStartDate] = React.useState(""); const [endDate, setEndDate] = React.useState(""); const [filterByCreator, setFilterByCreator] = React.useState(""); @@ -137,7 +137,7 @@ const TableImage = () => { // Panggil fetchData saat filter kategori berubah fetchData(); getCategories(); - }, [categoryFilter, page, limit, search, startDate, endDate]); + }, [categoryFilter, statusFilter, page, limit, search, startDate, endDate]); async function getCategories() { const category = await listEnableCategory("1"); @@ -181,9 +181,7 @@ const TableImage = () => { isForSelf, !isForSelf, categoryFilter, - statusFilter?.sort().join(",").includes("1") - ? "1,2" - : statusFilter?.sort().join(","), + statusFilter, statusFilter?.sort().join(",").includes("1") ? userLevelId : "", filterByCreator, filterBySource, @@ -220,6 +218,14 @@ const TableImage = () => { fetchData(); // Panggil ulang data dengan filter baru }; + function handleStatusCheckboxChange(value: any) { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + } + const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { @@ -330,22 +336,54 @@ const TableImage = () => { />
-
- - ) => - table - .getColumn("statusName") - ?.setFilterValue(event.target.value) - } - className="max-w-sm " + +
+ handleStatusCheckboxChange(1)} /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+ handleStatusCheckboxChange(4)} + /> +
diff --git a/app/[locale]/(protected)/contributor/content/image/page.tsx b/app/[locale]/(protected)/contributor/content/image/page.tsx index c661dd1a..a3d46ac4 100644 --- a/app/[locale]/(protected)/contributor/content/image/page.tsx +++ b/app/[locale]/(protected)/contributor/content/image/page.tsx @@ -13,7 +13,7 @@ const ReactTableImagePage = () => {
-
+
diff --git a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx index 7236cbe7..e3301f9d 100644 --- a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx @@ -90,7 +90,7 @@ const TableTeks = () => { [] ); const [categoryFilter, setCategoryFilter] = React.useState(""); - const [statusFilter, setStatusFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); const [startDate, setStartDate] = React.useState(""); const [endDate, setEndDate] = React.useState(""); const [filterByCreator, setFilterByCreator] = React.useState(""); @@ -130,7 +130,7 @@ const TableTeks = () => { React.useEffect(() => { fetchData(); getCategories(); - }, [categoryFilter, page, limit, search, startDate, endDate]); + }, [categoryFilter, statusFilter, page, limit, search, startDate, endDate]); async function getCategories() { const category = await listEnableCategory("3"); @@ -174,9 +174,7 @@ const TableTeks = () => { isForSelf, !isForSelf, categoryFilter, - statusFilter?.sort().join(",").includes("1") - ? "1,2" - : statusFilter?.sort().join(","), + statusFilter, statusFilter?.sort().join(",").includes("1") ? userLevelId : "", filterByCreator, filterBySource, @@ -213,6 +211,14 @@ const TableTeks = () => { fetchData(); // Panggil ulang data dengan filter baru }; + function handleStatusCheckboxChange(value: any) { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + } + const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { @@ -323,22 +329,54 @@ const TableTeks = () => { />
-
- - ) => - table - .getColumn("statusName") - ?.setFilterValue(event.target.value) - } - className="max-w-sm " + +
+ handleStatusCheckboxChange(1)} /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+ handleStatusCheckboxChange(4)} + /> +
diff --git a/app/[locale]/(protected)/contributor/content/teks/page.tsx b/app/[locale]/(protected)/contributor/content/teks/page.tsx index a352d007..73bf6661 100644 --- a/app/[locale]/(protected)/contributor/content/teks/page.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/page.tsx @@ -14,7 +14,7 @@ const ReactTableTeksPage = () => {
-
+
diff --git a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx index 90a47401..3b5f8bd1 100644 --- a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx +++ b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx @@ -90,7 +90,7 @@ const TableVideo = () => { [] ); const [categoryFilter, setCategoryFilter] = React.useState(""); - const [statusFilter, setStatusFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); const [startDate, setStartDate] = React.useState(""); const [endDate, setEndDate] = React.useState(""); const [filterByCreator, setFilterByCreator] = React.useState(""); @@ -130,7 +130,7 @@ const TableVideo = () => { React.useEffect(() => { fetchData(); getCategories(); - }, [categoryFilter, page, limit, search, startDate, endDate]); + }, [categoryFilter, statusFilter, page, limit, search, startDate, endDate]); async function getCategories() { const category = await listEnableCategory("2"); @@ -174,9 +174,7 @@ const TableVideo = () => { isForSelf, !isForSelf, categoryFilter, - statusFilter?.sort().join(",").includes("1") - ? "1,2" - : statusFilter?.sort().join(","), + statusFilter, statusFilter?.sort().join(",").includes("1") ? userLevelId : "", filterByCreator, filterBySource, @@ -213,6 +211,14 @@ const TableVideo = () => { fetchData(); // Panggil ulang data dengan filter baru }; + function handleStatusCheckboxChange(value: any) { + setStatusFilter((prev: any) => + prev.includes(value) + ? prev.filter((status: any) => status !== value) + : [...prev, value] + ); + } + const handleSearchFilterByCreator = ( e: React.ChangeEvent ) => { @@ -324,22 +330,54 @@ const TableVideo = () => { />
-
- - ) => - table - .getColumn("statusName") - ?.setFilterValue(event.target.value) - } - className="max-w-sm " + +
+ handleStatusCheckboxChange(1)} /> + +
+
+ handleStatusCheckboxChange(2)} + /> + +
+
+ handleStatusCheckboxChange(3)} + /> + +
+
+ handleStatusCheckboxChange(4)} + /> +
diff --git a/app/[locale]/(protected)/contributor/content/video/page.tsx b/app/[locale]/(protected)/contributor/content/video/page.tsx index d3202058..ef006ed0 100644 --- a/app/[locale]/(protected)/contributor/content/video/page.tsx +++ b/app/[locale]/(protected)/contributor/content/video/page.tsx @@ -14,7 +14,7 @@ const ReactTableVideoPage = () => {
-
+
diff --git a/app/[locale]/(protected)/contributor/task/components/task-table.tsx b/app/[locale]/(protected)/contributor/task/components/task-table.tsx index 7a089b02..64d80ec2 100644 --- a/app/[locale]/(protected)/contributor/task/components/task-table.tsx +++ b/app/[locale]/(protected)/contributor/task/components/task-table.tsx @@ -176,8 +176,8 @@ const TaskTable = () => {
-
-
+
+
@@ -185,7 +185,7 @@ const TaskTable = () => { diff --git a/app/[locale]/(protected)/contributor/task/page.tsx b/app/[locale]/(protected)/contributor/task/page.tsx index 00f328ef..0d91735d 100644 --- a/app/[locale]/(protected)/contributor/task/page.tsx +++ b/app/[locale]/(protected)/contributor/task/page.tsx @@ -25,7 +25,7 @@ const TaskPage = () => { -
+
Table Penugasan
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/audio.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/audio.tsx new file mode 100644 index 00000000..59a9759c --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/audio.tsx @@ -0,0 +1,129 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { listCuratedContent } from "@/service/curated-content/curated-content"; +import { getListContent } from "@/service/landing/landing"; +import { + formatDateToIndonesian, + generateLocalizedPath, + textEllipsis, +} from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { useParams, usePathname, useRouter } from "next/navigation"; +import React, { Component, useEffect, useState } from "react"; + +const AudioAll = () => { + const [audioData, setAudioData] = useState(); + const [displayAudio, setDisplayAudio] = useState([]); + const [page, setPage] = useState(1); + const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); + + useEffect(() => { + initFetch(); + }, [page, limit, search]); + + useEffect(() => { + if (audioData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [audioData]); + + const initFetch = async () => { + const response = await listCuratedContent(search, limit, page - 1, 4, "1"); + console.log(response); + + const data = response?.data?.data; + const contentData = data?.content; + setAudioData(contentData); + }; + + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...audioData]); + setDisplayAudio(shuffled.slice(0, 3)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + + return ( +
+
+ {displayAudio?.map((audio: any) => ( + +
+ + + +
+ +
+
+ {formatDateToIndonesian(new Date(audio?.createdAt))}{" "} + {audio?.timezone ? audio?.timezone : "WIB"} |{" "} + 518 +
+
+ {audio?.title} +
+
+
+
+ +
+
+ # +
+ {audio?.duration} +
+ + + +
+
+ + ))} +
+
+ ); +}; + +export default AudioAll; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/page.tsx index feb9ce71..a98d9b75 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/all/page.tsx @@ -23,6 +23,7 @@ import AudioSliderPage from "../../audio/audio"; import TeksSliderPage from "../../document/teks"; import ImageSliderPage from "../../image/image"; import VideoSliderPage from "../../video/audio-visual"; +import AudioAll from "./audio"; const AudioAllPage = () => { return ( @@ -56,7 +57,7 @@ const AudioAllPage = () => {
- +
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx index 9fd22e87..2cca7129 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx @@ -15,6 +15,7 @@ import { textEllipsis, } from "@/utils/globals"; import { Icon } from "@iconify/react/dist/iconify.js"; +import { hasData } from "jquery"; import { useParams, usePathname, useRouter } from "next/navigation"; import React, { Component, useEffect, useState } from "react"; @@ -24,18 +25,18 @@ const AudioSliderPage = () => { const [page, setPage] = useState(1); const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); - + const [hasData, setHasData] = useState(false); useEffect(() => { initFetch(); }, [page, limit, search]); - useEffect(() => { - if (audioData?.length > 0) { - shuffleAndSetVideos(); - const interval = setInterval(shuffleAndSetVideos, 5000); - return () => clearInterval(interval); // Cleanup interval on unmount - } - }, [audioData]); + // useEffect(() => { + // if (audioData?.length > 0) { + // shuffleAndSetVideos(); + // const interval = setInterval(shuffleAndSetVideos, 5000); + // return () => clearInterval(interval); // Cleanup interval on unmount + // } + // }, [audioData]); const initFetch = async () => { const response = await listCuratedContent(search, limit, page - 1, 4, "1"); @@ -43,13 +44,14 @@ const AudioSliderPage = () => { const data = response?.data?.data; const contentData = data?.content; - setAudioData(contentData); + setHasData(displayAudio && displayAudio.length > 0); + setDisplayAudio(contentData); }; - const shuffleAndSetVideos = () => { - const shuffled = shuffleArray([...audioData]); - setDisplayAudio(shuffled.slice(0, 3)); - }; + // const shuffleAndSetVideos = () => { + // const shuffled = shuffleArray([...audioData]); + // setDisplayAudio(shuffled.slice(0, 3)); + // }; const shuffleArray = (array: any[]) => { for (let i = array.length - 1; i > 0; i--) { @@ -60,69 +62,46 @@ const AudioSliderPage = () => { }; return ( -
-
- {displayAudio?.map((audio: any) => ( - -
- - - -
- -
-
- {formatDateToIndonesian(new Date(audio?.createdAt))}{" "} - {audio?.timezone ? audio?.timezone : "WIB"} |{" "} - 518 -
-
- {audio?.title} -
-
-
-
- -
-
- # -
- {audio?.duration} -
- + + {Array.from({ length: 5 }).map((_, index) => ( + +
+ {displayAudio?.map((audio: any) => ( + - - -
+
+ + + +
+ +
+
+ {audio?.title} +
+
+ + ))}
- + ))} -
-
+ + + + ); }; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx index d120f342..d7f4774e 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx @@ -21,8 +21,20 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import Cookies from "js-cookie"; import { postBlog } from "@/service/blog/blog"; import { Textarea } from "@/components/ui/textarea"; -import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; -import { detailMedia } from "@/service/curated-content/curated-content"; +import { + DotSquare, + InboxIcon, + Music, + PaperclipIcon, + SmileIcon, + TrashIcon, +} from "lucide-react"; +import { + deleteMediaCurationMessage, + detailMedia, + getMediaCurationMessage, + saveMediaCurationMessage, +} from "@/service/curated-content/curated-content"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/free-mode"; @@ -33,6 +45,15 @@ import "swiper/css"; import "swiper/css/navigation"; import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; import { Avatar, AvatarImage } from "@/components/ui/avatar"; +import WavesurferPlayer from "@wavesurfer/react"; +import WaveSurfer from "wavesurfer.js"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { Checkbox } from "@/components/ui/checkbox"; +import { Badge } from "@/components/ui/badge"; +import { htmlToString } from "@/utils/globals"; +import { getCookiesDecrypt } from "@/lib/utils"; +import { loading } from "@/lib/swal"; +import { formatDate } from "@fullcalendar/core/index.js"; const detailSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -69,6 +90,13 @@ export type curationDetail = { userGroupId: number; }; }; + publishedFor: string; // ID for selected radio button + publishedForObject: { + id: number; + name: string; + isInternal: boolean; + code: string; + }[]; tags: string; provinceId: string; is_active: string; @@ -119,10 +147,14 @@ export default function DetailAudio() { // files: [], // fileType: null, // }); + const userLevelNumber = getCookiesDecrypt("ulne"); + const userId = getCookiesDecrypt("uie"); const [detail, setDetail] = useState(); const [refresh] = useState(false); const [detailThumb, setDetailThumb] = useState([]); + const [detailAudio, setDetailAudio] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); + const [selectedValue, setSelectedValue] = useState(""); const { control, @@ -136,11 +168,30 @@ export default function DetailAudio() { const [commentsData, setCommentsData] = useState(initialComments); const [replyText, setReplyText] = useState(""); const [replyingTo, setReplyingTo] = useState(null); + const [selectedFileId, setSelectedFileId] = useState(null); + const [listData, setListData] = useState([]); + const [message, setMessage] = useState(""); + + const [wavesurfer, setWavesurfer] = useState(); + const [isPlaying, setIsPlaying] = useState(false); const handleReply = (commentId: number) => { setReplyingTo(commentId); }; + const handleInputChange = (e: React.ChangeEvent) => { + setMessage(e.target.value); + }; + + const onReady = (ws: any) => { + setWavesurfer(ws); + setIsPlaying(false); + }; + + const onPlayPause = () => { + wavesurfer && wavesurfer.playPause(); + }; + const addReply = (commentId: number) => { if (replyText.trim()) { const newCommentData = commentsData.map((comment: any) => { @@ -166,23 +217,131 @@ export default function DetailAudio() { } }; + useEffect(() => { + async function initState() { + // loading(); + const response = await getMediaCurationMessage(selectedFileId); + console.log("data", response?.data?.data); + console.log("userLvl", userLevelNumber); + setListData(response?.data?.data); + close(); + } + + initState(); + }, [selectedFileId]); + + const postData = async () => { + if (message?.length > 1 && selectedFileId) { + try { + const data = { + mediaUploadFileId: selectedFileId, + message, + parentId: null, + }; + + const response = await saveMediaCurationMessage(data); + console.log("Komentar terkirim:", response); + + const responseGet = await getMediaCurationMessage(selectedFileId); + setListData(responseGet?.data?.data); + + setMessage(""); + } catch (error) { + console.error("Error posting comment:", error); + } + } else { + console.log("Pesan atau file ID tidak valid."); + } + }; + + const sendReplyData = async (parentId: number) => { + const inputElement = document.querySelector( + `#input-comment-${parentId}` + ) as HTMLTextAreaElement; + + if (inputElement?.value?.length > 1 && selectedFileId) { + loading(); + const data = { + mediaUploadFileId: selectedFileId, + message: inputElement.value, + parentId, + }; + + console.log("Sending reply:", data); + const response = await saveMediaCurationMessage(data); + console.log(response); + + const responseGet = await getMediaCurationMessage(selectedFileId); + console.log("Updated comments:", responseGet?.data?.data); + setListData(responseGet?.data?.data); + + inputElement.value = ""; + close(); + setReplyingTo(null); + } + }; + + async function deleteDataSuggestion(dataId: any) { + loading(); + const response = await deleteMediaCurationMessage(dataId); + console.log(response); + const responseGet = await getMediaCurationMessage(selectedFileId); + console.log(responseGet?.data?.data); + setListData(responseGet?.data?.data); + close(); + } + + const deleteData = (dataId: any) => { + deleteDataSuggestion(dataId); + console.log(dataId); + }; + useEffect(() => { async function initState() { if (id) { const response = await detailMedia(id); const details = response?.data?.data; - - setDetail(details); const filesData = details.files || []; - const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => - file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + const fileUrls = filesData.map((file: any) => ({ + id: file.id, + secondaryUrl: file.secondaryUrl || "default-image.jpg", + placements: file.placements || "", + })); + setDetail(details); + setSelectedValue(details?.publishedFor || ""); + setSelectedFileId(details?.files[0]?.id); + setDetailAudio(fileUrls); + const fileUrlsThumbnail = filesData.map( + (file: { thumbnailFileUrl: string; placements: string }) => ({ + thumbnailFileUrl: file.thumbnailFileUrl + ? file.thumbnailFileUrl + : "default-image.jpg", + placements: file.placements || "", + }) ); - setDetailThumb(fileUrls); + + setDetailThumb(fileUrlsThumbnail); + // setDetailThumb(fileUrls); } } initState(); }, [id, refresh]); + const handleFileClick = async (fileId: any) => { + setSelectedFileId(fileId); + try { + const response = await getMediaCurationMessage(fileId); + console.log("Data komentar:", response?.data?.data); + setListData(response?.data?.data); + } catch (error) { + console.error("Error fetching comments:", error); + } + }; + + const handleValueChange = (value: string) => { + setSelectedValue(value); + }; + return (
{detail !== undefined ? ( @@ -190,8 +349,8 @@ export default function DetailAudio() {

Kurasi Detail

-
-
+
+
@@ -242,7 +401,7 @@ export default function DetailAudio() { name="description" render={({ field }) => ( +
+ - -
- )}
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/page.tsx index 2ba8e25a..8fab4905 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/page.tsx @@ -23,6 +23,7 @@ import AudioSliderPage from "../../audio/audio"; import TeksSliderPage from "../../document/teks"; import ImageSliderPage from "../../image/image"; import VideoSliderPage from "../../video/audio-visual"; +import TeksAll from "./teks"; const DocumentAllPage = () => { return ( @@ -56,7 +57,7 @@ const DocumentAllPage = () => {
- +
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/teks.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/teks.tsx new file mode 100644 index 00000000..28ff6077 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/all/teks.tsx @@ -0,0 +1,116 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { listCuratedContent } from "@/service/curated-content/curated-content"; +import { getListContent } from "@/service/landing/landing"; +import { + formatDateToIndonesian, + generateLocalizedPath, + textEllipsis, +} from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { useParams, usePathname, useRouter } from "next/navigation"; +import React, { Component, useEffect, useState } from "react"; + +const TeksAll = () => { + const [documentData, setDocumentData] = useState(); + const [displayDocument, setDisplayDocument] = useState([]); + const [page, setPage] = useState(1); + const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); + + useEffect(() => { + initFetch(); + }, [page, limit, search]); + + useEffect(() => { + if (documentData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [documentData]); + + const initFetch = async () => { + const response = await listCuratedContent(search, limit, page - 1, 3, "1"); + console.log(response); + + const data = response?.data?.data; + const contentData = data?.content; + setDocumentData(contentData); + }; + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...documentData]); + setDisplayDocument(shuffled.slice(0, 2)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + + return ( +
+
+ {displayDocument?.map((document: any) => ( + +
+ + + +
+ +
+
+ {formatDateToIndonesian(new Date(document?.createdAt))}{" "} + {document?.timezone ? document?.timezone : "WIB"} |{" "} + 518 +
+
+ {document?.title} +
+
+ + + + Download Dokumen +
+
+ + ))} +
+
+ ); +}; + +export default TeksAll; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx index 187a3eab..abbd4b54 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx @@ -21,8 +21,19 @@ import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import Cookies from "js-cookie"; import { postBlog } from "@/service/blog/blog"; import { Textarea } from "@/components/ui/textarea"; -import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; -import { detailMedia } from "@/service/curated-content/curated-content"; +import { + DotSquare, + InboxIcon, + PaperclipIcon, + SmileIcon, + TrashIcon, +} from "lucide-react"; +import { + deleteMediaCurationMessage, + detailMedia, + getMediaCurationMessage, + saveMediaCurationMessage, +} from "@/service/curated-content/curated-content"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/free-mode"; @@ -35,6 +46,11 @@ import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; import { Avatar, AvatarImage } from "@/components/ui/avatar"; import JoditEditor from "jodit-react"; import { Badge } from "@/components/ui/badge"; +import { Checkbox } from "@/components/ui/checkbox"; +import { htmlToString } from "@/utils/globals"; +import { loading } from "@/lib/swal"; +import { formatDate } from "@fullcalendar/core/index.js"; +import { getCookiesDecrypt } from "@/lib/utils"; const detailSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -51,6 +67,13 @@ type Category = { categoryName: string; }; +type PublishedForObject = { + id: number; + name: string; + isInternal: boolean; + code: string; +}; + export type curationDetail = { id: number; title: string; @@ -71,6 +94,13 @@ export type curationDetail = { userGroupId: number; }; }; + publishedFor: string; // ID for selected radio button + publishedForObject: { + id: number; + name: string; + isInternal: boolean; + code: string; + }[]; tags: string; provinceId: string; is_active: string; @@ -109,7 +139,8 @@ export default function DetailDocument() { console.log(id); const editor = useRef(null); type DetailSchema = z.infer; - + const userLevelNumber = getCookiesDecrypt("ulne"); + const userId = getCookiesDecrypt("uie"); const [selectedFiles, setSelectedFiles] = useState([]); const taskId = Cookies.get("taskId"); const scheduleId = Cookies.get("scheduleId"); @@ -125,6 +156,7 @@ export default function DetailDocument() { const [refresh] = useState(false); const [detailThumb, setDetailThumb] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); + const [selectedValue, setSelectedValue] = useState(""); const { control, @@ -138,11 +170,18 @@ export default function DetailDocument() { const [commentsData, setCommentsData] = useState(initialComments); const [replyText, setReplyText] = useState(""); const [replyingTo, setReplyingTo] = useState(null); + const [selectedFileId, setSelectedFileId] = useState(null); + const [listData, setListData] = useState([]); + const [message, setMessage] = useState(""); const handleReply = (commentId: number) => { setReplyingTo(commentId); }; + const handleInputChange = (e: React.ChangeEvent) => { + setMessage(e.target.value); + }; + const addReply = (commentId: number) => { if (replyText.trim()) { const newCommentData = commentsData.map((comment: any) => { @@ -168,6 +207,85 @@ export default function DetailDocument() { } }; + useEffect(() => { + async function initState() { + // loading(); + const response = await getMediaCurationMessage(selectedFileId); + console.log("data", response?.data?.data); + console.log("userLvl", userLevelNumber); + setListData(response?.data?.data); + close(); + } + + initState(); + }, [selectedFileId]); + + const postData = async () => { + if (message?.length > 1 && selectedFileId) { + try { + const data = { + mediaUploadFileId: selectedFileId, + message, + parentId: null, + }; + + const response = await saveMediaCurationMessage(data); + console.log("Komentar terkirim:", response); + + const responseGet = await getMediaCurationMessage(selectedFileId); + setListData(responseGet?.data?.data); + + setMessage(""); + } catch (error) { + console.error("Error posting comment:", error); + } + } else { + console.log("Pesan atau file ID tidak valid."); + } + }; + + const sendReplyData = async (parentId: number) => { + const inputElement = document.querySelector( + `#input-comment-${parentId}` + ) as HTMLTextAreaElement; + + if (inputElement?.value?.length > 1 && selectedFileId) { + loading(); + const data = { + mediaUploadFileId: selectedFileId, + message: inputElement.value, + parentId, + }; + + console.log("Sending reply:", data); + const response = await saveMediaCurationMessage(data); + console.log(response); + + const responseGet = await getMediaCurationMessage(selectedFileId); + console.log("Updated comments:", responseGet?.data?.data); + setListData(responseGet?.data?.data); + + inputElement.value = ""; + close(); + setReplyingTo(null); + } + }; + + async function deleteDataSuggestion(dataId: any) { + loading(); + const response = await deleteMediaCurationMessage(dataId); + console.log(response); + const responseGet = await getMediaCurationMessage(selectedFileId); + console.log(responseGet?.data?.data); + setListData(responseGet?.data?.data); + close(); + } + + const deleteData = (dataId: any) => { + deleteDataSuggestion(dataId); + console.log(dataId); + }; + useEffect(() => { async function initState() { if (id) { @@ -175,16 +293,37 @@ export default function DetailDocument() { const details = response?.data?.data; setDetail(details); + setSelectedValue(details?.publishedFor || ""); + setSelectedFileId(details?.files[0]?.id); const filesData = details.files || []; - const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => - file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" - ); + const fileUrls = filesData.map((file: any) => ({ + id: file.id, + url: file.secondaryUrl || "default-image.jpg", + format: file.format, + fileName: file.fileName, + placements: file.placements || "", + })); setDetailThumb(fileUrls); } } initState(); }, [id, refresh]); + const handleFileClick = async (fileId: any) => { + setSelectedFileId(fileId); + try { + const response = await getMediaCurationMessage(fileId); + console.log("Data komentar:", response?.data?.data); + setListData(response?.data?.data); + } catch (error) { + console.error("Error fetching comments:", error); + } + }; + + const handleValueChange = (value: string) => { + setSelectedValue(value); + }; + return (
{detail !== undefined ? ( @@ -192,8 +331,8 @@ export default function DetailDocument() {

Kurasi Detail

-
-
+
+
@@ -244,7 +383,7 @@ export default function DetailDocument() { name="description" render={({ field }) => ( +
+ - -
- )}
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx index 20e89711..a36d9269 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx @@ -7,6 +7,7 @@ import { CarouselNext, CarouselPrevious, } from "@/components/ui/carousel"; +import { listCuratedContent } from "@/service/curated-content/curated-content"; import { getListContent } from "@/service/landing/landing"; import { formatDateToIndonesian, @@ -21,94 +22,102 @@ const TeksSliderPage = () => { const [documentData, setDocumentData] = useState(); const [displayDocument, setDisplayDocument] = useState([]); const [page, setPage] = useState(1); + const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); + const [hasData, setHasData] = useState(false); useEffect(() => { initFetch(); - }, []); + }, [page, limit, search]); - useEffect(() => { - if (documentData?.length > 0) { - shuffleAndSetVideos(); - const interval = setInterval(shuffleAndSetVideos, 5000); - return () => clearInterval(interval); // Cleanup interval on unmount - } - }, [documentData]); + // useEffect(() => { + // if (documentData?.length > 0) { + // shuffleAndSetVideos(); + // const interval = setInterval(shuffleAndSetVideos, 5000); + // return () => clearInterval(interval); // Cleanup interval on unmount + // } + // }, [documentData]); const initFetch = async () => { - const response = await getListContent({ - page: page - 1, - size: 12, - sortBy: "createdAt", - contentTypeId: "3", - }); + const response = await listCuratedContent(search, limit, page - 1, 3, "1"); console.log(response); - setDocumentData(response?.data?.data?.content); - }; - const shuffleAndSetVideos = () => { - const shuffled = shuffleArray([...documentData]); - setDisplayDocument(shuffled.slice(0, 2)); - }; - const shuffleArray = (array: any[]) => { - for (let i = array.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [array[i], array[j]] = [array[j], array[i]]; - } - return array; + const data = response?.data?.data; + const contentData = data?.content; + setHasData(displayDocument && displayDocument.length > 0); + setDisplayDocument(contentData); }; + // const shuffleAndSetVideos = () => { + // const shuffled = shuffleArray([...documentData]); + // setDisplayDocument(shuffled.slice(0, 2)); + // }; + + // const shuffleArray = (array: any[]) => { + // for (let i = array.length - 1; i > 0; i--) { + // const j = Math.floor(Math.random() * (i + 1)); + // [array[i], array[j]] = [array[j], array[i]]; + // } + // return array; + // }; return ( -
-
- {displayDocument?.map((document: any) => ( - -
- + + +
+ {displayDocument?.map((document: any) => ( + - - -
+
+ + + +
-
-
- {formatDateToIndonesian(new Date(document?.createdAt))}{" "} - {document?.timezone ? document?.timezone : "WIB"} |{" "} - 518 -
-
- {document?.title} -
-
- - - - Download Dokumen -
-
- - ))} -
-
+
+
+ {formatDateToIndonesian(new Date(document?.createdAt))}{" "} + {document?.timezone ? document?.timezone : "WIB"} |{" "} + 518 +
+
+ {document?.title} +
+
+ + + + Download Dokumen +
+
+ + ))} +
+ + + + + ); }; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx index 90858da6..133d85c1 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx @@ -53,6 +53,8 @@ import { } from "@/service/task"; import { getCookiesDecrypt } from "@/lib/utils"; import { close, loading } from "@/lib/swal"; +import { Checkbox } from "@/components/ui/checkbox"; +import { htmlToString } from "@/utils/globals"; const detailSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -107,6 +109,13 @@ export type curationDetail = { userGroupId: number; }; }; + publishedFor: string; // ID for selected radio button + publishedForObject: { + id: number; + name: string; + isInternal: boolean; + code: string; + }[]; tags: string; provinceId: string; is_active: string; @@ -173,6 +182,7 @@ export default function DetailImage() { const [commentsData, setCommentsData] = useState(initialComments); const [replyText, setReplyText] = useState(""); const [replyingTo, setReplyingTo] = useState(null); + const [selectedValue, setSelectedValue] = useState(""); const handleReply = (commentId: number) => { setReplyingTo(commentId); @@ -272,11 +282,13 @@ export default function DetailImage() { const details = response?.data?.data; setDetail(details); + setSelectedValue(details?.publishedFor || ""); setSelectedFileId(details?.files[0]?.id); const filesData = details.files || []; const fileUrls = filesData.map((file: any) => ({ id: file.id, thumbnailFileUrl: file.thumbnailFileUrl || "default-image.jpg", + placements: file.placements || "", })); setDetailThumb(fileUrls); } @@ -294,6 +306,9 @@ export default function DetailImage() { console.error("Error fetching comments:", error); } }; + const handleValueChange = (value: string) => { + setSelectedValue(value); + }; return (
@@ -302,8 +317,8 @@ export default function DetailImage() {

Kurasi Detail

-
-
+
+
@@ -354,7 +369,7 @@ export default function DetailImage() { name="description" render={({ field }) => ( -
-
- - - -
-
-
- {commentsData.map((comment) => ( -
- - - -
- - {comment.username} - - - {comment.date} - -

{comment.text}

-
handleReply(comment.id)} - > - - Balas +
+ - -
- )}
diff --git a/app/[locale]/(protected)/shared/curated-content/page.tsx b/app/[locale]/(protected)/shared/curated-content/page.tsx index 661f7a88..6fe39f04 100644 --- a/app/[locale]/(protected)/shared/curated-content/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/page.tsx @@ -1,7 +1,7 @@ import SiteBreadcrumb from "@/components/site-breadcrumb"; import { Card, CardContent } from "@/components/ui/card"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; -import { Rows, Search, UploadIcon } from "lucide-react"; +import { ArrowRight, Rows, Search, UploadIcon } from "lucide-react"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; @@ -76,65 +76,76 @@ const CuratedContentPage = () => {
- +
+ + +
- - +
+ + +
- - +
+ + +
- +
+ + +
diff --git a/components/form/blog/blog--detail-form.tsx b/components/form/blog/blog--detail-form.tsx index 876dcd4f..a16c271e 100644 --- a/components/form/blog/blog--detail-form.tsx +++ b/components/form/blog/blog--detail-form.tsx @@ -210,7 +210,7 @@ export default function FormBlogDetail() { return (
{detail !== undefined ? ( -
+

Detail Indeks

@@ -302,7 +302,7 @@ export default function FormBlogDetail() {
-
+
diff --git a/components/form/blog/blog--update-form.tsx b/components/form/blog/blog--update-form.tsx index 30fb3c93..17786a66 100644 --- a/components/form/blog/blog--update-form.tsx +++ b/components/form/blog/blog--update-form.tsx @@ -267,7 +267,7 @@ export default function FormBlogUpdate() { return ( {detail !== undefined ? ( -
+

Update Indeks

@@ -362,8 +362,8 @@ export default function FormBlogUpdate() {
-
- +
+
-
+

Form Indeks

@@ -358,7 +358,7 @@ export default function FormBlog() {
-
+
diff --git a/components/form/content/audio-detail-form.tsx b/components/form/content/audio-detail-form.tsx index 865e600a..ebf74b2c 100644 --- a/components/form/content/audio-detail-form.tsx +++ b/components/form/content/audio-detail-form.tsx @@ -32,7 +32,7 @@ import { } from "@/service/content/content"; import { detailMedia } from "@/service/curated-content/curated-content"; import { Badge } from "@/components/ui/badge"; -import { MailIcon } from "lucide-react"; +import { MailIcon, Music } from "lucide-react"; import { Swiper, SwiperSlide } from "swiper/react"; import "swiper/css"; import "swiper/css/free-mode"; @@ -138,25 +138,23 @@ export default function FormAudioDetail() { const [selectedTarget, setSelectedTarget] = useState(""); const [files, setFiles] = useState([]); const [rejectedFiles, setRejectedFiles] = useState([]); - const [isMabesApprover, setIsMabesApprover] = useState(false); + const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [audioPlaying, setAudioPlaying] = useState(null); + const [filePlacements, setFilePlacements] = useState([]); const waveSurferRef = useRef(null); - const [wavesurfer, setWavesurfer] = useState(); - const [isPlaying, setIsPlaying] = useState(false) - + const [isPlaying, setIsPlaying] = useState(false); const onReady = (ws: any) => { - setWavesurfer(ws) + setWavesurfer(ws); setIsPlaying(false); - } + }; const onPlayPause = () => { wavesurfer && wavesurfer.playPause(); - } - + }; let fileTypeId = "4"; @@ -187,7 +185,7 @@ export default function FormAudioDetail() { userLevelId == "216" && roleId == "3" ) { - setIsMabesApprover(true); + setIsUserMabesApprover(true); } }, [userLevelId, roleId]); @@ -230,6 +228,14 @@ export default function FormAudioDetail() { } }; + const setupPlacementCheck = (length: number) => { + const temp = []; + for (let i = 0; i < length; i++) { + temp.push([]); + } + setFilePlacements(temp); + }; + useEffect(() => { async function initState() { if (id) { @@ -244,6 +250,7 @@ export default function FormAudioDetail() { names: details?.files[0]?.fileName, format: details?.files[0]?.format, }); + setupPlacementCheck(details?.files?.length); if (details.publishedForObject) { const publisherIds = details.publishedForObject.map( @@ -281,9 +288,16 @@ export default function FormAudioDetail() { }, [refresh, setValue]); const actionApproval = (e: string) => { + const temp = []; + for (const element of detail.files) { + temp.push([]); + } + setFilePlacements(temp); setStatus(e); - setModalOpen(true); + setFiles(detail.files); + setDescription(""); + setModalOpen(true); }; const submit = async () => { @@ -308,13 +322,26 @@ export default function FormAudioDetail() { } }; + const getPlacement = () => { + console.log("getPlaa", filePlacements); + const temp = []; + for (let i = 0; i < filePlacements?.length; i++) { + if (filePlacements[i].length !== 0) { + const now = filePlacements[i].filter((a) => a !== "all"); + const data = { mediaFileId: files[i].id, placements: now.join(",") }; + temp.push(data); + } + } + return temp; + }; + async function save() { const data = { mediaUploadId: id, statusId: status, message: description, - files: [], - // files: isMabesApprover ? getPlacement() : [], + // files: [], + files: isUserMabesApprover ? getPlacement() : [], }; loading(); @@ -337,6 +364,7 @@ export default function FormAudioDetail() { } close(); + submitApprovalSuccesss(); return false; } @@ -348,6 +376,40 @@ export default function FormAudioDetail() { rejects.push(id); setRejectedFiles(rejects); } + + const setupPlacement = ( + index: number, + placement: string, + checked: boolean + ) => { + let temp = [...filePlacements]; + if (checked) { + if (placement === "all") { + temp[index] = ["all", "mabes", "polda", "international"]; + } else { + const now = temp[index]; + now.push(placement); + if (now.length === 3 && !now.includes("all")) { + now.push("all"); + } + temp[index] = now; + } + } else { + if (placement === "all") { + temp[index] = []; + } else { + const now = temp[index].filter((a) => a !== placement); + console.log("now", now); + temp[index] = now; + if (now.length === 3 && now.includes("all")) { + const newData = now.filter((b) => b !== "all"); + temp[index] = newData; + } + } + } + setFilePlacements(temp); + }; + const handleMain = ( type: string, url: string, @@ -380,14 +442,14 @@ export default function FormAudioDetail() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/in/contributor/content/image"); + router.push("/in/contributor/content/audio"); }); }; return ( {detail !== undefined ? ( -
+

Form Konten Audio

@@ -469,14 +531,34 @@ export default function FormAudioDetail() { />
))} -

{isPlaying ? "Pause" : "Play"}

+
-
- +
+
@@ -609,7 +691,7 @@ export default function FormAudioDetail() { Berikan Komentar {status == "2" - ? files?.map((file) => ( + ? files?.map((file, index) => (
-
-
- - -
-
- - -
-
- - -
+ {isUserMabesApprover && ( +
+
+ + setupPlacement(index, "all", Boolean(e)) + } + /> + +
+
+ + setupPlacement(index, "mabes", Boolean(e)) + } + /> + +
+
+ + setupPlacement(index, "polda", Boolean(e)) + } + /> + +
-
- - +
+ + setupPlacement( + index, + "international", + Boolean(e) + ) + } + /> + +
-
+ )}
)) @@ -743,14 +868,16 @@ export default function FormAudioDetail() { diff --git a/components/form/content/audio-form.tsx b/components/form/content/audio-form.tsx index 94d2e478..18b76e5b 100644 --- a/components/form/content/audio-form.tsx +++ b/components/form/content/audio-form.tsx @@ -533,7 +533,7 @@ export default function FormAudio() { const csrfToken = resCsrf?.data?.token; console.log("CSRF TOKEN : ", csrfToken); const headers = { - "X-XSRF-TOKEN": csrfToken + "X-XSRF-TOKEN": csrfToken, }; const upload = new Upload(file, { @@ -549,8 +549,8 @@ export default function FormAudio() { isWatermark: "false", // hardcode }, onBeforeRequest: function (req) { - var xhr = req.getUnderlyingObject() - xhr.withCredentials = true + var xhr = req.getUnderlyingObject(); + xhr.withCredentials = true; }, onError: async (e: any) => { console.log("Error upload :", e); @@ -685,7 +685,7 @@ export default function FormAudio() { return ( -
+

Form Konten Audio

@@ -1026,11 +1026,9 @@ export default function FormAudio() {
- - {/* Submit Button */}
-
+
diff --git a/components/form/content/audio-update-form.tsx b/components/form/content/audio-update-form.tsx index 8028fe14..02bd974a 100644 --- a/components/form/content/audio-update-form.tsx +++ b/components/form/content/audio-update-form.tsx @@ -587,7 +587,7 @@ export default function FormAudioUpdate() { return ( {detail !== undefined ? ( -
+

Form Konten Audio

@@ -713,7 +713,7 @@ export default function FormAudioUpdate() { alt={file.fileName} className="w-16 h-16 object-cover rounded-md mr-4" /> -
+

{file.fileName}

-
+
diff --git a/components/form/content/image-detail-form.tsx b/components/form/content/image-detail-form.tsx index 5935a1ad..b0cb3340 100644 --- a/components/form/content/image-detail-form.tsx +++ b/components/form/content/image-detail-form.tsx @@ -295,7 +295,7 @@ export default function FormImageDetail() { for (let i = 0; i < filePlacements?.length; i++) { if (filePlacements[i].length !== 0) { const now = filePlacements[i].filter((a) => a !== "all"); - const data = { mediaFileId: files[i].id, placement: now.join(",") }; + const data = { mediaFileId: files[i].id, placements: now.join(",") }; temp.push(data); } } @@ -409,7 +409,7 @@ export default function FormImageDetail() { return ( {detail !== undefined ? ( -
+

Form Konten Foto

@@ -520,7 +520,7 @@ export default function FormImageDetail() {
-
+
diff --git a/components/form/content/image-form.tsx b/components/form/content/image-form.tsx index 9920e898..97a4fb7d 100644 --- a/components/form/content/image-form.tsx +++ b/components/form/content/image-form.tsx @@ -695,7 +695,7 @@ export default function FormImage() { return ( -
+

Form Konten Foto

@@ -1039,7 +1039,7 @@ export default function FormImage() { {/* Submit Button */}
-
+
diff --git a/components/form/content/image-update-form.tsx b/components/form/content/image-update-form.tsx index 7b6c94d6..e7577551 100644 --- a/components/form/content/image-update-form.tsx +++ b/components/form/content/image-update-form.tsx @@ -625,7 +625,7 @@ export default function FormImageUpdate() { return ( {detail !== undefined ? ( -
+

Form Konten Foto

@@ -752,7 +752,7 @@ export default function FormImageUpdate() { alt={file.fileName} className="w-16 h-16 object-cover rounded-md mr-4" /> -
+

{file.fileName}

-
- +
+
diff --git a/components/form/content/spit-convert-form.tsx b/components/form/content/spit-convert-form.tsx index f7898f04..bfc8f4b2 100644 --- a/components/form/content/spit-convert-form.tsx +++ b/components/form/content/spit-convert-form.tsx @@ -355,10 +355,8 @@ export default function FormConvertSPIT() { const handleCheckboxChange = (id: string): void => { if (id === "all") { if (publishedFor.includes("all")) { - // Uncheck all checkboxes setPublishedFor([]); } else { - // Select all checkboxes setPublishedFor( options .filter((opt: any) => opt.id !== "all") @@ -370,7 +368,6 @@ export default function FormConvertSPIT() { ? publishedFor.filter((item) => item !== id) : [...publishedFor, id]; - // Remove "all" if any checkbox is unchecked if (publishedFor.includes("all") && id !== "all") { setPublishedFor(updatedPublishedFor.filter((item) => item !== "all")); } else { @@ -416,10 +413,10 @@ export default function FormConvertSPIT() { description, htmlDescription: description, tags: "siap", - categoryId: 1, + categoryId: selectedCategoryId, publishedFor: publishedFor.join(","), creator: data.contentCreator, - files: isUserMabesApprover ? getPlacement() : [], // Include placement data + files: isUserMabesApprover ? getPlacement() : [], }; const response = await convertSPIT(requestData); @@ -544,7 +541,7 @@ export default function FormConvertSPIT() { return ( {detail !== undefined ? ( -
+

Form Konten Foto

@@ -698,7 +695,7 @@ export default function FormConvertSPIT() {
- +
( {` @@ -719,7 +716,7 @@ export default function FormConvertSPIT() {
( {` @@ -761,7 +758,7 @@ export default function FormConvertSPIT() { */}
-
+
-
+
diff --git a/components/form/content/teks-detail-form.tsx b/components/form/content/teks-detail-form.tsx index 404f143d..7ae5276c 100644 --- a/components/form/content/teks-detail-form.tsx +++ b/components/form/content/teks-detail-form.tsx @@ -138,6 +138,9 @@ export default function FormTeksDetail() { const [rejectedFiles, setRejectedFiles] = useState([]); const [isMabesApprover, setIsMabesApprover] = useState(false); + const [filePlacements, setFilePlacements] = useState([]); + const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); + let fileTypeId = "3"; const { @@ -167,7 +170,7 @@ export default function FormTeksDetail() { userLevelId == "216" && roleId == "3" ) { - setIsMabesApprover(true); + setIsUserMabesApprover(true); } }, [userLevelId, roleId]); @@ -210,6 +213,14 @@ export default function FormTeksDetail() { } }; + const setupPlacementCheck = (length: number) => { + const temp = []; + for (let i = 0; i < length; i++) { + temp.push([]); + } + setFilePlacements(temp); + }; + useEffect(() => { async function initState() { if (id) { @@ -255,9 +266,16 @@ export default function FormTeksDetail() { }, [refresh, setValue]); const actionApproval = (e: string) => { + const temp = []; + for (const element of detail.files) { + temp.push([]); + } + setFilePlacements(temp); setStatus(e); - setModalOpen(true); + setFiles(detail.files); + setDescription(""); + setModalOpen(true); }; const submit = async () => { @@ -266,29 +284,42 @@ export default function FormTeksDetail() { Number(status) == 2 || Number(status) == 4 ) { - MySwal.fire({ - title: "Simpan Approval", - text: "", - icon: "warning", - showCancelButton: true, - cancelButtonColor: "#d33", - confirmButtonColor: "#3085d6", - confirmButtonText: "Simpan", - }).then((result) => { - if (result.isConfirmed) { - save(); - } - }); + save(); + // MySwal.fire({ + // title: "Simpan Approval", + // text: "", + // icon: "warning", + // showCancelButton: true, + // cancelButtonColor: "#d33", + // confirmButtonColor: "#3085d6", + // confirmButtonText: "Simpan", + // }).then((result) => { + // if (result.isConfirmed) { + + // } + // }); } }; + const getPlacement = () => { + console.log("getPlaa", filePlacements); + const temp = []; + for (let i = 0; i < filePlacements?.length; i++) { + if (filePlacements[i].length !== 0) { + const now = filePlacements[i].filter((a) => a !== "all"); + const data = { mediaFileId: files[i].id, placements: now.join(",") }; + temp.push(data); + } + } + return temp; + }; + async function save() { const data = { mediaUploadId: id, statusId: status, message: description, - files: [], - // files: isMabesApprover ? getPlacement() : [], + files: isUserMabesApprover ? getPlacement() : [], }; loading(); @@ -311,10 +342,44 @@ export default function FormTeksDetail() { } close(); + submitApprovalSuccesss(); return false; } + const setupPlacement = ( + index: number, + placement: string, + checked: boolean + ) => { + let temp = [...filePlacements]; + if (checked) { + if (placement === "all") { + temp[index] = ["all", "mabes", "polda", "international"]; + } else { + const now = temp[index]; + now.push(placement); + if (now.length === 3 && !now.includes("all")) { + now.push("all"); + } + temp[index] = now; + } + } else { + if (placement === "all") { + temp[index] = []; + } else { + const now = temp[index].filter((a) => a !== placement); + console.log("now", now); + temp[index] = now; + if (now.length === 3 && now.includes("all")) { + const newData = now.filter((b) => b !== "all"); + temp[index] = newData; + } + } + } + setFilePlacements(temp); + }; + function handleDeleteFileApproval(id: number) { const selectedFiles = files.filter((file) => file.id != id); setFiles(selectedFiles); @@ -353,7 +418,7 @@ export default function FormTeksDetail() { return ( {detail !== undefined ? ( -
+

@@ -470,10 +535,10 @@ export default function FormTeksDetail() { ))} -

+
-
+
@@ -644,7 +709,7 @@ export default function FormTeksDetail() { Berikan Komentar {status == "2" - ? files?.map((file) => ( + ? files?.map((file, index) => (
-
-
- - -
-
- - -
-
- - -
+ {isUserMabesApprover && ( +
+
+ + setupPlacement(index, "all", Boolean(e)) + } + /> + +
+
+ + setupPlacement(index, "mabes", Boolean(e)) + } + /> + +
+
+ + setupPlacement(index, "polda", Boolean(e)) + } + /> + +
-
- - +
+ + setupPlacement( + index, + "international", + Boolean(e) + ) + } + /> + +
-
+ )}
)) @@ -778,14 +886,16 @@ export default function FormTeksDetail() { diff --git a/components/form/content/teks-form.tsx b/components/form/content/teks-form.tsx index fa587340..3349965d 100644 --- a/components/form/content/teks-form.tsx +++ b/components/form/content/teks-form.tsx @@ -532,7 +532,7 @@ export default function FormTeks() { const csrfToken = resCsrf?.data?.token; console.log("CSRF TOKEN : ", csrfToken); const headers = { - "X-XSRF-TOKEN": csrfToken + "X-XSRF-TOKEN": csrfToken, }; const upload = new Upload(file, { @@ -548,8 +548,8 @@ export default function FormTeks() { isWatermark: "false", // hardcode }, onBeforeRequest: function (req) { - var xhr = req.getUnderlyingObject() - xhr.withCredentials = true + var xhr = req.getUnderlyingObject(); + xhr.withCredentials = true; }, onError: async (e: any) => { console.log("Error upload :", e); @@ -684,7 +684,7 @@ export default function FormTeks() { return ( -
+

Form Konten Teks

@@ -1028,7 +1028,7 @@ export default function FormTeks() { {/* Submit Button */}
-
+
diff --git a/components/form/content/teks-update-form.tsx b/components/form/content/teks-update-form.tsx index f66f5d72..a448bb2b 100644 --- a/components/form/content/teks-update-form.tsx +++ b/components/form/content/teks-update-form.tsx @@ -552,7 +552,7 @@ export default function FormTeksUpdate() { return ( {detail !== undefined ? ( -
+

@@ -679,7 +679,7 @@ export default function FormTeksUpdate() { alt={file.fileName} className="w-16 h-16 object-cover rounded-md mr-4" /> -

+

{file.fileName}

-
+
diff --git a/components/form/content/video-detail-form.tsx b/components/form/content/video-detail-form.tsx index a4a4fee7..d41c4350 100644 --- a/components/form/content/video-detail-form.tsx +++ b/components/form/content/video-detail-form.tsx @@ -329,7 +329,7 @@ export default function FormVideoDetail() { for (let i = 0; i < filePlacements?.length; i++) { if (filePlacements[i].length !== 0) { const now = filePlacements[i].filter((a) => a !== "all"); - const data = { mediaFileId: files[i].id, placement: now.join(",") }; + const data = { mediaFileId: files[i].id, placements: now.join(",") }; temp.push(data); } } @@ -409,7 +409,7 @@ export default function FormVideoDetail() { return ( {detail !== undefined ? ( -
+

@@ -524,7 +524,7 @@ export default function FormVideoDetail() {

-
+
diff --git a/components/form/content/video-form.tsx b/components/form/content/video-form.tsx index 764d3b1f..b63f8f88 100644 --- a/components/form/content/video-form.tsx +++ b/components/form/content/video-form.tsx @@ -683,12 +683,11 @@ export default function FormVideo() { return ( -
+

Form Konten Video

- {/* Input Title */}
-
+
diff --git a/components/form/content/video-update-form.tsx b/components/form/content/video-update-form.tsx index 34e443b0..43f24e2c 100644 --- a/components/form/content/video-update-form.tsx +++ b/components/form/content/video-update-form.tsx @@ -606,7 +606,7 @@ export default function FormVideoUpdate() { return ( {detail !== undefined ? ( -
+

@@ -734,7 +734,7 @@ export default function FormVideoUpdate() { alt={file.fileName} className="w-16 h-16 object-cover rounded-md mr-4" /> -

+

{file.fileName}

-
+
diff --git a/components/form/contest/contest-detail-form.tsx b/components/form/contest/contest-detail-form.tsx index a7a7a9d5..8cefbfc5 100644 --- a/components/form/contest/contest-detail-form.tsx +++ b/components/form/contest/contest-detail-form.tsx @@ -46,6 +46,11 @@ import { } from "@/components/ui/dialog"; import dynamic from "next/dynamic"; import Cookies from "js-cookie"; +import FileUploader from "../shared/file-uploader"; +import { AudioRecorder } from "react-audio-voice-recorder"; +import { error, loading } from "@/lib/swal"; +import { Upload } from "tus-js-client"; +import { getCsrfToken } from "@/service/auth"; const contestSchema = z.object({ theme: z.string().min(1, { message: "Judul diperlukan" }), @@ -88,6 +93,10 @@ const CustomEditor = dynamic( { ssr: false } ); +interface FileWithPreview extends File { + preview: string; +} + export default function FormContestDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); @@ -105,6 +114,18 @@ export default function FormContestDetail() { const [checkedLevels, setCheckedLevels] = useState(new Set()); const [expandedPolda, setExpandedPolda] = useState([{}]); const [isLoading, setIsLoading] = useState(false); + const [audioFile, setAudioFile] = useState(null); + const [imageFiles, setImageFiles] = useState([]); + const [videoFiles, setVideoFiles] = useState([]); + const [textFiles, setTextFiles] = useState([]); + const [audioFiles, setAudioFiles] = useState([]); + const [isImageUploadFinish, setIsImageUploadFinish] = useState(false); + const [isVideoUploadFinish, setIsVideoUploadFinish] = useState(false); + const [isTextUploadFinish, setIsTextUploadFinish] = useState(false); + const [isAudioUploadFinish, setIsAudioUploadFinish] = useState(false); + const [isRecording, setIsRecording] = useState(false); + const [timer, setTimer] = useState(120); + const [links, setLinks] = useState([""]); const [platformTypeVisible, setPlatformTypeVisible] = useState(false); @@ -221,13 +242,6 @@ export default function FormContestDetail() { return Array.from(checkedLevels).join(","); // Mengonversi Set ke string }; - const toggleExpand = (poldaId: any) => { - setExpandedPolda((prev: any) => ({ - ...prev, - [poldaId]: !prev[poldaId], - })); - }; - const save = async (data: ContestSchema) => { const fileTypeMapping = { all: "1", @@ -276,24 +290,60 @@ export default function FormContestDetail() { fileTypeOutput: selectedOutputs, }; - if (id != undefined) { - requestData.id = id; - } + // if (id != undefined) { + // requestData.id = id; + // } const response = await postCreateContest(requestData); console.log("Form Data Submitted:", requestData); console.log("response", response); - MySwal.fire({ - title: "Sukses", - text: "Data berhasil disimpan.", - icon: "success", - confirmButtonColor: "#3085d6", - confirmButtonText: "OK", - }).then(() => { - router.push("/en/shared/contest"); + const id = response?.data?.data.id; + loading(); + if (imageFiles?.length == 0) { + setIsImageUploadFinish(true); + } + imageFiles?.map(async (item: any, index: number) => { + await uploadResumableFile(index, String(id), item, "1", "0"); }); + + if (videoFiles?.length == 0) { + setIsVideoUploadFinish(true); + } + videoFiles?.map(async (item: any, index: number) => { + await uploadResumableFile(index, String(id), item, "2", "0"); + }); + + if (textFiles?.length == 0) { + setIsTextUploadFinish(true); + } + textFiles?.map(async (item: any, index: number) => { + await uploadResumableFile(index, String(id), item, "3", "0"); + }); + + if (audioFiles?.length == 0) { + setIsAudioUploadFinish(true); + } + audioFiles.map(async (item: FileWithPreview, index: number) => { + await uploadResumableFile( + index, + String(id), + item, // Use .file to access the actual File object + "4", + "0" // Optional: Replace with actual duration if available + ); + }); + + // MySwal.fire({ + // title: "Sukses", + // text: "Data berhasil disimpan.", + // icon: "success", + // confirmButtonColor: "#3085d6", + // confirmButtonText: "OK", + // }).then(() => { + // router.push("/en/shared/contest"); + // }); }; const onSubmit = (data: ContestSchema) => { @@ -312,6 +362,179 @@ export default function FormContestDetail() { }); }; + const toggleExpand = (poldaId: any) => { + setExpandedPolda((prev: any) => ({ + ...prev, + [poldaId]: !prev[poldaId], + })); + }; + + const onRecordingStart = () => { + setIsRecording(true); + + const countdown = setInterval(() => { + setTimer((prevTimer) => { + if (prevTimer <= 1) { + clearInterval(countdown); + return 0; + } + return prevTimer - 1; + }); + }, 1000); + + setTimeout(() => { + if (isRecording) { + handleStopRecording(); + } + }, 120000); + }; + + const handleStopRecording = () => { + setIsRecording(false); + setTimer(120); // Reset the timer to 2 minutes for the next recording + }; + + const addAudioElement = (blob: Blob) => { + const url = URL.createObjectURL(blob); + const audio = document.createElement("audio"); + audio.src = url; + audio.controls = true; + document.body.appendChild(audio); + + // Convert Blob to File and add preview + const fileWithPreview: FileWithPreview = Object.assign( + new File([blob], "voiceNote.webm", { type: "audio/webm" }), + { preview: url } + ); + + // Add to state + setAudioFile(fileWithPreview); + setAudioFiles((prev) => [...prev, fileWithPreview]); + }; + + const handleDeleteAudio = (index: number) => { + setAudioFiles((prev) => prev.filter((_, idx) => idx !== index)); + }; + + async function uploadResumableFile( + idx: number, + id: string, + file: any, + fileTypeId: string, + duration: string + ) { + console.log(idx, id, file, fileTypeId, duration); + + const resCsrf = await getCsrfToken(); + const csrfToken = resCsrf?.data?.token; + console.log("CSRF TOKEN : ", csrfToken); + const headers = { + "X-XSRF-TOKEN": csrfToken, + }; + + const upload = new Upload(file, { + endpoint: `${process.env.NEXT_PUBLIC_API}/contest/file/upload`, + headers: headers, + retryDelays: [0, 3000, 6000, 12_000, 24_000], + chunkSize: 20_000, + metadata: { + assignmentId: id, + filename: file.name, + contentType: file.type, + fileTypeId: fileTypeId, + duration, + }, + onBeforeRequest: function (req) { + var xhr = req.getUnderlyingObject(); + xhr.withCredentials = true; + }, + onError: async (e: any) => { + console.log("Error upload :", e); + error(e); + }, + onChunkComplete: ( + chunkSize: any, + bytesAccepted: any, + bytesTotal: any + ) => { + // const uploadPersen = Math.floor((bytesAccepted / bytesTotal) * 100); + // progressInfo[idx].percentage = uploadPersen; + // counterUpdateProgress++; + // console.log(counterUpdateProgress); + // setProgressList(progressInfo); + // setCounterProgress(counterUpdateProgress); + }, + onSuccess: async () => { + // uploadPersen = 100; + // progressInfo[idx].percentage = 100; + // counterUpdateProgress++; + // setCounterProgress(counterUpdateProgress); + successTodo(); + if (fileTypeId == "1") { + setIsImageUploadFinish(true); + } else if (fileTypeId == "2") { + setIsVideoUploadFinish(true); + } + if (fileTypeId == "3") { + setIsTextUploadFinish(true); + } + if (fileTypeId == "4") { + setIsAudioUploadFinish(true); + } + }, + }); + + upload.start(); + } + + useEffect(() => { + successTodo(); + }, [ + isImageUploadFinish, + isVideoUploadFinish, + isAudioUploadFinish, + isTextUploadFinish, + ]); + + function successTodo() { + if ( + isImageUploadFinish && + isVideoUploadFinish && + isAudioUploadFinish && + isTextUploadFinish + ) { + successSubmit("/in/shared/contest"); + } + } + + const successSubmit = (redirect: string) => { + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push(redirect); + }); + }; + + const handleLinkChange = (index: number, value: string) => { + const updatedLinks = [...links]; + updatedLinks[index] = value; + setLinks(updatedLinks); + }; + + const handleAddRow = () => { + setLinks([...links, ""]); + }; + + // Remove a specific link row + const handleRemoveRow = (index: number) => { + const updatedLinks = links.filter((_: any, i: any) => i !== index); + setLinks(updatedLinks); + }; + return (
@@ -557,6 +780,119 @@ export default function FormContestDetail() {

)}
+
+ +
+
+ + setVideoFiles(files)} + /> +
+
+ + setImageFiles(files)} + /> +
+
+ + setTextFiles(files)} + /> +
+
+ + + + setAudioFiles((prev) => [...prev, ...files]) + } + className="mt-2" + /> +
+ {audioFiles?.map((audio: any, idx: any) => ( +
+

Voice Note

+ +
+ ))} + {isRecording &&

Recording... {timer} seconds remaining

}{" "} + {/* Display remaining time */} +
+

Link Berita

+ {links.map((link, index) => ( +
+ + handleLinkChange(index, e.target.value) + } + /> + {links.length > 1 && ( + + )} +
+ ))} + +
+
+
diff --git a/components/form/task/task-detail-form.tsx b/components/form/task/task-detail-form.tsx index 8dfab668..cb86bfac 100644 --- a/components/form/task/task-detail-form.tsx +++ b/components/form/task/task-detail-form.tsx @@ -47,6 +47,7 @@ import { DotSquare, ImageIcon, Music, + Search, TrashIcon, VideoIcon, } from "lucide-react"; @@ -63,6 +64,7 @@ import Image from "next/image"; import { Icon } from "@iconify/react/dist/iconify.js"; import WavesurferPlayer from "@wavesurfer/react"; import WaveSurfer from "wavesurfer.js"; +import { InputGroup, InputGroupText } from "@/components/ui/input-group"; const taskSchema = z.object({ uniqueCode: z.string().min(1, { message: "Judul diperlukan" }), @@ -242,6 +244,7 @@ export default function FormTaskDetail() { const [audioFile, setAudioFile] = useState(null); const [isRecording, setIsRecording] = useState(false); const [timer, setTimer] = useState(120); + const [search, setSearch] = React.useState(""); const [wavesurfer, setWavesurfer] = useState(); const [isPlaying, setIsPlaying] = useState(false); @@ -749,14 +752,19 @@ export default function FormTaskDetail() { const handleRemoveFile = (id: number) => {}; + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + // getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return ( {detail !== undefined ? (
-
+

Detail Penugasan

{errors.title.message}

)}
-
+
-
+
{Object.keys(unitSelection).map((key) => (
))}
-
+
-
-
+
+
{detail?.isDone !== true && (Number(userLevelNumber) !== 3 || Number(userLevelNumber) == 2) ? ( @@ -1317,7 +1325,7 @@ export default function FormTaskDetail() { color="primary" variant={"outline"} type="button" - className="btn btn-outline-primary ml-3" + className="btn btn-outline-primary lg:ml-3" onClick={() => handleForward()} > Forward @@ -1326,9 +1334,10 @@ export default function FormTaskDetail() { "" )}
-
+
{isTableResult && ( -
- - - - - - - - - - {uploadResults.map((item) => ( - - - - - +
+
+
+ + + + + + +
+ + + + + + + + Daftar Wilayah Polda dan Polres + + +
+ {listDest.map((polda: any) => ( +
+ + {expandedPolda[polda.id] && ( +
+ + {polda?.subDestination?.map((polres: any) => ( + + ))} +
+ )} +
+ ))} +
+
+
+
+
JudulKontenKategoryDiupload Oleh
{item.title}{item.fileType.name}{item.category.name}{item.creatorName}
+ + + + + + - ))} - -
JudulKontenKategoryDiupload Oleh
+ + + {uploadResults.map((item) => ( + + + {item.title} + + {item.fileType.name} + {item.category.name} + {item.creatorName} + + ))} + + + )} {showInput && ( <> @@ -1580,7 +1694,7 @@ export default function FormTaskDetail() { )} -
+
{detail?.createdBy?.id == Number(userId) && detail?.isDone !== true ? ( <> diff --git a/components/form/task/task-edit-form.tsx b/components/form/task/task-edit-form.tsx index a765b190..00f8f89d 100644 --- a/components/form/task/task-edit-form.tsx +++ b/components/form/task/task-edit-form.tsx @@ -643,7 +643,7 @@ export default function FormTaskEdit() {

{errors.title.message}

)}
-
+
-
+
{Object.keys(unitSelection).map((key) => (
))}
-
+
-
+
-
+
{Object.keys(unitSelection).map((key) => (
))}
-
+