Files
badoHair_fe/lib/api/products.ts

121 lines
3.6 KiB
TypeScript

import { api, PaginatedResult } from "@/lib/api";
import type { Product } from "@/data/products";
// Backend shape (snake_case)
interface ApiProduct {
id: string;
name: string;
category: "clip-in" | "tape-in" | "ponytail" | "keratin";
price: number;
original_price?: number;
image: string;
images: string[];
colors: string[];
lengths: string[];
description: string;
features: string[];
is_new?: boolean;
is_bestseller?: boolean;
rating: number;
review_count: number;
stock_quantity: number;
is_featured: boolean;
is_hidden: boolean;
}
function toProduct(p: ApiProduct): Product {
return {
id: p.id,
name: p.name,
category: p.category,
price: p.price,
originalPrice: p.original_price,
image: p.image,
images: p.images,
colors: p.colors,
lengths: p.lengths,
description: p.description,
features: p.features,
isNew: p.is_new,
isBestseller: p.is_bestseller,
rating: p.rating,
reviewCount: p.review_count,
stockQuantity: p.stock_quantity,
};
}
export interface ProductFilters {
page?: number;
per_page?: number;
search?: string;
category?: string;
bestseller?: boolean;
is_new?: boolean;
exclude?: string;
}
export async function listProducts(
filters: ProductFilters = {}
): Promise<PaginatedResult<Product>> {
const params = new URLSearchParams();
if (filters.page) params.set("page", String(filters.page));
if (filters.per_page) params.set("per_page", String(filters.per_page));
if (filters.search) params.set("search", filters.search);
if (filters.category) params.set("category", filters.category);
if (filters.bestseller) params.set("bestseller", "true");
if (filters.is_new) params.set("is_new", "true");
if (filters.exclude) params.set("exclude", filters.exclude);
const qs = params.toString();
const res = await api.get<PaginatedResult<ApiProduct>>(`/products${qs ? `?${qs}` : ""}`);
return { data: res.data.map(toProduct), meta: res.meta };
}
export async function getProduct(id: string): Promise<Product> {
const p = await api.get<ApiProduct>(`/products/${id}`);
return toProduct(p);
}
// ── Admin ─────────────────────────────────────────────────────────────────────
export interface ProductPayload {
name: string;
category: string;
price: number;
original_price?: number;
description?: string;
images?: string[];
colors?: string[];
lengths?: string[];
features?: string[];
is_new?: boolean;
is_bestseller?: boolean;
stock_quantity?: number;
}
export async function adminListProducts(): Promise<PaginatedResult<Product>> {
const res = await api.get<PaginatedResult<ApiProduct>>("/admin/products?per_page=100&include_hidden=true");
return { data: res.data.map(toProduct), meta: res.meta };
}
export async function adminCreateProduct(payload: ProductPayload): Promise<Product> {
const p = await api.post<ApiProduct>("/admin/products", payload);
return toProduct(p);
}
export async function adminUpdateProduct(id: string, payload: Partial<ProductPayload>): Promise<Product> {
const p = await api.put<ApiProduct>(`/admin/products/${id}`, payload);
return toProduct(p);
}
export async function adminDeleteProduct(id: string): Promise<void> {
await api.del(`/admin/products/${id}`);
}
export async function adminUploadProductImage(productId: string, file: File): Promise<Product> {
const form = new FormData();
form.append("file", file);
const p = await api.upload<ApiProduct>(`/admin/products/${productId}/images`, form);
return toProduct(p);
}