"use client"; import React, { useState, useEffect } 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 { Plus } 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"; 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; 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; bgColor: string; } interface APIResponse { error: boolean; message: any; data: AgendaSettingsAPIResponse[] | null; // `data` bisa berupa array atau null } const CalendarView = ({ categories }: CalendarViewProps) => { const [selectedCategory, setSelectedCategory] = useState( null ); const [selectedEventDate, setSelectedEventDate] = useState(null); const roleId = Number(getCookiesDecrypt("urie")) || 0; const [apiEvents, setApiEvents] = useState([]); const [loading, 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("dayGridMonth"); const [yearlyData, setYearlyData] = useState(); 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(() => { getCalendarEvents(); getYearlyEvents(); }, []); const getCalendarEvents = async () => { const res = await getAgendaSettingsList(INITIAL_YEAR, INITIAL_MONTH, ""); console.log("API Response:", res); if (res?.error) { error(res?.message); return; } // Map API data to the calendarEvents structure const events = res?.data?.data.map((event: any) => ({ id: event.id.toString(), title: event.title, createBy: "Mabes Polri - Approver", createdByName: event.createdByName, start: new Date(event.startDate), end: new Date(event.endDate), allDay: true, extendedProps: { calendar: event.agendaType, description: event.description, createdByName: event.createdByName, }, })); setCalendarEvents(events); console.log("event", events); }; const getYearlyEvents = async () => { const res = await getAgendaSettingsList(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) => selectedCategory?.includes(event.extendedProps.calendar) ); const displayedEvents = filteredEvents?.length > 1 ? filteredEvents : apiEvents; useEffect(() => { setSelectedCategory(categories?.map((c) => c.value)); }, [categories]); useEffect(() => { console.log("Selected categories:", selectedCategory); }, [selectedCategory]); useEffect(() => { const fetchAgendaEvents = async () => { 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, start: new Date(item.startDate), end: new Date(item.endDate), allDay: true, // Sesuaikan jika memang ada event sepanjang hari 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); } }; fetchAgendaEvents(); }, []); 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 } = eventInfo.event.extendedProps; // Akses dari extendedProps return ( <>

{title}

Create By: {createdByName}

); }; const handleClassName = (arg: EventContentArg) => { if (arg.event.extendedProps.calendar === "mabes") { return "bg-yellow-500 border-none"; } else if (arg.event.extendedProps.calendar === "polda") { return "bg-blue-400 border-none"; } else if (arg.event.extendedProps.calendar === "polres") { return "bg-slate-400 border-none"; } else if (arg.event.extendedProps.calendar === "international") { return "bg-green-400 border-none"; } else { return "primary"; } }; const handleDateChange = (startDate: string, endDate: string) => { console.log(startDate + " - " + endDate); }; const handleViewChange = (viewType: string) => { console.log(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 = { mabes: 'bg-yellow-500', polda: 'bg-blue-400', polres: 'bg-slate-400', international: '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, 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, bgColor }) => (
handleClickListItem(item)}>

{text}

Create 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 ? (

Belum ada data

) : ( <> {displayedEvents?.map((event: any, index: number) => ( ))} {hasMoreEvents && ( {label}
{events.map((event: any, index: number) => ( ))}
)} )}
); }; return ( <>
{ 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 => ( ))}
{/* Second Row */}
{months.slice(3, 6).map(month => ( ))}
{/* Third Row */}
{months.slice(6, 9).map(month => ( ))}
{/* Fourth Row */}
{months.slice(9, 12).map(month => ( ))}
)}
); }; export default CalendarView;