71 lines
3.2 KiB
TypeScript
71 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useState, type FormEvent, type MouseEvent, type ReactNode } from "react";
|
|
import { useRouter } from "next/navigation";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Dialog, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
|
|
export function CommissionTicketRename({ children }: { children: ReactNode }) {
|
|
const router = useRouter();
|
|
const [open, setOpen] = useState(false);
|
|
const [ticketId, setTicketId] = useState<string | null>(null);
|
|
const [value, setValue] = useState("");
|
|
const [busy, setBusy] = useState(false);
|
|
const [error, setError] = useState("");
|
|
|
|
function changeOpen(next: boolean) {
|
|
if (busy) return;
|
|
setOpen(next);
|
|
}
|
|
|
|
function openFromClick(event: MouseEvent<HTMLDivElement>) {
|
|
if (!(event.target instanceof Element)) return;
|
|
const trigger = event.target.closest<HTMLButtonElement>("[data-ticket-rename-id]");
|
|
if (!trigger) return;
|
|
setTicketId(trigger.dataset.ticketRenameId ?? null);
|
|
setValue(trigger.dataset.ticketRenameTitle ?? "");
|
|
setError("");
|
|
setOpen(true);
|
|
}
|
|
|
|
async function save(event: FormEvent<HTMLFormElement>) {
|
|
event.preventDefault();
|
|
if (busy || !ticketId) return;
|
|
setBusy(true); setError("");
|
|
try {
|
|
const response = await fetch(`/api/commission/tickets/${ticketId}/title`, {
|
|
method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ title: value }),
|
|
});
|
|
if (!response.ok) throw new Error();
|
|
setOpen(false);
|
|
router.refresh();
|
|
} catch { setError("เปลี่ยนชื่อ Ticket ไม่สำเร็จ กรุณาลองอีกครั้ง"); }
|
|
finally { setBusy(false); }
|
|
}
|
|
|
|
return <div className="flex flex-col gap-5" onClick={openFromClick}>{children}
|
|
<Dialog open={open} onOpenChange={changeOpen}>
|
|
<DialogContent>
|
|
<form onSubmit={save} className="flex flex-col gap-4">
|
|
<div className="flex flex-col gap-2">
|
|
<DialogTitle>เปลี่ยนชื่อ Ticket</DialogTitle>
|
|
<DialogDescription>ชื่อนี้จะแสดงให้ลูกค้าเห็น เว้นว่างเพื่อใช้หมายเลข Ticket เดิม</DialogDescription>
|
|
</div>
|
|
<div className="flex flex-col gap-2">
|
|
<Label htmlFor="commission-ticket-title">ชื่อ Ticket</Label>
|
|
<Input id="commission-ticket-title" value={value} onChange={(event) => setValue(event.target.value)}
|
|
maxLength={80} placeholder="เช่น ทีมสำหรับ Spiral Abyss" autoFocus disabled={busy} />
|
|
</div>
|
|
{error && <p role="alert" className="text-sm text-destructive">{error}</p>}
|
|
<div className="flex justify-end gap-2">
|
|
<Button type="button" variant="outline" onClick={() => changeOpen(false)} disabled={busy}>ยกเลิก</Button>
|
|
<Button type="submit" disabled={busy}>{busy ? "กำลังบันทึก..." : "บันทึก"}</Button>
|
|
</div>
|
|
</form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>;
|
|
}
|