import type { Article, Category, Order, Page, Product } from '@homaroma/types' import { API_BASE } from './api' const isDev = process.env.NODE_ENV === 'development' const defaultRevalidate = 0 type ProductListResponse = { data?: Product[] } export type Coupon = { id: number code: string type: 'PERCENTAGE' | 'FIXED_AMOUNT' | 'FREE_SHIPPING' | string value: number minPurchase: number usageLimit: number | null usedCount: number expiresAt?: string | null } export type ApiResult = | { ok: true; data: T } | { ok: false; error: string; status?: number } export async function fetchJson(path: string, init?: RequestInit & { next?: { revalidate?: number } }): Promise { try { const res = await fetch(`${API_BASE}${path}`, { ...init, next: init?.next ?? { revalidate: defaultRevalidate }, }) if (!res.ok) { console.error(`[website-api] ${path} returned ${res.status}`) return null } return await res.json() as T } catch (error) { console.error(`[website-api] Failed to fetch ${path}`, error) return null } } export async function fetchJsonResult(path: string, init?: RequestInit & { next?: { revalidate?: number } }): Promise> { try { const res = await fetch(`${API_BASE}${path}`, { ...init, next: init?.next ?? { revalidate: defaultRevalidate }, }) if (!res.ok) { return { ok: false, error: `${path} returned ${res.status}`, status: res.status } } return { ok: true, data: await res.json() as T } } catch (error) { return { ok: false, error: error instanceof Error ? error.message : `Failed to fetch ${path}`, } } } export async function getCategories(lang = 'all'): Promise { return await fetchJson(`/categories?lang=${lang}`, { next: { revalidate: 0 } }) ?? [] } export async function getCategoriesResult(lang = 'all'): Promise> { return await fetchJsonResult(`/categories?lang=${lang}`, { next: { revalidate: 0 } }) } export async function getCmsPage(slug: string, lang = 'all'): Promise { return await fetchJson(`/pages/${slug}?lang=${lang}`, { next: { revalidate: defaultRevalidate } }) } export async function getCmsPageResult(slug: string, lang = 'all'): Promise> { return await fetchJsonResult(`/pages/${slug}?lang=${lang}`, { next: { revalidate: defaultRevalidate } }) } export async function getArticlesResult(): Promise> { return await fetchJsonResult('/articles?publishedOnly=true', { next: { revalidate: defaultRevalidate } }) } export async function getActiveCouponsResult(): Promise> { const response = await fetchJsonResult('/coupons/active', { next: { revalidate: defaultRevalidate } }) if (!response.ok) return response return { ok: true, data: response.data.filter((coupon) => coupon.usageLimit === null || coupon.usedCount < coupon.usageLimit), } } export async function getOrderResult(id: string | number): Promise> { return await fetchJsonResult(`/orders/${id}`, { next: { revalidate: defaultRevalidate } }) } export async function getProduct(id: string | number, lang = 'all'): Promise { return await fetchJson(`/products/${id}?lang=${lang}`, { next: { revalidate: defaultRevalidate } }) } export async function getProductResult(id: string | number, lang = 'all'): Promise> { return await fetchJsonResult(`/products/${id}?lang=${lang}`, { next: { revalidate: defaultRevalidate } }) } export async function getProducts(query = '', lang = 'all'): Promise { const separator = query ? '&' : '' const response = await fetchJson(`/products?${query}${separator}lang=${lang}`, { next: { revalidate: defaultRevalidate }, }) return response?.data ?? [] } export async function getProductsResult(query = '', lang = 'all'): Promise> { const separator = query ? '&' : '' const response = await fetchJsonResult(`/products?${query}${separator}lang=${lang}`, { next: { revalidate: defaultRevalidate }, }) if (!response.ok) return response return { ok: true, data: response.data.data ?? [] } }