fix: add staleTime to job card expense, parts, and services queries; update job card general info and payments received components

This commit is contained in:
2026-05-13 17:20:59 +04:00
parent 6b356d2855
commit 05b55b5721
12 changed files with 174 additions and 91 deletions
@@ -5,7 +5,8 @@ import { AlertTriangle, Plus, Save } from "lucide-react"
import { Button } from "@/shared/components/ui/button"
import { Alert, AlertTitle } from "@/shared/components/ui/alert"
import { FieldGroup } from "@/shared/components/ui/field"
import { Field, FieldGroup, FieldLabel } from "@/shared/components/ui/field"
import { Input } from "@/shared/components/ui/input"
import {
Rhform,
RhfTextField,
@@ -36,6 +37,8 @@ export type PaymentReceivedFormProps = {
invoiceId?: string | null
invoiceCustomer?: { id?: number | null; first_name?: string | null; last_name?: string | null } | null
invoiceAmount?: number | string | null
lockJobCard?: boolean
lockCustomer?: boolean
}
// ── Default values ──
@@ -90,27 +93,33 @@ const STORE_OBJECT = { getOptionValue: (o: any) => o, getOptionLabel: (o: any) =
// ── Component ──
export function PaymentReceivedForm({ resourceId, initialData, onSuccess, defaultJobCard, invoiceId, invoiceCustomer, invoiceAmount }: PaymentReceivedFormProps) {
export function PaymentReceivedForm({ resourceId, initialData, onSuccess, defaultJobCard, invoiceId, invoiceCustomer, invoiceAmount, lockJobCard, lockCustomer }: PaymentReceivedFormProps) {
const api = useAuthApi()
const isJobCardLocked = !resourceId && (lockJobCard ?? !!defaultJobCard?.id)
const isCustomerLocked = !resourceId && (lockCustomer ?? !!invoiceCustomer?.id)
const customerLabel = invoiceCustomer?.first_name
? `${invoiceCustomer.first_name} ${invoiceCustomer.last_name || ""}`.trim()
: (invoiceCustomer as any)?.company_name || (invoiceCustomer as any)?.name || ""
const resolvedInitialData = useMemo(() => {
const base: any = { ...(initialData as any) }
if (!resourceId) {
if (defaultJobCard?.id != null) {
base.job_card = toRelation(defaultJobCard.id, defaultJobCard.title ?? undefined)
base.job_card_id = defaultJobCard.id
base.job_card_name = defaultJobCard.title ?? undefined
}
if (invoiceCustomer?.id != null) {
const customerLabel = invoiceCustomer.first_name
? `${invoiceCustomer.first_name} ${invoiceCustomer.last_name || ""}`.trim()
: (invoiceCustomer as any).company_name || (invoiceCustomer as any).name || undefined
base.customer = toRelation(invoiceCustomer.id, customerLabel)
base.customer_id = invoiceCustomer.id
base.customer_name = customerLabel
}
if (invoiceAmount != null && invoiceAmount !== "") {
base.amount_received = Number(invoiceAmount)
}
}
return Object.keys(base).length ? base : initialData
}, [resourceId, defaultJobCard, initialData, invoiceCustomer, invoiceAmount])
}, [resourceId, defaultJobCard, initialData, invoiceCustomer, invoiceAmount, customerLabel])
const { form, isEditing } = useResourceForm<PaymentReceivedFormValues, any>({
schema: paymentReceivedFormSchema,
@@ -153,33 +162,49 @@ export function PaymentReceivedForm({ resourceId, initialData, onSuccess, defaul
<FieldGroup>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<RhfAsyncSelectField
name="customer"
label="Customer"
placeholder="Select customer"
required
queryKey={[CUSTOMER_ROUTES.INDEX]}
listFn={() => api.customers.list()}
mapOption={(item: any) => ({
value: String(item.id),
label: item.first_name
? `${item.first_name} ${item.last_name || ""}`.trim()
: item.name || `#${item.id}`,
})}
{...STORE_OBJECT}
/>
<RhfAsyncSelectField
name="job_card"
label="Job Card"
placeholder="Select job card"
queryKey={[JOB_CARD_ROUTES.INDEX]}
listFn={() => api.jobCards.list()}
mapOption={(item: any) => ({
value: String(item.id),
label: item.title,
})}
{...STORE_OBJECT}
/>
{isCustomerLocked ? (
<Field>
<FieldLabel>
Customer<span className="text-destructive ms-0.5">*</span>
</FieldLabel>
<Input value={customerLabel} readOnly disabled />
</Field>
) : (
<RhfAsyncSelectField
name="customer"
label="Customer"
placeholder="Select customer"
required
queryKey={[CUSTOMER_ROUTES.INDEX]}
listFn={() => api.customers.list()}
mapOption={(item: any) => ({
value: String(item.id),
label: item.first_name
? `${item.first_name} ${item.last_name || ""}`.trim()
: item.name || `#${item.id}`,
})}
{...STORE_OBJECT}
/>
)}
{isJobCardLocked ? (
<Field>
<FieldLabel>Job Card</FieldLabel>
<Input value={defaultJobCard?.title ?? ""} readOnly disabled />
</Field>
) : (
<RhfAsyncSelectField
name="job_card"
label="Job Card"
placeholder="Select job card"
queryKey={[JOB_CARD_ROUTES.INDEX]}
listFn={() => api.jobCards.list()}
mapOption={(item: any) => ({
value: String(item.id),
label: item.title,
})}
{...STORE_OBJECT}
/>
)}
</div>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">