'use client'; import React from 'react'; import { t } from '@/i18n/locales'; import { useApi } from '@/lib/use-api'; /** * D8.4 IPO准备度检查清单 - 独立页面 */ interface CheckItem { id: string; item: string; category: string; status: 'done' | 'progress' | 'blocked' | 'pending'; owner: string; deadline: string; dependency?: string; note?: string; } interface IpoData { overallProgress: { total: number; done: number; inProgress: number; blocked: number; pending: number; percent: number }; milestones: { name: string; date: string; status: 'done' | 'progress' | 'pending' }[]; checklistItems: CheckItem[]; keyContacts: { role: string; name: string; status: string }[]; } const loadingBox: React.CSSProperties = { display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 40, color: 'var(--color-text-tertiary)', font: 'var(--text-body)', }; const categories = [ { key: 'legal', label: () => t('ipo_cat_legal'), icon: '§', color: 'var(--color-primary)' }, { key: 'financial', label: () => t('ipo_cat_financial'), icon: '$', color: 'var(--color-success)' }, { key: 'sox', label: () => t('ipo_cat_sox'), icon: '✓', color: 'var(--color-info)' }, { key: 'governance', label: () => t('ipo_cat_governance'), icon: '◆', color: 'var(--color-warning)' }, { key: 'insurance', label: () => t('ipo_cat_insurance'), icon: '☂', color: '#FF6B6B' }, ]; const statusConfig: Record string; bg: string; fg: string }> = { done: { label: () => t('completed'), bg: 'var(--color-success-light)', fg: 'var(--color-success)' }, progress: { label: () => t('in_progress'), bg: 'var(--color-warning-light)', fg: 'var(--color-warning)' }, blocked: { label: () => t('blocked'), bg: 'var(--color-error-light)', fg: 'var(--color-error)' }, pending: { label: () => t('pending'), bg: 'var(--color-gray-100)', fg: 'var(--color-text-tertiary)' }, }; export const IpoReadinessPage: React.FC = () => { const { data: ipoData, isLoading, error } = useApi('/api/v1/admin/compliance/reports'); const { data: insuranceData } = useApi<{ ipoReadiness: number }>('/api/v1/admin/insurance/stats'); if (error) return
Error: {error.message}
; if (isLoading) return
Loading...
; const overallProgress = ipoData?.overallProgress ?? { total: 0, done: 0, inProgress: 0, blocked: 0, pending: 0, percent: 0 }; const milestones = ipoData?.milestones ?? []; const checklistItems = ipoData?.checklistItems ?? []; const keyContacts = ipoData?.keyContacts ?? []; return (

{t('ipo_title')}

{t('ipo_subtitle')}

{/* Summary Stats */}
{[ { label: t('ipo_total_items'), value: overallProgress.total, color: 'var(--color-text-primary)' }, { label: t('completed'), value: overallProgress.done, color: 'var(--color-success)' }, { label: t('in_progress'), value: overallProgress.inProgress, color: 'var(--color-warning)' }, { label: t('blocked'), value: overallProgress.blocked, color: 'var(--color-error)' }, { label: t('pending'), value: overallProgress.pending, color: 'var(--color-text-tertiary)' }, ].map(s => (
{s.label}
{s.value}
))}
{/* Overall Progress Bar */}
{t('ipo_overall_progress')} {overallProgress.percent}%
0 ? (overallProgress.done / overallProgress.total * 100).toFixed(0) : 0}%`, height: '100%', background: 'var(--color-success)' }} />
0 ? (overallProgress.inProgress / overallProgress.total * 100).toFixed(0) : 0}%`, height: '100%', background: 'var(--color-warning)' }} />
0 ? (overallProgress.blocked / overallProgress.total * 100).toFixed(0) : 0}%`, height: '100%', background: 'var(--color-error)' }} />
{[ { label: t('completed'), color: 'var(--color-success)' }, { label: t('in_progress'), color: 'var(--color-warning)' }, { label: t('blocked'), color: 'var(--color-error)' }, { label: t('pending'), color: 'var(--color-gray-200)' }, ].map(l => (
{l.label}
))}
{/* Left: Checklist by Category */}
{categories.map(cat => { const items = checklistItems.filter(i => i.category === cat.key); const catDone = items.filter(i => i.status === 'done').length; if (items.length === 0) return null; return (
{cat.icon}
{cat.label()}
{catDone}/{items.length} {t('ipo_unit_done')}
{[t('ipo_th_id'), t('ipo_th_item'), t('ipo_th_owner'), t('ipo_th_deadline'), t('ipo_th_status')].map(h => ( ))} {items.map(item => { const st = statusConfig[item.status]; return ( ); })}
{h}
{item.id}
{item.item}
{item.note &&
{item.note}
} {item.dependency && (
{t('ipo_dependency')}: {item.dependency}
)}
{item.owner} {item.deadline} {st.label()}
); })}
{/* Right: Timeline & Blockers */}
{/* IPO Timeline */}

{t('ipo_timeline')}

{milestones.map((m, i) => (
{i < milestones.length - 1 && (
)}
{m.name}
{m.date}
))}
{/* Blockers */}

{t('ipo_blockers')}

{checklistItems.filter(i => i.status === 'blocked').map(item => (
{item.id}: {item.item}
{t('ipo_owner')}: {item.owner} · {t('ipo_deadline')}: {item.deadline}
{item.note && (
{item.note}
)}
))}
{/* Category Progress */}

{t('ipo_category_progress')}

{categories.map(cat => { const items = checklistItems.filter(i => i.category === cat.key); if (items.length === 0) return null; const catDone = items.filter(i => i.status === 'done').length; const pct = Math.round(catDone / items.length * 100); return (
{cat.label()} {pct}%
); })}
{/* Key Contacts */}

{t('ipo_key_contacts')}

{keyContacts.map(c => (
{c.role}
{c.name}
{c.status}
))}
); };