"use client"; import React, { useState, useEffect, act } from "react"; import FullCalendar from "@fullcalendar/react"; // must go before plugins import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin, { Draggable } from "@fullcalendar/interaction"; import listPlugin from "@fullcalendar/list"; import { Button } from "@/components/ui/button"; 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 { Book, CheckCheck, CheckSquare2, CheckSquare2Icon, Plus, Timer, TimerIcon, } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; import { EventContentArg } from "@fullcalendar/core"; import EventModal from "./event-modal"; import { useTranslations } from "next-intl"; import { getAgendaSettingsList } from "@/service/agenda-setting/agenda-setting"; import dayjs from "dayjs"; import { getCookiesDecrypt } from "@/lib/utils"; import { CalendarCategory } from "./data"; import { error } from "@/config/swal"; import { Popover, 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 { // events: CalendarEvent[]; categories: CalendarCategory[]; } export type CalendarEvent = { id: string; title: string; start: Date; end: Date; createBy: string; createdByName: string; isPublish: boolean | null; allDay: boolean; extendedProps: { calendar: string; description: string; }; }; const INITIAL_YEAR = dayjs().format("YYYY"); const INITIAL_MONTH = dayjs().format("M"); export interface AgendaSettingsAPIResponse { id: number; title: string; createdByName: string; description: string; agendaType: string; startDate: string; endDate: string; isActive: boolean; createdAt: string; updatedAt: string; createdById: number | null; } interface YearlyData { january?: Event[]; february?: Event[]; march?: Event[]; april?: Event[]; may?: Event[]; june?: Event[]; july?: Event[]; august?: Event[]; september?: Event[]; october?: Event[]; november?: Event[]; december?: Event[]; } interface MonthCardProps { monthId: keyof YearlyData; label: string; } interface ListItemProps { item: any; text: string; createdBy: string; isPublish: boolean | null; bgColor: string; } interface APIResponse { error: boolean; message: any; data: AgendaSettingsAPIResponse[] | null; } const CalendarView = ({ categories }: CalendarViewProps) => { const [selectedCategory, setSelectedCategory] = useState( null ); const [selectedEventDate, setSelectedEventDate] = useState(null); const roleId = Number(getCookiesDecrypt("urie")) || 0; const userLevelId = Number(getCookiesDecrypt("ulie")) || 0; console.log("roleId", roleId); console.log("userlevel", userLevelId); const [apiEvents, setApiEvents] = useState([]); const [Isloading, setLoading] = useState(false); const [draggableInitialized, setDraggableInitialized] = useState(false); const t = useTranslations("CalendarApp"); // event canvas state const [sheetOpen, setSheetOpen] = useState(false); const [date, setDate] = React.useState(new Date()); const [activeView, setActiveView] = useState("listYear"); const [yearlyData, setYearlyData] = useState(); 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( dayjs(new Date(Number(INITIAL_YEAR), Number(INITIAL_MONTH) - 1, 1)) ); const [dragEvents] = useState([ { title: "New Event Planning", id: "101", tag: "business" }, { title: "Meeting", id: "102", tag: "meeting" }, { title: "Generating Reports", id: "103", tag: "holiday" }, { title: "Create New theme", id: "104", tag: "etc" }, ]); const [calendarEvents, setCalendarEvents] = useState([]); useEffect(() => { if (activeView == "listYear") { getYearlyEvents(); } else { getCalendarEvents(); } }, [activeView, selectedMonth]); const getCalendarEvents = async () => { console.log("View : ", activeView); const res = await getAgendaSettingsList( selectedMonth?.format("YYYY") || INITIAL_YEAR, selectedMonth.format("M") || INITIAL_MONTH, "" ); console.log("View : API Response:", res); if (res?.error) { error(res?.message); return; } const data = res?.data?.data; if (data) { console.log("Dataaa : ", data); // Map API data to the calendarEvents structure const events = res?.data?.data?.map((event: any) => ({ id: event.id.toString(), title: event.title, createBy: event.createdById, createdByName: event.createdByName, start: new Date(event.startDate), end: new Date(event.endDate), allDay: true, extendedProps: { isPublish: event.isPublish, calendar: event.agendaType, description: event.description, createdByName: event.createdByName, }, })); console.log("Dataaa event : ", events); setCalendarEvents(events); } }; const getYearlyEvents = async () => { const res = await getAgendaSettingsList( selectedMonth?.format("YYYY") || INITIAL_YEAR, "", "" ); if (res?.error) { error(res.message); return false; } setYearlyData(res?.data?.data); }; useEffect(() => { setSelectedCategory(categories?.map((c) => c.value)); }, [categories]); const filteredEvents = calendarEvents?.filter((event) => { const eventCategories = event.extendedProps.calendar ?.split(",") .map((val: string) => val.trim()); // agar "1, 2" tetap dianggap benar return eventCategories?.some((cat: string) => selectedCategory?.includes(cat) ); }); const displayedEvents = filteredEvents?.length > 1 ? filteredEvents : apiEvents; useEffect(() => { setSelectedCategory(categories?.map((c: any) => c.value)); }, [categories]); useEffect(() => { console.log("Selected categories:", selectedCategory); }, [selectedCategory]); useEffect(() => { fetchAgendaEvents(); }, []); const fetchAgendaEvents = async (year?: string, month?: string) => { setLoading(true); try { const selectedMonth = new Date(); // Replace with your logic for selected month const year = selectedMonth.getFullYear().toString(); const month = (selectedMonth.getMonth() + 1).toString(); const typeFilter = ""; // Replace with your type filter logic if needed const response = await getAgendaSettingsList(year, month, typeFilter); if (response?.data && Array.isArray(response?.data)) { // Transform API data to match CalendarEvent type const eventsFromAPI: CalendarEvent[] = response?.data?.map((item) => ({ id: item.id.toString(), title: item.title, createBy: "Mabes Polri - Approver", createdByName: item.createdByName, isPublish: item.isPublish, start: new Date(item.startDate), end: new Date(item.endDate), allDay: true, extendedProps: { calendar: item.agendaType, description: item.description, }, })); setApiEvents(eventsFromAPI); } else { console.warn("No events found in API response."); setApiEvents([]); } } catch (error) { console.error("Failed to fetch agenda settings:", error); setApiEvents([]); } finally { setLoading(false); } }; useEffect(() => { console.log("Fetched events from API 1:", apiEvents); }, [apiEvents]); useEffect(() => { console.log("Filtered events based on category 1:", calendarEvents); }, [filteredEvents, apiEvents]); useEffect(() => { const draggableEl = document.getElementById("external-events"); const initDraggable = () => { if (draggableEl) { new Draggable(draggableEl, { itemSelector: ".fc-event", eventData: function (eventEl) { let title = eventEl.getAttribute("title"); let id = eventEl.getAttribute("data"); let event = dragEvents.find((e) => e.id === id); let tag = event ? event.tag : ""; return { title: title, id: id, extendedProps: { calendar: tag, }, }; }, }); } }; if (dragEvents.length > 0) { initDraggable(); } return () => { draggableEl?.removeEventListener("mousedown", initDraggable); }; }, [dragEvents]); // event click const handleEventClick = (arg: any) => { console.log("Event Click ", arg); setSelectedEventDate(null); setSheetOpen(true); setApiEvents(arg); wait().then(() => (document.body.style.pointerEvents = "auto")); }; // handle close modal const handleCloseModal = () => { setSheetOpen(false); setApiEvents([]); setSelectedEventDate(null); }; const handleDateClick = (arg: any) => { setSheetOpen(true); console.log("Date :", arg); setSelectedEventDate(arg); setApiEvents([]); wait().then(() => (document.body.style.pointerEvents = "auto")); }; const handleCategorySelection = (category: string) => { if (selectedCategory && selectedCategory.includes(category)) { setSelectedCategory(selectedCategory.filter((c) => c !== category)); } else { setSelectedCategory([...(selectedCategory || []), category]); } }; const renderEventContent = (eventInfo: any) => { const { title } = eventInfo.event; const { createdByName, isPublish } = eventInfo.event.extendedProps; return ( <>
{" "} {isPublish === true ? : }

