/** * AISheet — bottom sheet IA avec modes d'amélioration + résultat * Remplace les Alert.alert natifs par une UI propre au design Memento */ import { useState } from 'react' import { View, Text, TouchableOpacity, ActivityIndicator, ScrollView, StyleSheet, } from 'react-native' import { Sparkles, Scissors, MessageSquare, Pencil, CheckCircle2, RefreshCw } from 'lucide-react-native' import { BottomSheet } from '@/components/BottomSheet' import { apiFetch } from '@/lib/api' import { ENDPOINTS } from '@/lib/config' import { C } from '@/lib/theme' const MODES = [ { key: 'improve', label: 'Améliorer le style', icon: Sparkles, color: C.brand }, { key: 'fix_grammar', label: 'Corriger la grammaire', icon: CheckCircle2, color: '#5b7ec7' }, { key: 'shorten', label: 'Raccourcir', icon: Scissors, color: '#4a9b61' }, { key: 'clarify', label: 'Clarifier les idées', icon: MessageSquare,color: '#c77a3a' }, ] interface Props { visible: boolean onClose: () => void text: string onApply: (improved: string) => void } export function AISheet({ visible, onClose, text, onApply }: Props) { const [loading, setLoading] = useState(false) const [result, setResult] = useState(null) const [selectedMode, setSelectedMode] = useState(null) const handleClose = () => { setResult(null) setSelectedMode(null) onClose() } const handleMode = async (mode: string) => { setSelectedMode(mode) setLoading(true) setResult(null) try { const res = await apiFetch(ENDPOINTS.aiImprove, { method: 'POST', body: JSON.stringify({ text, mode }), }) const d = await res.json().catch(() => ({})) if (!res.ok) { setResult(`⚠️ ${d.error === 'quota_exceeded' ? 'Quota IA dépassé' : (d.error ?? 'Erreur serveur')}`) return } setResult(d.improved ?? '') } catch { setResult('⚠️ Erreur réseau — vérifiez votre connexion.') } finally { setLoading(false) } } const handleApply = () => { if (result && !result.startsWith('⚠️')) { onApply(result) } handleClose() } const handleRetry = () => { if (selectedMode) handleMode(selectedMode) } const title = result ? 'Résultat IA' : 'Améliorer avec l\'IA' return ( {!result && !loading && ( {MODES.map((m) => { const Icon = m.icon return ( handleMode(m.key)} style={s.modeRow} activeOpacity={0.7}> {m.label} ) })} )} {loading && ( Génération en cours… )} {result && !loading && ( {result} {!result.startsWith('⚠️') && ( Remplacer le texte )} Réessayer )} ) } const s = StyleSheet.create({ modeList: { paddingHorizontal: 12, paddingTop: 8, paddingBottom: 8 }, modeRow: { flexDirection: 'row', alignItems: 'center', gap: 14, paddingHorizontal: 12, paddingVertical: 14, borderRadius: 14, marginBottom: 4, }, modeIcon: { width: 40, height: 40, borderRadius: 12, alignItems: 'center', justifyContent: 'center' }, modeLabel: { fontSize: 15, fontWeight: '500', color: C.ink }, loadingBox: { alignItems: 'center', paddingVertical: 36, gap: 12 }, loadingText: { fontSize: 14, color: C.concrete }, resultBox: { paddingHorizontal: 20, paddingTop: 8 }, resultScroll: { maxHeight: 200, backgroundColor: C.white, borderWidth: 1, borderColor: C.border, borderRadius: 14, padding: 14, marginBottom: 14 }, resultText: { fontSize: 15, color: C.ink, lineHeight: 23 }, applyBtn: { flexDirection: 'row', alignItems: 'center', gap: 8, backgroundColor: C.ink, paddingVertical: 13, borderRadius: 14, justifyContent: 'center', marginBottom: 8 }, applyBtnText: { color: C.white, fontWeight: '700', fontSize: 14 }, retryBtn: { flexDirection: 'row', alignItems: 'center', gap: 6, justifyContent: 'center', paddingVertical: 10 }, retryText: { fontSize: 13, color: C.concrete }, })