112 lines
2.7 KiB
TypeScript
112 lines
2.7 KiB
TypeScript
import type {
|
|
Product,
|
|
ProductGalleryImage,
|
|
ProductOptionValue,
|
|
SellUnit,
|
|
} from '../data/products'
|
|
import { apiRequest } from './api'
|
|
|
|
export type ProductListResponse = {
|
|
items: Product[]
|
|
total: number
|
|
page: number
|
|
pageSize: number
|
|
}
|
|
|
|
export type ListProductsParams = {
|
|
q?: string
|
|
categoryId?: string
|
|
minPrice?: number
|
|
maxPrice?: number
|
|
tag?: string
|
|
page?: number
|
|
pageSize?: number
|
|
}
|
|
|
|
export type ProductOptionPayload = {
|
|
flavorId: string
|
|
amount: string
|
|
price: number
|
|
}
|
|
|
|
export type ProductGalleryPayload = {
|
|
url: string
|
|
storageKey: string
|
|
}
|
|
|
|
export type CreateProductPayload = {
|
|
nameFa: string
|
|
nameEn: string
|
|
categoryId: string
|
|
price: number
|
|
sellUnit: SellUnit
|
|
intro?: string
|
|
description?: string
|
|
/** null = ready immediately (no prep time) */
|
|
preparationHours?: number | null
|
|
tags?: string[]
|
|
mainImageUrl?: string
|
|
mainImageKey?: string
|
|
gallery?: ProductGalleryPayload[]
|
|
options?: ProductOptionPayload[]
|
|
}
|
|
|
|
export type UpdateProductPayload = Partial<CreateProductPayload>
|
|
|
|
function buildQuery(params: ListProductsParams) {
|
|
const search = new URLSearchParams()
|
|
if (params.q?.trim()) search.set('q', params.q.trim())
|
|
if (params.categoryId) search.set('categoryId', params.categoryId)
|
|
if (params.tag?.trim()) search.set('tag', params.tag.trim())
|
|
if (params.minPrice !== undefined) search.set('minPrice', String(params.minPrice))
|
|
if (params.maxPrice !== undefined) search.set('maxPrice', String(params.maxPrice))
|
|
if (params.page) search.set('page', String(params.page))
|
|
if (params.pageSize) search.set('pageSize', String(params.pageSize))
|
|
const qs = search.toString()
|
|
return qs ? `?${qs}` : ''
|
|
}
|
|
|
|
export function listProducts(params: ListProductsParams = {}) {
|
|
return apiRequest<ProductListResponse>(`/products${buildQuery(params)}`)
|
|
}
|
|
|
|
export function getProduct(id: string) {
|
|
return apiRequest<Product>(`/products/${id}`)
|
|
}
|
|
|
|
export function createProduct(payload: CreateProductPayload) {
|
|
return apiRequest<Product>('/products', {
|
|
method: 'POST',
|
|
body: payload,
|
|
})
|
|
}
|
|
|
|
export function updateProduct(id: string, payload: UpdateProductPayload) {
|
|
return apiRequest<Product>(`/products/${id}`, {
|
|
method: 'PATCH',
|
|
body: payload,
|
|
})
|
|
}
|
|
|
|
export function deleteProduct(id: string) {
|
|
return apiRequest<{ ok: true }>(`/products/${id}`, {
|
|
method: 'DELETE',
|
|
})
|
|
}
|
|
|
|
export function toOptionPayload(
|
|
options: ProductOptionValue[],
|
|
): ProductOptionPayload[] {
|
|
return options.map(({ flavorId, amount, price }) => ({
|
|
flavorId,
|
|
amount,
|
|
price,
|
|
}))
|
|
}
|
|
|
|
export function toGalleryPayload(
|
|
gallery: ProductGalleryImage[],
|
|
): ProductGalleryPayload[] {
|
|
return gallery.map(({ url, storageKey }) => ({ url, storageKey }))
|
|
}
|