fix(dashboard): resolve tutorial QA notes (clips 2–6)
- settings/company: show success toast on save (2.1) - inspection templates: add explicit Save button (2.6) - parts: label price fields with AED currency (3.1) - service groups: add parts/services picker to packages (3.3) - vehicles: add insurance (has_insurance + insurance type) field (4.2) - appointments: add calendar view with list/calendar toggle (5.1) - job card check-in: require department (5.4) - job card payments: refresh job card/invoice queries so PAID shows (5.6) - vendors: add phone + address fields (6.1) - bill payments: surface real vendor/employee validation errors (6.4) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
||||
RhfTextField,
|
||||
RhfTextareaField,
|
||||
RhfAsyncSelectField,
|
||||
RhfCheckboxField,
|
||||
RhfImageField,
|
||||
} from "@/shared/components/form"
|
||||
import { ShopTypeInlineForm } from "./inline-forms/shop-type-inline-form"
|
||||
@@ -24,7 +25,7 @@ import { useResourceForm } from "@/shared/hooks/use-resource-form"
|
||||
import { useFormMutation } from "@/shared/hooks/use-form-mutation"
|
||||
import { toRelation, toId } from "@/shared/lib/utils"
|
||||
import { formatUppercase } from "@/shared/utils/formatters"
|
||||
import { VEHICLE_ROUTES } from "@garage/api"
|
||||
import { VEHICLE_ROUTES, INSURANCE_TYPE_ROUTES } from "@garage/api"
|
||||
|
||||
import { vehicleFormSchema, type VehicleFormValues } from "./vehicle.schema"
|
||||
import { CustomerForm } from "../customers/customer-form"
|
||||
@@ -57,6 +58,8 @@ const DEFAULT_VALUES: VehicleFormValues = {
|
||||
drivetrain: "",
|
||||
mileage: "",
|
||||
note: "",
|
||||
has_insurance: false,
|
||||
insurance_type: null,
|
||||
image: null,
|
||||
}
|
||||
|
||||
@@ -92,6 +95,8 @@ function mapToFormValues(data: unknown): VehicleFormValues {
|
||||
drivetrain: toFormString(d.drivetrain),
|
||||
mileage: toFormString(d.mileage),
|
||||
note: toFormString(d.note),
|
||||
has_insurance: Boolean(d.has_insurance),
|
||||
insurance_type: toRelation(d.insurance_type_id, d.insurance_type?.title),
|
||||
image: null,
|
||||
}
|
||||
}
|
||||
@@ -115,6 +120,8 @@ function mapToPayload(values: VehicleFormValues) {
|
||||
drivetrain: values.drivetrain || undefined,
|
||||
mileage: values.mileage || undefined,
|
||||
note: values.note || undefined,
|
||||
has_insurance: values.has_insurance ?? false,
|
||||
insurance_type_id: values.has_insurance ? toId(values.insurance_type) : undefined,
|
||||
image: values.image instanceof File ? values.image : undefined,
|
||||
}
|
||||
}
|
||||
@@ -137,6 +144,8 @@ export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormP
|
||||
const existingImageUrl: string | null =
|
||||
(resolvedData as any)?.data?.image_url ?? (resolvedData as any)?.image_url ?? null
|
||||
|
||||
const hasInsurance = form.watch("has_insurance")
|
||||
|
||||
const { mutate, error, isPending } = useFormMutation(form, {
|
||||
mutationFn: (values: VehicleFormValues) => {
|
||||
const payload = mapToPayload(values)
|
||||
@@ -254,6 +263,24 @@ export function VehicleForm({ resourceId, initialData, onSuccess }: VehicleFormP
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Insurance */}
|
||||
<div className="border-t pt-4">
|
||||
<RhfCheckboxField name="has_insurance" label="Has Insurance?" />
|
||||
{hasInsurance && (
|
||||
<div className="mt-4">
|
||||
<RhfAsyncSelectField
|
||||
name="insurance_type"
|
||||
label="Insurance Type"
|
||||
placeholder="Select insurance type (e.g. Comprehensive)"
|
||||
queryKey={[INSURANCE_TYPE_ROUTES.INDEX]}
|
||||
listFn={() => api.insuranceTypes.list()}
|
||||
mapOption={mapLookupOption}
|
||||
{...STORE_OBJECT}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* License & identifiers */}
|
||||
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<RhfTextField
|
||||
|
||||
@@ -31,6 +31,10 @@ export const vehicleFormSchema = z.object({
|
||||
// ── Notes ──
|
||||
note: z.string().optional(),
|
||||
|
||||
// ── Insurance ──
|
||||
has_insurance: z.boolean().optional(),
|
||||
insurance_type: relationFieldSchema.optional(),
|
||||
|
||||
// ── Image ──
|
||||
image: z.any().optional(),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user