import { CrudClient } from "../infra/crud-client" import type { ApiClientOptions } from "../infra/client" import type { ApiPath, ApiRequestBody } from "../infra/types" import type { ApiListQueryParams } from "../contracts/types" export const INSPECTION_ROUTES = { CATEGORIES: "/api/inspection-categories", CATEGORY_BY_ID: "/api/inspection-categories/{id}", INDEX: "/api/inspections", BY_ID: "/api/inspections/{id}", FROM_TEMPLATE: "/api/inspections/from-template", CHANGE_STATUS: "/api/change-inspection-status", CHECKPOINT_LABELS: "/api/check-point-label", CHECKPOINT_LABEL_BY_ID: "/api/check-point-label/{id}", CHECKPOINTS: "/api/inspection-check-points", CHECKPOINT_BY_ID: "/api/inspection-check-points/{id}", TOGGLE_LABEL_TO_CHECKPOINT: "/api/toggle-label-to-checkpoint", CHECKPOINT_CHANGE_STATUS: "/api/inspection-check-points/change-status", CHECKPOINT_ADD_ATTACHMENT: "/api/inspection-check-points/add-attachment", CHECKPOINT_UPLOAD_MEDIA: "/api/inspection-check-points/{id}/upload-media", CHECKPOINT_MEDIA: "/api/inspection-check-points/{id}/media", } as const satisfies Record export class InspectionsClient extends CrudClient< typeof INSPECTION_ROUTES.INDEX, typeof INSPECTION_ROUTES.BY_ID > { constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) { super(baseUrl, defaultOptions, INSPECTION_ROUTES.INDEX, INSPECTION_ROUTES.BY_ID) } // ── Categories ── async listCategories(query?: ApiListQueryParams) { return this.get(INSPECTION_ROUTES.CATEGORIES, query ? { query } as never : undefined) } async createCategory(payload: ApiRequestBody) { return this.post(INSPECTION_ROUTES.CATEGORIES, payload) } async updateCategory(id: string, payload: ApiRequestBody) { return this.put(INSPECTION_ROUTES.CATEGORY_BY_ID, payload, { params: { id } }) } async destroyCategory(id: string) { return this.delete(INSPECTION_ROUTES.CATEGORY_BY_ID, { params: { id } }) } async getById(id: string) { const res = await super.list({ query: { id } } as never) return {...res, data: res.data?.[0] } } async changeStatus(payload: ApiRequestBody) { return this.post(INSPECTION_ROUTES.CHANGE_STATUS, payload) } async showOne(id: number | string): Promise<{ data: any }> { return this.get(`/api/inspections/{id}` as never, { params: { id: String(id) } } as never) as never } async sign(id: number | string, who: "technician" | "customer", dataUrl: string) { return this.post(`/api/inspections/{id}/sign` as never, { who, signature: dataUrl } as never, { params: { id: String(id) } } as never) as never } /** * Upload one or many photos/videos/audio files to a checkpoint via the * unified attachments endpoint. The single-file `addCheckpointAttachment` * (body-based) above stays available for legacy callers. */ async uploadCheckpointAttachments( checkpointId: number | string, files: File[], caption?: string, ): Promise<{ data: Array<{ id: number; url: string; media_type: string; sort_order: number; caption?: string | null }> }> { const fd = new FormData() files.forEach((f) => fd.append("attachments[]", f)) if (caption) fd.append("caption", caption) const url = `/api/inspection-check-points/${encodeURIComponent(String(checkpointId))}/attachments` return (this as any).postFormData(url, fd) } async destroyCheckpointAttachment(checkpointId: number | string, attachmentId: number | string) { return this.delete( `/api/inspection-check-points/{id}/attachments/{attachmentId}` as never, { params: { id: String(checkpointId), attachmentId: String(attachmentId) } } as never, ) as never } async share(id: number | string): Promise<{ data: { share_token: string; share_url: string; share_enabled_at: string; share_expires_at: string } }> { return this.post(`/api/inspections/{id}/share` as never, undefined as never, { params: { id: String(id) } } as never) as never } async revokeShare(id: number | string): Promise<{ message: string }> { return this.post(`/api/inspections/{id}/revoke-share` as never, undefined as never, { params: { id: String(id) } } as never) as never } async createFromTemplate(payload: { template_id: number title: string customer_id: number | string vehicle_id: number | string department_id: number | string employee_id: number | string order_number: string date: string time: string odometer?: number note?: string inspection_category_id?: number | string }) { return this.post(INSPECTION_ROUTES.FROM_TEMPLATE as never, payload as never) as never } // ── Checkpoint Labels ── async listCheckpointLabels(query?: ApiListQueryParams) { return this.get(INSPECTION_ROUTES.CHECKPOINT_LABELS, query ? { query } as never : undefined) } async createCheckpointLabel(payload: ApiRequestBody) { return this.post(INSPECTION_ROUTES.CHECKPOINT_LABELS, payload) } async updateCheckpointLabel(id: string, payload: ApiRequestBody) { return this.put(INSPECTION_ROUTES.CHECKPOINT_LABEL_BY_ID, payload, { params: { id } }) } async destroyCheckpointLabel(id: string) { return this.delete(INSPECTION_ROUTES.CHECKPOINT_LABEL_BY_ID, { params: { id } }) } // ── Checkpoints ── async listCheckpoints(query?: ApiListQueryParams) { return this.get(INSPECTION_ROUTES.CHECKPOINTS, query ? { query } as never : undefined) } async createCheckpoint(payload: ApiRequestBody) { return this.post(INSPECTION_ROUTES.CHECKPOINTS, payload) } async updateCheckpoint(id: string, payload: ApiRequestBody) { return this.put(INSPECTION_ROUTES.CHECKPOINT_BY_ID, payload, { params: { id } }) } async destroyCheckpoint(id: string) { return this.delete(INSPECTION_ROUTES.CHECKPOINT_BY_ID, { params: { id } }) } async toggleLabelToCheckpoint(payload: ApiRequestBody) { return this.post(INSPECTION_ROUTES.TOGGLE_LABEL_TO_CHECKPOINT, payload) } async changeCheckpointStatus(payload: ApiRequestBody, ) { return this.post(INSPECTION_ROUTES.CHECKPOINT_CHANGE_STATUS, payload) } async addCheckpointAttachment(payload: Record) { const fd = new FormData() for (const [key, value] of Object.entries(payload)) { if (value == null) continue if (value instanceof File) { fd.append(key, value) } else { fd.append(key, String(value)) } } return this.postFormData(INSPECTION_ROUTES.CHECKPOINT_ADD_ATTACHMENT, fd) } async uploadCheckpointMedia(id: string, payload: Record) { const fd = new FormData() for (const [key, value] of Object.entries(payload)) { if (value == null) continue if (value instanceof File) { fd.append(key, value) } else { fd.append(key, String(value)) } } const url = INSPECTION_ROUTES.CHECKPOINT_UPLOAD_MEDIA.replace("{id}", id) return this.postFormData(url, fd) } async deleteCheckpointMedia(id: string) { return this.delete(INSPECTION_ROUTES.CHECKPOINT_MEDIA, { params: { id } }) } }