From 56807dc5e40cb5e11a085ea4e95d5a0eeeec4d47 Mon Sep 17 00:00:00 2001 From: henrygd Date: Fri, 21 Nov 2025 17:49:17 -0500 Subject: [PATCH] updates --- .../routes/settings/quiet-hours.tsx | 155 ++++++++++++------ 1 file changed, 101 insertions(+), 54 deletions(-) diff --git a/internal/site/src/components/routes/settings/quiet-hours.tsx b/internal/site/src/components/routes/settings/quiet-hours.tsx index ef875a26..cdef957c 100644 --- a/internal/site/src/components/routes/settings/quiet-hours.tsx +++ b/internal/site/src/components/routes/settings/quiet-hours.tsx @@ -1,19 +1,11 @@ import { t } from "@lingui/core/macro" import { Trans } from "@lingui/react/macro" import { useStore } from "@nanostores/react" -import { CalendarClockIcon, MoreHorizontalIcon, PlusIcon, Trash2Icon } from "lucide-react" +import { MoreHorizontalIcon, PlusIcon, Trash2Icon, ServerIcon, ClockIcon, CalendarIcon, ActivityIcon, PenSquareIcon } from "lucide-react" import { useEffect, useState } from "react" -import { - AlertDialog, - AlertDialogAction, - AlertDialogCancel, - AlertDialogContent, - AlertDialogDescription, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogTitle, -} from "@/components/ui/alert-dialog" -import { Button, buttonVariants } from "@/components/ui/button" + +import { Badge } from "@/components/ui/badge" +import { Button } from "@/components/ui/button" import { Dialog, DialogContent, @@ -37,15 +29,13 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useToast } from "@/components/ui/use-toast" import { pb } from "@/lib/api" import { $systems } from "@/lib/stores" -import { cn, formatShortDate } from "@/lib/utils" +import { formatShortDate } from "@/lib/utils" import type { QuietHoursRecord } from "@/types" export function QuietHours() { const [data, setData] = useState([]) const [dialogOpen, setDialogOpen] = useState(false) const [editingRecord, setEditingRecord] = useState(null) - const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) - const [recordToDelete, setRecordToDelete] = useState(null) const { toast } = useToast() const systems = useStore($systems) @@ -87,11 +77,9 @@ export function QuietHours() { return () => unsubscribe?.() }, []) - const handleDelete = async () => { - if (!recordToDelete) return - setDeleteDialogOpen(false) + const handleDelete = async (id: string) => { try { - await pb.collection("quiet_hours").delete(recordToDelete) + await pb.collection("quiet_hours").delete(id) } catch (e: any) { toast({ variant: "destructive", @@ -99,12 +87,6 @@ export function QuietHours() { description: e.message || "Failed to delete quiet hours.", }) } - setRecordToDelete(null) - } - - const openDeleteDialog = (id: string) => { - setRecordToDelete(id) - setDeleteDialogOpen(true) } const openEditDialog = (record: QuietHoursRecord) => { @@ -130,6 +112,59 @@ export function QuietHours() { return end ? `${start} - ${end}` : start } + const getWindowState = (record: QuietHoursRecord): "active" | "past" | "future" => { + const now = new Date() + + if (record.type === "daily") { + // For daily windows, check if current time is within the window + const startDate = new Date(record.start) + const endDate = record.end ? new Date(record.end) : null + + // Get current time in local timezone + const currentMinutes = now.getHours() * 60 + now.getMinutes() + const startMinutes = startDate.getUTCHours() * 60 + startDate.getUTCMinutes() + const endMinutes = endDate ? endDate.getUTCHours() * 60 + endDate.getUTCMinutes() : null + + // Convert UTC to local time offset + const offset = now.getTimezoneOffset() + const localStartMinutes = (startMinutes - offset + 1440) % 1440 + const localEndMinutes = endMinutes !== null ? (endMinutes - offset + 1440) % 1440 : null + + if (localEndMinutes === null) { + // No end time, so it's always active from start time onwards each day + return "active" + } + + // Handle cases where window spans midnight + if (localStartMinutes <= localEndMinutes) { + return currentMinutes >= localStartMinutes && currentMinutes < localEndMinutes ? "active" : "future" + } else { + return currentMinutes >= localStartMinutes || currentMinutes < localEndMinutes ? "active" : "future" + } + } else { + // For one-time windows + const startDate = new Date(record.start) + const endDate = record.end ? new Date(record.end) : null + + if (endDate) { + if (now >= startDate && now <= endDate) { + return "active" + } else if (now > endDate) { + return "past" + } else { + return "future" + } + } else { + // No end date + if (now >= startDate) { + return "active" + } else { + return "future" + } + } + } + } + return ( <>
@@ -164,13 +199,28 @@ export function QuietHours() { - System + + + System + - Type + + + Type + - Schedule + + + State + + + + + + Schedule + Actions @@ -186,6 +236,22 @@ export function QuietHours() { {record.type === "daily" ? Daily : One-time} + + {(() => { + const state = getWindowState(record) + const stateConfig = { + active: { label: Active, variant: "success" as const }, + past: { label: Past, variant: "danger" as const }, + future: { label: Future, variant: "default" as const }, + } + const config = stateConfig[state] + return ( + + {config.label} + + ) + })()} + {formatDateTime(record)} @@ -197,10 +263,10 @@ export function QuietHours() { openEditDialog(record)}> - + Edit - openDeleteDialog(record.id)}> + handleDelete(record.id)}> Delete @@ -214,26 +280,7 @@ export function QuietHours() {
)} - - - - - Are you sure? - - - This will permanently delete these quiet hours. - - - - - Cancel - - - Delete - - - - + ) } @@ -289,7 +336,7 @@ function QuietHoursDialog({ } else { // Reset form setSelectedSystem("") - setIsGlobal(false) + setIsGlobal(true) setWindowType("one-time") setStartDateTime("") setEndDateTime("") @@ -366,12 +413,12 @@ function QuietHoursDialog({
setIsGlobal(value === "global")}> - - Specific System - All Systems + + Specific System +