{title}

Created By : {createdByName}

); }; const handleClassName = (arg: EventContentArg) => { if (arg.event.extendedProps.calendar === "1") { return "bg-yellow-500 border-none"; } else if (arg.event.extendedProps.calendar === "2") { return "bg-blue-400 border-none"; } else if (arg.event.extendedProps.calendar === "3") { return "bg-slate-400 border-none"; } else if (arg.event.extendedProps.calendar === "4") { return "bg-orange-500 border-none"; } else if (arg.event.extendedProps.calendar === "5") { return "bg-green-400 border-none"; } else { return "primary"; } }; const handleDateChange = (startDate: string, endDate: string) => { const startDateOfDate = new Date(startDate); const endDateOfDate = new Date(endDate); console.log("Change Date : ", startDateOfDate); setSelectedMonth(dayjs(startDateOfDate)); }; const handleViewChange = (viewType: string) => { console.log("Change view : ", viewType); setActiveView(viewType); }; const months: Array<{ id: keyof YearlyData; label: string }> = [ { id: "january", label: "Januari" }, { id: "february", label: "Februari" }, { id: "march", label: "Maret" }, { id: "april", label: "April" }, { id: "may", label: "Mei" }, { id: "june", label: "Juni" }, { id: "july", label: "Juli" }, { id: "august", label: "Agustus" }, { id: "september", label: "September" }, { id: "october", label: "Oktober" }, { id: "november", label: "November" }, { id: "december", label: "Desember" }, ]; const getEventColor = (type: Event["type"]): string => { const colors: Record = { 1: "bg-yellow-500", 2: "bg-blue-400", 3: "bg-slate-400", 4: "bg-orange-500", 5: "bg-green-400", }; return colors[type]; }; const handleClickListItem = (item: any) => { const formattedEvent: CalendarEvent = { id: item.id.toString(), title: item.title, start: new Date(item.startDate), end: new Date(item.endDate), createBy: "Mabes Polri - Approver", // Sesuaikan dengan data yang sebenarnya jika ada createdByName: item.createdByName, isPublish: item.isPublish, allDay: true, extendedProps: { calendar: item.agendaType, description: item.description, }, }; const finalEvent: any = { event: formattedEvent, }; console.log("Event click custom : ", finalEvent); setSelectedEventDate(null); setSheetOpen(true); setApiEvents(finalEvent); wait().then(() => (document.body.style.pointerEvents = "auto")); }; const ListItem: React.FC = ({ item, text, createdBy, isPublish, bgColor, }) => (
handleClickListItem(item)} >
{isPublish ? : }

{text}

Created By: {createdBy}

); const MonthCard: React.FC = (props: any) => { const { monthId, label } = props; const events: any = yearlyData?.[monthId]; const displayedEvents = events?.slice(0, 3); const hasMoreEvents = events?.length > 3; return (

{label}

{events?.length === 0 ? (

{t("no-data-yet")}

) : ( <> {displayedEvents?.map((event: any, index: number) => ( ))} {hasMoreEvents && ( {label}
{events.map((event: any, index: number) => ( ))}
)} )}
); }; const getModalContent = (type: "terkirim" | "diterima") => (
{Isloading ? (

Loading...

) : (
No Ticket Number Date and Time Title Status
{"1"} {"MIA - 001"} {"23/01/2025 13:00"} {"Daily Issue 25 Januari 2025 "} {type === "terkirim" ? "Completed" : "Completed"}
)}
); return ( <>
{roleId == 3 || roleId == 11 || roleId == 2 || roleId == 12 ? ( ) : ( "" )}
{roleId === 3 && userLevelId === 216 ? ( ) : null} {t("monitoring-results")} {getModalContent("terkirim")}
{ handleDateClick(s); }} className="rounded-md border w-full p-0 border-none" />
{/*

{t("shortDesc")}

{dragEvents.map((event) => ( ))}
*/}
{t("filter")}
  • { if (selectedCategory?.length === categories?.length) { setSelectedCategory([]); } else { setSelectedCategory(categories?.map((c) => c.value)); } }} />
  • {categories?.map((category) => (
  • handleCategorySelection(category.value)} />
  • ))}
handleViewChange(info.view.type)} datesSet={(info: any) => { console.log(info); handleDateChange(info.view.currentStart, info.view.currentEnd); handleViewChange(info.view.type); }} viewClassNames={ activeView === "listYear" ? "hide-calendar-grid" : "" } /> {activeView === "listYear" && (
{months.slice(0, 3).map((month) => ( ))}
{months.slice(3, 6).map((month) => ( ))}
{months.slice(6, 9).map((month) => ( ))}
{months.slice(9, 12).map((month) => ( ))}
)}
); }; export default CalendarView;