garage-erp/apps/dashboard/modules/job-cards/job-card-remarks-list.tsx
2026-04-07 06:32:40 +03:00

129 lines
4.2 KiB
TypeScript

"use client"
import { useState } from "react"
import { useMutation } from "@tanstack/react-query"
import { useRouter } from "next/navigation"
import { Plus, Trash2, MessageSquare } from "lucide-react"
import { toast } from "sonner"
import { useAuthApi } from "@/shared/useApi"
import { confirm } from "@/shared/components/confirm-dialog"
import { Button } from "@/shared/components/ui/button"
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "@/shared/components/ui/card"
import { Textarea } from "@/shared/components/ui/textarea"
type CustomerRemark = {
id: number
remark: string
created_at?: string
}
type Props = {
jobCardId: string
remarks: CustomerRemark[]
}
export function JobCardRemarksList({ jobCardId, remarks }: Props) {
const api = useAuthApi()
const router = useRouter()
const [newRemark, setNewRemark] = useState("")
const addMutation = useMutation({
mutationFn: (remark: string) =>
api.jobCards.addCustomerRemark(jobCardId, { remark }),
onSuccess: () => {
toast.success("Customer remark added")
setNewRemark("")
router.refresh()
},
onError: () => {
toast.error("Failed to add customer remark")
},
})
const deleteMutation = useMutation({
mutationFn: (remarkId: number) =>
api.jobCards.deleteCustomerRemark(jobCardId, remarkId),
onSuccess: () => {
toast.success("Customer remark deleted")
router.refresh()
},
onError: () => {
toast.error("Failed to delete customer remark")
},
})
const handleAdd = () => {
const trimmed = newRemark.trim()
if (!trimmed) return
addMutation.mutate(trimmed)
}
const handleDelete = async (remark: CustomerRemark) => {
const confirmed = await confirm({
title: "Delete Customer Remark",
description: "Are you sure you want to delete this remark?",
confirmLabel: "Delete",
variant: "destructive",
})
if (confirmed) {
deleteMutation.mutate(remark.id)
}
}
return (
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<MessageSquare className="size-4" />
Customer Remarks
</CardTitle>
</CardHeader>
<CardContent className="flex flex-col gap-4">
{remarks.length === 0 && (
<p className="text-sm text-muted-foreground">No customer remarks yet.</p>
)}
{remarks.map((remark) => (
<div
key={remark.id}
className="flex items-start justify-between gap-3 rounded-lg border px-4 py-3"
>
<p className="text-sm whitespace-pre-wrap">{remark.remark}</p>
<Button
variant="ghost"
size="icon"
className="shrink-0 text-muted-foreground hover:text-destructive"
onClick={() => handleDelete(remark)}
disabled={deleteMutation.isPending}
>
<Trash2 className="size-4" />
</Button>
</div>
))}
<div className="flex flex-col gap-2">
<Textarea
placeholder="Add a customer remark..."
value={newRemark}
onChange={(e) => setNewRemark(e.target.value)}
rows={2}
/>
<Button
size="sm"
className="self-end"
onClick={handleAdd}
disabled={addMutation.isPending || !newRemark.trim()}
>
<Plus className="size-4" />
{addMutation.isPending ? "Adding..." : "Add Remark"}
</Button>
</div>
</CardContent>
</Card>
)
}