"use client" import { useParams } from "next/navigation" import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" import { type ColumnDef } from "@tanstack/react-table" import { useState } from "react" import { Unlink, Plus, Loader2 } from "lucide-react" import { toast } from "sonner" import { useAuthApi } from "@/shared/useApi" import { DataTable } from "@/shared/data-view/table-view" import { ColumnHeader } from "@/shared/data-view/table-view" import { confirm } from "@/shared/components/confirm-dialog" import { Button } from "@/shared/components/ui/button" import { Card, CardContent } from "@/shared/components/ui/card" import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/shared/components/ui/dialog" import { RhfAsyncSelectField } from "@/shared/components/form" import { Rhform } from "@/shared/components/form" import { useForm } from "react-hook-form" import { TableCell, TableRow } from "@/shared/components/ui/table" import { ApiResponse, CustomersClient } from "@garage/api" import { paths } from "@garage/api/types" import DashboardPage from "@/base/components/layout/dashboard/dashboard-page" type Owner = { id: number name: string created_at: string updated_at: string } const mapCustomerOption = (item: any) => ({ value: String(item.id), label: `${item.first_name ?? ""} ${item.last_name ?? ""}`.trim() || item.name || `Customer #${item.id}`, }) const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label, } export default function VehicleOwnersPage() { const { id: vehicleId } = useParams<{ id: string }>() const api = useAuthApi() const queryClient = useQueryClient() const [linkDialogOpen, setLinkDialogOpen] = useState(false) const queryKey = ["vehicle-owners", vehicleId] const { data, isLoading } = useQuery({ queryKey, queryFn: () => api.vehicles.getOwners(vehicleId), }) const unlinkMutation = useMutation({ mutationFn: (customerId: number) => api.vehicles.unlinkCustomer({ customer_id: customerId, vehicle_id: Number(vehicleId) }), onSuccess: () => { toast.success("Owner unlinked successfully.") queryClient.invalidateQueries({ queryKey }) }, onError: () => { toast.error("Failed to unlink owner.") }, }) const handleUnlink = async (owner: Owner) => { const confirmed = await confirm({ title: "Unlink Owner", description: `Are you sure you want to unlink "${owner.name}" from this vehicle?`, confirmLabel: "Unlink", variant: "destructive", }) if (confirmed) { unlinkMutation.mutate(owner.id) } } const columns: ColumnDef[] = [ { accessorKey: "first_name", header: ({ column }) => , }, { accessorKey: "phone", header: ({ column }) => , }, { accessorKey: "created_at", header: ({ column }) => , cell: ({ getValue }) => { const val = getValue() return val ? new Date(val).toLocaleDateString() : "—" }, }, { id: "actions", header: () => Actions, cell: ({ row }) => ( ), enableSorting: false, }, ] const owners = (data as any)?.data ?? [] // [BackendIssue] [FrontendWorkaround] : pagination should be replaced with "meta" property const meta = (data as any)?.pagination const pagination = { page: meta?.current_page ?? 1, pageSize: meta?.per_page ?? 15, pageCount: meta?.last_page ?? 1, total: meta?.total ?? 0, } return ( setLinkDialogOpen(true)}> Add Owner }> { }} isLoading={isLoading} /> { queryClient.invalidateQueries({ queryKey }) setLinkDialogOpen(false) }} /> ) } function LinkOwnerDialog({ vehicleId, open, onOpenChange, onSuccess, }: { vehicleId: string open: boolean onOpenChange: (open: boolean) => void onSuccess: () => void }) { const api = useAuthApi() const form = useForm<{ customer: { value: string; label: string } | null }>({ defaultValues: { customer: null }, }) const linkMutation = useMutation({ mutationFn: (customerId: number) => api.vehicles.linkCustomer({ customer_id: customerId, vehicle_id: Number(vehicleId) }), onSuccess: () => { toast.success("Owner linked successfully.") form.reset() onSuccess() }, onError: () => { toast.error("Failed to link owner.") }, }) const handleSubmit = (values: { customer: { value: string; label: string } | null }) => { if (!values.customer) return linkMutation.mutate(Number(values.customer.value)) } return ( Add Owner
api.customers.list()} mapOption={mapCustomerOption} {...STORE_OBJECT} />
) }