'use client' import { useState, useEffect } from 'react' import { BookOpen, Loader2, Check, X, RefreshCw, Trash2, CalendarDays } from 'lucide-react' import { toast } from 'sonner' import { SettingsHelpBox } from '@/components/settings/settings-help-box' export default function IntegrationsPage() { // ── Readwise ─────────────────────────────────────────────────────────── const [rwToken, setRwToken] = useState('') const [rwConnected, setRwConnected] = useState(false) const [rwSyncing, setRwSyncing] = useState(false) const [rwConnecting, setRwConnecting] = useState(false) const [rwLastSync, setRwLastSync] = useState<{ created: number; updated: number } | null>(null) // ── Google Calendar ──────────────────────────────────────────────────── const [calConnected, setCalConnected] = useState(false) const [calLoading, setCalLoading] = useState(true) const [calEvents, setCalEvents] = useState([]) const [calFetching, setCalFetching] = useState(false) const [loading, setLoading] = useState(true) useEffect(() => { Promise.all([ fetch('/api/integrations/readwise').then((r) => r.json()), fetch('/api/integrations/calendar').then((r) => r.json()), ]).then(([rw, cal]) => { setRwConnected(rw.connected) setCalConnected(cal.connected) }).finally(() => { setLoading(false) setCalLoading(false) }) // Handle redirect params const params = new URLSearchParams(window.location.search) if (params.get('connected') === 'calendar') { setCalConnected(true) toast.success('Google Calendar connecté !') window.history.replaceState({}, '', '/settings/integrations') } if (params.get('error')) { toast.error(`Erreur: ${params.get('error')}`) window.history.replaceState({}, '', '/settings/integrations') } }, []) // ── Readwise handlers ────────────────────────────────────────────────── const handleRwConnect = async () => { if (!rwToken.trim()) return setRwConnecting(true) try { const res = await fetch('/api/integrations/readwise', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token: rwToken.trim() }), }) const data = await res.json() if (!res.ok) { toast.error(data.error || 'Erreur Readwise'); return } setRwConnected(true) setRwToken('') setRwLastSync({ created: data.created, updated: data.updated }) toast.success(`Readwise connecté — ${data.created} notes créées, ${data.updated} mises à jour`) } catch { toast.error('Erreur de connexion Readwise') } finally { setRwConnecting(false) } } const handleRwSync = async () => { setRwSyncing(true) try { const res = await fetch('/api/integrations/readwise', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}), }) const data = await res.json() if (!res.ok) { toast.error(data.error || 'Erreur de sync'); return } setRwLastSync({ created: data.created, updated: data.updated }) toast.success(`Sync Readwise — ${data.created} créées, ${data.updated} mises à jour`) } catch { toast.error('Erreur de synchronisation') } finally { setRwSyncing(false) } } const handleRwDisconnect = async () => { await fetch('/api/integrations/readwise', { method: 'DELETE' }) setRwConnected(false) toast.success('Readwise déconnecté') } // ── Calendar handlers ────────────────────────────────────────────────── const handleCalConnect = () => { window.location.href = '/api/integrations/calendar?connect=1' } const handleCalFetchEvents = async () => { setCalFetching(true) try { const res = await fetch('/api/integrations/calendar?events=1') const data = await res.json() if (!res.ok) { toast.error(data.error || 'Erreur'); return } setCalEvents(data.events ?? []) if (data.events.length === 0) toast.info('Aucun événement aujourd\'hui') } catch { toast.error('Erreur de chargement des événements') } finally { setCalFetching(false) } } const handleCreateMeetingNote = async (event: any) => { const res = await fetch('/api/integrations/calendar', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ eventId: event.id, summary: event.summary, start: event.start }), }) const data = await res.json() if (data.success) { toast.success(`Note de réunion créée : ${event.summary}`, { action: { label: 'Ouvrir', onClick: () => window.location.href = `/home?openNote=${data.note.id}` }, }) } else { toast.error('Erreur lors de la création de la note') } } const handleCalDisconnect = async () => { await fetch('/api/integrations/calendar', { method: 'DELETE' }) setCalConnected(false) setCalEvents([]) toast.success('Google Calendar déconnecté') } const StatusBadge = ({ connected }: { connected: boolean }) => connected ? ( Connecté ) : ( Non connecté ) return (

Intégrations

Connectez des services externes à Memento.

{/* ── Google Calendar ────────────────────────────────────────────── */}

Google Calendar

Accédez à vos événements et créez des notes de réunion

{calLoading ? : }
{!calConnected ? (
) : (
{calEvents.length > 0 && (
{calEvents.map((ev) => (

{ev.summary}

{ev.start ? new Date(ev.start).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' }) : ''}

))}
)}
)}
{/* ── Readwise ──────────────────────────────────────────────────── */}

Readwise

Importez vos surlignages de livres, articles et Kindle

{loading ? : }
{!rwConnected && (
setRwToken(e.target.value)} placeholder="Token Readwise…" className="flex-1 text-sm border border-border/40 rounded-xl px-3 py-2 bg-paper text-ink placeholder:text-concrete/50 focus:outline-none focus:ring-1 focus:ring-brand-accent/40" onKeyDown={(e) => e.key === 'Enter' && handleRwConnect()} />
)} {rwConnected && (
)} {rwLastSync && (

Dernière sync : {rwLastSync.created} notes créées, {rwLastSync.updated} mises à jour

)}
{/* Placeholder */}

D'autres intégrations arrivent bientôt — Zapier, GitHub, Notion import…

) }