Initial commit
This commit is contained in:
336
app/(main)/notifications/automatiques/page.tsx
Normal file
336
app/(main)/notifications/automatiques/page.tsx
Normal file
@@ -0,0 +1,336 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { Card } from 'primereact/card';
|
||||
import { DataTable } from 'primereact/datatable';
|
||||
import { Column } from 'primereact/column';
|
||||
import { InputSwitch } from 'primereact/inputswitch';
|
||||
import { Button } from 'primereact/button';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import { Message } from 'primereact/message';
|
||||
|
||||
interface NotificationRule {
|
||||
id: string;
|
||||
nom: string;
|
||||
description: string;
|
||||
type: 'info' | 'warning' | 'success' | 'error';
|
||||
evenement: string;
|
||||
actif: boolean;
|
||||
categorie: string;
|
||||
}
|
||||
|
||||
const NotificationsAutomatiquesPage = () => {
|
||||
const toast = useRef<Toast>(null);
|
||||
const [rules, setRules] = useState<NotificationRule[]>([
|
||||
{
|
||||
id: '1',
|
||||
nom: 'Nouveau chantier créé',
|
||||
description: 'Notification envoyée lors de la création d\'un nouveau chantier',
|
||||
type: 'success',
|
||||
evenement: 'chantier.created',
|
||||
actif: true,
|
||||
categorie: 'Chantiers'
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
nom: 'Chantier terminé',
|
||||
description: 'Notification envoyée lorsqu\'un chantier est marqué comme terminé',
|
||||
type: 'success',
|
||||
evenement: 'chantier.completed',
|
||||
actif: true,
|
||||
categorie: 'Chantiers'
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
nom: 'Dépassement de budget',
|
||||
description: 'Alerte envoyée lorsque le budget d\'un chantier est dépassé',
|
||||
type: 'warning',
|
||||
evenement: 'budget.exceeded',
|
||||
actif: true,
|
||||
categorie: 'Budget'
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
nom: 'Retard de chantier',
|
||||
description: 'Notification envoyée lorsqu\'un chantier est en retard',
|
||||
type: 'warning',
|
||||
evenement: 'chantier.delayed',
|
||||
actif: true,
|
||||
categorie: 'Chantiers'
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
nom: 'Phase terminée',
|
||||
description: 'Notification envoyée lorsqu\'une phase de chantier est terminée',
|
||||
type: 'success',
|
||||
evenement: 'phase.completed',
|
||||
actif: false,
|
||||
categorie: 'Phases'
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
nom: 'Nouveau client',
|
||||
description: 'Notification envoyée lors de l\'ajout d\'un nouveau client',
|
||||
type: 'info',
|
||||
evenement: 'client.created',
|
||||
actif: true,
|
||||
categorie: 'Clients'
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
nom: 'Stock faible',
|
||||
description: 'Alerte envoyée lorsque le stock d\'un matériel est faible',
|
||||
type: 'warning',
|
||||
evenement: 'stock.low',
|
||||
actif: true,
|
||||
categorie: 'Stock'
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
nom: 'Erreur système',
|
||||
description: 'Notification envoyée en cas d\'erreur système critique',
|
||||
type: 'error',
|
||||
evenement: 'system.error',
|
||||
actif: true,
|
||||
categorie: 'Système'
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
nom: 'Facture créée',
|
||||
description: 'Notification envoyée lors de la création d\'une facture',
|
||||
type: 'info',
|
||||
evenement: 'facture.created',
|
||||
actif: false,
|
||||
categorie: 'Facturation'
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
nom: 'Paiement reçu',
|
||||
description: 'Notification envoyée lors de la réception d\'un paiement',
|
||||
type: 'success',
|
||||
evenement: 'paiement.received',
|
||||
actif: true,
|
||||
categorie: 'Facturation'
|
||||
}
|
||||
]);
|
||||
|
||||
const toggleRule = (ruleId: string) => {
|
||||
setRules(rules.map(rule => {
|
||||
if (rule.id === ruleId) {
|
||||
const newActif = !rule.actif;
|
||||
toast.current?.show({
|
||||
severity: newActif ? 'success' : 'info',
|
||||
summary: newActif ? 'Activée' : 'Désactivée',
|
||||
detail: `La règle "${rule.nom}" a été ${newActif ? 'activée' : 'désactivée'}`,
|
||||
life: 3000
|
||||
});
|
||||
return { ...rule, actif: newActif };
|
||||
}
|
||||
return rule;
|
||||
}));
|
||||
};
|
||||
|
||||
const activerTout = () => {
|
||||
setRules(rules.map(rule => ({ ...rule, actif: true })));
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Succès',
|
||||
detail: 'Toutes les notifications automatiques ont été activées',
|
||||
life: 3000
|
||||
});
|
||||
};
|
||||
|
||||
const desactiverTout = () => {
|
||||
setRules(rules.map(rule => ({ ...rule, actif: false })));
|
||||
toast.current?.show({
|
||||
severity: 'info',
|
||||
summary: 'Désactivé',
|
||||
detail: 'Toutes les notifications automatiques ont été désactivées',
|
||||
life: 3000
|
||||
});
|
||||
};
|
||||
|
||||
const typeBodyTemplate = (rowData: NotificationRule) => {
|
||||
const getSeverity = (type: string) => {
|
||||
switch (type) {
|
||||
case 'info': return 'info';
|
||||
case 'warning': return 'warning';
|
||||
case 'success': return 'success';
|
||||
case 'error': return 'danger';
|
||||
default: return 'info';
|
||||
}
|
||||
};
|
||||
|
||||
const getIcon = (type: string) => {
|
||||
switch (type) {
|
||||
case 'info': return 'pi-info-circle';
|
||||
case 'warning': return 'pi-exclamation-triangle';
|
||||
case 'success': return 'pi-check-circle';
|
||||
case 'error': return 'pi-times-circle';
|
||||
default: return 'pi-info-circle';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tag
|
||||
value={rowData.type.toUpperCase()}
|
||||
severity={getSeverity(rowData.type)}
|
||||
icon={`pi ${getIcon(rowData.type)}`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const statusBodyTemplate = (rowData: NotificationRule) => {
|
||||
return (
|
||||
<Tag
|
||||
value={rowData.actif ? 'Activée' : 'Désactivée'}
|
||||
severity={rowData.actif ? 'success' : 'secondary'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const actionBodyTemplate = (rowData: NotificationRule) => {
|
||||
return (
|
||||
<InputSwitch
|
||||
checked={rowData.actif}
|
||||
onChange={() => toggleRule(rowData.id)}
|
||||
tooltip={rowData.actif ? 'Désactiver' : 'Activer'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const categorieBodyTemplate = (rowData: NotificationRule) => {
|
||||
const getCategorieColor = (categorie: string) => {
|
||||
switch (categorie) {
|
||||
case 'Chantiers': return 'info';
|
||||
case 'Budget': return 'warning';
|
||||
case 'Phases': return 'success';
|
||||
case 'Clients': return 'info';
|
||||
case 'Stock': return 'warning';
|
||||
case 'Système': return 'danger';
|
||||
case 'Facturation': return 'success';
|
||||
default: return 'info';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tag value={rowData.categorie} severity={getCategorieColor(rowData.categorie)} />
|
||||
);
|
||||
};
|
||||
|
||||
const header = (
|
||||
<div className="flex flex-column md:flex-row md:justify-content-between md:align-items-center">
|
||||
<h5 className="m-0">Règles de notifications automatiques</h5>
|
||||
<div className="flex gap-2 mt-2 md:mt-0">
|
||||
<Button
|
||||
label="Tout activer"
|
||||
icon="pi pi-check-square"
|
||||
className="p-button-text p-button-success"
|
||||
onClick={activerTout}
|
||||
/>
|
||||
<Button
|
||||
label="Tout désactiver"
|
||||
icon="pi pi-times"
|
||||
className="p-button-text p-button-secondary"
|
||||
onClick={desactiverTout}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const activeCount = rules.filter(r => r.actif).length;
|
||||
const totalCount = rules.length;
|
||||
|
||||
return (
|
||||
<div className="grid">
|
||||
<div className="col-12">
|
||||
<h2>Notifications Automatiques</h2>
|
||||
<p className="text-color-secondary">
|
||||
Configurez les notifications automatiques envoyées lors d'événements spécifiques
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<Toast ref={toast} />
|
||||
|
||||
<Card>
|
||||
<Message
|
||||
severity="info"
|
||||
content={
|
||||
<div>
|
||||
<div className="font-bold mb-2">Configuration des notifications automatiques</div>
|
||||
<div className="text-sm">
|
||||
{activeCount} règle{activeCount > 1 ? 's' : ''} activée{activeCount > 1 ? 's' : ''} sur {totalCount}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
className="mb-4"
|
||||
/>
|
||||
|
||||
<DataTable
|
||||
value={rules}
|
||||
dataKey="id"
|
||||
paginator
|
||||
rows={10}
|
||||
rowsPerPageOptions={[5, 10, 25]}
|
||||
className="datatable-responsive"
|
||||
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
|
||||
currentPageReportTemplate="Affichage de {first} à {last} sur {totalRecords} règles"
|
||||
emptyMessage="Aucune règle configurée."
|
||||
header={header}
|
||||
responsiveLayout="scroll"
|
||||
>
|
||||
<Column field="nom" header="Nom" sortable style={{ minWidth: '15rem' }} />
|
||||
<Column field="description" header="Description" style={{ minWidth: '20rem' }} />
|
||||
<Column field="categorie" header="Catégorie" body={categorieBodyTemplate} sortable style={{ minWidth: '10rem' }} />
|
||||
<Column field="type" header="Type" body={typeBodyTemplate} sortable style={{ minWidth: '8rem' }} />
|
||||
<Column field="actif" header="Statut" body={statusBodyTemplate} sortable style={{ minWidth: '8rem' }} />
|
||||
<Column header="Activer/Désactiver" body={actionBodyTemplate} style={{ minWidth: '10rem' }} />
|
||||
</DataTable>
|
||||
|
||||
<Divider />
|
||||
|
||||
<div className="text-sm text-color-secondary">
|
||||
<h5 className="mt-0 mb-3">Informations sur les notifications automatiques</h5>
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-6">
|
||||
<h6 className="text-color">Événements de chantiers</h6>
|
||||
<ul className="pl-3 mt-2">
|
||||
<li>Création de nouveau chantier</li>
|
||||
<li>Chantier terminé</li>
|
||||
<li>Retard détecté</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<h6 className="text-color">Événements de budget</h6>
|
||||
<ul className="pl-3 mt-2">
|
||||
<li>Dépassement de budget</li>
|
||||
<li>Seuil d'alerte atteint</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<h6 className="text-color">Événements de stock</h6>
|
||||
<ul className="pl-3 mt-2">
|
||||
<li>Stock faible</li>
|
||||
<li>Rupture de stock</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<h6 className="text-color">Événements système</h6>
|
||||
<ul className="pl-3 mt-2">
|
||||
<li>Erreurs critiques</li>
|
||||
<li>Mises à jour importantes</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotificationsAutomatiquesPage;
|
||||
|
||||
Reference in New Issue
Block a user