/opt/canhelp/apps/web/src/app/payment
NameSizeModeActions
page.tsx52980644editdlrm
Edit: /opt/canhelp/apps/web/src/app/payment/page.tsx (5298B)
'use client' import { useEffect, useState } from 'react' import { useSearchParams } from 'next/navigation' import Link from 'next/link' import type { ReactNode } from 'react' import { useLocale } from '@/context/locale' import * as api from '@/lib/api' // Status is determined either by: // 1. ?status=cancelled (from our cancel redirect) // 2. ?ref=ORDER_REF → we poll /payments/history to check the order status export default function PaymentPage() { const searchParams = useSearchParams() const { t } = useLocale() const statusParam = searchParams.get('status') const ref = searchParams.get('ref') const [status, setStatus] = useState<'pending' | 'success' | 'failed' | 'cancelled' | 'loading'>( statusParam === 'cancelled' ? 'cancelled' : ref ? 'loading' : 'pending', ) useEffect(() => { if (statusParam === 'cancelled') { setStatus('cancelled') return } if (!ref) return // Poll payment history to find the order status let attempts = 0 const MAX = 12 // ~24 seconds total const INTERVAL = 2000 const check = async () => { attempts++ try { const history = await api.getPaymentHistory() const payment = history.find((p) => p.orderRef === ref) if (payment && payment.status !== 'pending') { setStatus(payment.status as any) return } } catch {} if (attempts < MAX) { setTimeout(check, INTERVAL) } else { setStatus('pending') // timeout - show pending message } } setTimeout(check, INTERVAL) }, [ref, statusParam]) const config: Record = { success: { icon: ( ), title: t('payment.success.title'), desc: t('payment.success.desc'), color: 'text-green-700', bg: 'bg-green-50', border: 'border-green-200', }, cancelled: { icon: ( ), title: t('payment.cancelled.title'), desc: t('payment.cancelled.desc'), color: 'text-yellow-700', bg: 'bg-yellow-50', border: 'border-yellow-200', }, failed: { icon: ( ), title: t('payment.cancelled.title'), desc: t('payment.cancelled.desc'), color: 'text-red-700', bg: 'bg-red-50', border: 'border-red-200', }, pending: { icon: ( ), title: t('payment.pending.title'), desc: t('payment.pending.desc'), color: 'text-green-700', bg: 'bg-green-50', border: 'border-green-200', }, loading: { icon: ( ), title: t('payment.pending.title'), desc: t('payment.pending.desc'), color: 'text-gray-700', bg: 'bg-gray-50', border: 'border-gray-200', }, } const current = config[status] ?? config.pending return (
{current.icon}

{current.title}

{current.desc}

{t('payment.back_to_profile')}
) }