mirror of
http://88.130.71.182:3000/BlitTech/badoHair_fe.git
synced 2026-06-12 23:23:22 +00:00
120 lines
3.6 KiB
TypeScript
120 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,
|
|
};
|
|
}
|
|
|
|
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);
|
|
}
|