updates
This commit is contained in:
@@ -5,8 +5,8 @@ import type { ApiPath, ApiRequestBody } from "../infra/types"
|
||||
export const PARTS_ROUTES = {
|
||||
INDEX: "/api/parts",
|
||||
BY_ID: "/api/parts/{id}",
|
||||
IMPORT: "/api/import-parts",
|
||||
EXPORT: "/api/export-parts",
|
||||
IMPORT: "/api/parts/import",
|
||||
EXPORT: "/api/parts/export",
|
||||
TOGGLE_STATUS: "/api/toggle-part-status",
|
||||
} as const satisfies Record<string, ApiPath>
|
||||
|
||||
@@ -15,15 +15,15 @@ export class PartsClient extends CrudClient<
|
||||
typeof PARTS_ROUTES.BY_ID
|
||||
> {
|
||||
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
|
||||
super(baseUrl, defaultOptions, PARTS_ROUTES.INDEX, PARTS_ROUTES.BY_ID)
|
||||
}
|
||||
|
||||
async import(payload: ApiRequestBody<typeof PARTS_ROUTES.IMPORT, "post">) {
|
||||
return this.post(PARTS_ROUTES.IMPORT, payload)
|
||||
}
|
||||
|
||||
async export(payload: ApiRequestBody<typeof PARTS_ROUTES.EXPORT, "post">) {
|
||||
return this.post(PARTS_ROUTES.EXPORT, payload)
|
||||
super(
|
||||
baseUrl,
|
||||
defaultOptions,
|
||||
PARTS_ROUTES.INDEX,
|
||||
PARTS_ROUTES.BY_ID,
|
||||
PARTS_ROUTES.IMPORT,
|
||||
PARTS_ROUTES.EXPORT,
|
||||
"POST",
|
||||
)
|
||||
}
|
||||
|
||||
async toggleStatus(payload: ApiRequestBody<typeof PARTS_ROUTES.TOGGLE_STATUS, "post">) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CrudClient } from "../infra/crud-client"
|
||||
import type { ApiClientOptions } from "../infra/client"
|
||||
import type { ApiPath, ApiRequestBody } from "../infra/types"
|
||||
import type { ApiPath } from "../infra/types"
|
||||
|
||||
export const SERVICE_ROUTES = {
|
||||
INDEX: "/api/services",
|
||||
@@ -14,14 +14,14 @@ export class ServicesClient extends CrudClient<
|
||||
typeof SERVICE_ROUTES.BY_ID
|
||||
> {
|
||||
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
|
||||
super(baseUrl, defaultOptions, SERVICE_ROUTES.INDEX, SERVICE_ROUTES.BY_ID)
|
||||
}
|
||||
|
||||
async import(payload: ApiRequestBody<typeof SERVICE_ROUTES.IMPORT, "post">) {
|
||||
return this.post(SERVICE_ROUTES.IMPORT, payload)
|
||||
}
|
||||
|
||||
async export(payload: ApiRequestBody<typeof SERVICE_ROUTES.EXPORT, "post">) {
|
||||
return this.post(SERVICE_ROUTES.EXPORT, payload)
|
||||
super(
|
||||
baseUrl,
|
||||
defaultOptions,
|
||||
SERVICE_ROUTES.INDEX,
|
||||
SERVICE_ROUTES.BY_ID,
|
||||
SERVICE_ROUTES.IMPORT,
|
||||
SERVICE_ROUTES.EXPORT,
|
||||
"POST",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,28 @@ export class ApiClient {
|
||||
return data
|
||||
}
|
||||
|
||||
protected async fetchBlob(endpoint: string, options?: { method?: "GET" | "POST"; body?: unknown }): Promise<Blob> {
|
||||
const url = `${this.normalizeBaseUrl(this.baseUrl)}${endpoint}`
|
||||
const headers = new Headers(this.defaultOptions.headers as Record<string, string>)
|
||||
const method = options?.method ?? "POST"
|
||||
|
||||
const init: RequestInit = { method, headers }
|
||||
if (options?.body) {
|
||||
headers.set("Content-Type", "application/json")
|
||||
init.body = JSON.stringify(options.body)
|
||||
}
|
||||
|
||||
const response = await fetch(url, init)
|
||||
|
||||
if (!response.ok) {
|
||||
const text = await response.text()
|
||||
const data = text ? JSON.parse(text) : null
|
||||
throw new ApiError(response.status, response.statusText, endpoint, method.toLowerCase(), data)
|
||||
}
|
||||
|
||||
return response.blob()
|
||||
}
|
||||
|
||||
private toFetchOptions<Path extends ApiPath, Method extends HttpMethod>(
|
||||
options: ApiRequestOptions<Path, Method>,
|
||||
): Record<string, unknown> {
|
||||
|
||||
@@ -6,6 +6,8 @@ export const DEFAULT_PER_PAGE = 10
|
||||
|
||||
type CrudIndexRoute = ApiPathByMethod<"get"> & ApiPathByMethod<"post">
|
||||
type CrudByIdRoute = ApiPathByMethod<"put"> & ApiPathByMethod<"delete">
|
||||
type CrudImportRoute = ApiPathByMethod<"post">
|
||||
type CrudExportRoute = ApiPathByMethod<"get"> | ApiPathByMethod<"post">
|
||||
|
||||
export type CrudTypeOverrides = {
|
||||
listResponse?: unknown
|
||||
@@ -29,7 +31,10 @@ export abstract class CrudClient<
|
||||
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions,
|
||||
|
||||
public indexRoute?: IndexRoute,
|
||||
public byIdRoute?: ByIdRoute) {
|
||||
public byIdRoute?: ByIdRoute,
|
||||
public importRoute?: CrudImportRoute,
|
||||
public exportRoute?: CrudExportRoute,
|
||||
public exportMethod: "GET" | "POST" = "GET") {
|
||||
|
||||
super(baseUrl, defaultOptions)
|
||||
|
||||
@@ -54,6 +59,21 @@ export abstract class CrudClient<
|
||||
async destroy(id: string): Promise<Resolve<Overrides, 'destroyResponse', ApiResponse<ByIdRoute, "delete">>> {
|
||||
return this.delete<ByIdRoute>(this.byIdRoute as ByIdRoute, { params: { id } } as never) as never
|
||||
}
|
||||
|
||||
async importData(file: File): Promise<{ message?: string }> {
|
||||
const formData = new FormData()
|
||||
formData.append("file", file)
|
||||
const route = (this.importRoute ?? `${this.indexRoute}/import`) as string
|
||||
return this.postFormData(route, formData)
|
||||
}
|
||||
|
||||
async exportData(filters?: Record<string, unknown>): Promise<Blob> {
|
||||
const route = (this.exportRoute ?? `${this.indexRoute}/export`) as string
|
||||
if (this.exportMethod === "POST") {
|
||||
return this.fetchBlob(route, { method: "POST", body: filters ?? {} })
|
||||
}
|
||||
return this.fetchBlob(route)
|
||||
}
|
||||
}
|
||||
|
||||
export type BaseCrudItem = { id: number }
|
||||
|
||||
Reference in New Issue
Block a user