'use client'; import Link from 'next/link'; import { useQuery } from '@tanstack/react-query'; import { apiFetch, type Goal, type Transaction, type Decision } from '../../../lib/api'; import { useSession } from '../../../components/session-provider'; interface ExecDash { status: 'ready' | 'building'; counters: { openTasks: number; overdueTasks: number; deadlinesNext7Days: number; organizations: number; segments: number; researchBriefs: number; } | null; generatedAt: string | null; } export default function BusinessOverviewPage() { const { activeTenant } = useSession(); const tenantId = activeTenant?.tenantId ?? ''; const { data: exec } = useQuery({ queryKey: ['exec-dash-biz', tenantId], queryFn: () => apiFetch('/v1/dashboard/executive', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const { data: goals = [] } = useQuery({ queryKey: ['goals-biz', tenantId], queryFn: () => apiFetch('/v1/goals', { tenantId }), enabled: Boolean(tenantId), }); const { data: transactions = [] } = useQuery({ queryKey: ['transactions-biz', tenantId], queryFn: () => apiFetch('/v1/transactions', { tenantId }), enabled: Boolean(tenantId), }); const { data: decisions = [] } = useQuery({ queryKey: ['decisions-biz', tenantId], queryFn: () => apiFetch('/v1/decisions', { tenantId }), enabled: Boolean(tenantId), }); const c = exec?.counters; const goalsAtRisk = goals.filter((g) => g.status === 'at_risk').length; const txMissing = transactions.filter((t) => t.evidenceStatus === 'missing').length; const decisionsPending = decisions.filter((d) => !d.selectedOption).length; const modules = [ { label: 'Organizații', value: c?.organizations ?? '—', href: '/dashboard/organizations', badge: null, badgeColor: '', }, { label: 'Sarcini deschise', value: c?.openTasks ?? '—', href: '/dashboard/tasks', badge: c?.overdueTasks ? `${c.overdueTasks} restante` : null, badgeColor: 'bg-signal-danger text-white', }, { label: 'Obiective active', value: goals.length, href: '/dashboard/goals', badge: goalsAtRisk > 0 ? `${goalsAtRisk} la risc` : null, badgeColor: 'bg-signal-warn text-white', }, { label: 'Tranzacții', value: transactions.length, href: '/dashboard/transactions', badge: txMissing > 0 ? `${txMissing} fără dovadă` : null, badgeColor: 'bg-signal-warn text-white', }, { label: 'Decizii pending', value: decisionsPending, href: '/dashboard/decisions', badge: null, badgeColor: '', }, { label: 'Segmente', value: c?.segments ?? '—', href: '/dashboard/segments', badge: null, badgeColor: '', }, { label: 'Research briefs', value: c?.researchBriefs ?? '—', href: '/dashboard/research', badge: null, badgeColor: '', }, { label: 'Scadențe 7 zile', value: c?.deadlinesNext7Days ?? '—', href: '/dashboard/tasks', badge: null, badgeColor: '', }, ]; return (

Vedere Generală Business

Sumar executiv al tuturor modulelor CEO-OS. {exec?.generatedAt && ( <> Actualizat: {new Date(exec.generatedAt).toLocaleString('ro-RO')}. )}

{exec?.status === 'building' && (

Proiecția executive se construiește. Contoarele vor apărea în câteva secunde.

)}
{modules.map(({ label, value, href, badge, badgeColor }) => (

{label}

{value}

{badge && ( {badge} )} ))}

Obiective

{goals.length === 0 ? (

Niciun obiectiv definit.

) : (
    {goals.slice(0, 5).map((g) => { const dot = g.status === 'on_track' ? 'bg-signal-ok' : g.status === 'at_risk' ? 'bg-signal-warn' : g.status === 'achieved' ? 'bg-bronze-deep' : g.status === 'abandoned' ? 'bg-signal-danger' : 'bg-paper-sunken'; return (
  • {g.metric} {g.target}
  • ); })}
)} Toate obiectivele →

Tranzacții recente

{transactions.length === 0 ? (

Nicio tranzacție înregistrată.

) : (
    {transactions.slice(0, 5).map((t) => (
  • {t.type} {new Intl.NumberFormat('ro-RO', { style: 'currency', currency: t.currency, }).format(Number(t.amountMinorUnits) / 100)} {t.evidenceStatus}
  • ))}
)} Toate tranzacțiile →
); }