feat: add customer cart with expiry, shipping addresses with USPS validation, and multi-item PayPal checkout
SonarQube Analysis / sonarqube (pull_request) Failing after 59s
Tests / backend-unit (pull_request) Successful in 34s
Tests / backend-integration (pull_request) Failing after 1m33s
Tests / frontend-e2e (pull_request) Failing after 1m5s

This commit is contained in:
2026-08-14 14:02:25 -05:00
parent 433d7e1db5
commit 9ab689e624
18 changed files with 1242 additions and 189 deletions
+1 -31
View File
@@ -1,15 +1,9 @@
export interface ItemImage {
id: number;
image_path: string;
sort_order: number;
}
export interface Item {
id: number;
name: string;
description: string | null;
price_cents: number;
images: ItemImage[];
images: { id: number; image_path: string; sort_order: number }[];
status: 'available' | 'reserved' | 'sold';
}
@@ -57,27 +51,3 @@ export async function markAvailable(id: number): Promise<Item> {
const res = await fetch(`/api/admin/items/${id}/mark-available`, { method: 'POST' });
return res.json();
}
export async function createPaypalOrder(itemId: number): Promise<string> {
const res = await fetch(`/api/checkout/paypal/${itemId}/create`, { method: 'POST' });
const data = await res.json();
if (!res.ok) throw new Error(data.error || 'Could not start checkout');
return data.orderID;
}
export async function capturePaypalOrder(itemId: number, orderID: string): Promise<void> {
const res = await fetch(`/api/checkout/paypal/${itemId}/capture`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ orderID })
});
if (!res.ok) throw new Error('Payment captured but confirmation failed — contact the seller.');
}
export async function demoPurchase(itemId: number): Promise<void> {
const res = await fetch(`/api/checkout/demo/${itemId}/purchase`, { method: 'POST' });
if (!res.ok) {
const data = await res.json().catch(() => ({}));
throw new Error(data.error || 'Demo purchase failed');
}
}