nxtgauge-frontend-solid/src/components/dashboard/VerificationStatusPage.tsx
Tracewebstudio Dev 9358ab541f
All checks were successful
build-and-release / build (push) Successful in 1m37s
fix: verification page transitions cleanly to Pending Review after wizard submit
- VerificationStatusPage: showInlineEditors now hides for PENDING and
  UNDER_REVIEW (only shows when user action is needed: NOT_SUBMITTED,
  DOCUMENTS_REQUESTED, REVISION_REQUESTED, REJECTED). Previously the
  old ProfilePage form with validation errors appeared after submission.

- VerificationStatusPage: wrap onVerificationStatusChange passed to
  ProfilePage so the local status signal also updates when the wizard
  calls onSubmitted. Previously the status card kept showing NOT_SUBMITTED
  until a page reload.

- VerificationStatusPage progress tracker: inline signal reads directly
  in JSX instead of capturing them in local variables. In Solid.js, local
  const done = signal() inside a For callback is computed once and goes
  stale — the step circles stayed grey even after status changed to PENDING.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-30 15:36:29 +02:00

649 lines
29 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* VerificationStatusPage — shows the user their current verification state.
* Handles: NOT_SUBMITTED, PENDING, UNDER_REVIEW, DOCUMENTS_REQUESTED,
* REVISION_REQUESTED, APPROVED, REJECTED.
* Tabs: approval status, documents, activity
*/
import { For, Show, createMemo, createSignal, onMount } from 'solid-js';
import { ShieldCheck, FileText, Activity } from 'lucide-solid';
import { CARD, BTN_ORANGE, BTN_GHOST } from '~/components/DashboardShell';
import ProfilePage from '~/components/dashboard/ProfilePage';
import PortfolioPage from '~/components/dashboard/PortfolioPage';
import { getDocFields } from '~/lib/profile-fields-config';
import { presignDocumentUrl } from '~/lib/api';
const NAVY = '#0D0D2A';
const ORANGE = '#FF5E13';
type TabKey = 'approval_status' | 'documents' | 'activity';
// The K8s ingress routes /api/* directly to the Rust gateway service in
// production — there is no /api/gateway rewrite layer, so paths (already
// fully-qualified /api/... from callers) are hit as-is.
async function apiFetch(path: string, opts?: RequestInit) {
const token =
typeof window !== "undefined"
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
: "";
return fetch(path, {
...opts,
credentials: "include",
headers: {
"Content-Type": "application/json",
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts?.headers ?? {}),
},
});
}
// ── Status config ─────────────────────────────────────────────────────────────
const STATUS_CONFIG: Record<string, {
emoji: string;
label: string;
color: string;
bg: string;
border: string;
description: string;
}> = {
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 2448 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.',
},
COMPLETED: {
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;
case 'COMPLETED':
case 'APPROVED': return 4;
default: return 1;
}
}
// ── Component ─────────────────────────────────────────────────────────────────
interface Props {
roleKey: string;
onNavigate?: (sidebar: string) => void;
onVerificationStatusChange?: (status: string) => void;
runtimeFields?: string[];
runtimeTabs?: string[];
}
interface VerificationDocument {
type: string;
value: any;
status: string;
}
interface VerificationStatusResponse {
status: string;
reference_number: string;
document_request?: string | null;
rejection_reason?: string | null;
updated_at?: string | null;
activity_log?: Array<{ date: string; action: string; details: string }>;
documents: VerificationDocument[];
}
// Best-effort extraction of a viewable URL from a document's `value` payload,
// which may be a raw URL string or an upload-response object.
function docUrl(value: any): string | null {
if (!value) return null;
if (typeof value === 'string') return value;
if (typeof value === 'object') {
return value.url ?? value.file_url ?? value.fileUrl ?? value.path ?? null;
}
return null;
}
export default function VerificationStatusPage(props: Props) {
const [activeTab, setActiveTab] = createSignal<TabKey>('approval_status');
const [inlineSection, setInlineSection] = createSignal<'profile' | 'portfolio'>('profile');
const [status, setStatus] = createSignal('NOT_SUBMITTED');
const [referenceNumber, setReferenceNumber] = createSignal<string | null>(null);
const [docRequest, setDocRequest] = createSignal<string | null>(null);
const [rejectionReason, setRejectionReason] = createSignal<string | null>(null);
const [updatedAt, setUpdatedAt] = createSignal<string | null>(null);
const [loading, setLoading] = createSignal(true);
const [resubmitting, setResubmitting] = createSignal(false);
const [resubmitMsg, setResubmitMsg] = createSignal('');
const [activityLog, setActivityLog] = createSignal<Array<{ date: string; action: string; details: string }>>([]);
const [documents, setDocuments] = createSignal<VerificationDocument[]>([]);
onMount(async () => {
try {
const res = await apiFetch(`/api/me/verification-status?roleKey=${props.roleKey}`);
if (res.ok) {
const d: VerificationStatusResponse = await res.json();
const nextStatus = String(d.status ?? 'NOT_SUBMITTED');
setStatus(nextStatus);
props.onVerificationStatusChange?.(nextStatus);
setReferenceNumber(d.reference_number ?? null);
setDocRequest(d.document_request ?? null);
setRejectionReason(d.rejection_reason ?? null);
setUpdatedAt(d.updated_at ?? null);
if (d.activity_log) {
setActivityLog(d.activity_log);
}
if (d.documents) {
setDocuments(d.documents);
}
}
} finally {
setLoading(false);
}
});
const cfg = () => STATUS_CONFIG[status()] ?? STATUS_CONFIG.NOT_SUBMITTED;
const currentStep = () => stepIndex(status());
const docFields = createMemo(() => getDocFields(props.roleKey));
const canResubmit = () => ['DOCUMENTS_REQUESTED', 'REVISION_REQUESTED', 'REJECTED'].includes(status());
const isApproved = () => ['APPROVED', 'COMPLETED'].includes(status());
// Hide the inline form editors once submitted — PENDING/UNDER_REVIEW don't
// need editing, only statuses that require user action (NOT_SUBMITTED,
// DOCUMENTS_REQUESTED, REVISION_REQUESTED, REJECTED) do.
const showInlineEditors = () =>
['NOT_SUBMITTED', 'DOCUMENTS_REQUESTED', 'REVISION_REQUESTED', 'REJECTED'].includes(status());
const hasPortfolio = () => {
const role = String(props.roleKey || '').toUpperCase();
return role === 'JOB_SEEKER' || role !== 'COMPANY' && role !== 'CUSTOMER';
};
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');
props.onVerificationStatusChange?.('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);
}
};
const TABS: { key: TabKey; label: string; Icon: any }[] = [
{ key: 'approval_status', label: 'Approval Status', Icon: ShieldCheck },
{ key: 'documents', label: 'Documents', Icon: FileText },
{ key: 'activity', label: 'Activity', Icon: Activity },
];
return (
<div style={{ 'max-width': '640px' }}>
<div
style={{
background: NAVY,
"border-radius": "12px",
padding: "16px 20px",
display: "flex",
"align-items": "center",
gap: "12px",
"margin-bottom": "14px",
}}
>
<span style={{ color: ORANGE }}>
<ShieldCheck size={24} />
</span>
<div>
<p style={{ margin: "0", "font-size": "18px", "font-weight": "800", color: "#fff" }}>
Verification Portal
</p>
<p style={{ margin: "4px 0 0", "font-size": "13px", color: "rgba(255,255,255,0.65)" }}>
Track verification progress, documents, and updates.
</p>
<Show when={referenceNumber()}>
<p style={{ margin: "6px 0 0", "font-size": "13px", "font-family": "monospace", color: "rgba(255,255,255,0.85)" }}>
{referenceNumber()}
</p>
</Show>
</div>
</div>
{/* Tabs */}
<div style={{ display: 'flex', gap: '0', 'border-bottom': '1px solid #E5E7EB', 'margin-bottom': '14px' }}>
<For each={TABS}>
{(tab) => (
<button
type="button"
onClick={() => setActiveTab(tab.key)}
style={{
padding: "10px 16px",
"border-bottom": activeTab() === tab.key ? '2px solid #FF5E13' : '2px solid transparent',
background: "transparent",
color: activeTab() === tab.key ? "#FF5E13" : "#6B7280",
"font-size": "14px",
"font-weight": activeTab() === tab.key ? "700" : "500",
cursor: "pointer",
display: "flex",
"align-items": "center",
gap: "6px",
}}
>
<tab.Icon size={16} />
{tab.label}
</button>
)}
</For>
</div>
<Show when={loading()}>
<div style={{ ...CARD, 'text-align': 'center', padding: '32px', color: '#9CA3AF' }}>
Loading verification status…
</div>
</Show>
<Show when={!loading()}>
{/* ── Approval Status Tab ─────────────────────────────────────── */}
<Show when={activeTab() === 'approval_status'}>
{/* Main status card */}
<div style={{
...CARD,
background: cfg().bg,
border: `1px solid ${cfg().border}`,
'margin-bottom': '16px',
display: 'flex',
'flex-direction': 'column',
gap: '12px',
}}>
<div style={{ display: 'flex', 'align-items': 'center', gap: '12px' }}>
<span style={{ 'font-size': '36px', 'line-height': '1' }}>{cfg().emoji}</span>
<div>
<p style={{ margin: '0', 'font-size': '11px', 'text-transform': 'uppercase', 'letter-spacing': '0.08em', color: cfg().color, 'font-weight': '700' }}>
Verification Status
</p>
<p style={{ margin: '2px 0 0', 'font-size': '22px', 'font-weight': '800', color: cfg().color }}>
{cfg().label}
</p>
</div>
</div>
<p style={{ margin: '0', 'font-size': '13px', color: '#374151', 'line-height': '1.6' }}>
{cfg().description}
</p>
<Show when={updatedAt()}>
<p style={{ margin: '0', 'font-size': '11px', color: '#9CA3AF' }}>
Last updated: {new Date(updatedAt()!).toLocaleString('en-IN')}
</p>
</Show>
</div>
{/* Doc request / rejection reason */}
<Show when={docRequest()}>
<div style={{ ...CARD, background: '#FFF7ED', border: '1px solid #FED7AA', 'margin-bottom': '16px' }}>
<p style={{ margin: '0 0 6px', 'font-size': '12px', 'font-weight': '700', 'text-transform': 'uppercase', 'letter-spacing': '0.06em', color: '#C2410C' }}>
Document Request from Admin
</p>
<p style={{ margin: '0', 'font-size': '14px', color: '#374151', 'line-height': '1.6' }}>
{docRequest()}
</p>
</div>
</Show>
<Show when={rejectionReason()}>
<div style={{ ...CARD, background: '#FEF2F2', border: '1px solid #FECACA', 'margin-bottom': '16px' }}>
<p style={{ margin: '0 0 6px', 'font-size': '12px', 'font-weight': '700', 'text-transform': 'uppercase', 'letter-spacing': '0.06em', color: '#B91C1C' }}>
Rejection Reason
</p>
<p style={{ margin: '0', 'font-size': '14px', color: '#374151', 'line-height': '1.6' }}>
{rejectionReason()}
</p>
</div>
</Show>
{/* Progress timeline */}
<Show when={!['APPROVED', 'COMPLETED'].includes(status())}>
<div style={{ ...CARD, 'margin-bottom': '16px' }}>
<p style={{ margin: '0 0 14px', 'font-size': '14px', 'font-weight': '700', color: '#111827' }}>
Verification Progress
</p>
<div style={{ display: 'flex', 'align-items': 'center', gap: '0' }}>
<For each={FLOW_STEPS}>
{(step, idx) => (
<>
<div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center', 'flex-shrink': '0' }}>
<div style={{
width: '28px',
height: '28px',
'border-radius': '999px',
display: 'flex',
'align-items': 'center',
'justify-content': 'center',
'font-size': '11px',
'font-weight': '800',
background: currentStep() > idx() ? '#FF5E13' : currentStep() === idx() + 1 ? '#FFF3EE' : '#F3F4F6',
color: currentStep() > idx() ? '#fff' : currentStep() === idx() + 1 ? '#FF5E13' : '#9CA3AF',
border: currentStep() === idx() + 1 ? '2px solid #FF5E13' : '2px solid transparent',
}}>
{currentStep() > idx() ? '✓' : idx() + 1}
</div>
<p style={{ margin: '4px 0 0', 'font-size': '10px', 'font-weight': '600', color: currentStep() > idx() || currentStep() === idx() + 1 ? '#374151' : '#9CA3AF', 'white-space': 'nowrap', 'text-align': 'center' }}>
{step.label}
</p>
</div>
<Show when={idx() < FLOW_STEPS.length - 1}>
<div style={{ flex: '1', height: '2px', background: currentStep() > idx() ? '#FF5E13' : '#E5E7EB', 'margin-bottom': '18px' }} />
</Show>
</>
)}
</For>
</div>
</div>
</Show>
{/* Actions */}
<div style={{ display: 'flex', gap: '10px', 'flex-wrap': 'wrap' }}>
<Show when={status() === 'NOT_SUBMITTED'}>
<button type="button" onClick={() => setInlineSection('profile')} style={BTN_ORANGE}>
Fill My Profile
</button>
<button type="button" onClick={() => setInlineSection('portfolio')} style={BTN_GHOST}>
Fill My Portfolio
</button>
</Show>
<Show when={canResubmit()}>
<button type="button" onClick={() => setInlineSection('profile')} style={BTN_GHOST}>
Update My Profile
</button>
<button type="button" onClick={handleResubmit} disabled={resubmitting()} style={{ ...BTN_ORANGE, opacity: resubmitting() ? '0.7' : '1' }}>
{resubmitting() ? 'Resubmitting…' : 'Resubmit for Verification'}
</button>
</Show>
</div>
<Show when={resubmitMsg()}>
<p style={{ margin: '12px 0 0', 'font-size': '13px', 'font-weight': '600', color: resubmitMsg().includes('successfully') ? '#10B981' : '#EF4444' }}>
{resubmitMsg()}
</p>
</Show>
<Show when={['APPROVED', 'COMPLETED'].includes(status())}>
<div style={{ ...CARD, background: '#ECFDF5', border: '1px solid #6EE7B7', 'text-align': 'center', padding: '32px' }}>
<p style={{ margin: '0', 'font-size': '48px' }}>🎉</p>
<p style={{ margin: '12px 0 4px', 'font-size': '20px', 'font-weight': '800', color: '#065F46' }}>
You're Verified!
</p>
<p style={{ margin: '0', 'font-size': '14px', color: '#047857', 'line-height': '1.6' }}>
Your profile is approved. Start exploring opportunities on Nxtgauge.
</p>
</div>
</Show>
<Show when={showInlineEditors()}>
<div style={{ ...CARD, 'margin-top': '16px', padding: '16px' }}>
<div style={{ display: 'flex', 'justify-content': 'space-between', 'align-items': 'center', gap: '12px', 'flex-wrap': 'wrap', 'margin-bottom': '14px' }}>
<div>
<p style={{ margin: '0', 'font-size': '16px', 'font-weight': '800', color: '#111827' }}>
Complete Verification Details Here
</p>
<p style={{ margin: '6px 0 0', 'font-size': '13px', color: '#6B7280' }}>
Fill the required fields directly on this page, then submit for verification.
</p>
</div>
<div style={{ display: 'flex', gap: '8px', 'flex-wrap': 'wrap' }}>
<button
type="button"
onClick={() => setInlineSection('profile')}
style={inlineSection() === 'profile' ? BTN_ORANGE : BTN_GHOST}
>
Profile Fields
</button>
<Show when={hasPortfolio()}>
<button
type="button"
onClick={() => setInlineSection('portfolio')}
style={inlineSection() === 'portfolio' ? BTN_ORANGE : BTN_GHOST}
>
Portfolio Fields
</button>
</Show>
</div>
</div>
<Show when={inlineSection() === 'profile'}>
<ProfilePage
roleKey={props.roleKey}
runtimeFields={props.runtimeFields || []}
onVerificationStatusChange={(s) => {
setStatus(s);
props.onVerificationStatusChange?.(s);
}}
onNavigate={props.onNavigate}
/>
</Show>
<Show when={inlineSection() === 'portfolio' && hasPortfolio()}>
<PortfolioPage
roleKey={props.roleKey}
runtimeTabs={props.runtimeTabs || []}
runtimeFields={props.runtimeFields || []}
/>
</Show>
</div>
</Show>
</Show>
{/* ── Documents Tab ───────────────────────────────────────────── */}
<Show when={activeTab() === 'documents'}>
<div style={CARD}>
<p style={{ margin: '0 0 14px', 'font-size': '16px', 'font-weight': '700', color: '#111827' }}>
Submitted Documents
</p>
<Show when={!docRequest() && !rejectionReason() && status() === 'NOT_SUBMITTED'}>
<p style={{ margin: '0', 'font-size': '13px', color: '#6B7280' }}>
No documents submitted yet. Complete your profile to submit documents for verification.
</p>
</Show>
<Show when={docRequest()}>
<div style={{ background: '#FFF7ED', border: '1px solid #FED7AA', 'border-radius': '10px', padding: '14px', 'margin-bottom': '12px' }}>
<p style={{ margin: '0 0 6px', 'font-size': '13px', 'font-weight': '700', color: '#C2410C' }}>
Document Request
</p>
<p style={{ margin: '0', 'font-size': '13px', color: '#374151' }}>{docRequest()}</p>
</div>
</Show>
<Show when={rejectionReason()}>
<div style={{ background: '#FEF2F2', border: '1px solid #FECACA', 'border-radius': '10px', padding: '14px', 'margin-bottom': '12px' }}>
<p style={{ margin: '0 0 6px', 'font-size': '13px', 'font-weight': '700', color: '#B91C1C' }}>
Rejection Reason
</p>
<p style={{ margin: '0', 'font-size': '13px', color: '#374151' }}>{rejectionReason()}</p>
</div>
</Show>
<Show when={status() !== 'NOT_SUBMITTED'}>
<div style={{ display: 'flex', 'flex-direction': 'column', gap: '8px' }}>
<For each={documents().length > 0 ? documents() : docFields().map((f) => ({ type: f.key, value: null, status: status() }))}>
{(doc) => {
const fieldLabel = () => docFields().find((f) => f.key === doc.type)?.label ?? doc.type;
const url = () => docUrl(doc.value);
return (
<div style={{ border: '1px solid #E5E7EB', 'border-radius': '10px', padding: '12px', background: '#FCFCFD' }}>
<div style={{ display: 'flex', 'justify-content': 'space-between', 'align-items': 'center', gap: '10px', 'flex-wrap': 'wrap' }}>
<div>
<p style={{ margin: '0', 'font-size': '13px', 'font-weight': '600', color: '#111827' }}>{fieldLabel()}</p>
<Show
when={url()}
fallback={
<p style={{ margin: '4px 0 0', 'font-size': '12px', color: '#9CA3AF' }}>No file uploaded</p>
}
>
<button
type="button"
onClick={async () => {
const signed = await presignDocumentUrl(url()!);
window.open(signed, '_blank', 'noopener,noreferrer');
}}
style={{
margin: '4px 0 0', 'font-size': '12px', color: '#FF5E13',
'text-decoration': 'underline', display: 'inline-block',
background: 'none', border: 'none', padding: '0', cursor: 'pointer',
}}
>
View document
</button>
</Show>
</div>
<p style={{
margin: '0',
'font-size': '12px',
'font-weight': '600',
color: doc.status === 'APPROVED' ? '#059669' : doc.status === 'REJECTED' ? '#DC2626' : '#6B7280',
}}>
{doc.status === 'APPROVED' ? '✓ Verified' : doc.status === 'REJECTED' ? '✕ Rejected' : doc.status === 'SUBMITTED' ? '◌ Submitted' : '◌ Pending review'}
</p>
</div>
</div>
);
}}
</For>
</div>
</Show>
</div>
</Show>
{/* ── Activity Tab ────────────────────────────────────────────── */}
<Show when={activeTab() === 'activity'}>
<div style={CARD}>
<p style={{ margin: '0 0 14px', 'font-size': '16px', 'font-weight': '700', color: '#111827' }}>
Verification Activity
</p>
<Show when={activityLog().length === 0}>
<div style={{ display: 'flex', 'flex-direction': 'column', gap: '10px' }}>
<Show when={status() === 'NOT_SUBMITTED'}>
<div style={{ display: 'flex', gap: '12px', 'align-items': 'flex-start' }}>
<div style={{ width: '8px', height: '8px', 'border-radius': '50%', background: '#E5E7EB', 'margin-top': '6px', 'flex-shrink': '0' }} />
<div>
<p style={{ margin: '0', 'font-size': '13px', 'font-weight': '600', color: '#374151' }}>Profile created</p>
<p style={{ margin: '2px 0 0', 'font-size': '12px', color: '#9CA3AF' }}>{updatedAt() ? new Date(updatedAt()!).toLocaleString('en-IN') : 'Just now'}</p>
</div>
</div>
</Show>
<Show when={!['NOT_SUBMITTED'].includes(status())}>
<div style={{ display: 'flex', gap: '12px', 'align-items': 'flex-start' }}>
<div style={{ width: '8px', height: '8px', 'border-radius': '50%', background: '#FDE68A', 'margin-top': '6px', 'flex-shrink': '0' }} />
<div>
<p style={{ margin: '0', 'font-size': '13px', 'font-weight': '600', color: '#374151' }}>Profile submitted for verification</p>
<p style={{ margin: '2px 0 0', 'font-size': '12px', color: '#9CA3AF' }}>{updatedAt() ? new Date(updatedAt()!).toLocaleString('en-IN') : 'Recently'}</p>
</div>
</div>
</Show>
<Show when={['APPROVED', 'COMPLETED'].includes(status())}>
<div style={{ display: 'flex', gap: '12px', 'align-items': 'flex-start' }}>
<div style={{ width: '8px', height: '8px', 'border-radius': '50%', background: '#10B981', 'margin-top': '6px', 'flex-shrink': '0' }} />
<div>
<p style={{ margin: '0', 'font-size': '13px', 'font-weight': '600', color: '#374151' }}>Profile approved</p>
<p style={{ margin: '2px 0 0', 'font-size': '12px', color: '#9CA3AF' }}>{updatedAt() ? new Date(updatedAt()!).toLocaleString('en-IN') : 'Recently'}</p>
</div>
</div>
</Show>
</div>
</Show>
<Show when={activityLog().length > 0}>
<div style={{ display: 'flex', 'flex-direction': 'column', gap: '12px' }}>
<For each={activityLog()}>
{(item) => (
<div style={{ display: 'flex', gap: '12px', 'align-items': 'flex-start' }}>
<div style={{ width: '8px', height: '8px', 'border-radius': '50%', background: ORANGE, 'margin-top': '6px', 'flex-shrink': '0' }} />
<div>
<p style={{ margin: '0', 'font-size': '13px', 'font-weight': '600', color: '#374151' }}>{item.action}</p>
<p style={{ margin: '2px 0 0', 'font-size': '12px', color: '#9CA3AF' }}>{item.date}</p>
<Show when={item.details}>
<p style={{ margin: '4px 0 0', 'font-size': '12px', color: '#6B7280' }}>{item.details}</p>
</Show>
</div>
</div>
)}
</For>
</div>
</Show>
</div>
</Show>
</Show>
</div>
);
}