diff --git a/src/components/frontend/helpdesk/CreateTicketDialog.tsx b/src/components/frontend/helpdesk/CreateTicketDialog.tsx new file mode 100644 index 0000000..1e2a891 --- /dev/null +++ b/src/components/frontend/helpdesk/CreateTicketDialog.tsx @@ -0,0 +1,236 @@ +"use client"; + +import { useState } from "react"; +import { useRouter } from "next/navigation"; +import { toast } from "sonner"; +import { PlusIcon } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; +import { Textarea } from "@/components/ui/textarea"; +import { createTicket } from "@/app/(frontend)/helpdesk/actions"; +import { + TICKET_CATEGORIES, + TICKET_PRIORITIES, + type TicketCategory, + type TicketPriority, +} from "@/lib/tickets/ticketMeta"; +import { cn } from "@/lib/utils"; + +function isTicketCategory(value: string): value is TicketCategory { + return TICKET_CATEGORIES.some((option) => option.value === value); +} + +function isTicketPriority(value: string): value is TicketPriority { + return TICKET_PRIORITIES.some((option) => option.value === value); +} + +export function CreateTicketDialog() { + const router = useRouter(); + const [open, setOpen] = useState(false); + const [title, setTitle] = useState(""); + const [category, setCategory] = useState("support_request"); + const [priority, setPriority] = useState("medium"); + const [description, setDescription] = useState(""); + const [pending, setPending] = useState(false); + const [error, setError] = useState(null); + + function reset() { + setTitle(""); + setCategory("support_request"); + setPriority("medium"); + setDescription(""); + setPending(false); + setError(null); + } + + async function handleSubmit() { + const trimmedTitle = title.trim(); + const trimmedDescription = description.trim(); + if (!trimmedTitle) { + setError("Add a short title for your request."); + return; + } + if (!trimmedDescription) { + setError("Describe the issue or request so the team can help."); + return; + } + + setPending(true); + setError(null); + const result = await createTicket({ + title: trimmedTitle, + description: trimmedDescription, + category, + priority, + }); + + if (result.success) { + setOpen(false); + reset(); + toast.success("Ticket created"); + router.refresh(); + } else { + setError(result.error ?? "Could not create the ticket."); + setPending(false); + } + } + + const getColorForCategoryLabel = (label: string) => { + switch (label.toLowerCase()) { + case "support_request": + return "text-blue-300"; + case "feature_request": + return "text-green-300"; + case "bug_report": + return "text-red-300"; + default: + return "text-muted-foreground"; + } + }; + + const getColorForPriorityLabel = (label: string) => { + switch (label.toLowerCase()) { + case "low": + return "text-zinc-300"; + case "medium": + return "text-blue-300"; + case "high": + return "text-amber-300"; + case "critical": + return "text-red-300"; + default: + return "text-muted-foreground"; + } + } + + return ( + { + setOpen(nextOpen); + if (!nextOpen) reset(); + }} + > + + + + + + New ticket + + Share the details of what you need help with. The helpdesk will follow up here. + + +
{ + event.preventDefault(); + void handleSubmit(); + }} + > +
+ + setTitle(event.target.value)} + disabled={pending} + /> +
+ +
+
+ + +
+ +
+ + +
+
+ +
+ +
+ +
+ +