This commit is contained in:
2026-04-06 02:32:47 +03:00
parent 5f3d208158
commit 24a44481a0
152 changed files with 85913 additions and 44338 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+32
View File
@@ -31,6 +31,22 @@ import { HolidayYearsClient } from "./clients/holiday-years"
import { TaxesClient } from "./clients/taxes"
import { InvoicesClient } from "./clients/invoices"
import { HomeClient } from "./clients/home"
import { BillsClient } from "./clients/bills"
import { ReasonsClient } from "./clients/reasons"
import { HolidaysClient } from "./clients/holidays"
import { MakeAndModelsClient } from "./clients/make-and-models"
import { TimeSheetsClient } from "./clients/time-sheets"
import { InvoiceSequencesClient } from "./clients/invoice-sequences"
import { CreditNotesClient } from "./clients/credit-notes"
import { PaymentMadesClient } from "./clients/payment-mades"
import { VendorCreditsClient } from "./clients/vendor-credits"
import { InventoryAdjustmentsClient } from "./clients/inventory-adjustments"
import { ServiceGroupIncludesClient } from "./clients/service-group-includes"
import { ServiceGroupPricingsClient } from "./clients/service-group-pricings"
import { ServiceGroupServicesClient } from "./clients/service-group-services"
import { ServiceGroupPartsClient } from "./clients/service-group-parts"
import { SettingsClient } from "./clients/settings"
import { ConfigurationsClient } from "./clients/configurations"
export function createApi(options?: ApiClientOptions) {
return {
@@ -66,6 +82,22 @@ export function createApi(options?: ApiClientOptions) {
taxes: new TaxesClient(undefined, options),
invoices: new InvoicesClient(undefined, options),
home: new HomeClient(undefined, options),
bills: new BillsClient(undefined, options),
reasons: new ReasonsClient(undefined, options),
holidays: new HolidaysClient(undefined, options),
makeAndModels: new MakeAndModelsClient(undefined, options),
timeSheets: new TimeSheetsClient(undefined, options),
invoiceSequences: new InvoiceSequencesClient(undefined, options),
creditNotes: new CreditNotesClient(undefined, options),
paymentMades: new PaymentMadesClient(undefined, options),
vendorCredits: new VendorCreditsClient(undefined, options),
inventoryAdjustments: new InventoryAdjustmentsClient(undefined, options),
serviceGroupIncludes: new ServiceGroupIncludesClient(undefined, options),
serviceGroupPricings: new ServiceGroupPricingsClient(undefined, options),
serviceGroupServices: new ServiceGroupServicesClient(undefined, options),
serviceGroupParts: new ServiceGroupPartsClient(undefined, options),
settings: new SettingsClient(undefined, options),
configurations: new ConfigurationsClient(undefined, options),
}
}
+5
View File
@@ -6,6 +6,7 @@ export const APPOINTMENT_ROUTES = {
INDEX: "/api/appointments",
BY_ID: "/api/appointments/{id}",
UNLINK_JOB_CARD: "/api/appointments/{id}/un-link-job-card",
CHANGE_STATUS: "/api/appointments/{id}/change-status",
} as const satisfies Record<string, ApiPath>
export class AppointmentsClient extends ApiClient {
@@ -32,4 +33,8 @@ export class AppointmentsClient extends ApiClient {
async unlinkJobCard(id: string, payload: ApiRequestBody<typeof APPOINTMENT_ROUTES.UNLINK_JOB_CARD, "post">) {
return this.post(APPOINTMENT_ROUTES.UNLINK_JOB_CARD, payload, { params: { id } })
}
async changeStatus(id: string, payload: ApiRequestBody<typeof APPOINTMENT_ROUTES.CHANGE_STATUS, "post">) {
return this.post(APPOINTMENT_ROUTES.CHANGE_STATUS, payload, { params: { id } })
}
}
+17
View File
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const BILL_ROUTES = {
INDEX: "/api/bills",
BY_ID: "/api/bills/{id}",
} as const satisfies Record<string, ApiPath>
export class BillsClient extends CrudClient<
typeof BILL_ROUTES.INDEX,
typeof BILL_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, BILL_ROUTES.INDEX, BILL_ROUTES.BY_ID)
}
}
@@ -0,0 +1,26 @@
import { ApiClient, type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const CONFIGURATION_ROUTES = {
SALES_TAX_DISCOUNT: "/api/configurations/sales_tax_discount",
PURCHASE_TAX_DISCOUNT: "/api/configurations/purchase_tax_discount",
GENERAL_PREFERENCES: "/api/configurations/general_preferences",
} as const satisfies Record<string, ApiPath>
export class ConfigurationsClient extends ApiClient {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions)
}
async updateSalesTaxDiscount(payload: ApiRequestBody<typeof CONFIGURATION_ROUTES.SALES_TAX_DISCOUNT, "put">) {
return this.put(CONFIGURATION_ROUTES.SALES_TAX_DISCOUNT, payload)
}
async updatePurchaseTaxDiscount(payload: ApiRequestBody<typeof CONFIGURATION_ROUTES.PURCHASE_TAX_DISCOUNT, "put">) {
return this.put(CONFIGURATION_ROUTES.PURCHASE_TAX_DISCOUNT, payload)
}
async updateGeneralPreferences(payload: ApiRequestBody<typeof CONFIGURATION_ROUTES.GENERAL_PREFERENCES, "put">) {
return this.put(CONFIGURATION_ROUTES.GENERAL_PREFERENCES, payload)
}
}
+42
View File
@@ -0,0 +1,42 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const CREDIT_NOTE_ROUTES = {
INDEX: "/api/credit-notes",
BY_ID: "/api/credit-notes/{id}",
ADD_ATTACHMENT: "/api/credit-notes/{id}/add-attachment",
DELETE_ATTACHMENT: "/api/credit-notes/{id}/delete-attachment",
ADD_INTERNAL_NOTE: "/api/credit-notes/{id}/add-internal-note",
EDIT_INTERNAL_NOTE: "/api/credit-notes/{id}/edit-internal-note",
DELETE_INTERNAL_NOTE: "/api/credit-notes/{id}/delete-internal-note",
} as const satisfies Record<string, ApiPath>
export class CreditNotesClient extends CrudClient<
typeof CREDIT_NOTE_ROUTES.INDEX,
typeof CREDIT_NOTE_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, CREDIT_NOTE_ROUTES.INDEX, CREDIT_NOTE_ROUTES.BY_ID)
}
async addAttachment(id: string, payload: FormData) {
return this.post(CREDIT_NOTE_ROUTES.ADD_ATTACHMENT, payload as never, { params: { id } } as never)
}
async deleteAttachment(id: string, payload: ApiRequestBody<typeof CREDIT_NOTE_ROUTES.DELETE_ATTACHMENT, "delete">) {
return this.delete(CREDIT_NOTE_ROUTES.DELETE_ATTACHMENT, { params: { id }, body: payload } as never)
}
async addInternalNote(id: string, payload: ApiRequestBody<typeof CREDIT_NOTE_ROUTES.ADD_INTERNAL_NOTE, "post">) {
return this.post(CREDIT_NOTE_ROUTES.ADD_INTERNAL_NOTE, payload, { params: { id } } as never)
}
async editInternalNote(id: string, payload: ApiRequestBody<typeof CREDIT_NOTE_ROUTES.EDIT_INTERNAL_NOTE, "delete">) {
return this.delete(CREDIT_NOTE_ROUTES.EDIT_INTERNAL_NOTE, { params: { id }, body: payload } as never)
}
async deleteInternalNote(id: string, payload: ApiRequestBody<typeof CREDIT_NOTE_ROUTES.DELETE_INTERNAL_NOTE, "delete">) {
return this.delete(CREDIT_NOTE_ROUTES.DELETE_INTERNAL_NOTE, { params: { id }, body: payload } as never)
}
}
+20 -2
View File
@@ -9,19 +9,25 @@ export const CUSTOMER_ROUTES = {
EXPORT: "/api/customers/export",
IMPORT: "/api/customers/import",
CUSTOMER_TYPES: "/api/customer-types",
ADD_NOTE: "/api/customers/{id}/add-note",
DELETE_NOTE: "/api/customers/{id}/delete-note",
UPDATE_PERMISSIONS: "/api/customers/{id}/update-permissions",
} as const satisfies Record<string, ApiPath>
export class CustomersClient extends CrudClient<typeof CUSTOMER_ROUTES.INDEX, typeof CUSTOMER_ROUTES.BY_ID> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, CUSTOMER_ROUTES.INDEX, CUSTOMER_ROUTES.BY_ID)
}
async getById(id: string) {
return this.show(id)
}
async listCustomerTypes(query?: ApiListQueryParams) {
return this.get(CUSTOMER_ROUTES.CUSTOMER_TYPES, query ? { query } as never : undefined)
}
async export() {
return this.get(CUSTOMER_ROUTES.EXPORT)
}
@@ -29,4 +35,16 @@ export class CustomersClient extends CrudClient<typeof CUSTOMER_ROUTES.INDEX, ty
async import(payload: ApiRequestBody<typeof CUSTOMER_ROUTES.IMPORT, "post">) {
return this.post(CUSTOMER_ROUTES.IMPORT, payload)
}
async addNote(id: string, payload: { note: string }) {
return this.post(CUSTOMER_ROUTES.ADD_NOTE, payload as never, { params: { id } } as never)
}
async deleteNote(customerId: string, noteId: number) {
return this.delete(CUSTOMER_ROUTES.DELETE_NOTE, { params: { id: customerId }, query: { note_id: noteId } } as never)
}
async updatePermissions(id: string, payload: ApiRequestBody<typeof CUSTOMER_ROUTES.UPDATE_PERMISSIONS, "post">) {
return this.post(CUSTOMER_ROUTES.UPDATE_PERMISSIONS, payload as never, { params: { id } } as never)
}
}
+10 -1
View File
@@ -1,10 +1,11 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const EMPLOYEE_ROUTES = {
INDEX: "/api/employees",
BY_ID: "/api/employees/{id}",
UPDATE_PERMISSIONS: "/api/employees/{id}/update-permissions",
} as const satisfies Record<string, ApiPath>
export class EmployeesClient extends CrudClient<
@@ -14,4 +15,12 @@ export class EmployeesClient extends CrudClient<
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, EMPLOYEE_ROUTES.INDEX, EMPLOYEE_ROUTES.BY_ID)
}
async getById(id: string) {
return this.show(id)
}
async updatePermissions(id: string, payload: ApiRequestBody<typeof EMPLOYEE_ROUTES.UPDATE_PERMISSIONS, "post">) {
return this.post(EMPLOYEE_ROUTES.UPDATE_PERMISSIONS, payload as never, { params: { id } } as never)
}
}
+7
View File
@@ -21,6 +21,13 @@ export class EstimatesClient extends ApiClient {
return this.get(ESTIMATE_ROUTES.INDEX, query ? { query } as never : undefined)
}
// Note: GET /api/estimates/{id} is not in the OpenAPI schema.
// This method uses a type cast and relies on the backend supporting the route.
async getById(id: string) {
const data = await this.get(ESTIMATE_ROUTES.INDEX, { query: { id } } as never)
return {...data, data: (data as any)?.data?.[0] ?? null }
}
async create(payload: ApiRequestBody<typeof ESTIMATE_ROUTES.INDEX, "post">) {
return this.post(ESTIMATE_ROUTES.INDEX, payload)
}
+17
View File
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const HOLIDAY_ROUTES = {
INDEX: "/api/holidays",
BY_ID: "/api/holidays/{id}",
} as const satisfies Record<string, ApiPath>
export class HolidaysClient extends CrudClient<
typeof HOLIDAY_ROUTES.INDEX,
typeof HOLIDAY_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, HOLIDAY_ROUTES.INDEX, HOLIDAY_ROUTES.BY_ID)
}
}
+17 -1
View File
@@ -1,7 +1,7 @@
export { AuthClient, AUTH_ROUTES } from "./auth"
export { CustomersClient, CUSTOMER_ROUTES } from "./customers"
export { ReferralSourcesClient, REFERRAL_SOURCE_ROUTES } from "./referral-sources"
export { VehiclesClient, VEHICLE_ROUTES } from "./vehicles"
export * from "./vehicles"
export { VehicleAttributesClient, VEHICLE_ATTRIBUTE_ROUTES } from "./vehicle-attributes"
export { VehicleDocumentsClient, VEHICLE_DOCUMENT_ROUTES } from "./vehicle-documents"
export { DepartmentsClient, DEPARTMENT_ROUTES } from "./departments"
@@ -30,3 +30,19 @@ export { HolidayYearsClient, HOLIDAY_YEAR_ROUTES } from "./holiday-years"
export { TaxesClient, TAX_ROUTES } from "./taxes"
export { InvoicesClient, INVOICE_ROUTES } from "./invoices"
export { HomeClient, HOME_ROUTES, type HomeDashboardResponse } from "./home"
export { BillsClient, BILL_ROUTES } from "./bills"
export { ReasonsClient, REASON_ROUTES } from "./reasons"
export { HolidaysClient, HOLIDAY_ROUTES } from "./holidays"
export { MakeAndModelsClient, MAKE_AND_MODEL_ROUTES } from "./make-and-models"
export { TimeSheetsClient, TIME_SHEET_ROUTES } from "./time-sheets"
export { InvoiceSequencesClient, INVOICE_SEQUENCE_ROUTES } from "./invoice-sequences"
export { CreditNotesClient, CREDIT_NOTE_ROUTES } from "./credit-notes"
export { PaymentMadesClient, PAYMENT_MADE_ROUTES } from "./payment-mades"
export { VendorCreditsClient, VENDOR_CREDIT_ROUTES } from "./vendor-credits"
export { InventoryAdjustmentsClient, INVENTORY_ADJUSTMENT_ROUTES } from "./inventory-adjustments"
export { ServiceGroupIncludesClient, SERVICE_GROUP_INCLUDE_ROUTES } from "./service-group-includes"
export { ServiceGroupPricingsClient, SERVICE_GROUP_PRICING_ROUTES } from "./service-group-pricings"
export { ServiceGroupServicesClient, SERVICE_GROUP_SERVICE_ROUTES } from "./service-group-services"
export { ServiceGroupPartsClient, SERVICE_GROUP_PART_ROUTES } from "./service-group-parts"
export { SettingsClient, SETTINGS_ROUTES } from "./settings"
export { ConfigurationsClient, CONFIGURATION_ROUTES } from "./configurations"
+29 -5
View File
@@ -46,6 +46,11 @@ export class InspectionsClient extends ApiClient {
return this.get(INSPECTION_ROUTES.INDEX, query ? { query } as never : undefined)
}
async getById(id: string) {
const res = await this.list({ query: { id } } as never)
return {...res, data: res.data[0] }
}
async create(payload: ApiRequestBody<typeof INSPECTION_ROUTES.INDEX, "post">) {
return this.post(INSPECTION_ROUTES.INDEX, payload)
}
@@ -100,16 +105,35 @@ export class InspectionsClient extends ApiClient {
return this.post(INSPECTION_ROUTES.TOGGLE_LABEL_TO_CHECKPOINT, payload)
}
async changeCheckpointStatus(payload: ApiRequestBody<typeof INSPECTION_ROUTES.CHECKPOINT_CHANGE_STATUS, "post">) {
async changeCheckpointStatus(payload: ApiRequestBody<typeof INSPECTION_ROUTES.CHECKPOINT_CHANGE_STATUS, "post">, ) {
return this.post(INSPECTION_ROUTES.CHECKPOINT_CHANGE_STATUS, payload)
}
async addCheckpointAttachment(payload: ApiRequestBody<typeof INSPECTION_ROUTES.CHECKPOINT_ADD_ATTACHMENT, "post">) {
return this.post(INSPECTION_ROUTES.CHECKPOINT_ADD_ATTACHMENT, payload)
async addCheckpointAttachment(payload: Record<string, any>) {
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: ApiRequestBody<typeof INSPECTION_ROUTES.CHECKPOINT_UPLOAD_MEDIA, "post">) {
return this.post(INSPECTION_ROUTES.CHECKPOINT_UPLOAD_MEDIA, payload, { params: { id } })
async uploadCheckpointMedia(id: string, payload: Record<string, any>) {
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) {
@@ -0,0 +1,31 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const INVENTORY_ADJUSTMENT_ROUTES = {
INDEX: "/api/inventory-adjustments",
BY_ID: "/api/inventory-adjustments/{id}",
ADD_ATTACHMENT: "/api/inventory-adjustments/{id}/add-attachment",
DELETE_ATTACHMENT: "/api/inventory-adjustments/{id}/delete-attachment",
} as const satisfies Record<string, ApiPath>
export class InventoryAdjustmentsClient extends CrudClient<
typeof INVENTORY_ADJUSTMENT_ROUTES.INDEX,
typeof INVENTORY_ADJUSTMENT_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, INVENTORY_ADJUSTMENT_ROUTES.INDEX, INVENTORY_ADJUSTMENT_ROUTES.BY_ID)
}
async addAttachment(id: string, files: File[]) {
const fd = new FormData()
for (const file of files) {
fd.append("attachments[]", file)
}
return this.postFormData(`/api/inventory-adjustments/${id}/add-attachment`, fd)
}
async deleteAttachment(id: string, attachmentId: number) {
return this.delete(INVENTORY_ADJUSTMENT_ROUTES.DELETE_ATTACHMENT, { params: { id }, body: { attachment_id: attachmentId } } as never)
}
}
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const INVOICE_SEQUENCE_ROUTES = {
INDEX: "/api/invoice-sequences",
BY_ID: "/api/invoice-sequences/{id}",
} as const satisfies Record<string, ApiPath>
export class InvoiceSequencesClient extends CrudClient<
typeof INVOICE_SEQUENCE_ROUTES.INDEX,
typeof INVOICE_SEQUENCE_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, INVOICE_SEQUENCE_ROUTES.INDEX, INVOICE_SEQUENCE_ROUTES.BY_ID)
}
}
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const MAKE_AND_MODEL_ROUTES = {
INDEX: "/api/make-and-models",
BY_ID: "/api/make-and-models/{id}",
} as const satisfies Record<string, ApiPath>
export class MakeAndModelsClient extends CrudClient<
typeof MAKE_AND_MODEL_ROUTES.INDEX,
typeof MAKE_AND_MODEL_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, MAKE_AND_MODEL_ROUTES.INDEX, MAKE_AND_MODEL_ROUTES.BY_ID)
}
}
+27
View File
@@ -0,0 +1,27 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const PAYMENT_MADE_ROUTES = {
INDEX: "/api/payment-mades",
BY_ID: "/api/payment-mades/{id}",
ADD_ATTACHMENT: "/api/payment-mades/{id}/add-attachment",
DELETE_ATTACHMENT: "/api/payment-mades/{id}/delete-attachment",
} as const satisfies Record<string, ApiPath>
export class PaymentMadesClient extends CrudClient<
typeof PAYMENT_MADE_ROUTES.INDEX,
typeof PAYMENT_MADE_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, PAYMENT_MADE_ROUTES.INDEX, PAYMENT_MADE_ROUTES.BY_ID)
}
async addAttachment(id: string, payload: FormData) {
return this.post(PAYMENT_MADE_ROUTES.ADD_ATTACHMENT, payload as never, { params: { id } } as never)
}
async deleteAttachment(id: string, payload: ApiRequestBody<typeof PAYMENT_MADE_ROUTES.DELETE_ATTACHMENT, "delete">) {
return this.delete(PAYMENT_MADE_ROUTES.DELETE_ATTACHMENT, { params: { id }, body: payload } as never)
}
}
+8 -21
View File
@@ -1,30 +1,17 @@
import { ApiClient, type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
import type { ApiListQueryParams } from "../contracts/types"
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const PURCHASE_ORDER_ROUTES = {
INDEX: "/api/purchase-orders",
BY_ID: "/api/purchase-orders/{id}",
} as const satisfies Record<string, ApiPath>
export class PurchaseOrdersClient extends ApiClient {
export class PurchaseOrdersClient extends CrudClient<
typeof PURCHASE_ORDER_ROUTES.INDEX,
typeof PURCHASE_ORDER_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions)
}
async list(query?: ApiListQueryParams) {
return this.get(PURCHASE_ORDER_ROUTES.INDEX, query ? { query } as never : undefined)
}
async create(payload: ApiRequestBody<typeof PURCHASE_ORDER_ROUTES.INDEX, "post">) {
return this.post(PURCHASE_ORDER_ROUTES.INDEX, payload)
}
async update(id: string, payload: ApiRequestBody<typeof PURCHASE_ORDER_ROUTES.BY_ID, "put">) {
return this.put(PURCHASE_ORDER_ROUTES.BY_ID, payload, { params: { id } })
}
async destroy(id: string) {
return this.delete(PURCHASE_ORDER_ROUTES.BY_ID, { params: { id } })
super(baseUrl, defaultOptions, PURCHASE_ORDER_ROUTES.INDEX, PURCHASE_ORDER_ROUTES.BY_ID)
}
}
+17
View File
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const REASON_ROUTES = {
INDEX: "/api/reasons",
BY_ID: "/api/reasons/{id}",
} as const satisfies Record<string, ApiPath>
export class ReasonsClient extends CrudClient<
typeof REASON_ROUTES.INDEX,
typeof REASON_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, REASON_ROUTES.INDEX, REASON_ROUTES.BY_ID)
}
}
@@ -0,0 +1,22 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const SERVICE_GROUP_INCLUDE_ROUTES = {
INDEX: "/api/service-group-includes",
BY_ID: "/api/service-group-includes/{id}",
CHANGE_ARRANGEMENT: "/api/service-group-includes/{id}/change-arrangement",
} as const satisfies Record<string, ApiPath>
export class ServiceGroupIncludesClient extends CrudClient<
typeof SERVICE_GROUP_INCLUDE_ROUTES.INDEX,
typeof SERVICE_GROUP_INCLUDE_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, SERVICE_GROUP_INCLUDE_ROUTES.INDEX, SERVICE_GROUP_INCLUDE_ROUTES.BY_ID)
}
async changeArrangement(id: string, payload: { arrangement?: number }) {
return this.post(SERVICE_GROUP_INCLUDE_ROUTES.CHANGE_ARRANGEMENT, payload as never, { params: { id } } as never)
}
}
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const SERVICE_GROUP_PART_ROUTES = {
INDEX: "/api/service-group-parts",
BY_ID: "/api/service-group-parts/{id}",
} as const satisfies Record<string, ApiPath>
export class ServiceGroupPartsClient extends CrudClient<
typeof SERVICE_GROUP_PART_ROUTES.INDEX,
typeof SERVICE_GROUP_PART_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, SERVICE_GROUP_PART_ROUTES.INDEX, SERVICE_GROUP_PART_ROUTES.BY_ID)
}
}
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const SERVICE_GROUP_PRICING_ROUTES = {
INDEX: "/api/service-group-pricings",
BY_ID: "/api/service-group-pricings/{id}",
} as const satisfies Record<string, ApiPath>
export class ServiceGroupPricingsClient extends CrudClient<
typeof SERVICE_GROUP_PRICING_ROUTES.INDEX,
typeof SERVICE_GROUP_PRICING_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, SERVICE_GROUP_PRICING_ROUTES.INDEX, SERVICE_GROUP_PRICING_ROUTES.BY_ID)
}
}
@@ -0,0 +1,17 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
export const SERVICE_GROUP_SERVICE_ROUTES = {
INDEX: "/api/service-group-services",
BY_ID: "/api/service-group-services/{id}",
} as const satisfies Record<string, ApiPath>
export class ServiceGroupServicesClient extends CrudClient<
typeof SERVICE_GROUP_SERVICE_ROUTES.INDEX,
typeof SERVICE_GROUP_SERVICE_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, SERVICE_GROUP_SERVICE_ROUTES.INDEX, SERVICE_GROUP_SERVICE_ROUTES.BY_ID)
}
}
+17 -2
View File
@@ -1,10 +1,13 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath } from "../infra/types"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const SERVICE_GROUP_ROUTES = {
INDEX: "/api/service-groups",
BY_ID: "/api/service-groups/{id}",
TOGGLE_STATUS: "/api/service-groups/{id}/toggle-status",
ADD_LABEL: "/api/service-groups/{id}/add-label",
DELETE_LABEL: "/api/service-groups/{id}/delete-label",
} as const satisfies Record<string, ApiPath>
export class ServiceGroupsClient extends CrudClient<
@@ -14,4 +17,16 @@ export class ServiceGroupsClient extends CrudClient<
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, SERVICE_GROUP_ROUTES.INDEX, SERVICE_GROUP_ROUTES.BY_ID)
}
async toggleStatus(id: string) {
return this.post(SERVICE_GROUP_ROUTES.TOGGLE_STATUS, {} as never, { params: { id } } as never)
}
async addLabel(id: string, payload: ApiRequestBody<typeof SERVICE_GROUP_ROUTES.ADD_LABEL, "post">) {
return this.post(SERVICE_GROUP_ROUTES.ADD_LABEL, payload, { params: { id } } as never)
}
async deleteLabel(id: string, payload: ApiRequestBody<typeof SERVICE_GROUP_ROUTES.DELETE_LABEL, "delete">) {
return this.delete(SERVICE_GROUP_ROUTES.DELETE_LABEL, { params: { id }, body: payload } as never)
}
}
+20
View File
@@ -0,0 +1,20 @@
import { ApiClient, type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const SETTINGS_ROUTES = {
INDEX: "/api/settings",
} as const satisfies Record<string, ApiPath>
export class SettingsClient extends ApiClient {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions)
}
async fetch() {
return this.get(SETTINGS_ROUTES.INDEX)
}
async update(payload: ApiRequestBody<typeof SETTINGS_ROUTES.INDEX, "put">) {
return this.put(SETTINGS_ROUTES.INDEX, payload)
}
}
+27
View File
@@ -0,0 +1,27 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const TIME_SHEET_ROUTES = {
INDEX: "/api/time-sheets",
BY_ID: "/api/time-sheets/{id}",
CLOCK_IN: "/api/time-sheet/clock-in",
CLOCK_OUT: "/api/time-sheet/clock-out",
} as const satisfies Record<string, ApiPath>
export class TimeSheetsClient extends CrudClient<
typeof TIME_SHEET_ROUTES.INDEX,
typeof TIME_SHEET_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, TIME_SHEET_ROUTES.INDEX, TIME_SHEET_ROUTES.BY_ID)
}
async clockIn(payload: ApiRequestBody<typeof TIME_SHEET_ROUTES.CLOCK_IN, "post">) {
return this.post(TIME_SHEET_ROUTES.CLOCK_IN, payload)
}
async clockOut(payload: ApiRequestBody<typeof TIME_SHEET_ROUTES.CLOCK_OUT, "post">) {
return this.post(TIME_SHEET_ROUTES.CLOCK_OUT, payload)
}
}
+2
View File
@@ -77,3 +77,5 @@ export class VehiclesClient extends ApiClient {
return this.post(VEHICLE_ROUTES.UNLINK_CUSTOMER, payload)
}
}
export type VehicleListResponse = NonNullable<Awaited<ReturnType<VehiclesClient["list"]>>['data']>[number]
@@ -0,0 +1,42 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
export const VENDOR_CREDIT_ROUTES = {
INDEX: "/api/vendor-credits",
BY_ID: "/api/vendor-credits/{id}",
ADD_ATTACHMENT: "/api/vendor-credits/{id}/add-attachment",
DELETE_ATTACHMENT: "/api/vendor-credits/{id}/delete-attachment",
ADD_INTERNAL_NOTE: "/api/vendor-credits/{id}/add-internal-note",
EDIT_INTERNAL_NOTE: "/api/vendor-credits/{id}/edit-internal-note",
DELETE_INTERNAL_NOTE: "/api/vendor-credits/{id}/delete-internal-note",
} as const satisfies Record<string, ApiPath>
export class VendorCreditsClient extends CrudClient<
typeof VENDOR_CREDIT_ROUTES.INDEX,
typeof VENDOR_CREDIT_ROUTES.BY_ID
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, VENDOR_CREDIT_ROUTES.INDEX, VENDOR_CREDIT_ROUTES.BY_ID)
}
async addAttachment(id: string, payload: FormData) {
return this.post(VENDOR_CREDIT_ROUTES.ADD_ATTACHMENT, payload as never, { params: { id } } as never)
}
async deleteAttachment(id: string, payload: ApiRequestBody<typeof VENDOR_CREDIT_ROUTES.DELETE_ATTACHMENT, "delete">) {
return this.delete(VENDOR_CREDIT_ROUTES.DELETE_ATTACHMENT, { params: { id }, body: payload } as never)
}
async addInternalNote(id: string, payload: ApiRequestBody<typeof VENDOR_CREDIT_ROUTES.ADD_INTERNAL_NOTE, "post">) {
return this.post(VENDOR_CREDIT_ROUTES.ADD_INTERNAL_NOTE, payload, { params: { id } } as never)
}
async editInternalNote(id: string, payload: ApiRequestBody<typeof VENDOR_CREDIT_ROUTES.EDIT_INTERNAL_NOTE, "delete">) {
return this.delete(VENDOR_CREDIT_ROUTES.EDIT_INTERNAL_NOTE, { params: { id }, body: payload } as never)
}
async deleteInternalNote(id: string, payload: ApiRequestBody<typeof VENDOR_CREDIT_ROUTES.DELETE_INTERNAL_NOTE, "delete">) {
return this.delete(VENDOR_CREDIT_ROUTES.DELETE_INTERNAL_NOTE, { params: { id }, body: payload } as never)
}
}
+115
View File
@@ -0,0 +1,115 @@
// ⚙️ Settings
export const FirstDayOfWork = ['sunday', 'monday', 'saturday'] as const;
export type FirstDayOfWork = (typeof FirstDayOfWork)[number];
// 🏪 Shop Types
export const ShopType = ['Car', 'Motorcycle', 'Heavy Duty', 'Marine', 'Electronics Repair & Services', 'Other'] as const;
export type ShopType = (typeof ShopType)[number];
// 🏢 Departments
export const AssignmentType = ['none', 'bays', 'outsourced'] as const;
export type AssignmentType = (typeof AssignmentType)[number];
// 👨‍💼 Employees
export const WageType = ['Hourly(punch)', 'Hourly(clock)', 'Daily', 'Monthly'] as const;
export type WageType = (typeof WageType)[number];
export const EmployeeType = ['employee', 'sales_person'] as const;
export type EmployeeType = (typeof EmployeeType)[number];
// 🔍 Inspections
export const InspectionStatus = ['in_progress', 'completed', 'cancelled'] as const;
export type InspectionStatus = (typeof InspectionStatus)[number];
// 📋 Inspection Check Points
export const InspectionRecordType = ['record_conditions', 'record_audio', 'record_video', 'capture_photo', 'wire_frame', 'none'] as const;
export type InspectionRecordType = (typeof InspectionRecordType)[number];
export const InspectionCheckPointStatus = ['passed', 'failed', 'need_attention', 'not_applicable', 'not_inspected'] as const;
export type InspectionCheckPointStatus = (typeof InspectionCheckPointStatus)[number];
// 🧾 Job Cards
export const JobCardStatus = ['draft', 'check_in', 'in_progress', 'on_hold', 'ready_to_delivery', 'delivered'] as const;
export type JobCardStatus = (typeof JobCardStatus)[number];
export const FuelLevel = ['empty', 'reserve', 'quarter', 'half', 'three_quarter', 'full'] as const;
export type FuelLevel = (typeof FuelLevel)[number];
export const EstimateTo = ['Customer', 'Insurance'] as const;
export type EstimateTo = (typeof EstimateTo)[number];
export const TaxInclusive = ['Tax Inclusive', 'Tax Exclusive'] as const;
export type TaxInclusive = (typeof TaxInclusive)[number];
export const DiscountType = ['no', 'line_item_level', 'transaction_level'] as const;
export type DiscountType = (typeof DiscountType)[number];
export const DiscountAt = ['inclusive_of_tax', 'exclusive_of_tax'] as const;
export type DiscountAt = (typeof DiscountAt)[number];
// 💰 Bills
export const BillStatus = ['draft', 'open', 'un_paid', 'partially_paid', 'paid'] as const;
export type BillStatus = (typeof BillStatus)[number];
// 💸 Expenses
export const ExpenseStatus = ['draft', 'open', 'un_paid', 'partially_paid', 'paid'] as const;
export type ExpenseStatus = (typeof ExpenseStatus)[number];
// ✅ Tasks
export const TaskStatus = ['pending', 'completed'] as const;
export type TaskStatus = (typeof TaskStatus)[number];
// 📅 Appointments
export const AppointmentStatus = ['requested', 'confirmed', 'no_show', 'cancelled', 'completed'] as const;
export type AppointmentStatus = (typeof AppointmentStatus)[number];
// 🧾 Invoices
export const InvoiceStatus = ['draft', 'open', 'over_due', 'paid', 'partially_paid', 'un_paid'] as const;
export type InvoiceStatus = (typeof InvoiceStatus)[number];
export const InvoiceDiscount = ['no', 'line_item_level', 'transaction_level'] as const;
export type InvoiceDiscount = (typeof InvoiceDiscount)[number];
// 🔧 Invoice Services / Groups / Inspection Categories
export const RateType = ['flat_rate', 'hourly'] as const;
export type RateType = (typeof RateType)[number];
// 🧾 Credit Notes
export const CreditNoteStatus = ['draft', 'open', 'closed'] as const;
export type CreditNoteStatus = (typeof CreditNoteStatus)[number];
// 💳 Payments Made
export const PaymentFor = ['bill', 'expense'] as const;
export type PaymentFor = (typeof PaymentFor)[number];
// 🏦 Vendor Credits
export const VendorCreditStatus = ['draft', 'open', 'closed'] as const;
export type VendorCreditStatus = (typeof VendorCreditStatus)[number];
export const VendorCreditDiscount = ['no', 'line_item_level', 'transaction_level'] as const;
export type VendorCreditDiscount = (typeof VendorCreditDiscount)[number];
// ⏱️ Time Sheets
export const ActivityType = ['general', 'order', 'task'] as const;
export type ActivityType = (typeof ActivityType)[number];
// 📆 Shop Calendar Days
export const ShopCalendarDayType = ['full_day', 'half_day', 'week_off'] as const;
export type ShopCalendarDayType = (typeof ShopCalendarDayType)[number];
// 💵 Service Group Pricing / Services
export const ServiceGroupRateType = ['hourly', 'flat_rate'] as const;
export type ServiceGroupRateType = (typeof ServiceGroupRateType)[number];
// ⚙️ Configurations
export const SellRatesTaxInclusive = ['Tax Inclusive', 'Tax Exclusive'] as const;
export type SellRatesTaxInclusive = (typeof SellRatesTaxInclusive)[number];
export const GiveDiscounts = ['no', 'line_item_level', 'transaction_level'] as const;
export type GiveDiscounts = (typeof GiveDiscounts)[number];
export const PurchaseRatesTaxInclusive = ['Tax Inclusive', 'Tax Exclusive'] as const;
export type PurchaseRatesTaxInclusive = (typeof PurchaseRatesTaxInclusive)[number];
export const ReceiveDiscounts = ['no', 'line_item_level', 'transaction_level'] as const;
export type ReceiveDiscounts = (typeof ReceiveDiscounts)[number];
+2 -1
View File
@@ -3,6 +3,7 @@ export * from "./infra/index"
// ── Contracts ──
export * from "./contracts/types"
export * from "./contracts/enums"
// ── Domain Clients ──
export * from "./clients/index"
@@ -10,4 +11,4 @@ export * from "./clients/index"
// ── Factory ──
export { createApi, api } from "./api"
export * from "./types"
+17 -7
View File
@@ -45,14 +45,24 @@ export abstract class CrudClient<
export type BaseCrudItem = { id: number }
/** Extract the list (GET index) response type from a CrudClient subclass. */
export type CrudListResponse<C> = C extends CrudClient<infer IR, infer _BR> ? ApiResponse<IR, "get"> : never
type ClientMethodReturn<C, TMethod extends PropertyKey> =
C extends { [K in TMethod]: (...args: any[]) => infer TResult }
? Awaited<TResult>
: never
/** Extract the show (GET by-id) response type from a CrudClient subclass. */
export type CrudShowResponse<C> = C extends CrudClient<infer _IR, infer BR> ? ApiResponse<BR, "get"> : never
type ClientMethodFirstArg<C, TMethod extends PropertyKey> =
C extends { [K in TMethod]: (arg: infer TArg, ...args: any[]) => any }
? Exclude<TArg, undefined>
: never
/** Extract the list response type from a client with a `list()` method. */
export type CrudListResponse<C> = ClientMethodReturn<C, "list">
/** Extract the show response type from a client with a `show()` method. */
export type CrudShowResponse<C> = ClientMethodReturn<C, "show">
/** Extract a single item type from the `data` array of a CrudClient list response. */
export type CrudListItem<C> = CrudListResponse<C> extends { data?: (infer Item)[] } ? Item : never
export type CrudListItem<C> = CrudListResponse<C> extends { data?: readonly (infer Item)[] } ? Item : never
/** Extract the query-parameter type accepted by a CrudClient's `list()` method. */
export type CrudListParams<C> = C extends CrudClient<infer IR, infer _BR> ? ApiQueryParams<IR, "get"> : never
/** Extract the query-parameter type accepted by a client's `list()` method. */
export type CrudListParams<C> = ClientMethodFirstArg<C, "list">
+1
View File
@@ -0,0 +1 @@
export * from './job-cards'
+4
View File
@@ -0,0 +1,4 @@
import { JOB_CARD_ROUTES } from "../clients";
import { ApiResponse } from "../infra";
export type JobCardResponseData = NonNullable<ApiResponse<typeof JOB_CARD_ROUTES['INDEX'], 'get'>['data']>[number]
View File
+13588 -7362
View File
File diff suppressed because it is too large Load Diff