forked from hazem/yslootahrobotics
refactor: remove order synchronization logic from admin page and streamline order loading
This commit is contained in:
parent
9a1a562fc6
commit
bb3b1f25f2
BIN
prisma/lootah.db
BIN
prisma/lootah.db
Binary file not shown.
@ -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' && (
|
||||
<div>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '0.5rem', marginBottom: '0.75rem', alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{syncMsg && <span style={{ fontSize: '0.75rem', color: syncMsg.startsWith('✓') ? '#16a34a' : '#dc2626', marginRight: 'auto' }}>{syncMsg}</span>}
|
||||
<button onClick={handleSyncOrders} disabled={syncingOrders || ordersLoading} style={{ ...ghostBtnStyle, fontSize: '0.75rem' }} title="Pull all PaymentIntents from Stripe into DB">
|
||||
{syncingOrders ? 'Syncing…' : '⟳ Sync from Stripe'}
|
||||
</button>
|
||||
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '0.5rem', marginBottom: '0.75rem', alignItems: 'center' }}>
|
||||
<button onClick={loadOrders} disabled={ordersLoading} style={secondaryBtnStyle}>
|
||||
{ordersLoading ? 'Loading…' : 'Refresh'}
|
||||
</button>
|
||||
|
||||
@ -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<string, string> = {};
|
||||
|
||||
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<string, string>;
|
||||
} 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,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user