"use client"; import { EmptyStateContainer, EmptyStateTitle, } from "@/components/content/empty-state"; import { ProcessMessage } from "@/components/content/process-message"; import { FormCardContent, FormCardSeparator, } from "@/components/forms/form-card"; import { useFormSheetDirty } from "@/components/forms/form-sheet"; import { Button } from "@/components/ui/button"; import { Calendar } from "@/components/ui/calendar"; import { Checkbox } from "@/components/ui/checkbox"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { TabsContent } from "@/components/ui/tabs"; import { TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs } from "@/components/ui/tabs"; import { Textarea } from "@/components/ui/textarea"; import { useIsMobile } from "@/hooks/use-mobile"; import { useTRPC } from "@/lib/trpc/client"; import { cn } from "@/lib/utils"; import { zodResolver } from "@hookform/resolvers/zod"; import { useQuery } from "@tanstack/react-query"; import { isTRPCClientError } from "@trpc/client"; import { addDays, format } from "date-fns"; import { CalendarIcon, ClockIcon } from "lucide-react"; import React, { useTransition } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; import { z } from "zod"; const schema = z .object({ title: z.string().min(1, "Title is required"), message: z.string(), startDate: z.date(), endDate: z.date(), pageComponents: z.array(z.number()), notifySubscribers: z.boolean().optional(), }) .refine((data) => data.endDate > data.startDate, { error: "End date cannot be earlier than start date.", path: ["endDate"], }); export type FormValues = z.infer; export function FormMaintenance({ defaultValues, onSubmit, className, pageComponents, ...props }: Omit, "onSubmit"> & { defaultValues?: FormValues; pageComponents: { id: number; name: string }[]; onSubmit: (values: FormValues) => Promise; }) { const trpc = useTRPC(); const { data: workspace } = useQuery( trpc.workspace.getWorkspace.queryOptions(), ); const mobile = useIsMobile(); const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; const form = useForm({ resolver: zodResolver(schema), defaultValues: defaultValues ?? { title: "", message: "", startDate: new Date(), endDate: addDays(new Date(), 1), pageComponents: [], notifySubscribers: true, }, }); const watchEndDate = form.watch("endDate"); const watchMessage = form.watch("message"); const [isPending, startTransition] = useTransition(); const { setIsDirty } = useFormSheetDirty(); const formIsDirty = form.formState.isDirty; React.useEffect(() => { setIsDirty(formIsDirty); }, [formIsDirty, setIsDirty]); function submitAction(values: FormValues) { if (isPending) return; startTransition(async () => { try { const promise = onSubmit(values); toast.promise(promise, { loading: "Saving...", success: () => "Saved", error: (error) => { if (isTRPCClientError(error)) { return error.message; } return "Failed to save"; }, }); await promise; } catch (error) { console.error(error); } }); } return (
( Title )} /> {/* TODO: */} ( Start Date { if (!selectedDate) return; const newDate = new Date(selectedDate); newDate.setHours( field.value.getHours(), field.value.getMinutes(), field.value.getSeconds(), field.value.getMilliseconds(), ); field.onChange(newDate); // NOTE: if end date is before start date, set it to the same day as the start date if (watchEndDate && newDate > watchEndDate) { form.setValue("endDate", newDate); } }} initialFocus />
{ try { const timeValue = e.target.value; if (!timeValue || !field.value) return; const [hours, minutes, seconds] = timeValue .split(":") .map(Number); const newDate = new Date(field.value); newDate.setHours( hours, minutes, seconds || 0, 0, ); field.onChange(newDate); } catch (error) { console.error(error); } }} />
When the maintenance starts. Shown in your timezone ( {timezone} ) and saved as Unix time ( UTC ).
)} />
( End Date { if (!selectedDate) return; const newDate = new Date(selectedDate); newDate.setHours( field.value.getHours(), field.value.getMinutes(), field.value.getSeconds(), field.value.getMilliseconds(), ); field.onChange(newDate); }} initialFocus />
{ try { const timeValue = e.target.value; if (!timeValue || !field.value) return; const [hours, minutes, seconds] = timeValue .split(":") .map(Number); const newDate = new Date(field.value); newDate.setHours( hours, minutes, seconds || 0, 0, ); field.onChange(newDate); } catch (error) { console.error(error); } }} />
When the maintenance ends. Shown in your timezone ( {timezone} ) and saved as Unix time ( UTC ).
)} />
Writing Preview ( Message