'use client'; import { Textarea } from '@/components/input'; import { Button } from '@/components/ui/button'; import { apiFetch } from '@/lib/api'; import { Loader2 } from 'lucide-react'; import Link from 'next/link'; import { useParams } from 'next/navigation'; import { useEffect, useState } from 'react'; interface Ticket { id: string; subject: string; status: 'awaiting_admin' | 'awaiting_user' | 'closed'; createdAt: string; lastMessageAt: string; } interface Message { id: string; authorIsAdmin: boolean; body: string; createdAt: string; } export default function TicketDetail() { const params = useParams<{ id: string }>(); const [data, setData] = useState<{ ticket: Ticket; messages: Message[] } | null>(null); const [reply, setReply] = useState(''); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); function load() { if (!params?.id) return; apiFetch<{ ticket: Ticket; messages: Message[] }>(`/v1/support/tickets/${params.id}`) .then(setData) .catch((e) => setError((e as Error).message)); } useEffect(load, [params?.id]); async function sendReply(e: React.FormEvent) { e.preventDefault(); if (!params?.id || reply.trim().length === 0) return; setBusy(true); setError(null); try { await apiFetch(`/v1/support/tickets/${params.id}/messages`, { method: 'POST', body: JSON.stringify({ body: reply }), }); setReply(''); load(); } catch (err) { setError((err as Error).message); } finally { setBusy(false); } } if (!data && !error) { return (
); } if (error || !data) { return (

{error ?? 'Ticket not found.'}

← Back to support
); } const { ticket, messages } = data; const isClosed = ticket.status === 'closed'; return (
← All tickets

{ticket.subject}

{ticket.status.replace('_', ' ')}
{messages.map((m) => (
{m.authorIsAdmin ? 'Support' : 'You'} {new Date(m.createdAt).toLocaleString()}

{m.body}

))}
{!isClosed && (