init projet

This commit is contained in:
2026-05-20 10:43:18 +02:00
parent 51f27903bb
commit 9a402b0b34
57 changed files with 5622 additions and 0 deletions
+230
View File
@@ -0,0 +1,230 @@
// src/pages/Admin/Admin.jsx
// Page Administration : onglets pour gérer monitorings, services, catégories, contacts
import { useState, useEffect } from 'react';
import { Plus, Edit, Trash2 } from 'lucide-react';
import { getMonitorings, getServices, getCategories, getContacts } from '../../services/api';
import DataTable from '../../components/common/DataTable';
import LoadingSpinner from '../../components/common/LoadingSpinner';
import ErrorMessage from '../../components/common/ErrorMessage';
import Button from '../../components/common/Button';
import styles from './Admin.module.css';
/* Modale générique pour ajouter/modifier */
function Modal({ isOpen, onClose, title, children }) {
if (!isOpen) return null;
return (
<div className={styles.modalOverlay} onClick={onClose}>
<div className={styles.modal} onClick={e => e.stopPropagation()}>
<div className={styles.modalHeader}>
<h2>{title}</h2>
<button className={styles.closeBtn} onClick={onClose}>×</button>
</div>
<div className={styles.modalBody}>
{children}
</div>
</div>
</div>
);
}
export default function Admin() {
const [activeTab, setActiveTab] = useState('monitorings');
const [data, setData] = useState({});
const [loading, setLoading] = useState(true);
const [erreur, setErreur] = useState('');
const [modalOpen, setModalOpen] = useState(false);
const [editingItem, setEditingItem] = useState(null);
useEffect(() => {
async function loadData() {
setLoading(true);
setErreur('');
try {
const [monitorings, services, categories, contacts] = await Promise.all([
getMonitorings(),
getServices(),
getCategories(),
getContacts()
]);
setData({
monitorings: Array.isArray(monitorings) ? monitorings : [],
services: Array.isArray(services) ? services : [],
categories: Array.isArray(categories) ? categories : [],
contacts: Array.isArray(contacts) ? contacts : []
});
} catch (e) {
setErreur(e.message || 'Erreur lors du chargement des données administratives.');
} finally {
setLoading(false);
}
}
loadData();
}, []);
function handleAdd() {
setEditingItem(null);
setModalOpen(true);
}
function handleEdit(item) {
setEditingItem(item);
setModalOpen(true);
}
function handleDelete(item) {
// Simulation de suppression (pas d'API pour ça)
console.log('Supprimer', item);
}
const tabs = [
{ key: 'monitorings', label: 'Monitorings' },
{ key: 'services', label: 'Services' },
{ key: 'categories', label: 'Catégories' },
{ key: 'contacts', label: 'Contacts' }
];
const columns = {
monitorings: [
{ key: 'monito_intitule', label: 'Nom' },
{ key: 'id_service', label: 'Service' },
{ key: 'id_categorie', label: 'Catégorie' },
{ key: 'bdd_source', label: 'Source' },
{ key: 'table_source', label: 'Table' },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<div className={styles.actions}>
<button className={styles.actionBtn} onClick={() => handleEdit(row)}>
<Edit size={14} />
Modifier
</button>
<button className={styles.actionBtn} onClick={() => handleDelete(row)}>
<Trash2 size={14} />
Désactiver
</button>
</div>
)
}
],
services: [
{ key: 'nom_service', label: 'Nom' },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<div className={styles.actions}>
<button className={styles.actionBtn} onClick={() => handleEdit(row)}>
<Edit size={14} />
Modifier
</button>
<button className={styles.actionBtn} onClick={() => handleDelete(row)}>
<Trash2 size={14} />
Désactiver
</button>
</div>
)
}
],
categories: [
{ key: 'intitule_categorie', label: 'Nom' },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<div className={styles.actions}>
<button className={styles.actionBtn} onClick={() => handleEdit(row)}>
<Edit size={14} />
Modifier
</button>
<button className={styles.actionBtn} onClick={() => handleDelete(row)}>
<Trash2 size={14} />
Désactiver
</button>
</div>
)
}
],
contacts: [
{ key: 'intitule_contact', label: 'Intitulé' },
{ key: 'nom', label: 'Nom' },
{ key: 'prenom', label: 'Prénom' },
{ key: 'mail', label: 'Email' },
{ key: 'id_service', label: 'Service' },
{
key: 'actions',
label: 'Actions',
render: (val, row) => (
<div className={styles.actions}>
<button className={styles.actionBtn} onClick={() => handleEdit(row)}>
<Edit size={14} />
Modifier
</button>
<button className={styles.actionBtn} onClick={() => handleDelete(row)}>
<Trash2 size={14} />
Désactiver
</button>
</div>
)
}
]
};
if (loading) return <LoadingSpinner message="Chargement des données administratives..." />;
if (erreur) return <ErrorMessage message={erreur} />;
return (
<div className={styles.page}>
<h1 className={styles.title}>Administration</h1>
{/* Onglets */}
<div className={styles.tabs}>
{tabs.map(tab => (
<button
key={tab.key}
className={`${styles.tab} ${activeTab === tab.key ? styles.active : ''}`}
onClick={() => setActiveTab(tab.key)}
>
{tab.label}
</button>
))}
</div>
{/* Contenu de l'onglet actif */}
<div className={styles.tabContent}>
<div className={styles.header}>
<h2>{tabs.find(t => t.key === activeTab)?.label}</h2>
<Button variant="primary" onClick={handleAdd}>
<Plus size={14} />
Ajouter
</Button>
</div>
<DataTable
columns={columns[activeTab]}
data={data[activeTab] || []}
pageSize={50}
emptyMessage={`Aucun ${activeTab.slice(0, -1)} trouvé.`}
/>
</div>
{/* Modale */}
<Modal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
title={`${editingItem ? 'Modifier' : 'Ajouter'} ${tabs.find(t => t.key === activeTab)?.label.slice(0, -1)}`}
>
<p>Formulaire à implémenter selon les besoins.</p>
<div className={styles.modalActions}>
<Button variant="secondary" onClick={() => setModalOpen(false)}>
Annuler
</Button>
<Button variant="primary" onClick={() => setModalOpen(false)}>
Enregistrer
</Button>
</div>
</Modal>
</div>
);
}