// "use client"; import React, { useState, useEffect, useRef, Fragment } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useForm, Controller } from "react-hook-form"; import { cn } from "@/lib/utils"; import { format } from "date-fns"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Calendar } from "@/components/ui/calendar"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { Loader2, CalendarIcon, ChevronUp, ChevronDown } from "lucide-react"; import DeleteConfirmationDialog from "@/components/delete-confirmation-dialog"; import { CalendarCategory } from "./data"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Textarea } from "@/components/ui/textarea"; import { error, loading, success } from "@/lib/swal"; import Cookies from "js-cookie"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; import { useRouter } from "next/navigation"; import { postSchedule } from "@/service/schedule/schedule"; import { getAgendaSettingsById, saveAgendaSettings } from "@/service/agenda-setting/agenda-setting"; import { Checkbox } from "@/components/ui/checkbox"; import { getUserLevelForAssignments } from "@/service/task"; import { AudioRecorder } from "react-audio-voice-recorder"; import FileUploader from "@/components/form/shared/file-uploader"; import { Upload } from "tus-js-client"; import { getCsrfToken } from "@/service/auth"; import { Icon } from "@iconify/react"; import Image from "next/image"; const schema = z.object({ title: z.string().min(3, { message: "Required" }), description: z.string().min(3, { message: "Required" }), }); interface FileWithPreview extends File { preview: string; } interface FileUploaded { id: number; url: string; } const EventModal = ({ open, onClose, categories, event, selectedDate, }: { open: boolean; onClose: () => void; categories: any; event: any; selectedDate: any; }) => { const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); const [isPending, startTransition] = React.useTransition(); const [agendaType, setAgendaType] = React.useState(categories[0].value); const [listDest, setListDest] = useState([]); const [deleteModalOpen, setDeleteModalOpen] = useState(false); const [eventIdToDelete, setEventIdToDelete] = useState(null); const MySwal = withReactContent(Swal); const router = useRouter(); const [isLoading, setIsLoading] = useState(false); const [checkedLevels, setCheckedLevels] = useState(new Set()); const [expandedPolda, setExpandedPolda] = useState([{}]); const [audioFile, setAudioFile] = useState(null); const [isRecording, setIsRecording] = useState(false); const [timer, setTimer] = useState(120); const [detailData, setDetailData] = useState(); const [imageFiles, setImageFiles] = useState([]); const [videoFiles, setVideoFiles] = useState([]); const [textFiles, setTextFiles] = useState([]); const [audioFiles, setAudioFiles] = useState([]); const [imageUploadedFiles, setImageUploadedFiles] = useState([]); const [videoUploadedFiles, setVideoUploadedFiles] = useState([]); const [textUploadedFiles, setTextUploadedFiles] = useState([]); const [audioUploadedFiles, setAudioUploadedFiles] = useState([]); const [isImageUploadFinish, setIsImageUploadFinish] = useState(false); const [isVideoUploadFinish, setIsVideoUploadFinish] = useState(false); const [isTextUploadFinish, setIsTextUploadFinish] = useState(false); const [isAudioUploadFinish, setIsAudioUploadFinish] = useState(false); let progressInfo: any = []; let counterUpdateProgress = 0; const [progressList, setProgressList] = useState([]); let uploadPersen = 0; const [isStartUpload, setIsStartUpload] = useState(false); const [counterProgress, setCounterProgress] = useState(0); const { register, control, reset, setValue, formState: { errors }, handleSubmit, } = useForm({ resolver: zodResolver(schema), mode: "all", }); useEffect(() => { async function fetchDetailData(){ const res = await getAgendaSettingsById(event?.event?.id); const detail = res?.data?.data; setDetailData(detail); const attachments = detail?.attachments; setImageUploadedFiles(attachments?.filter((file: any) => file.fileTypeId == 1)); setVideoUploadedFiles(attachments?.filter((file: any) => file.fileTypeId == 2)); setTextUploadedFiles(attachments?.filter((file: any) => file.fileTypeId == 3)); setAudioUploadedFiles(attachments?.filter((file: any) => file.fileTypeId == 4)); } fetchDetailData(); }, [event]); useEffect(() => { async function fetchPoldaPolres() { setIsLoading(true); try { const response = await getUserLevelForAssignments(); const levelList = response?.data?.data.list; let listFiltered = []; if (agendaType == "polda") { listFiltered = levelList.filter( (level: any) => level.name != "SATKER POLRI" ); } else if (agendaType == "polres") { listFiltered = levelList.filter( (level: any) => level.name != "SATKER POLRI" ); } else if (agendaType == "satker") { listFiltered = levelList.filter( (level: any) => level.name == "SATKER POLRI" ); } setListDest(listFiltered); const initialExpandedState = listFiltered.reduce( (acc: any, polda: any) => { acc[polda.id] = false; return acc; }, {} ); setExpandedPolda(initialExpandedState); } catch (error) { console.error("Error fetching Polda/Polres data:", error); } finally { setIsLoading(false); } } fetchPoldaPolres(); }, [agendaType]); const handleCheckboxChange = (levelId: number) => { setCheckedLevels((prev) => { const updatedLevels = new Set(prev); if (updatedLevels.has(levelId)) { updatedLevels.delete(levelId); } else { updatedLevels.add(levelId); } return updatedLevels; }); }; const save = async (data: any) => { // const formData = new FormData(); // formData.append("voiceNote", audioFile); const reqData = { title: data.title, description: data.description, agendaType: agendaType, startDate: format(startDate, "yyyy-MM-dd"), endDate: format(endDate, "yyyy-MM-dd"), }; console.log("Submitted Data:", reqData); const response = await saveAgendaSettings(reqData); if (response?.error) { error(response?.message); return false; } 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: any, index: number) => { await uploadResumableFile(index, String(id), item, "4", "0"); }); // Optional: Use Swal for success feedback // MySwal.fire({ // title: "Sukses", // text: "Data berhasil disimpan.", // icon: "success", // confirmButtonColor: "#3085d6", // confirmButtonText: "OK", // }).then(() => { // router.push("en/contributor/agenda-setting"); // }); }; const onSubmit = (data: any) => { save(data); }; useEffect(() => { if (selectedDate) { setStartDate(selectedDate.date); setEndDate(selectedDate.date); } if (event) { setStartDate(event?.event?.start); setEndDate(event?.event?.end); const eventCalendar = event?.event?.extendedProps?.calendar; setAgendaType(eventCalendar || categories[0].value); } setValue("title", event?.event?.title || ""); setValue("description", event?.event?.description || ""); }, [event, selectedDate, open, categories, setValue]); const onDeleteEventAction = async () => { try { } catch (error) {} }; const handleOpenDeleteModal = (eventId: string) => { setEventIdToDelete(eventId); setDeleteModalOpen(true); onClose(); }; const toggleExpand = (poldaId: any) => { console.log("Toogle : ", expandedPolda); setExpandedPolda((prev: any) => ({ ...prev, [poldaId]: !prev[poldaId], })); }; const onRecordingStart = () => { setIsRecording(true); // Start a timer that stops the recording after 2 minutes (120 seconds) const countdown = setInterval(() => { setTimer((prevTimer) => { if (prevTimer <= 1) { clearInterval(countdown); // Stop the timer when it reaches 0 return 0; } return prevTimer - 1; }); }, 1000); // Update every second // Automatically stop recording after 2 minutes setTimeout(() => { if (isRecording) { handleStopRecording(); } }, 120000); // Stop after 2 minutes (120,000 ms) }; 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 const file = new File([blob], "voiceNote.webm", { type: "audio/webm" }); setAudioFile(file); }; const handleDeleteAudio = () => { // Remove the audio file by setting state to null setAudioFile(null); const audioElements = document.querySelectorAll("audio"); audioElements.forEach((audio) => audio.remove()); }; 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}/agenda-settings/file/upload`, headers: headers, retryDelays: [0, 3000, 6000, 12_000, 24_000], chunkSize: 20_000, metadata: { agendaSettingId: 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/contributor/agenda-setting"); } } const successSubmit = (redirect: string) => { MySwal.fire({ title: "Sukses", text: "Data berhasil disimpan.", icon: "success", confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { router.push(redirect); }); }; const renderFilePreview = (url: string) => { return ( {"file ); }; const handleRemoveFile = (id: number) => { }; return ( <> setDeleteModalOpen(false)} onConfirm={onDeleteEventAction} defaultToast={false} /> {event?.length > 1 ? "Edit Agenda Setting" : "Create Agenda Setting"}{" "} {event?.title}
( )} /> {errors?.title?.message && (
{typeof errors?.title?.message === "string" ? errors?.title?.message : JSON.stringify(errors?.title?.message)}
)}
( setStartDate(date as Date)} initialFocus /> )} />
( setEndDate(date as Date)} initialFocus /> )} />
( )} />
{(agendaType === "polda" || agendaType === "polres" || agendaType === "satker") && (
Daftar Wilayah Polda dan Polres
{listDest.map((polda: any) => (
{(agendaType == "polres" || agendaType == "satker") && expandedPolda[polda.id] && (
{polda?.subDestination?.map( (polres: any) => ( ) )}
)}
))}
)}
(