mediahub-fe/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx

373 lines
12 KiB
TypeScript
Raw Normal View History

2024-11-27 04:14:10 +00:00
"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 } from "@/components/ui/card";
import { Plus } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox";
import { EventContentArg } from "@fullcalendar/core";
2024-11-27 04:14:10 +00:00
import EventModal from "./event-modal";
import { useTranslations } from "next-intl";
import { getAgendaSettingsList } from "@/service/agenda-setting/agenda-setting";
import dayjs from "dayjs";
2024-12-30 13:43:39 +00:00
import { getCookiesDecrypt } from "@/lib/utils";
2025-01-01 08:33:42 +00:00
import { CalendarCategory } from "./data";
2024-11-27 04:14:10 +00:00
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
interface CalendarViewProps {
2025-01-01 08:33:42 +00:00
// events: CalendarEvent[];
2024-11-27 04:14:10 +00:00
categories: CalendarCategory[];
}
const INITIAL_YEAR = dayjs().format("YYYY");
const INITIAL_MONTH = dayjs().format("M");
2024-12-16 01:25:47 +00:00
export interface AgendaSettingsAPIResponse {
id: number;
title: string;
description: string;
agendaType: string;
startDate: string; // API mengembalikan tanggal dalam bentuk string
endDate: string;
isActive: boolean;
createdAt: string;
updatedAt: string;
createdById: number | null;
createdByName: string | null;
}
interface APIResponse {
error: boolean;
message: any;
data: AgendaSettingsAPIResponse[] | null; // `data` bisa berupa array atau null
}
2025-01-01 08:33:42 +00:00
const CalendarView = ({ categories }: CalendarViewProps) => {
const [selectedCategory, setSelectedCategory] = useState<string[] | null>(
null
);
2024-11-27 04:14:10 +00:00
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(null);
2024-12-30 13:43:39 +00:00
const roleId = Number(getCookiesDecrypt("urie")) || 0;
2024-12-16 01:25:47 +00:00
const [apiEvents, setApiEvents] = useState<CalendarEvent[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const [draggableInitialized, setDraggableInitialized] =
useState<boolean>(false);
const t = useTranslations("CalendarApp");
2024-11-27 04:14:10 +00:00
// event canvas state
const [sheetOpen, setSheetOpen] = useState<boolean>(false);
const [date, setDate] = React.useState<Date>(new Date());
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" },
]);
2025-01-01 08:33:42 +00:00
const [calendarEvents, setCalendarEvents] = useState<CalendarEvent[]>([]);
useEffect(() => {
getCalendarEvents();
2025-01-01 08:33:42 +00:00
}, []);
const getCalendarEvents = async () => {
const res = await getAgendaSettingsList(INITIAL_YEAR, INITIAL_MONTH, "");
2025-01-01 08:33:42 +00:00
console.log("API Response:", res);
if (res.error) {
2025-01-01 08:33:42 +00:00
return;
}
2025-01-01 08:33:42 +00:00
// Map API data to the calendarEvents structure
const events = res?.data?.data.map((event: any) => ({
id: event.id.toString(),
title: event.title,
start: new Date(event.startDate),
end: new Date(event.endDate),
allDay: true, // Assuming all events are all-day by default
extendedProps: {
calendar: event.agendaType, // Map agendaType to the calendar category
description: event.description,
},
}));
setCalendarEvents(events);
console.log("event", events);
};
2024-11-27 04:14:10 +00:00
useEffect(() => {
setSelectedCategory(categories?.map((c) => c.value));
2025-01-01 08:33:42 +00:00
}, [categories]);
2024-12-16 01:25:47 +00:00
2025-01-01 08:33:42 +00:00
const filteredEvents = calendarEvents?.filter((event) =>
2024-12-16 01:25:47 +00:00
selectedCategory?.includes(event.extendedProps.calendar)
);
const displayedEvents =
2025-01-01 08:33:42 +00:00
filteredEvents?.length > 1 ? filteredEvents : apiEvents;
2024-12-16 01:25:47 +00:00
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: APIResponse = 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,
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,
},
}));
2025-01-01 08:33:42 +00:00
2024-12-16 01:25:47 +00:00
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();
}, []);
2025-01-01 08:33:42 +00:00
useEffect(() => {
console.log("Fetched events from API 1:", apiEvents);
}, [apiEvents]);
useEffect(() => {
console.log("Filtered events based on category 1:", calendarEvents);
}, [filteredEvents, apiEvents]);
2024-11-27 04:14:10 +00:00
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]);
2024-12-16 01:25:47 +00:00
2024-11-27 04:14:10 +00:00
// event click
const handleEventClick = (arg: any) => {
setSelectedEventDate(null);
setSheetOpen(true);
2024-12-16 01:25:47 +00:00
setApiEvents(arg);
2024-11-27 04:14:10 +00:00
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
// handle close modal
const handleCloseModal = () => {
setSheetOpen(false);
2024-12-16 01:25:47 +00:00
setApiEvents([]);
2024-11-27 04:14:10 +00:00
setSelectedEventDate(null);
};
const handleDateClick = (arg: any) => {
setSheetOpen(true);
setSelectedEventDate(arg);
2024-12-16 01:25:47 +00:00
setApiEvents([]);
2024-11-27 04:14:10 +00:00
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]);
2024-11-27 04:14:10 +00:00
}
};
const handleClassName = (arg: EventContentArg) => {
2024-12-16 01:25:47 +00:00
if (arg.event.extendedProps.calendar === "mabes") {
2024-11-27 04:14:10 +00:00
return "primary";
} else if (arg.event.extendedProps.calendar === "polda") {
2024-11-27 04:14:10 +00:00
return "success";
} else if (arg.event.extendedProps.calendar === "polres") {
return "destructive";
} else if (arg.event.extendedProps.calendar === "international") {
2024-11-27 04:14:10 +00:00
return "info";
} else {
2024-11-27 04:14:10 +00:00
return "primary";
}
};
return (
<>
<div className="grid grid-cols-12 gap-6 divide-x divide-border">
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
<CardContent className="p-0">
2025-01-01 08:33:42 +00:00
<CardHeader className="border-none mb-2 pt-5">
<Button
onClick={handleDateClick}
className="dark:bg-background dark:text-foreground"
>
<Plus className="w-4 h-4 me-1" />
{"Tambahkan Agenda baru"}
</Button>
</CardHeader>
2024-11-27 04:14:10 +00:00
<div className="px-3">
<Calendar
mode="single"
selected={date}
onSelect={(s) => {
handleDateClick(s);
}}
className="rounded-md border w-full p-0 border-none"
/>
</div>
{/* <div id="external-events" className=" space-y-1.5 mt-6 px-4">
2024-11-27 04:14:10 +00:00
<p className="text-sm font-medium text-default-700 mb-3">
{t("shortDesc")}
2024-11-27 04:14:10 +00:00
</p>
{dragEvents.map((event) => (
<ExternalDraggingevent key={event.id} event={event} />
))}
</div> */}
2024-11-27 04:14:10 +00:00
<div className="py-4 text-default-800 font-semibold text-xs uppercase mt-4 mb-2 px-4">
{t("filter")}
2024-11-27 04:14:10 +00:00
</div>
<ul className="space-y-3 px-4">
<li className=" flex gap-3">
<Checkbox
checked={selectedCategory?.length === categories?.length}
onClick={() => {
if (selectedCategory?.length === categories?.length) {
setSelectedCategory([]);
} else {
setSelectedCategory(categories.map((c) => c.value));
}
}}
/>
<Label>All</Label>
</li>
{categories?.map((category) => (
<li className="flex gap-3 " key={category.value}>
<Checkbox
className={category.className}
id={category.label}
checked={selectedCategory?.includes(category.value)}
onClick={() => handleCategorySelection(category.value)}
/>
<Label htmlFor={category.label}>{category.label}</Label>
</li>
))}
</ul>
</CardContent>
</Card>
<Card className="col-span-12 lg:col-span-8 2xl:col-span-9 pt-5">
<CardContent className="dashcode-app-calendar">
<FullCalendar
plugins={[
dayGridPlugin,
timeGridPlugin,
interactionPlugin,
listPlugin,
]}
headerToolbar={{
left: "prev,next today",
center: "title",
2025-01-01 08:33:42 +00:00
right: "dayGridMonth,listWeek,",
2024-11-27 04:14:10 +00:00
}}
2024-12-29 09:09:10 +00:00
events={displayedEvents}
2024-11-27 04:14:10 +00:00
editable={true}
rerenderDelay={10}
eventDurationEditable={false}
selectable={true}
selectMirror={true}
droppable={true}
dayMaxEvents={2}
weekends={true}
eventClassNames={handleClassName}
dateClick={handleDateClick}
eventClick={handleEventClick}
initialView="dayGridMonth"
/>
</CardContent>
</Card>
</div>
<EventModal
open={sheetOpen}
onClose={handleCloseModal}
categories={categories}
2024-12-16 01:25:47 +00:00
event={apiEvents}
2024-11-27 04:14:10 +00:00
selectedDate={selectedEventDate}
/>
</>
);
};
export default CalendarView;
2025-01-01 08:33:42 +00:00
export type CalendarEvent = {
id: string;
title: string;
start: Date;
end: Date;
allDay: boolean;
extendedProps: {
calendar: string;
description: string;
};
};