'use client'; import { useMemo, useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { apiFetch } from '../../../lib/api'; import { useSession } from '../../../components/session-provider'; interface Task { id: string; title: string; description: string | null; status: string; priority: string | null; tags: string[]; targetDate: string | null; createdAt: string; } const EVENT_TAGS = ['eveniment','event','conferinta','conference','workshop','meetup','webinar','summit','hackathon','networking']; const EVENT_TYPES: Record = { conferinta:'🎤', conference:'🎤', workshop:'🛠️', meetup:'🤝', webinar:'💻', summit:'🏔️', hackathon:'⚡', networking:'🌐', eveniment:'📅', event:'📅', }; function daysUntil(iso: string | null): number | null { if (!iso) return null; return Math.ceil((new Date(iso).getTime() - Date.now()) / 86_400_000); } export default function EventsPage() { const { activeTenant } = useSession(); const tenantId = activeTenant?.tenantId ?? ''; const qc = useQueryClient(); const [tab, setTab] = useState<'upcoming' | 'past'>('upcoming'); const [showAdd, setShowAdd] = useState(false); const [form, setForm] = useState({ title: '', type: 'conferinta', date: '', location: '', url: '', prep: false }); const { data: tasks = [], isLoading } = useQuery({ queryKey: ['events', tenantId], queryFn: () => apiFetch('/v1/tasks?limit=500', { tenantId }), enabled: Boolean(tenantId), staleTime: 60_000, }); const events = useMemo(() => tasks.filter((t) => t.tags.some((tag) => EVENT_TAGS.includes(tag.toLowerCase()))), [tasks]); const upcoming = useMemo(() => events .filter((e) => !e.targetDate || new Date(e.targetDate) >= new Date(new Date().toDateString())) .filter((e) => e.status !== 'cancelled') .sort((a, b) => (a.targetDate ?? '9999').localeCompare(b.targetDate ?? '9999')), [events]); const past = useMemo(() => events .filter((e) => e.targetDate && new Date(e.targetDate) < new Date(new Date().toDateString())) .sort((a, b) => b.targetDate!.localeCompare(a.targetDate!)), [events]); const urgent = upcoming.filter((e) => { const d = daysUntil(e.targetDate); return d !== null && d <= 14; }); const addMut = useMutation({ mutationFn: () => apiFetch('/v1/tasks', { tenantId, method: 'POST', body: { title: form.title, description: [form.location && `📍 ${form.location}`, form.url && `🔗 ${form.url}`].filter(Boolean).join('\n') || undefined, tags: ['eveniment', form.type, ...(form.prep ? ['prep-needed'] : [])], status: 'todo', priority: 'normal', targetDate: form.date || undefined, }}), onSuccess: () => { qc.invalidateQueries({ queryKey: ['events', tenantId] }); setShowAdd(false); setForm({ title: '', type: 'conferinta', date: '', location: '', url: '', prep: false }); }, }); const patchMut = useMutation({ mutationFn: ({ id, status }: { id: string; status: string }) => apiFetch(`/v1/tasks/${id}`, { tenantId, method: 'PATCH', body: { status } }), onSuccess: () => qc.invalidateQueries({ queryKey: ['events', tenantId] }), }); function eventType(t: Task): string { return t.tags.find((tag) => EVENT_TYPES[tag.toLowerCase()]) ?? 'event'; } const displayList = tab === 'upcoming' ? upcoming : past; return (

Event Tracker

{upcoming.length} viitoare · {past.length} trecute

{urgent.length > 0 && (

⚡ În următoarele 14 zile

{urgent.map((e) => { const d = daysUntil(e.targetDate); return (

{EVENT_TYPES[eventType(e)] ?? '📅'} {e.title}

{d === 0 ? 'Azi!' : d === 1 ? 'Mâine' : `${d} zile`}
); })}
)} {showAdd && (

Eveniment nou

setForm((p) => ({ ...p, title: e.target.value }))} className="w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
setForm((p) => ({ ...p, date: e.target.value }))} className="rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" /> setForm((p) => ({ ...p, location: e.target.value }))} className="rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" /> setForm((p) => ({ ...p, url: e.target.value }))} className="rounded-lg border bg-background px-3 py-2 text-sm font-mono text-xs text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
)} {/* Tabs */}
{(['upcoming', 'past'] as const).map((t) => ( ))}
{isLoading ? (
Se încarcă…
) : displayList.length === 0 ? (

🗓️

{tab === 'upcoming' ? 'Niciun eveniment viitor.' : 'Niciun eveniment trecut.'}

) : (
{displayList.map((e) => { const d = daysUntil(e.targetDate); const icon = EVENT_TYPES[eventType(e)] ?? '📅'; const needsPrep = e.tags.includes('prep-needed'); const [loc, url] = (e.description ?? '').split('\n'); return (
{icon}

{e.title}

{e.targetDate &&

📅 {new Date(e.targetDate).toLocaleDateString('ro-RO', { weekday:'short', day:'numeric', month:'short' })}

} {loc?.startsWith('📍') &&

{loc}

} {needsPrep && 🛠️ Prep needed}
{url?.startsWith('🔗') && (

{url.replace('🔗 ', '')}

)}
{d !== null && tab === 'upcoming' && (

{d === 0 ? 'Azi' : d === 1 ? 'Mâine' : `${d}z`}

)} {tab === 'past' && e.status !== 'completed' && ( )} {tab === 'past' && e.status === 'completed' && ( ✓ Participat )}
); })}
)}
); }