import { useEffect, useState, useCallback } from 'react' import { View, Text, StyleSheet, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl, } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' import { useRouter } from 'expo-router' import { GraduationCap, BookOpen, ChevronRight, Clock } from 'lucide-react-native' import { C } from '@/lib/theme' import { apiFetch } from '@/lib/api' import { ENDPOINTS } from '@/lib/config' interface Deck { id: string name: string notebookName: string | null totalCards: number dueCount: number masteredCount: number } export default function RevisionScreen() { const router = useRouter() const [decks, setDecks] = useState([]) const [loading, setLoading] = useState(true) const [refreshing, setRefreshing] = useState(false) const [error, setError] = useState(null) const load = useCallback(async (silent = false) => { if (!silent) setLoading(true) setError(null) try { const res = await apiFetch(ENDPOINTS.flashcardDecks) const data = await res.json() if (!res.ok) throw new Error(data.error ?? `Erreur ${res.status}`) setDecks(data.decks ?? []) } catch (e: any) { setError(e.message ?? 'Erreur de chargement') } finally { setLoading(false) setRefreshing(false) } }, []) useEffect(() => { load() }, [load]) const totalDue = decks.reduce((s, d) => s + d.dueCount, 0) if (loading) return ( ) return ( {/* Header */} Révision {totalDue > 0 && ( {totalDue} à revoir )} {error ? ( {error} load()} style={s.retryBtn}> Réessayer ) : decks.length === 0 ? ( Aucun paquet Générez des flashcards depuis une note (bouton ✦ dans l'éditeur) pour commencer à réviser. ) : ( d.id} refreshControl={ { setRefreshing(true); load(true) }} tintColor={C.brand} />} contentContainerStyle={s.list} renderItem={({ item }) => router.push({ pathname: '/revision/session', params: { deckId: item.id, deckName: item.name } })} />} /> )} ) } function DeckCard({ deck, onPress }: { deck: Deck; onPress: () => void }) { const progress = deck.totalCards > 0 ? deck.masteredCount / deck.totalCards : 0 return ( {deck.name} {deck.notebookName && {deck.notebookName}} {deck.masteredCount}/{deck.totalCards} maîtrisées {deck.dueCount > 0 ? ( {deck.dueCount} ) : ( )} ) } const s = StyleSheet.create({ safe: { flex: 1, backgroundColor: C.paper }, center: { flex: 1, alignItems: 'center', justifyContent: 'center', padding: 24 }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 20, paddingTop: 12, paddingBottom: 16, borderBottomWidth: 1, borderBottomColor: C.border, }, headerLeft: { flexDirection: 'row', alignItems: 'center', gap: 8 }, title: { fontSize: 20, fontWeight: '700', color: C.ink }, badge: { backgroundColor: '#fee2e2', paddingHorizontal: 10, paddingVertical: 4, borderRadius: 20 }, badgeTxt: { fontSize: 12, fontWeight: '600', color: '#e11d48' }, list: { padding: 16, gap: 10 }, card: { backgroundColor: C.surface, borderRadius: 14, padding: 14, flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', borderWidth: 1, borderColor: C.border, }, cardLeft: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: 12, marginRight: 8 }, deckIcon: { width: 40, height: 40, borderRadius: 12, backgroundColor: '#f0f7ff', alignItems: 'center', justifyContent: 'center', }, cardInfo: { flex: 1 }, deckName: { fontSize: 15, fontWeight: '600', color: C.ink, marginBottom: 2 }, deckSub: { fontSize: 12, color: C.concrete, marginBottom: 6 }, progressBar: { height: 4, backgroundColor: C.border, borderRadius: 2, marginBottom: 4 }, progressFill: { height: 4, backgroundColor: C.brand, borderRadius: 2 }, progressTxt: { fontSize: 11, color: C.concrete }, cardRight: { alignItems: 'flex-end', gap: 2 }, duePill: { flexDirection: 'row', alignItems: 'center', gap: 3, backgroundColor: '#fee2e2', paddingHorizontal: 8, paddingVertical: 3, borderRadius: 10, }, dueTxt: { fontSize: 12, fontWeight: '700', color: '#e11d48' }, upToDate: { fontSize: 16, color: C.brand, fontWeight: '700' }, emptyTitle: { fontSize: 18, fontWeight: '700', color: C.ink, marginTop: 16, marginBottom: 8 }, emptyHint: { fontSize: 14, color: C.concrete, textAlign: 'center', lineHeight: 20 }, errorTxt: { fontSize: 15, color: '#e11d48', textAlign: 'center', marginBottom: 12 }, retryBtn: { backgroundColor: C.brand, paddingHorizontal: 20, paddingVertical: 10, borderRadius: 10 }, retryTxt: { color: '#fff', fontWeight: '600' }, })