import { useState } from 'react'; import { Alert, FlatList, Modal, Pressable, StyleSheet, Text, View, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { LabeledField } from '../../src/components/LabeledField'; import { PrimaryButton } from '../../src/components/PrimaryButton'; import { useApp } from '../../src/context/AppContext'; import { colors } from '../../src/theme/colors'; import type { InvestisseurRow } from '../../src/data/types'; import { router } from 'expo-router'; function parseNum(s: string): number | null { const v = Number(s.replace(',', '.').replace(/\s/g, '')); return Number.isFinite(v) ? v : null; } export default function InvestisseursScreen() { const insets = useSafeAreaInsets(); const app = useApp(); const [open, setOpen] = useState(false); const [editing, setEditing] = useState(null); const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [phone, setPhone] = useState(''); const [minMargin, setMinMargin] = useState('12'); const [maxTicket, setMaxTicket] = useState(''); const [zones, setZones] = useState(''); const cloudNeedsAuth = app.runtimeMode === 'cloud' && !app.user; const openNew = () => { setEditing(null); setName(''); setEmail(''); setPhone(''); setMinMargin('12'); setMaxTicket(''); setZones(''); setOpen(true); }; const openEdit = (row: InvestisseurRow) => { setEditing(row); setName(row.display_name); setEmail(row.email ?? ''); setPhone(row.phone ?? ''); setMinMargin(String(row.min_margin_pct)); setMaxTicket(row.max_ticket_eur != null ? String(row.max_ticket_eur) : ''); setZones((row.zones ?? []).join(', ')); setOpen(true); }; const save = async () => { if (!app.user) { router.push('/auth/login'); return; } const uid = app.user.id; const mm = parseNum(minMargin) ?? 12; const mt = maxTicket.trim() ? parseNum(maxTicket) : null; const z = zones .split(',') .map((s) => s.trim()) .filter(Boolean); await app.upsertInvestisseur({ id: editing?.id, user_id: uid, display_name: name.trim() || 'Investisseur', email: email.trim() || null, phone: phone.trim() || null, min_margin_pct: mm, max_ticket_eur: mt, zones: z.length ? z : null, strategies: null, notes: null, }); setOpen(false); }; if (cloudNeedsAuth) { return ( Connectez-vous pour gérer vos investisseurs. router.push('/auth/login')} /> ); } return ( i.id} contentContainerStyle={{ padding: 16, paddingBottom: insets.bottom + 80, }} ListEmptyComponent={ Ajoutez des profils pour le module « Investisseur flash » (matching marge / ticket / zones). } renderItem={({ item }) => ( openEdit(item)}> {item.display_name} Marge mini {item.min_margin_pct}% — ticket max{' '} {item.max_ticket_eur != null ? `${item.max_ticket_eur.toLocaleString('fr-FR')} €` : '—'} {item.zones?.length ? ( Zones : {item.zones.join(', ')} ) : null} )} /> {editing ? 'Modifier investisseur' : 'Nouvel investisseur'} void save()} /> {editing ? ( { Alert.alert( 'Supprimer', 'Confirmer la suppression ?', [ { text: 'Annuler', style: 'cancel' }, { text: 'Supprimer', style: 'destructive', onPress: () => { void app.deleteInvestisseur(editing.id).then(() => setOpen(false), ); }, }, ], ); }} /> ) : null} setOpen(false)} /> ); } const styles = StyleSheet.create({ root: { flex: 1, backgroundColor: colors.bg }, center: { flex: 1, padding: 20, backgroundColor: colors.bg, gap: 12 }, muted: { color: colors.textMuted, textAlign: 'center', lineHeight: 20 }, card: { backgroundColor: colors.bgCard, borderRadius: 14, padding: 16, marginBottom: 12, borderWidth: 1, borderColor: colors.border, }, name: { color: colors.text, fontSize: 17, fontWeight: '700' }, meta: { color: colors.textMuted, marginTop: 6, fontSize: 13 }, fabRow: { position: 'absolute', left: 16, right: 16 }, modalBackdrop: { flex: 1, backgroundColor: 'rgba(0,0,0,0.55)', justifyContent: 'flex-end', }, modalCard: { backgroundColor: colors.bgCard, borderTopLeftRadius: 18, borderTopRightRadius: 18, padding: 20, borderWidth: 1, borderColor: colors.border, }, modalTitle: { color: colors.text, fontSize: 20, fontWeight: '700', marginBottom: 16, }, });