updates
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
"use client"
|
||||
|
||||
import { useRouter } from "next/navigation"
|
||||
import { ResourcePage } from "@/shared/data-view/resource-page"
|
||||
import { ColumnHeader } from "@/shared/data-view/table-view"
|
||||
import FormDialog from "@/shared/components/form-dialog"
|
||||
import { AppointmentForm } from "@/modules/appointments/appointment-form"
|
||||
import { APPOINTMENT_ROUTES } from "@garage/api"
|
||||
import type { AppointmentsClient } from "@garage/api"
|
||||
import { CalendarCheck2Icon, ClipboardListIcon, ClockIcon, ExternalLinkIcon } from "lucide-react"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
|
||||
const STATUS_COLORS: Record<string, string> = {
|
||||
requested: "bg-yellow-100 text-yellow-800",
|
||||
confirmed: "bg-blue-100 text-blue-800",
|
||||
in_progress: "bg-purple-100 text-purple-800",
|
||||
completed: "bg-green-100 text-green-800",
|
||||
cancelled: "bg-red-100 text-red-800",
|
||||
}
|
||||
|
||||
export default function AppointmentsPage() {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<ResourcePage<AppointmentsClient>
|
||||
pageTitle="Appointments"
|
||||
routeKey={APPOINTMENT_ROUTES.INDEX}
|
||||
getClient={(api) => api.appointments}
|
||||
onRowClick={(row) => router.push(`/calendar/appointment/${(row as any).id}`)}
|
||||
headerProps={({ selectedItem, invalidateQuery }) => ({
|
||||
actions: (
|
||||
<FormDialog title="Appointment">
|
||||
{(resourceId) => (
|
||||
<AppointmentForm
|
||||
resourceId={resourceId}
|
||||
initialData={selectedItem}
|
||||
onSuccess={invalidateQuery}
|
||||
/>
|
||||
)}
|
||||
</FormDialog>
|
||||
),
|
||||
})}
|
||||
columns={({ actionsColumn }) => [
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Title" />,
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-2">
|
||||
<CalendarCheck2Icon className="size-4 text-muted-foreground" />
|
||||
<span>{(row.original as any).title}</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "date",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Date" />,
|
||||
},
|
||||
{
|
||||
accessorKey: "from_time",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Time" />,
|
||||
cell: ({ row }) => {
|
||||
const r = row.original as any
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<ClockIcon className="size-3 text-muted-foreground" />
|
||||
<span>{r.from_time} – {r.to_time}</span>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Status" />,
|
||||
cell: ({ row }) => {
|
||||
const status = (row.original as any).status
|
||||
const colorClass = STATUS_COLORS[status] ?? "bg-gray-100 text-gray-800"
|
||||
return (
|
||||
<Badge className={colorClass}>
|
||||
{status?.replace("_", " ") ?? "—"}
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "job_card",
|
||||
header: ({ column }) => <ColumnHeader column={column} title="Job Card" />,
|
||||
cell: ({ row }) => {
|
||||
const jobCardId = (row.original as any).job_card_id
|
||||
if (!jobCardId) return <span className="text-muted-foreground">—</span>
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 gap-1.5"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
router.push(`/sales/job-cards/${jobCardId}`)
|
||||
}}
|
||||
>
|
||||
<ClipboardListIcon className="size-3" />
|
||||
#{jobCardId}
|
||||
<ExternalLinkIcon className="size-3" />
|
||||
</Button>
|
||||
)
|
||||
},
|
||||
},
|
||||
actionsColumn(),
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user