From 46d3836567dfed88429f5259f148f952869b5f63 Mon Sep 17 00:00:00 2001 From: admin-valentin Date: Sun, 2 Aug 2026 17:41:48 +0000 Subject: [PATCH] feat(CC-087): add Trust Credit Readiness (financial data completeness, MANDATORY disclaimers) --- .../dashboard/trust/credit-readiness/page.tsx | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/app/dashboard/trust/credit-readiness/page.tsx diff --git a/src/app/dashboard/trust/credit-readiness/page.tsx b/src/app/dashboard/trust/credit-readiness/page.tsx new file mode 100644 index 0000000..c3f23cb --- /dev/null +++ b/src/app/dashboard/trust/credit-readiness/page.tsx @@ -0,0 +1,130 @@ +'use client'; + +import { useMemo } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import Link from 'next/link'; +import { apiFetch } from '../../../../lib/api'; +import { useSession } from '../../../../components/session-provider'; + +interface Transaction { id: string; type: string; amount: number; currency: string | null; date: string; description: string | null; } +interface Goal { id: string; status: string; tags: string[]; } +interface Observation { id: string; metric: string; value: string; confidence: number | null; } + +const INCOME_TYPES = ['income', 'venit', 'revenue', 'incasare']; +const EXPENSE_TYPES = ['expense', 'cheltuiala', 'cheltuială', 'cost']; + +export default function TrustCreditReadinessPage() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + + const { data: transactions = [] } = useQuery({ queryKey: ['cr-txn', tenantId], queryFn: () => apiFetch('/v1/transactions?limit=500', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 }); + const { data: goals = [] } = useQuery({ queryKey: ['cr-goals', tenantId], queryFn: () => apiFetch('/v1/goals?limit=200', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 }); + const { data: observations = [] } = useQuery({ queryKey: ['cr-obs', tenantId], queryFn: () => apiFetch('/v1/observations', { tenantId }), enabled: Boolean(tenantId), staleTime: 120_000 }); + + const analysis = useMemo(() => { + const income = transactions.filter((t) => INCOME_TYPES.includes(t.type.toLowerCase())); + const expense = transactions.filter((t) => EXPENSE_TYPES.includes(t.type.toLowerCase())); + const totalIncome = income.reduce((s, t) => s + t.amount, 0); + const totalExpense = expense.reduce((s, t) => s + Math.abs(t.amount), 0); + const cashflow = totalIncome - totalExpense; + const savingsRate = totalIncome > 0 ? Math.round((cashflow / totalIncome) * 100) : 0; + + const months = new Set(transactions.map((t) => t.date.slice(0, 7))).size; + + const finGoals = goals.filter((g) => g.tags.some((tag) => ['financial','financiar','investitie','investment','economii','savings'].includes(tag.toLowerCase()))); + const credObs = observations.filter((o) => o.metric.toLowerCase().includes('certif') || o.metric.toLowerCase().includes('diploma')); + const avgConf = observations.length > 0 ? observations.reduce((s, o) => s + (o.confidence ?? 1), 0) / observations.length : 0; + + const checks = [ + { label: 'Venituri logate', done: income.length > 0, detail: `${income.length} tranzacții`, impact: 25 }, + { label: 'Flux de numerar pozitiv', done: cashflow > 0, detail: cashflow > 0 ? `+${cashflow.toFixed(0)}` : `${cashflow.toFixed(0)}`, impact: 20 }, + { label: 'Rată economii > 10%', done: savingsRate >= 10, detail: `${savingsRate}%`, impact: 20 }, + { label: 'Consistență date (3+ luni)', done: months >= 3, detail: `${months} luni`, impact: 15 }, + { label: 'Obiective financiare', done: finGoals.length > 0, detail: `${finGoals.length} obiective`, impact: 10 }, + { label: 'Credențiale verificabile', done: credObs.length > 0, detail: `${credObs.length} credențiale`, impact: 10 }, + ]; + + const score = checks.filter((c) => c.done).reduce((s, c) => s + c.impact, 0); + return { checks, score, totalIncome, totalExpense, cashflow, savingsRate, months }; + }, [transactions, goals, observations]); + + function scoreCls(s: number) { return s >= 70 ? 'text-signal-ok' : s >= 40 ? 'text-warn' : 'text-signal-danger'; } + function barCls(s: number) { return s >= 70 ? 'bg-signal-ok' : s >= 40 ? 'bg-warn' : 'bg-signal-danger'; } + + return ( +
+
+ +

Credit Readiness

+

Pregătire pentru finanțare — analiză internă din datele CEO OS.

+
+ +
+

Nu este un scor de credit

+

+ Acest indicator reflectă disponibilitatea datelor financiare auto-raportate din CEO OS. + Nu este un scor de credit bancar, nu reflectă istoricul de plăți și nu poate fi folosit ca garanție sau evaluare externă. + Pentru finanțare reală, consultă o instituție financiară autorizată. +

+
+ + {/* Score */} +
+
+

{analysis.score}

+

pregătire date

+
+
+
+
+
+

+ {analysis.score >= 70 ? '✅ Date financiare bine documentate' : analysis.score >= 40 ? '⚠ Lipsesc câteva categorii cheie' : '❌ Date financiare insuficiente în CEO OS'} +

+
+
+ + {/* Financial snapshot */} +
+
+

{analysis.totalIncome.toLocaleString()}

+

venituri totale

+
+
+

{analysis.totalExpense.toLocaleString()}

+

cheltuieli totale

+
+
+

= 0 ? 'text-signal-ok' : 'text-signal-danger'}`}> + {analysis.cashflow >= 0 ? '+' : ''}{analysis.cashflow.toLocaleString()} +

+

cash flow net

+
+
+ + {/* Checklist */} +
+

Criterii de pregătire date

+ {analysis.checks.map((c) => ( +
+ + {c.done ? '✓' : '○'} + +
+

{c.label}

+

{c.detail}

+
+ +{c.impact}pt +
+ ))} +
+ +
+ Finance Dashboard → + Profil Credibilitate → +
+
+ ); +}