uh oh stinky

This commit is contained in:
NotII
2025-03-08 04:44:35 +00:00
parent 125a529646
commit 8968c974d4
8 changed files with 1180 additions and 9 deletions

69
lib/client-service.ts Normal file
View File

@@ -0,0 +1,69 @@
'use client';
import { toast } from "@/components/ui/use-toast";
type FetchMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
interface FetchOptions {
method?: FetchMethod;
body?: any;
cache?: RequestCache;
headers?: HeadersInit;
}
export async function fetchClient<T>(
endpoint: string,
options: FetchOptions = {}
): Promise<T> {
const { method = 'GET', body, headers = {}, ...rest } = options;
const apiUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
const url = `${apiUrl}/api${endpoint.startsWith('/') ? endpoint : `/${endpoint}`}`;
const fetchOptions: RequestInit = {
method,
credentials: 'include',
headers: {
'Content-Type': 'application/json',
...headers,
},
...rest,
};
if (body && method !== 'GET') {
fetchOptions.body = JSON.stringify(body);
}
try {
const response = await fetch(url, fetchOptions);
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
const errorMessage = errorData.message || errorData.error || 'An error occurred';
throw new Error(errorMessage);
}
if (response.status === 204) {
return {} as T;
}
const data = await response.json();
return data;
} catch (error) {
console.error('API request failed:', error);
// Only show toast if this is a client-side error (not during SSR)
if (typeof window !== 'undefined') {
const message = error instanceof Error ? error.message : 'Failed to connect to server';
toast({
title: 'Error',
description: message,
variant: 'destructive',
});
}
throw error;
}
}

28
lib/types/promotion.ts Normal file
View File

@@ -0,0 +1,28 @@
export interface Promotion {
_id: string;
storeId: string;
code: string;
discountType: 'percentage' | 'fixed';
discountValue: number;
minOrderAmount: number;
maxUsage: number | null;
usageCount: number;
isActive: boolean;
startDate: string;
endDate: string | null;
description: string;
createdAt: string;
updatedAt: string;
}
export interface PromotionFormData {
code: string;
discountType: 'percentage' | 'fixed';
discountValue: number;
minOrderAmount: number;
maxUsage: number | null;
isActive: boolean;
startDate: string;
endDate: string | null;
description: string;
}