feat : fixing calendar view of agenda-settings

This commit is contained in:
hanif salafi 2025-06-08 16:53:46 +07:00
parent d7747da00b
commit 2d57cd606a
2 changed files with 299 additions and 441 deletions

View File

@ -1,23 +1,19 @@
"use client";
import React, { useState, useEffect, act } from "react";
import FullCalendar from "@fullcalendar/react"; // must go before plugins
import React, { useState, useEffect } from "react";
import FullCalendar from "@fullcalendar/react";
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";
@ -42,8 +38,8 @@ import {
} from "@/components/ui/dialog";
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
interface CalendarViewProps {
// events: CalendarEvent[];
categories: CalendarCategory[];
}
@ -59,12 +55,11 @@ export type CalendarEvent = {
extendedProps: {
calendar: string;
description: string;
isPublish?: boolean;
createdByName?: string;
};
};
const INITIAL_YEAR = dayjs().format("YYYY");
const INITIAL_MONTH = dayjs().format("M");
export interface AgendaSettingsAPIResponse {
id: number;
title: string;
@ -74,24 +69,25 @@ export interface AgendaSettingsAPIResponse {
startDate: string;
endDate: string;
isActive: boolean;
isPublish: 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[];
january?: AgendaSettingsAPIResponse[];
february?: AgendaSettingsAPIResponse[];
march?: AgendaSettingsAPIResponse[];
april?: AgendaSettingsAPIResponse[];
may?: AgendaSettingsAPIResponse[];
june?: AgendaSettingsAPIResponse[];
july?: AgendaSettingsAPIResponse[];
august?: AgendaSettingsAPIResponse[];
september?: AgendaSettingsAPIResponse[];
october?: AgendaSettingsAPIResponse[];
november?: AgendaSettingsAPIResponse[];
december?: AgendaSettingsAPIResponse[];
}
interface MonthCardProps {
@ -100,7 +96,7 @@ interface MonthCardProps {
}
interface ListItemProps {
item: any;
item: AgendaSettingsAPIResponse;
text: string;
createdBy: string;
isPublish: boolean | null;
@ -109,78 +105,74 @@ interface ListItemProps {
}
interface APIResponse {
error: boolean;
message: any;
data: AgendaSettingsAPIResponse[] | null;
success: boolean;
message: string;
data: YearlyData | null;
errorCode: string | null;
}
type EventType = "0" | "1" | "2" | "3" | "4" | "5";
const INITIAL_YEAR = dayjs().format("YYYY");
const INITIAL_MONTH = dayjs().format("M");
const CalendarView = ({ categories }: CalendarViewProps) => {
const [selectedCategory, setSelectedCategory] = useState<string[] | null>(
null
);
const [selectedCategory, setSelectedCategory] = useState<string[]>([]);
const [selectedEventDate, setSelectedEventDate] = useState<Date | null>(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<CalendarEvent[]>([]);
const [Isloading, setLoading] = useState<boolean>(false);
const [draggableInitialized, setDraggableInitialized] =
useState<boolean>(false);
const [calendarEvents, setCalendarEvents] = useState<CalendarEvent[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(false);
const t = useTranslations("CalendarApp");
// event canvas state
// Modal states
const [sheetOpen, setSheetOpen] = useState<boolean>(false);
const [date, setDate] = React.useState<Date>(new Date());
const [date, setDate] = useState<Date>(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 [yearlyData, setYearlyData] = useState<YearlyData>({});
const [open, setOpen] = useState(false);
const [selectedEventData, setSelectedEventData] = useState<any>(null);
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<CalendarEvent[]>([]);
// Load events when view or month changes
useEffect(() => {
if (activeView == "listYear") {
if (activeView === "listYear") {
getYearlyEvents();
} else {
getCalendarEvents();
}
}, [activeView, selectedMonth]);
// Initialize selected categories
useEffect(() => {
if (categories?.length > 0) {
setSelectedCategory(categories.map((c) => c.value));
}
}, [categories]);
const getCalendarEvents = async () => {
console.log("View : ", activeView);
setIsLoading(true);
try {
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);
error(res?.message || "Failed to fetch events");
return;
}
const data = res?.data?.data;
if (data) {
console.log("Dataaa : ", data);
// For monthly view, we need to extract events from the specific month
const monthData = res?.data?.data;
if (monthData) {
const allEvents: CalendarEvent[] = [];
// Map API data to the calendarEvents structure
const events = res?.data?.data?.map((event: any) => ({
const events = monthData?.map((event: any) => ({
id: event.id.toString(),
title: event.title,
createBy: event.createdById,
@ -196,300 +188,196 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
},
}));
console.log("Dataaa event : ", events);
console.log("Event Data : ", events);
setCalendarEvents(events);
}
} catch (err) {
console.error("Failed to fetch calendar events:", err);
error("Failed to fetch calendar events");
} finally {
setIsLoading(false);
}
};
const getYearlyEvents = async () => {
setIsLoading(true);
try {
const res = await getAgendaSettingsList(
selectedMonth?.format("YYYY") || INITIAL_YEAR,
"",
""
);
if (res?.error) {
error(res.message);
return false;
error(res?.message || "Failed to fetch yearly events");
return;
}
// The API already returns data organized by months
const yearlyData = res?.data?.data;
if (yearlyData) {
setYearlyData(yearlyData);
}
} catch (err) {
console.error("Failed to fetch yearly events:", err);
error("Failed to fetch yearly events");
} finally {
setIsLoading(false);
}
setYearlyData(res?.data?.data);
};
useEffect(() => {
setSelectedCategory(categories?.map((c) => c.value));
}, [categories]);
// Filter events based on selected categories
const filteredEvents = calendarEvents.filter((event) => {
if (!selectedCategory.length) return false;
console.log("Event category : ", selectedCategory);
const filteredEvents = calendarEvents?.filter((event) => {
const eventCategories = event.extendedProps.calendar
?.split(",")
.map((val: string) => val.trim()); // agar "1, 2" tetap dianggap benar
.map((val: string) => val.trim());
const allCategoryId = ["1", "2", "3", "4", "5"];
// Cek apakah SEMUA validTypeIds ada di typeIdsInData
const hasAllCategories = allCategoryId.every(categoryId => selectedCategory.includes(categoryId));
return eventCategories?.some((cat: string) =>
selectedCategory?.includes(cat)
selectedCategory.includes(cat) || (hasAllCategories && cat == "0")
);
});
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
// Event handlers
const handleEventClick = (arg: any) => {
console.log("Event Click ", arg);
setSelectedEventDate(null);
setSelectedEventData(arg);
setSheetOpen(true);
setApiEvents(arg);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
// handle close modal
const handleCloseModal = () => {
setSheetOpen(false);
setApiEvents([]);
setSelectedEventData(null);
setSelectedEventDate(null);
};
const handleDateClick = (arg: any) => {
setSheetOpen(true);
console.log("Date :", arg);
setSelectedEventDate(arg);
setApiEvents([]);
setSelectedEventData(null);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
const handleCategorySelection = (category: string) => {
if (selectedCategory && selectedCategory.includes(category)) {
setSelectedCategory(selectedCategory.filter((c) => c !== category));
setSelectedCategory(prev => {
if (prev.includes(category)) {
return prev.filter((c) => c !== category);
} else {
setSelectedCategory([...(selectedCategory || []), category]);
}
};
const renderEventContent = (eventInfo: any) => {
const { title } = eventInfo.event;
const { createdByName, isPublish } = eventInfo.event.extendedProps;
return (
<div className="w-full p-2 mb-2 rounded-md text-white text-sm bg-yellow-500 flex justify-between items-stretch">
<div className="flex-1">
<div className="flex flex-row items-center">
{isPublish === true ? <CheckCheck size={15} /> : <Timer size={15} />}
<p className="ml-1">{title}</p>
</div>
<p className="ml-1 text-xs text-start mt-2">
Created By : {createdByName}
</p>
</div>
<div className="w-3 flex flex-col h-full ml-2 rounded-r-md">
<div className="flex-1 bg-red-500"></div>
<div className="flex-1 bg-yellow-400"></div>
<div className="flex-1 bg-green-500"></div>
</div>
</div>
);
};
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";
return [...prev, category];
}
});
};
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 typeSplit = type.split(",");
const firstType = typeSplit && typeSplit[0];
const colors: Record<Event["type"], string> = {
"0": "bg-black",
"1": "bg-yellow-500",
"2": "bg-blue-400",
"3": "bg-slate-400",
"4": "bg-orange-500",
"5": "bg-green-400",
};
console.log("Type : ", colors[firstType]);
return colors[firstType];
};
const getEventColorList = (type: Event["type"]): string[] | null => {
const typeSplit = type.split(",");
const typeList = typeSplit?.slice(1);
if (typeList.length === 0) return null;
const colors: Record<Event["type"], string> = {
"0": "bg-black",
"1": "bg-yellow-500",
"2": "bg-blue-400",
"3": "bg-slate-400",
"4": "bg-orange-500",
"5": "bg-green-400",
};
const typeListColor = typeList.map((item) => colors[item] || "bg-gray-200");
console.log("Type List Color : ", typeListColor);
return typeListColor;
};
const handleClickListItem = (item: any) => {
const handleClickListItem = (item: AgendaSettingsAPIResponse) => {
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
createBy: item.createdById?.toString() || "",
createdByName: item.createdByName,
isPublish: item.isPublish,
allDay: true,
extendedProps: {
calendar: item.agendaType,
description: item.description,
isPublish: item.isPublish,
createdByName: item.createdByName,
},
};
const finalEvent: any = {
event: formattedEvent,
};
console.log("Event click custom : ", finalEvent);
const eventArg = { event: formattedEvent };
setSelectedEventDate(null);
setSelectedEventData(eventArg);
setSheetOpen(true);
setApiEvents(finalEvent);
wait().then(() => (document.body.style.pointerEvents = "auto"));
};
// Utility functions
const getEventColor = (type: EventType): string => {
const typeSplit = type.split(",");
const firstType = typeSplit[0] as EventType;
const colors: Record<EventType, string> = {
"0": "bg-black",
"1": "bg-yellow-500",
"2": "bg-blue-400",
"3": "bg-slate-400",
"4": "bg-orange-500",
"5": "bg-green-400",
};
return colors[firstType] || "bg-gray-400";
};
const getEventColorList = (type: EventType): string[] | null => {
const typeSplit = type.split(",");
const typeList = typeSplit.slice(1);
if (typeList.length === 0) return null;
const colors: Record<EventType, string> = {
"0": "bg-black",
"1": "bg-yellow-500",
"2": "bg-blue-400",
"3": "bg-slate-400",
"4": "bg-orange-500",
"5": "bg-green-400",
};
return typeList.map((item) => colors[item as EventType] || "bg-gray-200");
};
const renderEventContent = (eventInfo: any) => {
const { title } = eventInfo.event;
const { createdByName, isPublish, calendar } = eventInfo.event.extendedProps;
const bgColor = getEventColor(calendar);
const colorList = getEventColorList(calendar);
return (
<div className={`w-full p-2 mb-2 rounded-md text-white text-sm flex justify-between items-stretch ${bgColor}`}>
<div className="flex-1">
<div className="flex flex-row items-center">
{isPublish === true ? <CheckCheck size={15} /> : <Timer size={15} />}
<p className="ml-1">{title}</p>
</div>
<p className="ml-1 text-xs text-start mt-2">
Created By: {createdByName}
</p>
</div>
{colorList && colorList.length > 0 && (
<div className="w-3 flex flex-col h-full ml-2 overflow-hidden item-stretch gap-1">
{colorList.map((color: string, index: number) => (
<div key={index} className={`h-[10px] rounded-sm ${color}`}></div>
))}
</div>
)}
</div>
);
};
const handleClassName = (arg: EventContentArg) => {
const eventColor = getEventColor(arg.event.extendedProps.calendar);
return eventColor || "primary";
};
// Components
const ListItem: React.FC<ListItemProps> = ({
item,
text,
@ -498,7 +386,8 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
bgColor,
colorList,
}) => (
<div className={`w-full p-2 mb-2 rounded-md text-white text-sm flex justify-between items-stretch ${bgColor}`}
<div
className={`w-full p-2 mb-2 rounded-md text-white text-sm flex justify-between items-stretch cursor-pointer hover:opacity-80 ${bgColor}`}
onClick={() => handleClickListItem(item)}
>
<div className="flex-1">
@ -508,45 +397,44 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
</div>
<p className="ml-1 text-xs text-start mt-2">Created By: {createdBy}</p>
</div>
{colorList && colorList.length > 0 && (
<div className="w-3 flex flex-col h-full ml-2 overflow-hidden item-stretch gap-1">
{colorList?.map((color: string) => (
<div className={`h-[10px] rounded-sm ${color}`}></div>
{colorList.map((color: string, index: number) => (
<div key={index} className={`h-[10px] rounded-sm ${color}`}></div>
))}
</div>
)}
</div>
);
const MonthCard: React.FC<MonthCardProps> = (props: any) => {
const { monthId, label } = props;
const events: any = yearlyData?.[monthId];
const displayedEvents = events?.slice(0, 3);
const hasMoreEvents = events?.length > 3;
const MonthCard: React.FC<MonthCardProps> = ({ monthId, label }) => {
const events = yearlyData[monthId] || [];
const displayedEvents = events.slice(0, 3);
const hasMoreEvents = events.length > 3;
return (
<div className="flex-1 bg-white rounded-lg shadow-sm border border-gray-200 pb-3 mr-1">
<div className="py-3">
<h4 className="font-bold text-center">{label}</h4>
</div>
<div className="px-2">
{events?.length === 0 ? (
{events.length === 0 ? (
<div className="mt-1 py-2 rounded-lg bg-white border border-black">
<p className="text-center">{t("no-data-yet")}</p>
</div>
) : (
<>
{displayedEvents?.map((event: any, index: number) => (
{displayedEvents.map((event, index) => (
<ListItem
key={index}
key={`${event.id}-${index}`}
item={event}
text={event.title}
createdBy={event.createdByName}
isPublish={event.isPublish}
bgColor={getEventColor(event.agendaType)}
colorList={getEventColorList(event.agendaType)}
bgColor={getEventColor(event.agendaType as EventType)}
colorList={getEventColorList(event.agendaType as EventType)}
/>
))}
{hasMoreEvents && (
<Popover>
<PopoverTrigger asChild>
@ -566,15 +454,15 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
</CardHeader>
<CardContent className="p-2 text-sm">
<div className="max-h-[300px] overflow-y-auto border rounded-md border-gray-300 p-2">
{events.map((event: any, index: number) => (
{events.map((event, index) => (
<ListItem
key={index}
key={`${event.id}-full-${index}`}
item={event}
text={event.title}
createdBy={event.createdByName}
isPublish={event.isPublish}
bgColor={getEventColor(event.agendaType)}
colorList={getEventColorList(event.agendaType)}
bgColor={getEventColor(event.agendaType as EventType)}
colorList={getEventColorList(event.agendaType as EventType)}
/>
))}
</div>
@ -590,9 +478,24 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
);
};
const getModalContent = (type: "terkirim" | "diterima") => (
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 getModalContent = () => (
<div className="overflow-x-auto overflow-y-auto">
{Isloading ? (
{isLoading ? (
<p>Loading...</p>
) : (
<table className="w-full border-collapse border border-gray-300">
@ -606,14 +509,12 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
</tr>
</thead>
<tbody>
<tr key={""} className="border-b">
<td className="px-4 py-2">{"1"}</td>
<td className="px-4 py-2">{"MIA - 001"}</td>
<td className="px-4 py-2">{"23/01/2025 13:00"}</td>
<td className="px-4 py-2">{"Daily Issue 25 Januari 2025 "}</td>
<td className="px-4 py-2">
{type === "terkirim" ? "Completed" : "Completed"}
</td>
<tr className="border-b">
<td className="px-4 py-2">1</td>
<td className="px-4 py-2">MIA - 001</td>
<td className="px-4 py-2">23/01/2025 13:00</td>
<td className="px-4 py-2">Daily Issue 25 Januari 2025</td>
<td className="px-4 py-2">Completed</td>
</tr>
</tbody>
</table>
@ -627,7 +528,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
<Card className="col-span-12 lg:col-span-4 2xl:col-span-3 pb-5">
<CardContent className="p-0">
<CardHeader className="border-none mb-2 pt-5">
{roleId == 3 || roleId == 11 || roleId == 2 || roleId == 12 ? (
{[3, 11, 2, 12].includes(roleId) && (
<Button
onClick={handleDateClick}
className="dark:bg-background dark:text-foreground w-full"
@ -635,72 +536,64 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
<Plus className="w-4 h-4 me-1" />
{t("addEvent")}
</Button>
) : (
""
)}
<div>
{roleId === 3 && userLevelId === 216 && (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
{roleId === 3 && userLevelId === 216 ? (
<Button className="dark:bg-background dark:text-foreground w-full">
<Book size={15} className="w-4 h-4 mr-3" />
{t("bag-pa-monitoring-results")}
</Button>
) : null}
</DialogTrigger>
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px] overflow-y-auto max-h-[500px]">
<DialogHeader>
<DialogTitle>{t("monitoring-results")}</DialogTitle>
</DialogHeader>
{getModalContent("terkirim")}
{getModalContent()}
</DialogContent>
</Dialog>
</div>
)}
</CardHeader>
<div className="px-3">
<Calendar
mode="single"
selected={date}
onSelect={(s) => {
handleDateClick(s);
onSelect={(selectedDate) => {
if (selectedDate) {
setDate(selectedDate);
handleDateClick(selectedDate);
}
}}
className="rounded-md border w-full p-0 border-none"
/>
</div>
{/* <div id="external-events" className=" space-y-1.5 mt-6 px-4">
<p className="text-sm font-medium text-default-700 mb-3">
{t("shortDesc")}
</p>
{dragEvents.map((event) => (
<ExternalDraggingevent key={event.id} event={event} />
))}
</div> */}
<div className="py-4 text-default-800 font-semibold text-xs uppercase mt-4 mb-2 px-4">
{t("filter")}
</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) {
checked={selectedCategory.length === categories.length}
onCheckedChange={() => {
if (selectedCategory.length === categories.length) {
setSelectedCategory([]);
} else {
setSelectedCategory(categories?.map((c) => c.value));
setSelectedCategory(categories.map((c) => c.value));
}
}}
/>
<Label>All</Label>
</li>
{categories?.map((category) => (
{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)}
checked={selectedCategory.includes(category.value)}
onCheckedChange={() => handleCategorySelection(category.value)}
/>
<Label htmlFor={category.label}>{category.label}</Label>
</li>
@ -712,12 +605,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
<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,
]}
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin]}
headerToolbar={{
left: "prev,next today",
center: "title",
@ -729,7 +617,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
buttonText: "Year",
},
}}
events={displayedEvents}
events={filteredEvents}
editable={true}
rerenderDelay={10}
eventDurationEditable={false}
@ -745,19 +633,17 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
eventContent={renderEventContent}
viewDidMount={(info) => 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" : ""
}
viewClassNames={activeView === "listYear" ? "hide-calendar-grid" : ""}
/>
{activeView === "listYear" && (
<div className="custom-ui">
<div className="flex gap-1 mt-1">
{months.slice(0, 3).map((month) => (
{[0, 3, 6, 9].map((startIndex) => (
<div key={startIndex} className="flex gap-1 mt-1">
{months.slice(startIndex, startIndex + 3).map((month) => (
<MonthCard
key={month.id}
monthId={month.id}
@ -765,46 +651,18 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
/>
))}
</div>
<div className="flex gap-1 mt-1">
{months.slice(3, 6).map((month) => (
<MonthCard
key={month.id}
monthId={month.id}
label={month.label}
/>
))}
</div>
<div className="flex gap-1 mt-1">
{months.slice(6, 9).map((month) => (
<MonthCard
key={month.id}
monthId={month.id}
label={month.label}
/>
))}
</div>
<div className="flex gap-1 mt-1">
{months.slice(9, 12).map((month) => (
<MonthCard
key={month.id}
monthId={month.id}
label={month.label}
/>
))}
</div>
</div>
)}
</CardContent>
</Card>
</div>
<EventModal
open={sheetOpen}
onClose={handleCloseModal}
categories={categories}
event={apiEvents}
event={selectedEventData}
selectedDate={selectedEventDate}
/>
</>

View File

@ -21,7 +21,7 @@ const CalenderPage = () => {
const categories = await getCategories();
let valueShowed: string[] = [];
if (userLevelNumber == 1) {
valueShowed = ["1", "2", "3", "4", "5"];
valueShowed = ["0", "1", "2", "3", "4", "5"];
} else if (userLevelNumber == 2 && userLevelId != 761) {
valueShowed = ["2", "3"];
} else if (