function ProjectList({ onSelectProject, user }) { const [projects, setProjects] = React.useState([]); const [loading, setLoading] = React.useState(true); const [showNewModal, setShowNewModal] = React.useState(false); const [newName, setNewName] = React.useState(''); const [newDesc, setNewDesc] = React.useState(''); const [creating, setCreating] = React.useState(false); const loadProjects = async () => { try { const data = await API.get('/api/projects'); setProjects(data); } catch (err) { Toasts.error(err.message); } finally { setLoading(false); } }; React.useEffect(() => { loadProjects(); }, []); const handleCreate = async () => { if (!newName.trim()) return; setCreating(true); try { await API.post('/api/projects', { name: newName, description: newDesc }); setShowNewModal(false); setNewName(''); setNewDesc(''); Toasts.success('Projet créé'); loadProjects(); } catch (err) { Toasts.error(err.message); } finally { setCreating(false); } }; const handleDelete = async (e, id, name) => { e.stopPropagation(); if (!confirm(`Supprimer le projet "${name}" et toutes ses données ?`)) return; try { await API.delete(`/api/projects/${id}`); Toasts.success('Projet supprimé'); loadProjects(); } catch (err) { Toasts.error(err.message); } }; if (loading) { return React.createElement('div', { className: 'loading-page' }, React.createElement('span', { className: 'loading-spinner' }), 'Chargement...' ); } const isAdmin = user && user.role === 'admin'; return React.createElement('div', { className: 'projects-page' }, React.createElement('div', { className: 'projects-header' }, React.createElement('h2', null, 'Mes Projets'), isAdmin && React.createElement('button', { className: 'btn btn-primary', onClick: () => setShowNewModal(true) }, '+ Nouveau projet') ), projects.length === 0 ? React.createElement('div', { style: { textAlign: 'center', padding: '80px 20px', color: 'var(--text-muted)' } }, React.createElement('p', { style: { fontSize: '48px', marginBottom: '16px' } }, '\uD83D\uDCCB'), React.createElement('p', { style: { fontSize: '18px' } }, 'Aucun projet disponible'), isAdmin && React.createElement('p', { style: { fontSize: '14px', marginTop: '8px' } }, 'Créez votre premier projet pour commencer' ) ) : React.createElement('div', { className: 'projects-grid' }, projects.map((p, i) => { const progress = p.step_count > 0 ? Math.round((p.done_count / p.step_count) * 100) : 0; return React.createElement('div', { key: p.id, className: 'project-card', style: { animationDelay: `${i * 0.1}s` }, onClick: () => onSelectProject(p.id) }, React.createElement('div', { className: 'project-card-header' }, React.createElement('h3', null, p.name), isAdmin && React.createElement('div', { className: 'project-card-actions' }, React.createElement('button', { onClick: (e) => handleDelete(e, p.id, p.name), title: 'Supprimer' }, '\u2715') ) ), p.description && React.createElement('div', { className: 'project-card-desc' }, p.description), React.createElement('div', { className: 'project-card-stats' }, React.createElement('span', { className: 'stat-badge stat-done' }, '\u2713 ', p.done_count || 0), React.createElement('span', { className: 'stat-badge stat-active' }, '\u25CF ', p.active_count || 0), React.createElement('span', { className: 'stat-badge stat-blocked' }, '! ', p.blocked_count || 0), React.createElement('span', { className: 'stat-badge stat-wait' }, '\u25CB ', (p.step_count || 0) - (p.done_count || 0) - (p.active_count || 0) - (p.blocked_count || 0) ) ), React.createElement('div', { className: 'project-card-progress' }, React.createElement('div', { className: 'project-card-progress-bar', style: { width: `${progress}%` } }) ), React.createElement('div', { className: 'project-card-meta' }, React.createElement('span', null, `${p.phase_count || 0} phases \u2022 ${p.step_count || 0} \u00e9tapes`), React.createElement('span', null, `${progress}%`) ) ); }) ), // New project modal showNewModal && React.createElement('div', { className: 'modal-overlay', onClick: (e) => { if (e.target === e.currentTarget) setShowNewModal(false); } }, React.createElement('div', { className: 'modal-content' }, React.createElement('div', { className: 'modal-header' }, React.createElement('h3', null, 'Nouveau Projet'), React.createElement('button', { className: 'modal-close', onClick: () => setShowNewModal(false) }, '\u2715') ), React.createElement('div', { className: 'new-project-form' }, React.createElement('div', { className: 'form-group' }, React.createElement('label', null, 'Nom du projet'), React.createElement('input', { type: 'text', value: newName, placeholder: 'Ex: PetCam v2', onChange: e => setNewName(e.target.value), autoFocus: true }) ), React.createElement('div', { className: 'form-group' }, React.createElement('label', null, 'Description'), React.createElement('textarea', { value: newDesc, placeholder: 'Description du projet...', onChange: e => setNewDesc(e.target.value), rows: 3 }) ) ), React.createElement('div', { className: 'modal-actions' }, React.createElement('button', { className: 'btn btn-ghost', onClick: () => setShowNewModal(false) }, 'Annuler'), React.createElement('button', { className: 'btn btn-primary', disabled: !newName.trim() || creating, onClick: handleCreate }, creating ? 'Création...' : 'Créer le projet') ) ) ) ); }