import { ReviewSummary } from "@/types/review"; import { Calendar } from "../ui/calendar"; import { useMemo } from "react"; import { FaCircle } from "react-icons/fa"; import { getUTCOffset } from "@/utils/dateUtil"; import { type DayContentProps } from "react-day-picker"; import { LAST_24_HOURS_KEY } from "@/types/filter"; import { usePersistence } from "@/hooks/use-persistence"; type WeekStartsOnType = 0 | 1 | 2 | 3 | 4 | 5 | 6; type ReviewActivityCalendarProps = { reviewSummary?: ReviewSummary; selectedDay?: Date; onSelect: (day?: Date) => void; }; export default function ReviewActivityCalendar({ reviewSummary, selectedDay, onSelect, }: ReviewActivityCalendarProps) { const [weekStartsOn] = usePersistence("weekStartsOn", 0); const disabledDates = useMemo(() => { const tomorrow = new Date(); tomorrow.setHours(tomorrow.getHours() + 24, -1, 0, 0); const future = new Date(); future.setFullYear(tomorrow.getFullYear() + 10); return { from: tomorrow, to: future }; }, []); const modifiers = useMemo(() => { if (!reviewSummary) { return { alerts: [], detections: [] }; } const unreviewedDetections: Date[] = []; const unreviewedAlerts: Date[] = []; Object.entries(reviewSummary).forEach(([date, data]) => { if (date == LAST_24_HOURS_KEY) { return; } const parts = date.split("-"); const cal = new Date(date); cal.setFullYear( parseInt(parts[0]), parseInt(parts[1]) - 1, parseInt(parts[2]), ); if (data.total_alert > data.reviewed_alert) { unreviewedAlerts.push(cal); } else if (data.total_detection > data.reviewed_detection) { unreviewedDetections.push(cal); } }); return { alerts: unreviewedAlerts, detections: unreviewedDetections, }; }, [reviewSummary]); return ( ); } function ReviewActivityDay({ date, activeModifiers }: DayContentProps) { const dayActivity = useMemo(() => { if (activeModifiers["alerts"]) { return "alert"; } else if (activeModifiers["detections"]) { return "detection"; } else { return "none"; } }, [activeModifiers]); return (
{date.getDate()} {dayActivity != "none" && ( )}
); } type TimezoneAwareCalendarProps = { timezone?: string; selectedDay?: Date; onSelect: (day?: Date) => void; }; export function TimezoneAwareCalendar({ timezone, selectedDay, onSelect, }: TimezoneAwareCalendarProps) { const [weekStartsOn] = usePersistence("weekStartsOn", 0); const timezoneOffset = useMemo( () => timezone ? Math.round(getUTCOffset(new Date(), timezone)) : undefined, [timezone], ); const disabledDates = useMemo(() => { const tomorrow = new Date(); if (timezoneOffset) { tomorrow.setHours( tomorrow.getHours() + 24, tomorrow.getMinutes() + timezoneOffset, 0, 0, ); } else { tomorrow.setHours(tomorrow.getHours() + 24, -1, 0, 0); } const future = new Date(); future.setFullYear(tomorrow.getFullYear() + 10); return { from: tomorrow, to: future }; }, [timezoneOffset]); const today = useMemo(() => { if (!timezoneOffset) { return undefined; } const date = new Date(); const utc = Date.UTC( date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), ); const todayUtc = new Date(utc); todayUtc.setMinutes(todayUtc.getMinutes() + timezoneOffset, 0, 0); return todayUtc; }, [timezoneOffset]); return ( ); }