'use client'; import { useQuery } from '@tanstack/react-query'; import { apiFetch } from '../../../../lib/api'; import { useSession } from '../../../../components/session-provider'; interface Decision { id: string; context: string; selectedOption: string | null; status: string; createdAt: string; horizon: string | null; } interface Scenario { id: string; decisionId: string | null; title: string; probability: string; status: string; financialImpactMinorUnits: string | null; financialImpactCurrency: string; impactDirection: string; } interface ActionPlan { id: string; decisionId: string | null; title: string; status: string; priority: string; dueDate: string | null; } interface OutcomeReview { id: string; decisionId: string | null; title: string; wasSuccessful: boolean | null; rating: number | null; createdAt: string; } interface Assumption { id: string; decisionId: string | null; statement: string; status: string; confidence: string; } const PROB_WEIGHT: Record = { low: 0.2, medium: 0.5, high: 0.8 }; function fmtMoney(v: string | null, currency: string) { if (!v) return null; return new Intl.NumberFormat('ro-RO', { style: 'currency', currency, maximumFractionDigits: 0 }).format(parseFloat(v) / 100); } function LifecycleDot({ count, cls }: { count: number; cls: string }) { if (count === 0) return 0; return {count}; } export default function DecisionReportsPage() { const { activeTenant } = useSession(); const tenantId = activeTenant?.tenantId ?? ''; const { data: decisions = [], isLoading: dl } = useQuery({ queryKey: ['dec-r', tenantId], queryFn: () => apiFetch('/v1/decisions?limit=200', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const { data: scenarios = [] } = useQuery({ queryKey: ['scen-r', tenantId], queryFn: () => apiFetch('/v1/scenarios', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const { data: actionPlans = [] } = useQuery({ queryKey: ['ap-r', tenantId], queryFn: () => apiFetch('/v1/action-plans', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const { data: reviews = [] } = useQuery({ queryKey: ['or-r', tenantId], queryFn: () => apiFetch('/v1/outcome-reviews', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const { data: assumptions = [] } = useQuery({ queryKey: ['ass-r', tenantId], queryFn: () => apiFetch('/v1/assumptions', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const enrich = decisions.map((d) => ({ ...d, scenarios: scenarios.filter((s) => s.decisionId === d.id), plans: actionPlans.filter((a) => a.decisionId === d.id), reviews: reviews.filter((r) => r.decisionId === d.id), assumptions: assumptions.filter((a) => a.decisionId === d.id), })); const withReviews = enrich.filter((d) => d.reviews.length > 0); const avgRating = withReviews.reduce((s, d) => s + (d.reviews[0]?.rating ?? 0), 0) / (withReviews.length || 1); const successRate = withReviews.length > 0 ? Math.round(withReviews.filter((d) => d.reviews[0]?.wasSuccessful).length / withReviews.length * 100) : null; const totalEV = scenarios .filter((s) => s.status !== 'ruled_out') .reduce((sum, s) => { const v = parseFloat(s.financialImpactMinorUnits ?? '0') / 100; return sum + v * (PROB_WEIGHT[s.probability] ?? 0.5) * (s.impactDirection === 'negative' ? -1 : 1); }, 0); return (

Raport Decizii

{dl ? 'Se încarcă…' : `${decisions.length} decizii · ${scenarios.length} scenarii · ${actionPlans.length} planuri de acțiune`}

{/* Summary */}

{decisions.length}

Decizii totale

= 70 ? 'text-signal-ok' : 'text-signal-warn'}`}> {successRate !== null ? `${successRate}%` : '—'}

Rată succes

= 7 ? 'text-signal-ok' : avgRating >= 5 ? 'text-signal-warn' : 'text-signal-danger'}`}> {withReviews.length > 0 ? `${avgRating.toFixed(1)}` : '—'}

Rating mediu /10

= 0 ? 'text-signal-ok' : 'text-signal-danger'}`}> {totalEV !== 0 ? `${totalEV > 0 ? '+' : ''}${(totalEV/1000).toFixed(0)}k` : '—'}

EV ponderat (RON)

{/* Decision lifecycle table */}
{dl ? ( ) : enrich.length === 0 ? ( ) : enrich.map((d) => { const ev = d.scenarios .filter((s) => s.status !== 'ruled_out') .reduce((sum, s) => { const v = parseFloat(s.financialImpactMinorUnits ?? '0') / 100; return sum + v * (PROB_WEIGHT[s.probability] ?? 0.5) * (s.impactDirection === 'negative' ? -1 : 1); }, 0); const activePlans = d.plans.filter((p) => p.status === 'active').length; const refuted = d.assumptions.filter((a) => a.status === 'refuted').length; const reviewed = d.reviews[0]; return ( ); })}
Decizie Scenarii Planuri Asumpții Revizuiri EV
Se încarcă…
Nicio decizie.

{(d.context ?? '').slice(0, 80)}

{d.selectedOption && (

→ {d.selectedOption}

)}
{activePlans > 0 && {activePlans} activ}
{refuted > 0 && {refuted} inf.}
{reviewed ? (
{reviewed.wasSuccessful ? '✅' : reviewed.wasSuccessful === false ? '❌' : '📋'} {reviewed.rating && {reviewed.rating}/10}
) : ( )}
{ev !== 0 ? ( 0 ? 'text-signal-ok' : 'text-signal-danger'}`}> {ev > 0 ? '+' : ''}{(ev/1000).toFixed(0)}k ) : ( )}
); }