mirror of
http://88.130.71.182:3000/BlitTech/badoHair_fe.git
synced 2026-06-13 10:41:11 +00:00
Update May 12 by Elvis
This commit is contained in:
119
lib/api/products.ts
Normal file
119
lib/api/products.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user