finish bills , po , jobcards relational fields creation
This commit is contained in:
@@ -2,11 +2,14 @@
|
||||
|
||||
import { useRef, useState } from "react"
|
||||
import { useFormContext, useController, type FieldValues, type FieldPath } from "react-hook-form"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { Car, Loader2 } from "lucide-react"
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import { Car, Loader2, PlusIcon } from "lucide-react"
|
||||
import { useAuthApi } from "@/shared/useApi"
|
||||
import { VEHICLE_ROUTES } from "@garage/api"
|
||||
import { FieldShell } from "@/shared/components/form/field-shell"
|
||||
import { Field, FieldLabel, FieldError, FieldDescription } from "@/shared/components/ui/field"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/shared/components/ui/dialog"
|
||||
import { ScrollArea } from "@/shared/components/ui/scroll-area"
|
||||
import {
|
||||
Combobox,
|
||||
ComboboxInput,
|
||||
@@ -15,8 +18,8 @@ import {
|
||||
ComboboxItem,
|
||||
ComboboxEmpty,
|
||||
} from "@/shared/components/ui/combobox"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import Image from "next/image"
|
||||
import { VehicleForm } from "./vehicle-form"
|
||||
|
||||
// ── Vehicle option type (enriched for display) ──
|
||||
|
||||
@@ -87,6 +90,8 @@ export function RhfVehicleSelectField<
|
||||
const api = useAuthApi()
|
||||
const anchorRef = useRef<HTMLDivElement>(null)
|
||||
const [inputValue, setInputValue] = useState("")
|
||||
const [isCreateOpen, setIsCreateOpen] = useState(false)
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const { control } = useFormContext<TValues>()
|
||||
const {
|
||||
@@ -113,14 +118,17 @@ export function RhfVehicleSelectField<
|
||||
)
|
||||
: options
|
||||
|
||||
return (
|
||||
<FieldShell
|
||||
label={label}
|
||||
error={error?.message}
|
||||
description={description}
|
||||
required={required}
|
||||
>
|
||||
<div ref={anchorRef}>
|
||||
const handleCreateSuccess = (data?: any) => {
|
||||
const item = data?.data ?? data
|
||||
if (item?.id) {
|
||||
field.onChange(buildVehicleOption(item))
|
||||
}
|
||||
queryClient.invalidateQueries({ queryKey: [VEHICLE_ROUTES.INDEX, "vehicle-select"] })
|
||||
setIsCreateOpen(false)
|
||||
}
|
||||
|
||||
const combobox = (
|
||||
<div ref={anchorRef}>
|
||||
<Combobox
|
||||
value={field.value}
|
||||
onValueChange={(val: VehicleOption | VehicleOption[] | null) => {
|
||||
@@ -204,6 +212,44 @@ export function RhfVehicleSelectField<
|
||||
</ComboboxContent>
|
||||
</Combobox>
|
||||
</div>
|
||||
</FieldShell>
|
||||
)
|
||||
|
||||
return (
|
||||
<Field data-invalid={!!error?.message || undefined}>
|
||||
{label && (
|
||||
<div className="flex items-center justify-between">
|
||||
<FieldLabel>
|
||||
{label}
|
||||
{required && <span className="text-destructive ms-0.5">*</span>}
|
||||
</FieldLabel>
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
className="h-5 w-5"
|
||||
onClick={() => setIsCreateOpen(true)}
|
||||
title={`Add new ${label}`}
|
||||
>
|
||||
<PlusIcon className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{combobox}
|
||||
{description && <FieldDescription>{description}</FieldDescription>}
|
||||
{error?.message && <FieldError>{error.message}</FieldError>}
|
||||
|
||||
<Dialog open={isCreateOpen} onOpenChange={(v) => { if (!v) setIsCreateOpen(false) }}>
|
||||
<DialogContent className="min-w-xl">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-2xl font-bold">
|
||||
Add {label}
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<ScrollArea className="max-h-[80vh] px-4">
|
||||
<VehicleForm onSuccess={handleCreateSuccess} />
|
||||
</ScrollArea>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</Field>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import { VEHICLE_ROUTES } from "@garage/api"
|
||||
export type VehicleFormProps = {
|
||||
resourceId?: string | null
|
||||
initialData?: unknown
|
||||
onSuccess?: () => void
|
||||
onSuccess?: (data?: any) => void
|
||||
}
|
||||
|
||||
// ── Default values ──
|
||||
@@ -138,9 +138,9 @@ export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormP
|
||||
})
|
||||
return promise
|
||||
},
|
||||
onSuccess: () => {
|
||||
onSuccess: (data) => {
|
||||
form.reset()
|
||||
onSuccess?.()
|
||||
onSuccess?.(data)
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user