feat(CC-082): add Calendar Integration page (setup guide + sync policy)

This commit is contained in:
admin-valentin 2026-08-02 17:16:26 +00:00
parent 7786bcbb1b
commit 623667b822

View file

@ -0,0 +1,85 @@
'use client';
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import { apiFetch } from '../../../../lib/api';
import { useSession } from '../../../../components/session-provider';
interface DataSource { id: string; name: string; type: string; status: string; lastSyncAt: string | null; }
export default function CalendarIntegrationPage() {
const { activeTenant } = useSession();
const tenantId = activeTenant?.tenantId ?? '';
const { data: sources = [] } = useQuery({
queryKey: ['cal-sources', tenantId],
queryFn: () => apiFetch<DataSource[]>('/v1/data-sources', { tenantId }),
enabled: Boolean(tenantId), staleTime: 60_000,
});
const calSources = sources.filter((s) => s.type === 'calendar' || s.name.toLowerCase().includes('calendar') || s.name.toLowerCase().includes('google'));
return (
<div className="max-w-3xl space-y-6 p-6">
<div>
<h1 className="font-display text-2xl font-semibold text-ink">Integrare Calendar</h1>
<p className="text-sm text-ink-faint mt-1">Sincronizare evenimente și participanți cu CEO OS Calendar.</p>
</div>
<div className={`card p-4 ${calSources.length > 0 ? 'bg-signal-ok/5 border-signal-ok/30' : 'bg-warn/5 border-warn/30'}`}>
<p className={`text-xs font-semibold ${calSources.length > 0 ? 'text-signal-ok' : 'text-warn'} mb-1`}>
{calSources.length > 0 ? `${calSources.length} calendar conectat` : 'Status: Neconectat'}
</p>
<p className="text-xs text-ink-faint">
{calSources.length > 0
? `Ultima sincronizare: ${calSources[0].lastSyncAt ? new Date(calSources[0].lastSyncAt).toLocaleString('ro-RO') : 'niciodată'}`
: 'Niciun calendar conectat. Urmează pașii de mai jos.'}
</p>
</div>
<div className="space-y-3">
<p className="text-xs font-semibold uppercase tracking-wider text-ink-faint">Configurare</p>
{[
{ step: '1', title: 'Selectează provider calendar', desc: 'Google Calendar, Outlook Calendar, sau CalDAV generic.' },
{ step: '2', title: 'Autentificare OAuth2', desc: 'Read-only access implicit. Write access opțional pentru creare evenimente din CEO OS.' },
{ step: '3', title: 'Selectează calendare de sincronizat', desc: 'Alege specific care calendare să fie vizibile în CEO OS Calendar.' },
{ step: '4', title: 'Mapare participanți', desc: 'CEO OS mapează automat participanții la contactele existente în CRM.' },
].map((s) => (
<div key={s.step} className="card p-4 flex gap-4">
<div className="w-7 h-7 rounded-full bg-primary/10 flex items-center justify-center text-xs font-bold text-primary shrink-0">{s.step}</div>
<div>
<p className="text-sm font-medium text-ink">{s.title}</p>
<p className="text-[10px] text-ink-faint mt-0.5">{s.desc}</p>
</div>
</div>
))}
</div>
<div className="card p-4 bg-primary/5 border-primary/20 space-y-1">
<p className="text-xs font-semibold text-ink">Ce se sincronizează</p>
<div className="grid grid-cols-2 gap-1 text-[10px] text-ink-faint">
<p> Titlu și descriere eveniment</p>
<p> Participanți (mapați la contacte)</p>
<p> Termen + durată</p>
<p> Locație</p>
<p> Atașamente (doar metadata)</p>
<p> Conținut privat marcat "private"</p>
</div>
</div>
<div className="flex gap-3">
<button disabled className="rounded-lg bg-primary/40 px-4 py-2 text-sm text-white cursor-not-allowed">
Conectează Google Calendar (în curând)
</button>
<button disabled className="rounded-lg border px-4 py-2 text-sm text-ink-faint cursor-not-allowed">
CalDAV (în curând)
</button>
</div>
<div className="flex gap-3">
<Link href="/dashboard/calendar" className="text-xs text-primary hover:underline">CEO OS Calendar </Link>
<Link href="/dashboard/integrations" className="text-xs text-ink-faint hover:underline">Toate integrările</Link>
</div>
</div>
);
}