diff --git a/prisma/lootah.db b/prisma/lootah.db
index ef62704..863eaa4 100644
Binary files a/prisma/lootah.db and b/prisma/lootah.db differ
diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx
index 85e4849..d0f3387 100644
--- a/src/app/admin/page.tsx
+++ b/src/app/admin/page.tsx
@@ -228,8 +228,6 @@ export default function AdminPage() {
const [ordersLoading, setOrdersLoading] = useState(false);
const [ordersError, setOrdersError] = useState('');
const [totalRevenue, setTotalRevenue] = useState(0);
- const [syncingOrders, setSyncingOrders] = useState(false);
- const [syncMsg, setSyncMsg] = useState('');
const loadOrders = useCallback(async () => {
setOrdersLoading(true);
@@ -248,23 +246,6 @@ export default function AdminPage() {
}
}, []);
- const handleSyncOrders = async () => {
- setSyncingOrders(true);
- setSyncMsg('');
- try {
- const res = await fetch('/api/admin/sync-orders/', { method: 'POST' });
- const data = await res.json();
- if (!res.ok) throw new Error(data.error ?? 'Sync failed');
- setSyncMsg(`✓ Synced ${data.synced} order(s) from Stripe`);
- await loadOrders();
- } catch (err) {
- setSyncMsg(err instanceof Error ? err.message : 'Sync failed');
- } finally {
- setSyncingOrders(false);
- setTimeout(() => setSyncMsg(''), 4000);
- }
- };
-
useEffect(() => {
if (activeTab === 'orders') loadOrders();
}, [activeTab, loadOrders]);
@@ -634,11 +615,7 @@ export default function AdminPage() {
{/* ===== ORDERS TAB ===== */}
{activeTab === 'orders' && (
-
- {syncMsg &&
{syncMsg}}
-
+
diff --git a/src/app/api/orders/save/route.ts b/src/app/api/orders/save/route.ts
index 4eaa375..b29b28c 100644
--- a/src/app/api/orders/save/route.ts
+++ b/src/app/api/orders/save/route.ts
@@ -20,24 +20,27 @@ export async function POST(request: Request) {
return NextResponse.json({ error: 'Missing paymentIntentId' }, { status: 400 });
}
- // Verify with Stripe that this PaymentIntent actually succeeded — prevents spoofing
- let pi: Stripe.PaymentIntent;
+ // Try to get authoritative data from Stripe, but don't block save if it fails
+ let stripeAmount: number | null = null;
+ let stripeCurrency: string | null = null;
+ let stripeStatus: string | null = null;
+ let stripeMetadata: Record = {};
+
try {
- pi = await stripe.paymentIntents.retrieve(paymentIntentId);
+ const pi = await stripe.paymentIntents.retrieve(paymentIntentId);
+ stripeAmount = pi.amount;
+ stripeCurrency = pi.currency;
+ stripeStatus = pi.status;
+ stripeMetadata = (pi.metadata ?? {}) as Record;
} catch {
- return NextResponse.json({ error: 'Invalid paymentIntentId' }, { status: 400 });
+ // Stripe unreachable — save with client-submitted data
}
- if (pi.status !== 'succeeded') {
- return NextResponse.json({ error: `Payment not succeeded (status: ${pi.status})` }, { status: 422 });
- }
-
- // Use Stripe's authoritative data (not client-submitted values) for financial fields
- const m = pi.metadata ?? {};
+ const m = stripeMetadata;
const data = {
- amount: pi.amount,
- currency: pi.currency,
- status: pi.status,
+ amount: stripeAmount ?? (typeof body.amount === 'number' ? body.amount : 0),
+ currency: stripeCurrency ?? (typeof body.currency === 'string' ? body.currency : 'aed'),
+ status: stripeStatus ?? (typeof body.status === 'string' ? body.status : 'pending'),
customerName: (body.customerName as string | null) ?? m.customerName ?? null,
customerEmail: (body.customerEmail as string | null) ?? m.customerEmail ?? null,
customerPhone: (body.customerPhone as string | null) ?? m.customerPhone ?? null,