const { useState, useMemo, useEffect } = React; const data = [ { id: 1, dom: "Droit civil", sd: "Relations personnelles hors mariage", dem: "Infidélité dans un concubinage", mis: "Suspicion d'un fait constitutif d'infidélité dans une union de fait (préjudice existant)", cj: ["Art. 515.8 du Code civil", "Art. 1240 du Code civil"], jp: ["JP Civ. 30 mai 1838, Bouvier Juris. Générale V° Mariage, n°82 Sirey 1838, 1, 492 (Rupture de fiançailles)", "JP CA Reims n°05/01583 du 19/10/06"] }, { id: 2, dom: "Droit civil", sd: "Relations personnelles hors mariage", dem: "Infidélité dans un PACS", mis: "Suspicion d'un fait constitutif d'infidélité entre partenaires de PACS", cj: ["Art. 515.1 à 7 du Code civil", "Art. 1104 du Code civil"], jp: [] }, { id: 3, dom: "Droit civil", sd: "Relations personnelles hors mariage", dem: "Départ du domicile", mis: "Déterminer la cessation de vie commune dans le cadre d'un PACS", cj: ["Art. 515.4 du Code civil"], jp: [] }, { id: 4, dom: "Droit civil", sd: "Mariage", dem: "Enquêtes de moralité", mis: "Suspicion d'un défaut de capacité ou d'empêchement légal au mariage", cj: ["Art. 144 du Code civil", "Art. 146 du Code civil", "Art. 161 du Code civil"], jp: [] }, { id: 5, dom: "Droit civil", sd: "Mariage", dem: "Enquête sur la validité du mariage célébré", mis: "Suspicion de non-conformité de la cérémonie matrimoniale", cj: ["Art. 165 du Code civil", "Art. 180 du Code civil"], jp: [] }, { id: 6, dom: "Droit civil", sd: "Divorce et séparation", dem: "Adultère", mis: "Suspicion de violation du devoir de fidélité", cj: ["Art. 212 du Code civil", "Art. 242 du Code civil"], jp: [] }, { id: 7, dom: "Droit civil", sd: "Divorce et séparation", dem: "Départ du domicile", mis: "Déterminer la cessation de vie commune", cj: ["Art. 215 du Code civil", "Art. 237 et 238 du Code civil"], jp: [] }, { id: 8, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Prestation compensatoire", mis: "Déterminer les conditions de vie des époux", cj: ["Art. 270 et 271 du Code civil"], jp: [] }, { id: 9, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Pension alimentaire entre époux", mis: "Déterminer les conditions de vie des époux", cj: ["Art. 212 du Code civil", "Art. 255.6 du Code civil"], jp: [] }, { id: 10, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Dommages et intérêts", mis: "Déterminer les conditions de vie des époux", cj: ["Art. 266 du Code civil"], jp: [] }, { id: 11, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Enquête de patrimoine", mis: "Déterminer du patrimoine dans le cadre de la liquidation du régime matrimonial", cj: ["Art. 1467 du Code civil"], jp: [] }, { id: 12, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Pension alimentaire enfants", mis: "Déterminer les conditions de vie d'un parent", cj: ["Art. 371.2 et 373.2.2 du Code civil"], jp: [] }, { id: 13, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Garde d'enfants", mis: "Déterminer les conditions de vie d'un parent", cj: ["Art. 373.2.7 du Code civil"], jp: [] }, { id: 14, dom: "Droit civil", sd: "Effets du divorce/de la séparation", dem: "Conditions de garde", mis: "Déterminer les carences éducatives", cj: ["Art. 371.4 du Code civil", "Art. 375 du Code civil"], jp: [] }, { id: 15, dom: "Droit civil", sd: "Filiation / absence et successions", dem: "Enquête de moralité sur mineur", mis: "Déterminer les fréquentations d'un mineur", cj: ["Art. 371.1.2° du Code civil"], jp: [] }, { id: 16, dom: "Droit civil", sd: "Filiation / absence et successions", dem: "Recherche de paternité", mis: "Déterminer une filiation", cj: ["Art. 327 du Code civil"], jp: [] }, { id: 17, dom: "Droit civil", sd: "Filiation / absence et successions", dem: "Recherche d'héritiers", mis: "Procédure d'identification des ayants droit", cj: ["Art. 725 du Code civil", "Loi n°2014-617 du 13/06/2014"], jp: [] }, { id: 18, dom: "Droit civil", sd: "Filiation / absence et successions", dem: "Recherche de personnes", mis: "Établir la disparition", cj: ["Art. 112 du Code civil", "Art. 1240 du Code civil"], jp: [] }, { id: 19, dom: "Droit civil", sd: "Filiation / absence et successions", dem: "Recherche de débiteur", mis: "Localiser un débiteur", cj: ["Art. 1217 du Code civil"], jp: [] }, { id: 20, dom: "Droit civil", sd: "Contrats juridiques", dem: "Enquête sur co-contractant", mis: "Suspicion de non respect des conditions de validité", cj: ["Art. 1112.1 du Code civil"], jp: [] }, { id: 21, dom: "Droit civil", sd: "Contrats juridiques", dem: "Enquête sur les effets d'un contrat", mis: "Suspicion de défaillance d'exécution", cj: ["Art. 1103 du Code civil"], jp: [] }, { id: 22, dom: "Droit civil", sd: "Faits juridiques", dem: "Responsabilité extra-contractuelle", mis: "Déterminer la responsabilité d'un tiers", cj: ["Art. 1240 du Code civil"], jp: [] }, { id: 23, dom: "Droit penal des affaires", sd: "Détournements d'actifs", dem: "Vol interne ou externe", mis: "Suspicion d'actes de vols", cj: ["Art. 311-1 du Code penal"], jp: [] }, { id: 24, dom: "Droit penal des affaires", sd: "Détournements d'actifs", dem: "Escroquerie", mis: "Suspicion d'escroquerie", cj: ["Art. 313-1 du Code penal"], jp: [] }, { id: 25, dom: "Droit penal des affaires", sd: "Détournements d'actifs", dem: "Abus de confiance", mis: "Suspicion abus de confiance", cj: ["Art. 314-1 du Code penal"], jp: [] }, { id: 26, dom: "Droit penal des affaires", sd: "Abus de biens sociaux", dem: "Abus de biens sociaux", mis: "Suspicion d'abus", cj: ["Art. L241-3 du Code du commerce"], jp: [] }, { id: 27, dom: "Droit pénal", sd: "Vols et déprédations", dem: "Vandalisme et vol", mis: "Suspicion de destruction", cj: ["Art. 322-1 du Code penal"], jp: [] }, { id: 28, dom: "Droit pénal", sd: "Contrefaçon", dem: "Contrefaçon", mis: "Suspicion de contrefaçons", cj: ["Art. L335-2 du CPI"], jp: [] }, { id: 29, dom: "Droit pénal", sd: "Harcèlement", dem: "Harcèlement", mis: "Suspicion de harcèlement", cj: ["Art. 222-33 du Code pénal"], jp: [] }, { id: 30, dom: "Droit pénal", sd: "Provocation de mineur", dem: "Provocation de mineur", mis: "Suspicion de mise en péril", cj: ["Art. 227-18 du Code pénal"], jp: [] }, { id: 31, dom: "Droit pénal", sd: "Trouble de voisinage", dem: "Tapage", mis: "Suspicion de tapage nocturne", cj: ["Art. R623-2 du Code pénal"], jp: [] }, { id: 32, dom: "Droit pénal", sd: "Révision de justice", dem: "Révision de décision", mis: "Révision de décision de justice", cj: ["Art. 622 du CPP"], jp: [] }, { id: 33, dom: "Droit du travail", sd: "Relation de travail", dem: "Seconde relation de travail", mis: "Suspicion de travail illégal", cj: ["Art. L1237-3 du Code du travail"], jp: [] }, { id: 34, dom: "Droit du travail", sd: "Exécution du contrat", dem: "Conditions de travail", mis: "Suspicion de non respect des obligations", cj: ["Art. L3121-27 du Code du travail"], jp: [] }, { id: 35, dom: "Droit du travail", sd: "Exécution du contrat", dem: "Obligations du salarié", mis: "Suspicion de non respect de loyauté", cj: ["Art. L1222-1 du Code du travail"], jp: [] }, { id: 36, dom: "Droit du travail", sd: "Concurrence déloyale", dem: "Concurrence déloyale", mis: "Suspicion d'actes de concurrence déloyal", cj: ["Art. 1240 du Code civil"], jp: ["Notions: dénigrement, parasitisme"] }, { id: 37, dom: "Droit du travail", sd: "Concurrence déloyale", dem: "Clause de non concurrence", mis: "Suspicion de non-respect de clause", cj: ["Art. 1240 du Code civil"], jp: [] }, { id: 38, dom: "Droit du travail", sd: "Suspension travail", dem: "Arrêt maladie", mis: "Suspicion de non respect de loyauté", cj: ["Art. L1222-1 du Code du travail"], jp: [] }, { id: 39, dom: "Droit du travail", sd: "Vérification factuels", dem: "Constat commissaire", mis: "Préparation de constat", cj: ["Art. L621-1 du CSI"], jp: [] } ]; const L = ({ className }) => ( ); function App() { const [t, setT] = useState('dark'); const [adm, setAdm] = useState(false); const [s, setS] = useState(''); const [d, setD] = useState('tous'); const [sd, setSd] = useState('tous'); const [sel, setSel] = useState(null); const [rip, setRip] = useState([]); const [counters, setCounters] = useState({ domains: 0, subdomains: 0, cadres: 0 }); const [showScrollTop, setShowScrollTop] = useState(false); const [cadresData, setCadresData] = useState(data); const [authenticated, setAuthenticated] = useState(false); const [showLoginModal, setShowLoginModal] = useState(false); const [loginPassword, setLoginPassword] = useState(''); const [loginError, setLoginError] = useState(''); const [adminView, setAdminView] = useState('main'); const [editingCadre, setEditingCadre] = useState(null); const [showEditModal, setShowEditModal] = useState(false); const [isAddingNew, setIsAddingNew] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [cadreToDelete, setCadreToDelete] = useState(null); const [formData, setFormData] = useState({ dom: '', sd: '', dem: '', mis: '', cj: [], jp: [], note: '' }); const [isCreatingDomain, setIsCreatingDomain] = useState(false); const [isCreatingSubdomain, setIsCreatingSubdomain] = useState(false); const [customDomain, setCustomDomain] = useState(''); const [customSubdomain, setCustomSubdomain] = useState(''); const [copiedMissionId, setCopiedMissionId] = useState(null); const modalDomains = useMemo(() => { return [...new Set(cadresData.map(c => c.dom).filter(d => d))].sort(); }, [cadresData]); const modalSubdomains = useMemo(() => { if (!formData.dom) return []; return [...new Set(cadresData.filter(c => c.dom === formData.dom).map(c => c.sd).filter(s => s))].sort(); }, [cadresData, formData.dom]); useEffect(() => { const sv = localStorage.getItem('theme') || 'dark'; setT(sv); // Charger les données depuis le serveur au démarrage loadFromServer(); }, []); useEffect(() => { const totalDomains = new Set(cadresData.map(c => c.dom)).size; const totalSubdomains = new Set(cadresData.map(c => c.sd)).size; const totalCadres = cadresData.length; const duration = 2800; const startTime = performance.now(); const animate = (currentTime) => { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const easeOutCubic = 1 - Math.pow(1 - progress, 3); setCounters({ domains: Math.round(easeOutCubic * totalDomains), subdomains: Math.round(easeOutCubic * totalSubdomains), cadres: Math.round(easeOutCubic * totalCadres) }); if (progress < 1) { requestAnimationFrame(animate); } }; requestAnimationFrame(animate); const handleScroll = () => { setShowScrollTop(window.scrollY > 300); }; window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, [cadresData]); const tog = () => { const nt = t === 'dark' ? 'light' : 'dark'; setT(nt); localStorage.setItem('theme', nt); }; const handleAdminToggle = () => { if (authenticated) { setAdm(!adm); if (!adm) setAdminView('main'); } else { setShowLoginModal(true); } }; const handleLogin = async (e) => { e.preventDefault(); setLoginError(''); // Authentification serveur const isAuthenticated = await authenticateServer(loginPassword); if (isAuthenticated) { setAuthenticated(true); setShowLoginModal(false); setLoginPassword(''); setAdm(true); } else { setLoginError('Mot de passe incorrect'); setLoginPassword(''); } }; const handleLogout = () => { setAuthenticated(false); setAdm(false); setAdminView('main'); }; // ======================================== // FONCTIONS SERVEUR (PHP Backend) // ======================================== const loadFromServer = async () => { try { const timestamp = Date.now(); const response = await fetch(`load.php?t=${timestamp}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); if (Array.isArray(data)) { setCadresData(data); console.log(`✅ ${data.length} cadres chargés depuis le serveur`); } else { console.error('❌ Format de données invalide'); } } catch (error) { console.error('❌ Erreur chargement serveur:', error); // Fallback sur les données locales en cas d'erreur console.log('⚠️ Utilisation des données locales (fallback)'); } }; const saveToServer = async (data) => { console.log('🔵 [SAVE] Début de la sauvegarde...', { nbCadres: data.length, timestamp: new Date().toLocaleTimeString() }); try { const response = await fetch('save.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify(data) }); console.log('🔵 [SAVE] Réponse reçue:', { status: response.status, ok: response.ok }); if (!response.ok) { const error = await response.json(); console.error('🔴 [SAVE] Erreur serveur:', error); throw new Error(error.message || `HTTP error! status: ${response.status}`); } const result = await response.json(); console.log('✅ [SAVE] Sauvegarde réussie:', result); return true; } catch (error) { console.error('❌ [SAVE] Erreur sauvegarde serveur:', error); alert('⚠️ Erreur de sauvegarde sur le serveur. Vérifiez votre connexion.'); return false; } }; const authenticateServer = async (password) => { try { const response = await fetch('auth.php', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify({ password }) }); if (!response.ok) { return false; } const result = await response.json(); return result.success === true; } catch (error) { console.error('❌ Erreur authentification serveur:', error); return false; } }; const exportToCSV = () => { const headers = ['ID', 'Domaine', 'Sous-domaine', 'Titre', 'Mission', 'Cadres Juridiques', 'URLs Cadres', 'Jurisprudences', 'URLs Jurisprudences', 'Note']; const csvContent = [ headers.join(','), ...cadresData.map(c => { const cjTexts = c.cj.map(cj => typeof cj === 'string' ? cj : cj.text).join(' | '); const cjUrls = c.cj.map(cj => typeof cj === 'object' && cj.url ? cj.url : '').filter(u => u).join(' | '); const jpTexts = c.jp.map(jp => typeof jp === 'string' ? jp : jp.text).join(' | '); const jpUrls = c.jp.map(jp => typeof jp === 'object' && jp.url ? jp.url : '').filter(u => u).join(' | '); return [ c.id, `"${c.dom.replace(/"/g, '""')}"`, `"${c.sd.replace(/"/g, '""')}"`, `"${c.dem.replace(/"/g, '""')}"`, `"${c.mis.replace(/"/g, '""')}"`, `"${cjTexts.replace(/"/g, '""')}"`, `"${cjUrls.replace(/"/g, '""')}"`, `"${jpTexts.replace(/"/g, '""')}"`, `"${jpUrls.replace(/"/g, '""')}"`, `"${(c.note || '').replace(/"/g, '""')}"` ].join(','); }) ].join('\n'); const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `ONARP_Cadres_Juridiques_${new Date().toISOString().split('T')[0]}.csv`; link.click(); }; const exportToJSON = () => { const jsonContent = JSON.stringify(cadresData, null, 2); const blob = new Blob([jsonContent], { type: 'application/json' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = `ONARP_Cadres_Juridiques_${new Date().toISOString().split('T')[0]}.json`; link.click(); }; const handleEditCadre = (cadre) => { setIsAddingNew(false); setEditingCadre(cadre); setIsCreatingDomain(false); setIsCreatingSubdomain(false); setCustomDomain(''); setCustomSubdomain(''); const cjArray = Array.isArray(cadre.cj) && cadre.cj.length > 0 ? cadre.cj.map(item => typeof item === 'string' ? { text: item, url: '' } : { text: item.text || '', url: item.url || '' }) : []; const jpArray = Array.isArray(cadre.jp) && cadre.jp.length > 0 ? cadre.jp.map(item => typeof item === 'string' ? { text: item, url: '' } : { text: item.text || '', url: item.url || '' }) : []; setFormData({ dom: cadre.dom || '', sd: cadre.sd || '', dem: cadre.dem || '', mis: cadre.mis || '', cj: cjArray, jp: jpArray, note: cadre.note || '' }); setShowEditModal(true); }; const handleAddNewCadre = () => { setIsAddingNew(true); setEditingCadre(null); setIsCreatingDomain(false); setIsCreatingSubdomain(false); setCustomDomain(''); setCustomSubdomain(''); setFormData({ dom: '', sd: '', dem: '', mis: '', cj: [], jp: [], note: '' }); setShowEditModal(true); }; const handleSaveCadre = async () => { const finalDomain = isCreatingDomain ? customDomain.trim() : formData.dom; const finalSubdomain = isCreatingSubdomain ? customSubdomain.trim() : formData.sd; if (!finalDomain || !finalSubdomain || !formData.dem || !formData.mis) { alert('Veuillez remplir tous les champs obligatoires : Domaine, Sous-domaine, Titre et Mission'); return; } if (isAddingNew) { const newId = Math.max(...cadresData.map(c => c.id), 0) + 1; const newCadre = { id: newId, dom: finalDomain, sd: finalSubdomain, dem: formData.dem, mis: formData.mis, cj: formData.cj.map(item => item.url ? { text: item.text, url: item.url } : item.text), jp: formData.jp.map(item => item.url ? { text: item.text, url: item.url } : item.text), note: formData.note }; const updatedData = [...cadresData, newCadre]; setCadresData(updatedData); console.log('💾 [AJOUT] Appel saveToServer avec', updatedData.length, 'cadres'); await saveToServer(updatedData); alert('✅ Nouveau cadre créé avec succès !'); } else { const updatedCadre = { ...editingCadre, dom: finalDomain, sd: finalSubdomain, dem: formData.dem, mis: formData.mis, cj: formData.cj.map(item => item.url ? { text: item.text, url: item.url } : item.text), jp: formData.jp.map(item => item.url ? { text: item.text, url: item.url } : item.text), note: formData.note }; const updatedData = cadresData.map(c => c.id === editingCadre.id ? updatedCadre : c ); setCadresData(updatedData); console.log('💾 [MODIFICATION] Appel saveToServer avec', updatedData.length, 'cadres'); await saveToServer(updatedData); if (sel?.id === editingCadre.id) { setSel(updatedCadre); } alert('✅ Modifications sauvegardées avec succès !'); } setShowEditModal(false); setEditingCadre(null); setIsAddingNew(false); setIsCreatingDomain(false); setIsCreatingSubdomain(false); setCustomDomain(''); setCustomSubdomain(''); setAdminView('main'); }; const handleDeleteCadre = (cadreId) => { const cadre = cadresData.find(c => c.id === cadreId); if (!cadre) { alert('Erreur : Cadre introuvable'); return; } setCadreToDelete(cadre); setShowDeleteConfirm(true); }; const confirmDelete = async () => { if (cadreToDelete) { const updatedData = cadresData.filter(c => c.id !== cadreToDelete.id); setCadresData(updatedData); console.log('💾 [SUPPRESSION] Appel saveToServer avec', updatedData.length, 'cadres'); await saveToServer(updatedData); if (sel?.id === cadreToDelete.id) { setSel(null); } setShowDeleteConfirm(false); setCadreToDelete(null); alert('✅ Cadre supprimé avec succès !'); } }; const cancelDelete = () => { setShowDeleteConfirm(false); setCadreToDelete(null); }; const addCjItem = () => { setFormData({ ...formData, cj: [...formData.cj, { text: '', url: '' }] }); }; const addJpItem = () => { setFormData({ ...formData, jp: [...formData.jp, { text: '', url: '' }] }); }; const removeCjItem = (index) => { setFormData({ ...formData, cj: formData.cj.filter((_, i) => i !== index) }); }; const removeJpItem = (index) => { setFormData({ ...formData, jp: formData.jp.filter((_, i) => i !== index) }); }; const updateCjItem = (index, field, value) => { const newCj = [...formData.cj]; newCj[index][field] = value; setFormData({ ...formData, cj: newCj }); }; const updateJpItem = (index, field, value) => { const newJp = [...formData.jp]; newJp[index][field] = value; setFormData({ ...formData, jp: newJp }); }; const moveCjItem = (index, direction) => { if ((direction === 'up' && index === 0) || (direction === 'down' && index === formData.cj.length - 1)) return; const newCj = [...formData.cj]; const newIndex = direction === 'up' ? index - 1 : index + 1; [newCj[index], newCj[newIndex]] = [newCj[newIndex], newCj[index]]; setFormData({ ...formData, cj: newCj }); }; const moveJpItem = (index, direction) => { if ((direction === 'up' && index === 0) || (direction === 'down' && index === formData.jp.length - 1)) return; const newJp = [...formData.jp]; const newIndex = direction === 'up' ? index - 1 : index + 1; [newJp[index], newJp[newIndex]] = [newJp[newIndex], newJp[index]]; setFormData({ ...formData, jp: newJp }); }; const handleRip = (e) => { const x = e.clientX; const y = e.clientY; const id = Date.now(); setRip(prev => [...prev, { x, y, id }]); setTimeout(() => setRip(prev => prev.filter(r => r.id !== id)), 1500); }; const scrollToTop = () => { const duration = 1500; const start = window.pageYOffset; const startTime = performance.now(); const animateScroll = (currentTime) => { const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); const easeInOutCubic = progress < 0.5 ? 4 * progress * progress * progress : 1 - Math.pow(-2 * progress + 2, 3) / 2; window.scrollTo(0, start * (1 - easeInOutCubic)); if (progress < 1) { requestAnimationFrame(animateScroll); } }; requestAnimationFrame(animateScroll); }; const doms = useMemo(() => ['tous', ...new Set(cadresData.map(c => c.dom))], [cadresData]); const sds = useMemo(() => { if (d === 'tous') return []; return ['tous', ...new Set(cadresData.filter(c => c.dom === d).map(c => c.sd))]; }, [d, cadresData]); const filt = useMemo(() => { return cadresData.filter(c => { const md = d === 'tous' || c.dom === d; const msd = sd === 'tous' || c.sd === sd; const ms = !s || c.dem.toLowerCase().includes(s.toLowerCase()) || c.mis.toLowerCase().includes(s.toLowerCase()); return md && msd && ms; }); }, [d, sd, s, cadresData]); const btnClass = (active) => `relative px-5 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ease-in-out hover:scale-105 active:scale-95 hover:shadow-lg hover:shadow-amber-500/30 hover:ring-2 hover:ring-amber-500/50 ${active ? t==='dark' ? 'bg-amber-500 text-slate-900 shadow-lg ring-2 ring-amber-400' : 'bg-amber-500 text-white shadow-lg ring-2 ring-amber-400' : t==='dark' ? 'bg-slate-700 hover:bg-slate-600 text-white border border-slate-600' : 'bg-[#F0EDE7] hover:bg-[#DDD9D3] text-gray-700 border border-gray-300'}`; return (
{rip.map(r => ( ))}

ONARP

Outil d'aide à la détermination du cadre juridique

{authenticated && ( )}
{counters.domains}
Domaines juridiques
{counters.subdomains}
Sous-domaines juridiques
{counters.cadres}
Cadres juridiques
{adm && (

🔒 Mode Administration

)}
{adm ? (
{adminView === 'main' && (
)} {adminView === 'export' && (

Exporter les données

)} {adminView === 'modify' && (

Liste des cadres juridiques ({cadresData.length})

{cadresData.map(c => (
{c.dem}
{c.dom} • {c.sd}
{sel?.id === c.id && (

Mission dévolue

{c.mis}

Cadre juridique

    {c.cj.map((x,i)=> { const isObject = typeof x === 'object' && x !== null; const text = isObject ? x.text : x; const url = isObject ? x.url : null; return url ? (
  • {text}
  • ) : (
  • {text}
  • ); })}
{c.jp.length>0&&(

Jurisprudence

    {c.jp.map((j,i)=> { const isObject = typeof j === 'object' && j !== null; const text = isObject ? j.text : j; const url = isObject ? j.url : null; return url ? (
  • {text}
  • ) : (
  • {text}
  • ); })}
)} {c.note && (

Note particulière

{c.note}

)}
)}
))}
)}
) : (
setS(e.target.value)} className={`w-full px-5 py-3 sm:py-4 pl-12 rounded-xl border focus:outline-none focus:border-amber-500 focus:ring-2 focus:ring-amber-500/50 transition-all duration-200 text-sm sm:text-base ${t==='dark'?'bg-slate-800/50 border-slate-700 text-white placeholder-slate-400':'bg-[#F5F2EC] border-gray-300 text-black placeholder-gray-400'}`}/>
{doms.map(dm=>( ))}
{sds.length > 0 && (
{sds.map(s=>( ))}
)}
{filt.length} cadre{filt.length>1?'s':''}
{filt.map(c=>(
setSel(sel?.id===c.id?null:c)} className={`p-4 sm:p-6 rounded-xl cursor-pointer border transition-all duration-300 hover:scale-[1.02] hover:shadow-xl hover:shadow-amber-500/20 hover:ring-2 hover:ring-amber-500/50 ${sel?.id===c.id?t==='dark'?'bg-slate-800 border-amber-500 shadow-xl ring-2 ring-amber-400':'bg-amber-50 border-amber-400 ring-2 ring-amber-400':t==='dark'?'bg-slate-800/50 border-slate-700':'bg-[#F0EDE7] border-gray-300'}`}>
{c.dom}

{c.dem}

{c.sd}

{sel?.id===c.id&&(

Mission dévolue

{c.mis}

Cadre juridique

    {c.cj.map((x,i)=> { const isObject = typeof x === 'object' && x !== null; const text = isObject ? x.text : x; const url = isObject ? x.url : null; return url ? (
  • {text}
  • ) : (
  • {text}
  • ); })}
{c.jp.length>0&&(

Jurisprudence

    {c.jp.map((j,i)=> { const isObject = typeof j === 'object' && j !== null; const text = isObject ? j.text : j; const url = isObject ? j.url : null; return url ? (
  • {text}
  • ) : (
  • {text}
  • ); })}
)} {c.note && (

Note particulière

{c.note}

)}
)}
))}
)}
{showLoginModal && (

Espace Administrateur

Authentification sécurisée requise

{ setLoginPassword(e.target.value); setLoginError(''); }} className={`w-full px-5 py-3 sm:py-4 rounded-xl border-2 focus:outline-none focus:ring-4 focus:ring-amber-500/30 transition-all text-base sm:text-lg ${t==='dark'?'bg-slate-800 border-slate-700 text-white focus:border-amber-500':'bg-white border-gray-300 text-black focus:border-amber-500'}`} placeholder="Entrez votre mot de passe" autoFocus required />
{loginError && (
⚠️ {loginError}
)}

🛡️ Connexion sécurisée par ONARP

)} {showEditModal && (editingCadre || isAddingNew) && (
e.stopPropagation()}>

{isAddingNew ? 'Ajouter un cadre juridique' : 'Éditer le cadre juridique'}

{!isCreatingDomain ? ( ) : (
setCustomDomain(e.target.value)} placeholder="Ex: Droit administratif" className={`flex-1 px-3 sm:px-4 py-2 sm:py-3 rounded-lg border text-sm sm:text-base focus:outline-none focus:ring-2 focus:ring-amber-500/50 transition-all ${t==='dark'?'bg-slate-700 border-slate-600 text-white placeholder-slate-400':'bg-[#F5F2EC] border-gray-300 text-black placeholder-gray-400'}`} />
)}
{!isCreatingSubdomain ? ( ) : (
setCustomSubdomain(e.target.value)} placeholder="Ex: Contentieux administratif" className={`flex-1 px-3 sm:px-4 py-2 sm:py-3 rounded-lg border text-sm sm:text-base focus:outline-none focus:ring-2 focus:ring-amber-500/50 transition-all ${t==='dark'?'bg-slate-700 border-slate-600 text-white placeholder-slate-400':'bg-[#F5F2EC] border-gray-300 text-black placeholder-gray-400'}`} />
)}
setFormData({...formData, dem: e.target.value})} className={`w-full px-3 sm:px-4 py-2 sm:py-3 rounded-lg border text-sm sm:text-base focus:outline-none focus:ring-2 focus:ring-amber-500/50 transition-all ${t==='dark'?'bg-slate-700 border-slate-600 text-white':'bg-[#F5F2EC] border-gray-300 text-black'}`} placeholder="Ex: Infidélité dans un concubinage" />