"use client" import { useState, useEffect, useRef } from "react" import { useMutation, useQueryClient } from "@tanstack/react-query" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { useToast } from "@/components/ui/use-toast" import { Button } from "@/components/ui/button" // Generate slug from name const generateSlug = (name: string): string => { return name .toLowerCase() .replace(/[^a-z0-9]+/g, '-') .replace(/^-|-$/g, '') .slice(0, 50) } import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Textarea } from "@/components/ui/textarea" import { Switch } from "@/components/ui/switch" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { createStatusPage, updateStatusPage, getStatusPageUrl, type StatusPage, } from "@/lib/statuspages" import { ExternalLink, RefreshCw } from "lucide-react" const formSchema = z.object({ name: z.string().min(1, "Name is required"), slug: z.string().min(1, "Slug is required").regex(/^[a-z0-9-]+$/, "Slug must be lowercase letters, numbers, and hyphens"), title: z.string().min(1, "Title is required"), description: z.string().optional(), logo: z.string().optional(), favicon: z.string().optional(), theme: z.enum(["light", "dark", "auto"] as const), custom_css: z.string().optional(), public: z.boolean(), show_uptime: z.boolean(), }) type FormData = z.infer interface StatusPageDialogProps { open: boolean onOpenChange: (open: boolean) => void page?: StatusPage | null isEdit?: boolean } export function StatusPageDialog({ open, onOpenChange, page, isEdit = false, }: StatusPageDialogProps) { const { toast } = useToast() const queryClient = useQueryClient() const [activeTab, setActiveTab] = useState("basic") const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { name: "", slug: "", title: "", description: "", logo: "", favicon: "", theme: "auto", custom_css: "", public: true, show_uptime: true, }, }) useEffect(() => { if (open && isEdit && page) { form.reset({ name: page.name, slug: page.slug, title: page.title, description: page.description || "", logo: page.logo || "", favicon: page.favicon || "", theme: page.theme, custom_css: "", public: page.public, show_uptime: page.show_uptime, }) } else if (open && !isEdit) { form.reset({ name: "", slug: "", title: "", description: "", logo: "", favicon: "", theme: "auto", custom_css: "", public: true, show_uptime: true, }) } }, [open, isEdit, page, form]) const createMutation = useMutation({ mutationFn: createStatusPage, onSuccess: () => { toast({ title: "Status page created successfully" }) queryClient.invalidateQueries({ queryKey: ["status-pages"] }) onOpenChange(false) }, onError: (error: Error) => { toast({ title: "Failed to create status page", description: error.message, variant: "destructive", }) }, }) const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: Partial }) => updateStatusPage(id, data), onSuccess: () => { toast({ title: "Status page updated successfully" }) queryClient.invalidateQueries({ queryKey: ["status-pages"] }) onOpenChange(false) }, onError: (error: Error) => { toast({ title: "Failed to update status page", description: error.message, variant: "destructive", }) }, }) const onSubmit = (data: FormData) => { if (isEdit && page) { updateMutation.mutate({ id: page.id, data }) } else { createMutation.mutate(data) } } const isPending = createMutation.isPending || updateMutation.isPending // Auto-generate slug from name when creating new status page const lastAutoSlug = useRef("") useEffect(() => { if (isEdit) return // Don't auto-generate in edit mode const subscription = form.watch((value, { name: fieldName }) => { if (fieldName === 'name') { const name = value.name || '' const currentSlug = form.getValues('slug') || '' const newSlug = generateSlug(name) // Only auto-generate if: // 1. Slug is empty, OR // 2. Current slug matches the last auto-generated slug (user hasn't manually edited) if (!currentSlug || currentSlug === lastAutoSlug.current) { form.setValue('slug', newSlug, { shouldValidate: true }) lastAutoSlug.current = newSlug } } }) return () => subscription.unsubscribe() }, [form, isEdit]) return ( {isEdit ? "Edit Status Page" : "Create Status Page"} Configure a public status page to share your service status.
Basic Appearance Advanced ( Name )} /> ( URL Slug {!isEdit && form.getValues('name') && ( )}
/status/
Full URL: {typeof window !== 'undefined' ? window.location.origin : ''}{getStatusPageUrl(field.value)} {field.value && ( e.stopPropagation()} > Preview )}
)} /> ( Page Title )} /> ( Description