/** * VerificationStatusPage — shows the user their current verification state. * Handles: NOT_SUBMITTED, PENDING, UNDER_REVIEW, DOCUMENTS_REQUESTED, * REVISION_REQUESTED, APPROVED, REJECTED. */ import { Show, createSignal, onMount } from 'solid-js'; import { CARD, BTN_ORANGE, BTN_GHOST } from '~/components/DashboardShell'; const API = '/api/gateway'; async function apiFetch(path: string, opts?: RequestInit) { const token = typeof window !== "undefined" ? window.sessionStorage.getItem("nxtgauge_access_token") || "" : ""; return fetch(`${API}${path}`, { ...opts, credentials: "include", headers: { "Content-Type": "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}), ...(opts?.headers ?? {}), }, }); } // ── Status config ───────────────────────────────────────────────────────────── const STATUS_CONFIG: Record = { NOT_SUBMITTED: { emoji: '📋', label: 'Not Submitted', color: '#6B7280', bg: '#F9FAFB', border: '#E5E7EB', description: 'Complete your My Profile and My Portfolio, then submit for verification to start using the platform.', }, PENDING: { emoji: '⏳', label: 'Pending Review', color: '#92400E', bg: '#FFFBEB', border: '#FDE68A', description: 'Your profile has been submitted and is in the review queue. We typically respond within 24–48 hours.', }, UNDER_REVIEW: { emoji: '🔍', label: 'Under Review', color: '#1E40AF', bg: '#EEF2FF', border: '#BFDBFE', description: 'Our team is actively reviewing your submission. You will be notified once a decision is made.', }, DOCUMENTS_REQUESTED: { emoji: '📎', label: 'Documents Requested', color: '#C2410C', bg: '#FFF7ED', border: '#FED7AA', description: 'Admin has requested additional or clearer documents. Please review the message below and resubmit.', }, REVISION_REQUESTED: { emoji: '✏️', label: 'Revision Requested', color: '#C2410C', bg: '#FFF7ED', border: '#FED7AA', description: 'Admin has requested changes to your profile information. Please update and resubmit.', }, APPROVED: { emoji: '✅', label: 'Approved', color: '#065F46', bg: '#ECFDF5', border: '#6EE7B7', description: 'Your profile has been verified and approved. You now have full access to the platform.', }, REJECTED: { emoji: '❌', label: 'Rejected', color: '#991B1B', bg: '#FEF2F2', border: '#FECACA', description: 'Your verification was rejected. Please review the reason below, update your profile, and resubmit.', }, }; const FLOW_STEPS = [ { key: 'submit', label: 'Submit Profile' }, { key: 'review', label: 'Under Review' }, { key: 'verify', label: 'Verified' }, { key: 'approved', label: 'Approved' }, ]; function stepIndex(status: string): number { switch (status) { case 'NOT_SUBMITTED': return 0; case 'PENDING': return 1; case 'UNDER_REVIEW': return 2; case 'DOCUMENTS_REQUESTED': case 'REVISION_REQUESTED': return 2; // still at review stage case 'APPROVED': return 4; default: return 1; } } // ── Component ───────────────────────────────────────────────────────────────── interface Props { roleKey: string; onNavigate?: (sidebar: string) => void; } export default function VerificationStatusPage(props: Props) { const [status, setStatus] = createSignal('NOT_SUBMITTED'); const [docRequest, setDocRequest] = createSignal(null); const [rejectionReason, setRejectionReason] = createSignal(null); const [updatedAt, setUpdatedAt] = createSignal(null); const [loading, setLoading] = createSignal(true); const [resubmitting, setResubmitting] = createSignal(false); const [resubmitMsg, setResubmitMsg] = createSignal(''); onMount(async () => { try { const res = await apiFetch(`/api/me/verification-status?roleKey=${props.roleKey}`); if (res.ok) { const d = await res.json(); setStatus(d.status ?? 'NOT_SUBMITTED'); setDocRequest(d.document_request ?? null); setRejectionReason(d.rejection_reason ?? null); setUpdatedAt(d.updated_at ?? null); } } finally { setLoading(false); } }); const cfg = () => STATUS_CONFIG[status()] ?? STATUS_CONFIG.NOT_SUBMITTED; const currentStep = () => stepIndex(status()); const canResubmit = () => ['DOCUMENTS_REQUESTED', 'REVISION_REQUESTED', 'REJECTED'].includes(status()); const handleResubmit = async () => { setResubmitting(true); setResubmitMsg(''); try { const res = await apiFetch('/api/profile/submit-for-verification', { method: 'POST', body: JSON.stringify({ roleKey: props.roleKey }), }); const d = await res.json().catch(() => ({})); if (res.ok) { setStatus('PENDING'); setDocRequest(null); setRejectionReason(null); setResubmitMsg('Resubmitted successfully! We will review your profile.'); } else if (res.status === 409) { setResubmitMsg(d.error ?? 'A verification is already in progress.'); } else { setResubmitMsg(d.error ?? 'Resubmission failed. Please try again.'); } } catch { setResubmitMsg('Network error. Please try again.'); } finally { setResubmitting(false); } }; return (
Loading verification status…
{/* ── Main status card ─────────────────────────────────────────── */}
{cfg().emoji}

Verification Status

{cfg().label}

{cfg().description}

Last updated: {new Date(updatedAt()!).toLocaleString('en-IN')}

{/* ── Doc request / rejection reason ──────────────────────────── */}

Document Request from Admin

{docRequest()}

Rejection Reason

{rejectionReason()}

{/* ── Progress timeline ──────────────────────────────────────── */}

Verification Progress

{FLOW_STEPS.map((step, idx) => { const done = currentStep() > idx; const active = currentStep() === idx + 1; return ( <>
{done ? '✓' : idx + 1}

{step.label}

{idx < FLOW_STEPS.length - 1 && (
)} ); })}
{/* ── Actions ───────────────────────────────────────────────── */}

{resubmitMsg()}

{/* ── Approved state: success message ───────────────────────── */}

🎉

You're Verified!

Your profile is approved. Start exploring opportunities on Nxtgauge.

); }