updates
This commit is contained in:
parent
c47f7c1b6a
commit
38ef10da4d
@ -58,11 +58,11 @@ export default function JobCardsPage() {
|
|||||||
title: "Job Cards",
|
title: "Job Cards",
|
||||||
actions: (
|
actions: (
|
||||||
<FormDialog classNames={{ dialogContent: 'min-w-6xl' }} title="Job Card" >
|
<FormDialog classNames={{ dialogContent: 'min-w-6xl' }} title="Job Card" >
|
||||||
{(resourceId) => (
|
{(resourceId, {close}) => (
|
||||||
<JobCardForm
|
<JobCardForm
|
||||||
resourceId={resourceId}
|
resourceId={resourceId}
|
||||||
initialData={selectedItem}
|
initialData={selectedItem}
|
||||||
onSuccess={invalidateQuery}
|
onSuccess={()=>{ invalidateQuery(); close();}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</FormDialog>
|
</FormDialog>
|
||||||
|
|||||||
@ -55,9 +55,9 @@ export function LoginForm({
|
|||||||
|
|
||||||
const { mutate, error, isPending: isSubmitting } = useMutation({
|
const { mutate, error, isPending: isSubmitting } = useMutation({
|
||||||
mutationFn: (values: LoginFormValues) => api.auth.login(values),
|
mutationFn: (values: LoginFormValues) => api.auth.login(values),
|
||||||
onSuccess: async (data) => {
|
onSuccess: async (data:any) => {
|
||||||
if (data.data?.token && data.data?.user) {
|
if (data.token && data.user) {
|
||||||
await login(data.data.token, data.data.user as Parameters<typeof login>[1])
|
await login(data.token, data.user as Parameters<typeof login>[1])
|
||||||
router.push("/")
|
router.push("/")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
159
apps/dashboard/modules/job-cards/job-card-check-in-dialog.tsx
Normal file
159
apps/dashboard/modules/job-cards/job-card-check-in-dialog.tsx
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { z } from "zod"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
|
import { toast } from "sonner"
|
||||||
|
import { useAuthApi } from "@/shared/useApi"
|
||||||
|
import {
|
||||||
|
Rhform,
|
||||||
|
RhfTextField,
|
||||||
|
RhfSelectField,
|
||||||
|
RhfDateField,
|
||||||
|
RhfTimeField,
|
||||||
|
RhfAsyncSelectField,
|
||||||
|
} from "@/shared/components/form"
|
||||||
|
import { FieldGroup } from "@/shared/components/ui/field"
|
||||||
|
import { Button } from "@/shared/components/ui/button"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/shared/components/ui/dialog"
|
||||||
|
import { DEPARTMENT_ROUTES } from "@garage/api"
|
||||||
|
import { FUEL_LEVEL_OPTIONS } from "./job-card.schema"
|
||||||
|
import { toId } from "@/shared/lib/utils"
|
||||||
|
|
||||||
|
// ── Schema ──
|
||||||
|
|
||||||
|
const checkInSchema = z.object({
|
||||||
|
check_in_date: z.string().optional(),
|
||||||
|
check_in_time: z.string().optional(),
|
||||||
|
km_in: z.string().optional(),
|
||||||
|
fuel_level: z.string().optional(),
|
||||||
|
start_date: z.string().optional(),
|
||||||
|
start_time: z.string().optional(),
|
||||||
|
department: z.object({ value: z.any(), label: z.string() }).nullable().optional(),
|
||||||
|
delivery_date: z.string().optional(),
|
||||||
|
delivery_time: z.string().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
type CheckInFormValues = z.infer<typeof checkInSchema>
|
||||||
|
|
||||||
|
const mapLookupOption = (item: any) => ({
|
||||||
|
value: String(item.id),
|
||||||
|
label: item.name,
|
||||||
|
})
|
||||||
|
|
||||||
|
const STORE_OBJECT = { storeObject: true } as const
|
||||||
|
|
||||||
|
// ── Props ──
|
||||||
|
|
||||||
|
type JobCardCheckInDialogProps = {
|
||||||
|
jobCardId: string
|
||||||
|
open: boolean
|
||||||
|
onOpenChange: (open: boolean) => void
|
||||||
|
onSuccess?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Component ──
|
||||||
|
|
||||||
|
export function JobCardCheckInDialog({
|
||||||
|
jobCardId,
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
onSuccess,
|
||||||
|
}: JobCardCheckInDialogProps) {
|
||||||
|
const api = useAuthApi()
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const todayStr = now.toISOString().split("T")[0]
|
||||||
|
const currentTime = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}`
|
||||||
|
|
||||||
|
const form = useForm<CheckInFormValues>({
|
||||||
|
resolver: zodResolver(checkInSchema),
|
||||||
|
defaultValues: {
|
||||||
|
check_in_date: todayStr,
|
||||||
|
check_in_time: currentTime,
|
||||||
|
km_in: "",
|
||||||
|
fuel_level: "",
|
||||||
|
start_date: "",
|
||||||
|
start_time: "",
|
||||||
|
department: null,
|
||||||
|
delivery_date: "",
|
||||||
|
delivery_time: "",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleSubmit = async (values: CheckInFormValues) => {
|
||||||
|
try {
|
||||||
|
await api.jobCards.checkIn(jobCardId, {
|
||||||
|
check_in_date: values.check_in_date || undefined,
|
||||||
|
check_in_time: values.check_in_time || undefined,
|
||||||
|
km_in: values.km_in ? Number(values.km_in) : undefined,
|
||||||
|
fuel_level: values.fuel_level || undefined,
|
||||||
|
start_date: values.start_date || undefined,
|
||||||
|
start_time: values.start_time || undefined,
|
||||||
|
department_id: values.department ? Number(toId(values.department)) : undefined,
|
||||||
|
delivery_date: values.delivery_date || undefined,
|
||||||
|
delivery_time: values.delivery_time || undefined,
|
||||||
|
})
|
||||||
|
toast.success("Job card checked in successfully")
|
||||||
|
form.reset()
|
||||||
|
onSuccess?.()
|
||||||
|
} catch {
|
||||||
|
toast.error("Failed to check in job card")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="min-w-xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="text-2xl font-bold">Check In</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<Rhform form={form} onSubmit={handleSubmit}>
|
||||||
|
<FieldGroup>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfDateField name="check_in_date" label="Check-in Date" />
|
||||||
|
<RhfTimeField name="check_in_time" label="Check-in Time" />
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfTextField name="km_in" label="KM In" type="number" placeholder="e.g. 50321" />
|
||||||
|
<RhfSelectField name="fuel_level" label="Fuel Level" options={FUEL_LEVEL_OPTIONS} />
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfDateField name="start_date" label="Start Date" />
|
||||||
|
<RhfTimeField name="start_time" label="Start Time" />
|
||||||
|
</div>
|
||||||
|
<RhfAsyncSelectField
|
||||||
|
name="department"
|
||||||
|
label="Department"
|
||||||
|
placeholder="Select department"
|
||||||
|
queryKey={[DEPARTMENT_ROUTES.INDEX]}
|
||||||
|
listFn={() => api.departments.list()}
|
||||||
|
mapOption={(op:any)=> ({value: op.id, label: op.name})}
|
||||||
|
{...STORE_OBJECT}
|
||||||
|
getOptionLabel={op=>op.label}
|
||||||
|
getOptionValue={op=>op}
|
||||||
|
|
||||||
|
/>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfDateField name="delivery_date" label="Delivery Date" />
|
||||||
|
<RhfTimeField name="delivery_time" label="Delivery Time" />
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" disabled={form.formState.isSubmitting}>
|
||||||
|
{form.formState.isSubmitting ? "Checking in..." : "Check In"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FieldGroup>
|
||||||
|
</Rhform>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
139
apps/dashboard/modules/job-cards/job-card-delivery-dialog.tsx
Normal file
139
apps/dashboard/modules/job-cards/job-card-delivery-dialog.tsx
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import { z } from "zod"
|
||||||
|
import { useForm } from "react-hook-form"
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod"
|
||||||
|
import { toast } from "sonner"
|
||||||
|
import { useAuthApi } from "@/shared/useApi"
|
||||||
|
import {
|
||||||
|
Rhform,
|
||||||
|
RhfTextField,
|
||||||
|
RhfSelectField,
|
||||||
|
RhfDateField,
|
||||||
|
RhfTimeField,
|
||||||
|
RhfAsyncSelectField,
|
||||||
|
} from "@/shared/components/form"
|
||||||
|
import { FieldGroup } from "@/shared/components/ui/field"
|
||||||
|
import { Button } from "@/shared/components/ui/button"
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
} from "@/shared/components/ui/dialog"
|
||||||
|
import { DEPARTMENT_ROUTES } from "@garage/api"
|
||||||
|
import { FUEL_LEVEL_OPTIONS } from "./job-card.schema"
|
||||||
|
import { toId } from "@/shared/lib/utils"
|
||||||
|
|
||||||
|
// ── Schema ──
|
||||||
|
|
||||||
|
const deliverySchema = z.object({
|
||||||
|
check_out_date: z.string().optional(),
|
||||||
|
check_out_time: z.string().optional(),
|
||||||
|
km_out: z.string().optional(),
|
||||||
|
fuel_level: z.string().optional(),
|
||||||
|
department: z.object({ value: z.number(), label: z.string() }).nullable().optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
type DeliveryFormValues = z.infer<typeof deliverySchema>
|
||||||
|
|
||||||
|
const mapLookupOption = (item: any) => ({
|
||||||
|
value: String(item.id),
|
||||||
|
label: item.name,
|
||||||
|
})
|
||||||
|
|
||||||
|
const STORE_OBJECT = { storeObject: true } as const
|
||||||
|
|
||||||
|
// ── Props ──
|
||||||
|
|
||||||
|
type JobCardDeliveryDialogProps = {
|
||||||
|
jobCardId: string
|
||||||
|
open: boolean
|
||||||
|
onOpenChange: (open: boolean) => void
|
||||||
|
onSuccess?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Component ──
|
||||||
|
|
||||||
|
export function JobCardDeliveryDialog({
|
||||||
|
jobCardId,
|
||||||
|
open,
|
||||||
|
onOpenChange,
|
||||||
|
onSuccess,
|
||||||
|
}: JobCardDeliveryDialogProps) {
|
||||||
|
const api = useAuthApi()
|
||||||
|
|
||||||
|
const now = new Date()
|
||||||
|
const todayStr = now.toISOString().split("T")[0]
|
||||||
|
const currentTime = `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}:${String(now.getSeconds()).padStart(2, "0")}`
|
||||||
|
|
||||||
|
const form = useForm<DeliveryFormValues>({
|
||||||
|
resolver: zodResolver(deliverySchema),
|
||||||
|
defaultValues: {
|
||||||
|
check_out_date: todayStr,
|
||||||
|
check_out_time: currentTime,
|
||||||
|
km_out: "",
|
||||||
|
fuel_level: "",
|
||||||
|
department: null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleSubmit = async (values: DeliveryFormValues) => {
|
||||||
|
try {
|
||||||
|
await api.jobCards.delivery(jobCardId, {
|
||||||
|
check_out_date: values.check_out_date || undefined,
|
||||||
|
check_out_time: values.check_out_time || undefined,
|
||||||
|
km_out: values.km_out ? Number(values.km_out) : undefined,
|
||||||
|
fuel_level: values.fuel_level || undefined,
|
||||||
|
department_id: values.department ? Number(toId(values.department as any)) : undefined,
|
||||||
|
})
|
||||||
|
toast.success("Job card marked as delivered successfully")
|
||||||
|
form.reset()
|
||||||
|
onSuccess?.()
|
||||||
|
} catch {
|
||||||
|
toast.error("Failed to mark job card as delivered")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="min-w-xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="text-2xl font-bold">Delivery</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<Rhform form={form} onSubmit={handleSubmit}>
|
||||||
|
<FieldGroup>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfDateField name="check_out_date" label="Check-out Date" />
|
||||||
|
<RhfTimeField name="check_out_time" label="Check-out Time" />
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||||
|
<RhfTextField name="km_out" label="KM Out" type="number" placeholder="e.g. 50480" />
|
||||||
|
<RhfSelectField name="fuel_level" label="Fuel Level" options={FUEL_LEVEL_OPTIONS} />
|
||||||
|
</div>
|
||||||
|
<RhfAsyncSelectField
|
||||||
|
name="department"
|
||||||
|
label="Department"
|
||||||
|
placeholder="Select department"
|
||||||
|
queryKey={[DEPARTMENT_ROUTES.INDEX]}
|
||||||
|
listFn={() => api.departments.list()}
|
||||||
|
mapOption={(op: any) => ({ value: op.id, label: op.name })}
|
||||||
|
{...STORE_OBJECT}
|
||||||
|
getOptionLabel={op => op.label}
|
||||||
|
getOptionValue={op => op}
|
||||||
|
|
||||||
|
/>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" disabled={form.formState.isSubmitting}>
|
||||||
|
{form.formState.isSubmitting ? "Delivering..." : "Mark as Delivered"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</FieldGroup>
|
||||||
|
</Rhform>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -28,6 +28,7 @@ import { CrudShowResponse, JobCardsClient, PAYMENT_RECEIVED_ROUTES, PaymentRecei
|
|||||||
import { ResourcePage } from "@/shared/data-view/resource-page"
|
import { ResourcePage } from "@/shared/data-view/resource-page"
|
||||||
import PaymentReceivedPage from "@/app/(authenticated)/sales/payment-received/page"
|
import PaymentReceivedPage from "@/app/(authenticated)/sales/payment-received/page"
|
||||||
import JobCardPaymentsReceived from "./job-card-payments-received"
|
import JobCardPaymentsReceived from "./job-card-payments-received"
|
||||||
|
import { formatDate } from "@/shared/utils/formatters"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -116,7 +117,7 @@ export function JobCardGeneralInfo({ jobCard }: { jobCard: JobCard }) {
|
|||||||
<InfoItem
|
<InfoItem
|
||||||
icon={Calendar}
|
icon={Calendar}
|
||||||
label="Check-in Date"
|
label="Check-in Date"
|
||||||
value={jobCard.check_in_date}
|
value={formatDate(jobCard.check_in_date)}
|
||||||
/>
|
/>
|
||||||
<InfoItem
|
<InfoItem
|
||||||
icon={Gauge}
|
icon={Gauge}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
|
import { useState } from "react"
|
||||||
import { useMutation } from "@tanstack/react-query"
|
import { useMutation } from "@tanstack/react-query"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import { cn } from "@/shared/lib/utils"
|
import { cn } from "@/shared/lib/utils"
|
||||||
@ -20,6 +21,8 @@ import {
|
|||||||
PackageCheck,
|
PackageCheck,
|
||||||
CheckCircle2,
|
CheckCircle2,
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
import { JobCardCheckInDialog } from "./job-card-check-in-dialog"
|
||||||
|
import { JobCardDeliveryDialog } from "./job-card-delivery-dialog"
|
||||||
|
|
||||||
// ── Status icon mapping ──
|
// ── Status icon mapping ──
|
||||||
|
|
||||||
@ -45,6 +48,9 @@ export function JobCardStatusStepper({ jobCardId }: JobCardStatusStepperProps) {
|
|||||||
|
|
||||||
const currentIndex = JOB_CARD_STATUSES.findIndex((s) => s.value === currentStatus)
|
const currentIndex = JOB_CARD_STATUSES.findIndex((s) => s.value === currentStatus)
|
||||||
|
|
||||||
|
const [checkInOpen, setCheckInOpen] = useState(false)
|
||||||
|
const [deliveryOpen, setDeliveryOpen] = useState(false)
|
||||||
|
|
||||||
const { mutate, isPending, variables } = useMutation({
|
const { mutate, isPending, variables } = useMutation({
|
||||||
mutationFn: async (status: JobCardStatus) => {
|
mutationFn: async (status: JobCardStatus) => {
|
||||||
const promise = api.jobCards.changeStatus(jobCardId, { status })
|
const promise = api.jobCards.changeStatus(jobCardId, { status })
|
||||||
@ -60,9 +66,17 @@ export function JobCardStatusStepper({ jobCardId }: JobCardStatusStepperProps) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleClick = (status: JobCardStatus, index: number) => {
|
const handleClick = (status: JobCardStatus) => {
|
||||||
if (isPending) return
|
if (isPending) return
|
||||||
if (status === currentStatus) return
|
if (status === currentStatus) return
|
||||||
|
if (status === "check_in") {
|
||||||
|
setCheckInOpen(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (status === "delivered") {
|
||||||
|
setDeliveryOpen(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
mutate(status)
|
mutate(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +96,7 @@ export function JobCardStatusStepper({ jobCardId }: JobCardStatusStepperProps) {
|
|||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => handleClick(step.value, index)}
|
onClick={() => handleClick(step.value)}
|
||||||
disabled={!isClickable}
|
disabled={!isClickable}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all",
|
"relative flex items-center gap-2 rounded-full px-4 py-2 text-sm font-medium transition-all",
|
||||||
@ -120,6 +134,26 @@ export function JobCardStatusStepper({ jobCardId }: JobCardStatusStepperProps) {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<JobCardCheckInDialog
|
||||||
|
jobCardId={jobCardId}
|
||||||
|
open={checkInOpen}
|
||||||
|
onOpenChange={setCheckInOpen}
|
||||||
|
onSuccess={() => {
|
||||||
|
setCheckInOpen(false)
|
||||||
|
;(jobCard as any)?.setStatus("check_in")
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<JobCardDeliveryDialog
|
||||||
|
jobCardId={jobCardId}
|
||||||
|
open={deliveryOpen}
|
||||||
|
onOpenChange={setDeliveryOpen}
|
||||||
|
onSuccess={() => {
|
||||||
|
setDeliveryOpen(false)
|
||||||
|
;(jobCard as any)?.setStatus("delivered")
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,7 +59,9 @@ export function useFormDialog(paramKey?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function FormDialog(props: {
|
export default function FormDialog(props: {
|
||||||
children: (resourceId: string | null) => React.ReactNode
|
children: (resourceId: string | null,
|
||||||
|
ctx: { open: (resourceId?: string) => void, close: () => void,isOpen:boolean }
|
||||||
|
) => React.ReactNode
|
||||||
title: string
|
title: string
|
||||||
paramKey?: string
|
paramKey?: string
|
||||||
classNames?: {
|
classNames?: {
|
||||||
@ -85,7 +87,7 @@ export default function FormDialog(props: {
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ScrollArea className={`max-h-[80vh] px-4 ${cn(props.classNames?.scrollArea)}`}>
|
<ScrollArea className={`max-h-[80vh] px-4 ${cn(props.classNames?.scrollArea)}`}>
|
||||||
{props.children(resourceId)}
|
{props.children(resourceId, { open, close , isOpen})}
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|||||||
@ -24549,6 +24549,255 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/api/job-cards/{id}/check-in": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Job Cards"
|
||||||
|
],
|
||||||
|
"summary": "POST /api/job-cards/{id}/check-in",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"check_in_date": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_in_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"km_in": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"fuel_level": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start_date": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"department_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"delivery_date": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"delivery_time": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"check_in_date": "2026-04-07",
|
||||||
|
"check_in_time": "09:30",
|
||||||
|
"km_in": 50321,
|
||||||
|
"fuel_level": "half",
|
||||||
|
"start_date": "2026-04-07",
|
||||||
|
"start_time": "10:00",
|
||||||
|
"department_id": 1,
|
||||||
|
"delivery_date": "2026-04-08",
|
||||||
|
"delivery_time": "17:15"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_in_date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"check_in_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"km_in": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"fuel_level": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"start_date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"start_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"department_id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"delivery_date": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time"
|
||||||
|
},
|
||||||
|
"delivery_time": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"message": "Job card checked in successfully.",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"status": "check_in",
|
||||||
|
"check_in_date": "2026-04-07T00:00:00.000000Z",
|
||||||
|
"check_in_time": "09:30:00",
|
||||||
|
"km_in": 50321,
|
||||||
|
"fuel_level": "half",
|
||||||
|
"start_date": "2026-04-07T00:00:00.000000Z",
|
||||||
|
"start_time": "10:00:00",
|
||||||
|
"department_id": 1,
|
||||||
|
"delivery_date": "2026-04-08T00:00:00.000000Z",
|
||||||
|
"delivery_time": "17:15:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/api/job-cards/{id}/delivery": {
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"Job Cards"
|
||||||
|
],
|
||||||
|
"summary": "POST /api/job-cards/{id}/delivery",
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"check_out_date": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_out_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"km_out": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"fuel_level": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"department_id": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"check_out_date": "2026-04-08",
|
||||||
|
"check_out_time": "17:15",
|
||||||
|
"km_out": 50480,
|
||||||
|
"fuel_level": "quarter",
|
||||||
|
"department_id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_out_date": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"check_out_time": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"km_out": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"fuel_level": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"department_id": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"message": "Job card marked as delivered successfully.",
|
||||||
|
"data": {
|
||||||
|
"id": 1,
|
||||||
|
"status": "delivered",
|
||||||
|
"check_out_date": "2026-04-08",
|
||||||
|
"check_out_time": "17:15:00",
|
||||||
|
"km_out": 50480,
|
||||||
|
"fuel_level": "quarter",
|
||||||
|
"department_id": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/api/job-cards/{id}/add-customer-remark": {
|
"/api/job-cards/{id}/add-customer-remark": {
|
||||||
"post": {
|
"post": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"info": {
|
"info": {
|
||||||
"_postman_id": "4fac95bb-3550-48ab-9943-212b6e3a11d8",
|
"_postman_id": "bf46649e-48e0-49d5-aa87-1790dcbc3c24",
|
||||||
"name": "Reparee Collection",
|
"name": "Reparee Collection",
|
||||||
"description": "Auto-generated from OpenAPI spec. Import storage/app/openapi-default.json for the full schema.",
|
"description": "Auto-generated from OpenAPI spec. Import storage/app/openapi-default.json for the full schema.",
|
||||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
|
||||||
@ -8025,7 +8025,7 @@
|
|||||||
"{{table}}"
|
"{{table}}"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"description": "Set {{table}} to job_cards or estimates. Returns next sequence like ORD-0001 or EST-0001."
|
"description": "Set {{table}} to any supported table with a number column. Explicit prefixes: job_cards=ORD-, estimates=EST-, invoices=INV-, purchase_orders=PO-, bills=BILL-, expenses=EXP-, tasks=TASK-, appointments=APPT-, services=SRV-, parts=PART-, expense_items=EXP-ITEM-, inspections=INS-. Returns next sequence like ORD-0001."
|
||||||
},
|
},
|
||||||
"response": [
|
"response": [
|
||||||
{
|
{
|
||||||
@ -16771,6 +16771,222 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/job-cards/{id}/check-in",
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{auth_token}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"check_in_date\": \"2026-04-07\",\n \"check_in_time\": \"09:30\",\n \"km_in\": 50321,\n \"fuel_level\": \"half\",\n \"start_date\": \"2026-04-07\",\n \"start_time\": \"10:00\",\n \"department_id\": 1,\n \"delivery_date\": \"2026-04-08\",\n \"delivery_time\": \"17:15\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{base_url}}/api/job-cards/{{id}}/check-in",
|
||||||
|
"host": [
|
||||||
|
"{{base_url}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"job-cards",
|
||||||
|
"{{id}}",
|
||||||
|
"check-in"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Marks job card as `check_in` and updates check-in context. Optional fields: `check_in_date`, `check_in_time` (HH:MM or HH:MM:SS), `km_in`, `fuel_level`, `start_date`, `start_time`, `department_id`, `delivery_date`, `delivery_time` (HH:MM or HH:MM:SS). If check-in date/time is omitted, server current date/time is used."
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "200 OK",
|
||||||
|
"originalRequest": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{auth_token}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"check_in_date\": \"2026-04-07\",\n \"check_in_time\": \"09:30\",\n \"km_in\": 50321,\n \"fuel_level\": \"half\",\n \"start_date\": \"2026-04-07\",\n \"start_time\": \"10:00\",\n \"department_id\": 1,\n \"delivery_date\": \"2026-04-08\",\n \"delivery_time\": \"17:15\"\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{base_url}}/api/job-cards/{{id}}/check-in",
|
||||||
|
"host": [
|
||||||
|
"{{base_url}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"job-cards",
|
||||||
|
"{{id}}",
|
||||||
|
"check-in"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"message\": \"Job card checked in successfully.\",\n \"data\": {\n \"id\": 1,\n \"status\": \"check_in\",\n \"check_in_date\": \"2026-04-07T00:00:00.000000Z\",\n \"check_in_time\": \"09:30:00\",\n \"km_in\": 50321,\n \"fuel_level\": \"half\",\n \"start_date\": \"2026-04-07T00:00:00.000000Z\",\n \"start_time\": \"10:00:00\",\n \"department_id\": 1,\n \"delivery_date\": \"2026-04-08T00:00:00.000000Z\",\n \"delivery_time\": \"17:15:00\"\n }\n}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "POST /api/job-cards/{id}/delivery",
|
||||||
|
"request": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{auth_token}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"check_out_date\": \"2026-04-08\",\n \"check_out_time\": \"17:15\",\n \"km_out\": 50480,\n \"fuel_level\": \"quarter\",\n \"department_id\": 1\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{base_url}}/api/job-cards/{{id}}/delivery",
|
||||||
|
"host": [
|
||||||
|
"{{base_url}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"job-cards",
|
||||||
|
"{{id}}",
|
||||||
|
"delivery"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"description": "Marks job card as `delivered` and updates delivery context. Optional fields: `check_out_date`, `check_out_time` (HH:MM or HH:MM:SS), `km_out`, `fuel_level`, `department_id`. If check-out date/time is omitted, server current date/time is used."
|
||||||
|
},
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"name": "200 OK",
|
||||||
|
"originalRequest": {
|
||||||
|
"auth": {
|
||||||
|
"type": "bearer",
|
||||||
|
"bearer": [
|
||||||
|
{
|
||||||
|
"key": "token",
|
||||||
|
"value": "{{auth_token}}",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Accept",
|
||||||
|
"value": "application/json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"body": {
|
||||||
|
"mode": "raw",
|
||||||
|
"raw": "{\n \"check_out_date\": \"2026-04-08\",\n \"check_out_time\": \"17:15\",\n \"km_out\": 50480,\n \"fuel_level\": \"quarter\",\n \"department_id\": 1\n}",
|
||||||
|
"options": {
|
||||||
|
"raw": {
|
||||||
|
"language": "json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"raw": "{{base_url}}/api/job-cards/{{id}}/delivery",
|
||||||
|
"host": [
|
||||||
|
"{{base_url}}"
|
||||||
|
],
|
||||||
|
"path": [
|
||||||
|
"api",
|
||||||
|
"job-cards",
|
||||||
|
"{{id}}",
|
||||||
|
"delivery"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"status": "OK",
|
||||||
|
"code": 200,
|
||||||
|
"_postman_previewlanguage": "json",
|
||||||
|
"header": [
|
||||||
|
{
|
||||||
|
"key": "Content-Type",
|
||||||
|
"value": "application/json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cookie": [],
|
||||||
|
"body": "{\n \"message\": \"Job card marked as delivered successfully.\",\n \"data\": {\n \"id\": 1,\n \"status\": \"delivered\",\n \"check_out_date\": \"2026-04-08\",\n \"check_out_time\": \"17:15:00\",\n \"km_out\": 50480,\n \"fuel_level\": \"quarter\",\n \"department_id\": 1\n }\n}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "POST /api/job-cards/{id}/add-customer-remark",
|
"name": "POST /api/job-cards/{id}/add-customer-remark",
|
||||||
"request": {
|
"request": {
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import { CrudClient } from "../infra/crud-client"
|
import { CrudClient } from "../infra/crud-client"
|
||||||
import type { ApiClientOptions } from "../infra/client"
|
import type { ApiClientOptions } from "../infra/client"
|
||||||
import type { ApiOperationResponse, ApiPath, ApiRequestBody, ApiResponse } from "../infra/types"
|
import type { ApiOperationResponse, ApiPath, ApiRequestBody, ApiResponse } from "../infra/types"
|
||||||
import { ApiBaseResponse } from "../contracts/types"
|
import { ApiBaseResponse } from "src/contracts/types"
|
||||||
|
|
||||||
export const JOB_CARD_ROUTES = {
|
export const JOB_CARD_ROUTES = {
|
||||||
INDEX: "/api/job-cards",
|
INDEX: "/api/job-cards",
|
||||||
BY_ID: "/api/job-cards/{id}",
|
BY_ID: "/api/job-cards/{id}",
|
||||||
CHANGE_DATE: "/api/job-cards/{id}/change-date",
|
CHANGE_DATE: "/api/job-cards/{id}/change-date",
|
||||||
CHANGE_STATUS: "/api/job-cards/{id}/change-status",
|
CHANGE_STATUS: "/api/job-cards/{id}/change-status",
|
||||||
|
CHECK_IN: "/api/job-cards/{id}/check-in",
|
||||||
|
DELIVERY: "/api/job-cards/{id}/delivery",
|
||||||
ADD_CUSTOMER_REMARK: "/api/job-cards/{id}/add-customer-remark",
|
ADD_CUSTOMER_REMARK: "/api/job-cards/{id}/add-customer-remark",
|
||||||
EDIT_CUSTOMER_REMARK: "/api/job-cards/{id}/edit-customer-remark",
|
EDIT_CUSTOMER_REMARK: "/api/job-cards/{id}/edit-customer-remark",
|
||||||
DELETE_CUSTOMER_REMARK: "/api/job-cards/{id}/delete-customer-remark",
|
DELETE_CUSTOMER_REMARK: "/api/job-cards/{id}/delete-customer-remark",
|
||||||
@ -53,6 +55,14 @@ export class JobCardsClient extends CrudClient<
|
|||||||
return this.post(JOB_CARD_ROUTES.CHANGE_STATUS, payload, { params: { id } })
|
return this.post(JOB_CARD_ROUTES.CHANGE_STATUS, payload, { params: { id } })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkIn(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CHECK_IN, "post">) {
|
||||||
|
return this.post(JOB_CARD_ROUTES.CHECK_IN, payload, { params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
|
async delivery(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.DELIVERY, "post">) {
|
||||||
|
return this.post(JOB_CARD_ROUTES.DELIVERY, payload, { params: { id } })
|
||||||
|
}
|
||||||
|
|
||||||
async addCustomerRemark(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, "post">) {
|
async addCustomerRemark(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, "post">) {
|
||||||
return this.post(JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, payload, { params: { id } })
|
return this.post(JOB_CARD_ROUTES.ADD_CUSTOMER_REMARK, payload, { params: { id } })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16105,6 +16105,189 @@ export interface paths {
|
|||||||
patch?: never;
|
patch?: never;
|
||||||
trace?: never;
|
trace?: never;
|
||||||
};
|
};
|
||||||
|
"/api/job-cards/{id}/check-in": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
get?: never;
|
||||||
|
put?: never;
|
||||||
|
/** POST /api/job-cards/{id}/check-in */
|
||||||
|
post: {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
/**
|
||||||
|
* @example {
|
||||||
|
* "check_in_date": "2026-04-07",
|
||||||
|
* "check_in_time": "09:30",
|
||||||
|
* "km_in": 50321,
|
||||||
|
* "fuel_level": "half",
|
||||||
|
* "start_date": "2026-04-07",
|
||||||
|
* "start_time": "10:00",
|
||||||
|
* "department_id": 1,
|
||||||
|
* "delivery_date": "2026-04-08",
|
||||||
|
* "delivery_time": "17:15"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
"application/json": {
|
||||||
|
check_in_date?: string;
|
||||||
|
check_in_time?: string;
|
||||||
|
km_in?: number;
|
||||||
|
fuel_level?: string;
|
||||||
|
start_date?: string;
|
||||||
|
start_time?: string;
|
||||||
|
department_id?: number;
|
||||||
|
delivery_date?: string;
|
||||||
|
delivery_time?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description OK */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
/**
|
||||||
|
* @example {
|
||||||
|
* "message": "Job card checked in successfully.",
|
||||||
|
* "data": {
|
||||||
|
* "id": 1,
|
||||||
|
* "status": "check_in",
|
||||||
|
* "check_in_date": "2026-04-07T00:00:00.000000Z",
|
||||||
|
* "check_in_time": "09:30:00",
|
||||||
|
* "km_in": 50321,
|
||||||
|
* "fuel_level": "half",
|
||||||
|
* "start_date": "2026-04-07T00:00:00.000000Z",
|
||||||
|
* "start_time": "10:00:00",
|
||||||
|
* "department_id": 1,
|
||||||
|
* "delivery_date": "2026-04-08T00:00:00.000000Z",
|
||||||
|
* "delivery_time": "17:15:00"
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
"application/json": {
|
||||||
|
message?: string;
|
||||||
|
data?: {
|
||||||
|
id?: number;
|
||||||
|
status?: string;
|
||||||
|
/** Format: date-time */
|
||||||
|
check_in_date?: string;
|
||||||
|
check_in_time?: string;
|
||||||
|
km_in?: number;
|
||||||
|
fuel_level?: string;
|
||||||
|
/** Format: date-time */
|
||||||
|
start_date?: string;
|
||||||
|
start_time?: string;
|
||||||
|
department_id?: number;
|
||||||
|
/** Format: date-time */
|
||||||
|
delivery_date?: string;
|
||||||
|
delivery_time?: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
|
"/api/job-cards/{id}/delivery": {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path?: never;
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
get?: never;
|
||||||
|
put?: never;
|
||||||
|
/** POST /api/job-cards/{id}/delivery */
|
||||||
|
post: {
|
||||||
|
parameters: {
|
||||||
|
query?: never;
|
||||||
|
header?: never;
|
||||||
|
path: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
cookie?: never;
|
||||||
|
};
|
||||||
|
requestBody: {
|
||||||
|
content: {
|
||||||
|
/**
|
||||||
|
* @example {
|
||||||
|
* "check_out_date": "2026-04-08",
|
||||||
|
* "check_out_time": "17:15",
|
||||||
|
* "km_out": 50480,
|
||||||
|
* "fuel_level": "quarter",
|
||||||
|
* "department_id": 1
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
"application/json": {
|
||||||
|
check_out_date?: string;
|
||||||
|
check_out_time?: string;
|
||||||
|
km_out?: number;
|
||||||
|
fuel_level?: string;
|
||||||
|
department_id?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
responses: {
|
||||||
|
/** @description OK */
|
||||||
|
200: {
|
||||||
|
headers: {
|
||||||
|
[name: string]: unknown;
|
||||||
|
};
|
||||||
|
content: {
|
||||||
|
/**
|
||||||
|
* @example {
|
||||||
|
* "message": "Job card marked as delivered successfully.",
|
||||||
|
* "data": {
|
||||||
|
* "id": 1,
|
||||||
|
* "status": "delivered",
|
||||||
|
* "check_out_date": "2026-04-08",
|
||||||
|
* "check_out_time": "17:15:00",
|
||||||
|
* "km_out": 50480,
|
||||||
|
* "fuel_level": "quarter",
|
||||||
|
* "department_id": 1
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
"application/json": {
|
||||||
|
message?: string;
|
||||||
|
data?: {
|
||||||
|
id?: number;
|
||||||
|
status?: string;
|
||||||
|
check_out_date?: string;
|
||||||
|
check_out_time?: string;
|
||||||
|
km_out?: number;
|
||||||
|
fuel_level?: string;
|
||||||
|
department_id?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
delete?: never;
|
||||||
|
options?: never;
|
||||||
|
head?: never;
|
||||||
|
patch?: never;
|
||||||
|
trace?: never;
|
||||||
|
};
|
||||||
"/api/job-cards/{id}/add-customer-remark": {
|
"/api/job-cards/{id}/add-customer-remark": {
|
||||||
parameters: {
|
parameters: {
|
||||||
query?: never;
|
query?: never;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user