134 lines
2.9 KiB
TypeScript
134 lines
2.9 KiB
TypeScript
// lib/api/adminCategoryMappings.ts
|
||
|
||
const API_BASE =
|
||
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
|
||
|
||
export interface AdminCategory {
|
||
id: number;
|
||
slug: string;
|
||
name: string;
|
||
description?: string | null;
|
||
groupName?: string | null;
|
||
sortOrder?: number | null;
|
||
}
|
||
|
||
export interface AdminPartRoleMapping {
|
||
id: number;
|
||
platform: string;
|
||
partRole: string;
|
||
categorySlug: string;
|
||
groupName?: string | null;
|
||
notes?: string | null;
|
||
}
|
||
|
||
export interface CreatePartRoleMappingRequest {
|
||
platform: string;
|
||
partRole: string;
|
||
categorySlug: string;
|
||
notes?: string;
|
||
}
|
||
|
||
export interface UpdatePartRoleMappingRequest {
|
||
platform?: string;
|
||
partRole?: string;
|
||
categorySlug?: string;
|
||
notes?: string;
|
||
}
|
||
|
||
async function apiFetch<T>(
|
||
path: string,
|
||
options: {
|
||
token?: string;
|
||
method?: string;
|
||
body?: any;
|
||
} = {}
|
||
): Promise<T> {
|
||
const { token, method = "GET", body } = options;
|
||
|
||
const headers: Record<string, string> = {
|
||
"Content-Type": "application/json",
|
||
};
|
||
if (token) {
|
||
headers["Authorization"] = `Bearer ${token}`;
|
||
}
|
||
|
||
const res = await fetch(`${API_BASE}${path}`, {
|
||
method,
|
||
headers,
|
||
body: body ? JSON.stringify(body) : undefined,
|
||
});
|
||
|
||
if (!res.ok) {
|
||
const text = await res.text().catch(() => "");
|
||
throw new Error(
|
||
`API error ${res.status}: ${res.statusText}${text ? ` – ${text}` : ""}`
|
||
);
|
||
}
|
||
|
||
return (await res.json()) as T;
|
||
}
|
||
|
||
export async function fetchAdminCategories(token: string) {
|
||
return apiFetch<AdminCategory[]>("/api/admin/categories", { token });
|
||
}
|
||
|
||
// ---------------- Part-role mappings ----------------
|
||
|
||
const PART_ROLE_BASE = "/api/admin/part-role-mappings";
|
||
|
||
/**
|
||
* Fetch part-role/category mappings scoped by platform.
|
||
* Backend should expose: GET /api/admin/part-role-mappings?platform=AR-15
|
||
*/
|
||
export async function fetchPartRoleMappings(
|
||
token: string,
|
||
platform = "AR-15"
|
||
) {
|
||
const params = new URLSearchParams({ platform });
|
||
return apiFetch<AdminPartRoleMapping[]>(
|
||
`${PART_ROLE_BASE}?${params.toString()}`,
|
||
{ token }
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Create a new part-role → category mapping
|
||
* POST /api/admin/part-role-mappings
|
||
*/
|
||
export async function createPartRoleMapping(
|
||
token: string,
|
||
payload: CreatePartRoleMappingRequest
|
||
) {
|
||
return apiFetch<AdminPartRoleMapping>(PART_ROLE_BASE, {
|
||
token,
|
||
method: "POST",
|
||
body: payload,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Update an existing part-role mapping
|
||
* PUT /api/admin/part-role-mappings/{id}
|
||
*/
|
||
export async function updatePartRoleMapping(
|
||
token: string,
|
||
id: number,
|
||
payload: UpdatePartRoleMappingRequest
|
||
) {
|
||
return apiFetch<AdminPartRoleMapping>(`${PART_ROLE_BASE}/${id}`, {
|
||
token,
|
||
method: "PUT",
|
||
body: payload,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Delete a part-role mapping
|
||
* DELETE /api/admin/part-role-mappings/{id}
|
||
*/
|
||
export async function deletePartRoleMapping(token: string, id: number) {
|
||
await apiFetch<void>(`${PART_ROLE_BASE}/${id}`, {
|
||
token,
|
||
method: "DELETE",
|
||
});
|
||
} |