diff --git a/src/app/dashboard/briefing/page.tsx b/src/app/dashboard/briefing/page.tsx index cbd4c0e..dff98b6 100644 --- a/src/app/dashboard/briefing/page.tsx +++ b/src/app/dashboard/briefing/page.tsx @@ -1,75 +1,193 @@ 'use client'; +import Link from 'next/link'; import { useQuery } from '@tanstack/react-query'; -import { apiFetch, type Briefing } from '../../../lib/api'; +import { apiFetch } from '../../../lib/api'; +import type { BriefingData } from '../../../lib/api'; import { useSession } from '../../../components/session-provider'; -export const dynamic = 'force-dynamic'; +const B = '/dashboard'; -export default function DailyBriefingPage() { +function ScoreMeter({ score }: { score: number }) { + const color = score >= 80 ? 'text-signal-ok' : score >= 60 ? 'text-signal-warn' : 'text-signal-danger'; + return ( +
+
{score}
+
Executive Health Score
+
+ ); +} + +export default function BriefingPage() { const { activeTenant } = useSession(); const tenantId = activeTenant?.tenantId ?? ''; + const today = new Date().toLocaleDateString('ro-RO', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }); - const { data: briefing, isLoading } = useQuery({ + const { data, isLoading, error } = useQuery({ queryKey: ['briefing', tenantId], - queryFn: () => apiFetch('/v1/briefing/today', { tenantId }), + queryFn: () => apiFetch('/v1/briefing', { tenantId }), enabled: Boolean(tenantId), + staleTime: 300_000, }); return ( -
-

Daily Briefing

-

- Prioritizarea e deterministă; AI-ul doar explică rezultatul, nu decide ordinea. -

+
+
+

Daily Briefing

+

{today}

+
- {isLoading &&

Se încarcă…

} - - {briefing && ( -
- {briefing.aiExplanation && ( -
-

Sinteza zilei

-

{briefing.aiExplanation}

-
- )} - -
-

Sarcini restante

- {briefing.overdueTasks.length === 0 ? ( -

Nicio sarcină restantă.

- ) : ( -
    - {briefing.overdueTasks.map((task) => ( -
  • - {task.title} - - {task.dueAt && new Date(task.dueAt).toLocaleDateString('ro-RO')} - -
  • - ))} -
- )} -
- -
-

Următoarele 7 zile

- {briefing.upcomingTasks.length === 0 ? ( -

Nimic programat în următoarea săptămână.

- ) : ( -
    - {briefing.upcomingTasks.map((task) => ( -
  • - {task.title} - - {task.dueAt && new Date(task.dueAt).toLocaleDateString('ro-RO')} - -
  • - ))} -
- )} -
+ {isLoading ? ( +
+

Se pregătește briefing-ul…

+ ) : error || !data ? ( +
+

Nu s-a putut încărca briefing-ul.

+
+ ) : ( + <> + {/* Score */} +
+ +

+ Generat la {new Date(data.generatedAt).toLocaleTimeString('ro-RO', { hour: '2-digit', minute: '2-digit' })} +

+ {data.score < 70 && ( +

+ {data.atRiskGoals.length > 0 && `${data.atRiskGoals.length} obiective la risc. `} + {data.overdueTasks.length > 0 && `${data.overdueTasks.length} taskuri expirate. `} + {data.pendingDecisions.length > 0 && `${data.pendingDecisions.length} decizii necesită review.`} +

+ )} +
+ + {/* Alerts grid */} +
+ + {/* Tasks due today */} +
+
+

Taskuri azi

+ → +
+ {data.todayTasks.length === 0 ? ( +

Nicio urgență pentru azi ✓

+ ) : ( +
    + {data.todayTasks.slice(0, 4).map((t) => ( +
  • + +

    {t.title}

    +
  • + ))} + {data.todayTasks.length > 4 &&
  • +{data.todayTasks.length - 4} mai multe
  • } +
+ )} +
+ + {/* Overdue tasks */} +
+
+

Taskuri expirate

+ → +
+ {data.overdueTasks.length === 0 ? ( +

Nicio întârziere ✓

+ ) : ( +
    + {data.overdueTasks.slice(0, 4).map((t) => ( +
  • + +

    {t.title}

    +
  • + ))} + {data.overdueTasks.length > 4 &&
  • +{data.overdueTasks.length - 4} mai multe
  • } +
+ )} +
+ + {/* At-risk goals */} +
+
+

Obiective la risc

+ → +
+ {data.atRiskGoals.length === 0 ? ( +

Toate obiectivele pe plan ✓

+ ) : ( +
    + {data.atRiskGoals.slice(0, 4).map((g) => ( +
  • + +

    {g.metric} → {g.target} ({g.horizon})

    +
  • + ))} +
+ )} +
+ + {/* Pending decision reviews */} +
+
+

Review decizii

+ → +
+ {data.pendingDecisions.length === 0 ? ( +

Niciun review restant ✓

+ ) : ( +
    + {data.pendingDecisions.slice(0, 3).map((d) => ( +
  • + +

    {d.context}

    +
  • + ))} +
+ )} +
+ + {/* Critical market signals */} +
+
+

Semnale critice

+ → +
+ {data.criticalSignals.length === 0 ? ( +

Niciun semnal critic ✓

+ ) : ( +
    + {data.criticalSignals.slice(0, 3).map((s) => ( +
  • + +

    {s.title}

    +
  • + ))} +
+ )} +
+ + {/* Expiring opportunities */} +
+
+

Oportunități care expiră

+ → +
+ {data.expiringOpportunities.length === 0 ? ( +

Niciuna în 7 zile ✓

+ ) : ( +
    + {data.expiringOpportunities.slice(0, 3).map((o) => ( +
  • + +

    {o.source}: {o.nextAction ?? 'acțiune necesară'}

    +
  • + ))} +
+ )} +
+
+ )}
);