feat: enhance import/export functionality with detailed results dialog and improved data handling
This commit is contained in:
@@ -52,6 +52,27 @@ function buildVehicleOption(item: any): VehicleOption {
|
||||
}
|
||||
}
|
||||
|
||||
function VehicleThumb({ src }: { src?: string }) {
|
||||
const [broken, setBroken] = useState(false)
|
||||
if (!src || broken) {
|
||||
return (
|
||||
<div className="flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground border border-border">
|
||||
<Car className="size-4" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<Image
|
||||
height={60}
|
||||
width={60}
|
||||
src={src}
|
||||
alt=""
|
||||
onError={() => setBroken(true)}
|
||||
className="size-9 shrink-0 rounded-md object-cover border border-border"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function extractItems(response: unknown): any[] {
|
||||
if (Array.isArray(response)) return response
|
||||
const obj = response as any
|
||||
@@ -168,20 +189,7 @@ export function RhfVehicleSelectField<
|
||||
filtered.map((opt) => (
|
||||
<ComboboxItem key={opt.value} value={opt}>
|
||||
<div className="flex items-center gap-3 py-0.5 w-full min-w-0">
|
||||
{/* Thumbnail */}
|
||||
{opt.image_url ? (
|
||||
<Image
|
||||
height={60}
|
||||
width={60}
|
||||
src={opt.image_url}
|
||||
alt=""
|
||||
className="size-9 shrink-0 rounded-md object-cover border border-border"
|
||||
/>
|
||||
) : (
|
||||
<div className="flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground border border-border">
|
||||
<Car className="size-4" />
|
||||
</div>
|
||||
)}
|
||||
<VehicleThumb src={opt.image_url} />
|
||||
|
||||
{/* Identity */}
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
|
||||
|
||||
@@ -69,6 +69,9 @@ const mapLookupOption = (item: any) => ({
|
||||
|
||||
const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) => o.label }
|
||||
|
||||
const toFormString = (value: unknown): string =>
|
||||
value == null ? "" : String(value)
|
||||
|
||||
function mapToFormValues(data: unknown): VehicleFormValues {
|
||||
const d = (data as any)?.data ?? data ?? {}
|
||||
|
||||
@@ -79,16 +82,16 @@ function mapToFormValues(data: unknown): VehicleFormValues {
|
||||
vehicle_transmission_id: toRelation(d.vehicle_transmission_id, d.vehicle_transmission?.title),
|
||||
vehicle_color_id: toRelation(d.vehicle_color_id, d.vehicle_color?.title),
|
||||
customer_id: toRelation(d.customer_id, d.customer?.name),
|
||||
make: d.make || "",
|
||||
model: d.model || "",
|
||||
year: d.year || "",
|
||||
sub_model: d.sub_model || "",
|
||||
license_plate: d.license_plate || "",
|
||||
vin_number: d.vin_number || "",
|
||||
engine_size: d.engine_size || "",
|
||||
drivetrain: d.drivetrain || "",
|
||||
mileage: d.mileage || "",
|
||||
note: d.note || "",
|
||||
make: toFormString(d.make),
|
||||
model: toFormString(d.model),
|
||||
year: toFormString(d.year),
|
||||
sub_model: toFormString(d.sub_model),
|
||||
license_plate: toFormString(d.license_plate),
|
||||
vin_number: toFormString(d.vin_number),
|
||||
engine_size: toFormString(d.engine_size),
|
||||
drivetrain: toFormString(d.drivetrain),
|
||||
mileage: toFormString(d.mileage),
|
||||
note: toFormString(d.note),
|
||||
image: null,
|
||||
}
|
||||
}
|
||||
@@ -121,7 +124,7 @@ function mapToPayload(values: VehicleFormValues) {
|
||||
export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormProps) {
|
||||
const api = useAuthApi()
|
||||
|
||||
const { form, isEditing } = useResourceForm<VehicleFormValues, any>({
|
||||
const { form, isEditing, data: resolvedData } = useResourceForm<VehicleFormValues, any>({
|
||||
schema: vehicleFormSchema,
|
||||
defaultValues: DEFAULT_VALUES,
|
||||
resourceId,
|
||||
@@ -131,6 +134,9 @@ export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormP
|
||||
mapToFormValues,
|
||||
})
|
||||
|
||||
const existingImageUrl: string | null =
|
||||
(resolvedData as any)?.data?.image_url ?? (resolvedData as any)?.image_url ?? null
|
||||
|
||||
const { mutate, error, isPending } = useFormMutation(form, {
|
||||
mutationFn: (values: VehicleFormValues) => {
|
||||
const payload = mapToPayload(values)
|
||||
@@ -260,7 +266,11 @@ export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormP
|
||||
<RhfTextField name="mileage" label="Mileage" placeholder="e.g. 10000" />
|
||||
</div>
|
||||
|
||||
<RhfImageField name="image" label="Image" />
|
||||
<RhfImageField
|
||||
name="image"
|
||||
label="Image"
|
||||
initialPreviewUrl={existingImageUrl}
|
||||
/>
|
||||
|
||||
<RhfTextareaField name="note" label="Notes" rows={3} />
|
||||
|
||||
|
||||
Reference in New Issue
Block a user