fix: Resolve TypeScript errors in page.tsx and phases-chantier/page.tsx

This commit is contained in:
dahoud
2025-10-15 20:01:04 +00:00
parent 763ab81da3
commit aed2ce0182
22 changed files with 152 additions and 118 deletions

View File

@@ -255,8 +255,7 @@ const FacturesPage = () => {
const editFacture = (facture: Facture) => { const editFacture = (facture: Facture) => {
setFacture({ setFacture({
...facture, ...facture
client: facture.client?.id || null
}); });
setFactureDialog(true); setFactureDialog(true);
}; };
@@ -390,7 +389,7 @@ const FacturesPage = () => {
/> />
<ActionButton <ActionButton
icon="pi pi-send" icon="pi pi-send"
color="secondary" color="blue"
tooltip="Envoyer par email" tooltip="Envoyer par email"
onClick={() => { onClick={() => {
toast.current?.show({ toast.current?.show({
@@ -402,10 +401,12 @@ const FacturesPage = () => {
}} }}
/> />
<EditButton <EditButton
onClick={() => editFacture(rowData)} tooltip="Modifier"
onClick={() => editFacture(rowData)}
/> />
<DeleteButton <DeleteButton
onClick={() => confirmDeleteFacture(rowData)} tooltip="Supprimer"
onClick={() => confirmDeleteFacture(rowData)}
/> />
</ActionButtonGroup> </ActionButtonGroup>
); );
@@ -456,9 +457,9 @@ const FacturesPage = () => {
}; };
return ( return (
<Tag <Tag
value={getTypeLabel(rowData.type)} value={getTypeLabel(rowData.typeFacture)}
severity={rowData.type === 'AVOIR' ? 'warning' : 'info'} severity={rowData.typeFacture === 'AVOIR' ? 'warning' : 'info'}
/> />
); );
}; };
@@ -526,6 +527,7 @@ const FacturesPage = () => {
value={factures} value={factures}
selection={selectedFactures} selection={selectedFactures}
onSelectionChange={(e) => setSelectedFactures(e.value)} onSelectionChange={(e) => setSelectedFactures(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}
@@ -575,12 +577,12 @@ const FacturesPage = () => {
</div> </div>
<div className="field col-12 md:col-6"> <div className="field col-12 md:col-6">
<label htmlFor="type">Type</label> <label htmlFor="typeFacture">Type</label>
<Dropdown <Dropdown
id="type" id="typeFacture"
value={facture.type} value={facture.typeFacture}
options={types} options={types}
onChange={(e) => onDropdownChange(e, 'type')} onChange={(e) => onDropdownChange(e, 'typeFacture')}
placeholder="Sélectionnez un type" placeholder="Sélectionnez un type"
/> />
</div> </div>
@@ -636,35 +638,35 @@ const FacturesPage = () => {
<div className="field col-12 md:col-4"> <div className="field col-12 md:col-4">
<label htmlFor="dateEmission">Date d'émission</label> <label htmlFor="dateEmission">Date d'émission</label>
<Calendar <Calendar
id="dateEmission" id="dateEmission"
value={facture.dateEmission} value={facture.dateEmission ? new Date(facture.dateEmission) : null}
onChange={(e) => onDateChange(e, 'dateEmission')} onChange={(e) => onDateChange(e, 'dateEmission')}
dateFormat="dd/mm/yy" dateFormat="dd/mm/yy"
showIcon showIcon
/> />
</div> </div>
<div className="field col-12 md:col-4"> <div className="field col-12 md:col-4">
<label htmlFor="dateEcheance">Date d'échéance</label> <label htmlFor="dateEcheance">Date d'échéance</label>
<Calendar <Calendar
id="dateEcheance" id="dateEcheance"
value={facture.dateEcheance} value={facture.dateEcheance ? new Date(facture.dateEcheance) : null}
onChange={(e) => onDateChange(e, 'dateEcheance')} onChange={(e) => onDateChange(e, 'dateEcheance')}
dateFormat="dd/mm/yy" dateFormat="dd/mm/yy"
showIcon showIcon
minDate={facture.dateEmission} minDate={facture.dateEmission ? new Date(facture.dateEmission) : undefined}
/> />
</div> </div>
<div className="field col-12 md:col-4"> <div className="field col-12 md:col-4">
<label htmlFor="datePaiement">Date de paiement</label> <label htmlFor="datePaiement">Date de paiement</label>
<Calendar <Calendar
id="datePaiement" id="datePaiement"
value={facture.datePaiement} value={facture.datePaiement ? new Date(facture.datePaiement) : null}
onChange={(e) => onDateChange(e, 'datePaiement')} onChange={(e) => onDateChange(e, 'datePaiement')}
dateFormat="dd/mm/yy" dateFormat="dd/mm/yy"
showIcon showIcon
/> />
</div> </div>

View File

@@ -488,6 +488,7 @@ RECOMMANDATIONS:
value={factures} value={factures}
selection={selectedFactures} selection={selectedFactures}
onSelectionChange={(e) => setSelectedFactures(e.value)} onSelectionChange={(e) => setSelectedFactures(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -20,6 +20,7 @@ import { Checkbox } from 'primereact/checkbox';
import { factureService } from '../../../../../services/api'; import { factureService } from '../../../../../services/api';
import { formatDate, formatCurrency } from '../../../../../utils/formatters'; import { formatDate, formatCurrency } from '../../../../../utils/formatters';
import type { Facture } from '../../../../../types/btp'; import type { Facture } from '../../../../../types/btp';
import { StatutFacture } from '../../../../../types/btp';
interface Relance { interface Relance {
id: string; id: string;
@@ -85,7 +86,7 @@ const FactureRelancePage = () => {
// Charger la facture // Charger la facture
const factureResponse = await factureService.getById(factureId); const factureResponse = await factureService.getById(factureId);
setFacture(factureResponse.data); setFacture(factureResponse);
// TODO: Charger les relances et templates depuis l'API // TODO: Charger les relances et templates depuis l'API
// const relancesResponse = await factureService.getRelances(factureId); // const relancesResponse = await factureService.getRelances(factureId);
@@ -142,8 +143,8 @@ const FactureRelancePage = () => {
setTemplates(mockTemplates); setTemplates(mockTemplates);
// Pré-remplir le destinataire // Pré-remplir le destinataire
if (factureResponse.data.client) { if (factureResponse.client) {
const client = factureResponse.data.client; const client = factureResponse.client;
setNouvelleRelance(prev => ({ setNouvelleRelance(prev => ({
...prev, ...prev,
destinataire: typeof client === 'string' ? client : client.email || client.nom destinataire: typeof client === 'string' ? client : client.email || client.nom
@@ -309,9 +310,9 @@ const FactureRelancePage = () => {
<div> <div>
<h2 className="text-2xl font-bold mb-2">Relances - Facture #{facture.numero}</h2> <h2 className="text-2xl font-bold mb-2">Relances - Facture #{facture.numero}</h2>
<p className="text-600 mb-3">{facture.objet}</p> <p className="text-600 mb-3">{facture.objet}</p>
<Tag <Tag
value={facture.statut} value={facture.statut}
severity={facture.statut === 'EN_RETARD' ? 'danger' : 'warning'} severity={facture.statut === StatutFacture.ECHUE ? 'danger' : 'warning'}
/> />
</div> </div>
<div className="text-right"> <div className="text-right">

View File

@@ -314,7 +314,7 @@ BTP Express`
return <Tag value="À échoir" severity="info" />; return <Tag value="À échoir" severity="info" />;
} }
let severity = 'warning'; let severity: "warning" | "danger" = 'warning';
if (rowData.joursRetard > 60) severity = 'danger'; if (rowData.joursRetard > 60) severity = 'danger';
else if (rowData.joursRetard > 30) severity = 'warning'; else if (rowData.joursRetard > 30) severity = 'warning';
@@ -340,7 +340,7 @@ BTP Express`
}; };
const risqueBodyTemplate = (rowData: any) => { const risqueBodyTemplate = (rowData: any) => {
const config = { const config: Record<string, { color: "success" | "warning" | "danger", icon: string }> = {
'FAIBLE': { color: 'success', icon: 'pi-check-circle' }, 'FAIBLE': { color: 'success', icon: 'pi-check-circle' },
'MOYEN': { color: 'warning', icon: 'pi-exclamation-triangle' }, 'MOYEN': { color: 'warning', icon: 'pi-exclamation-triangle' },
'FORT': { color: 'danger', icon: 'pi-times-circle' } 'FORT': { color: 'danger', icon: 'pi-times-circle' }
@@ -360,20 +360,22 @@ BTP Express`
<ActionButtonGroup> <ActionButtonGroup>
<ActionButton <ActionButton
icon="pi pi-send" icon="pi pi-send"
color="warning" color="orange"
tooltip="Envoyer relance" tooltip="Envoyer relance"
onClick={() => ouvrirRelance(rowData)} onClick={() => ouvrirRelance(rowData)}
disabled={rowData.joursRetard <= 0} disabled={rowData.joursRetard <= 0}
/> />
<ActionButton <ActionButton
icon="pi pi-phone" icon="pi pi-phone"
color="info" color="blue"
tooltip="Appeler client" tooltip="Appeler client"
onClick={() => {}}
/> />
<ViewButton <ViewButton
tooltip="Voir historique" tooltip="Voir historique"
onClick={() => {}}
/> />
</ActionButtonGroup> </ActionButtonGroup>
); );

View File

@@ -18,6 +18,7 @@ import { ProgressBar } from 'primereact/progressbar';
import { factureService } from '../../../../services/api'; import { factureService } from '../../../../services/api';
import { formatDate, formatCurrency } from '../../../../utils/formatters'; import { formatDate, formatCurrency } from '../../../../utils/formatters';
import type { Facture } from '../../../../types/btp'; import type { Facture } from '../../../../types/btp';
import { StatutFacture } from '../../../../types/btp';
import factureActionsService from '../../../../services/factureActionsService'; import factureActionsService from '../../../../services/factureActionsService';
const FacturesRetardPage = () => { const FacturesRetardPage = () => {
@@ -66,12 +67,12 @@ const FacturesRetardPage = () => {
try { try {
setLoading(true); setLoading(true);
const data = await factureService.getAll(); const data = await factureService.getAll();
// Filtrer les factures en retard (échéance dépassée + statut EN_RETARD) // Filtrer les factures en retard (échéance dépassée + statut ECHUE)
const facturesEnRetard = data.filter(facture => { const facturesEnRetard = data.filter(facture => {
const today = new Date(); const today = new Date();
const echeanceDate = new Date(facture.dateEcheance); const echeanceDate = new Date(facture.dateEcheance);
return (facture.statut === 'EN_RETARD' || return (facture.statut === StatutFacture.ECHUE ||
(echeanceDate < today && facture.statut !== 'PAYEE' && !facture.datePaiement)); (echeanceDate < today && facture.statut !== StatutFacture.PAYEE && !facture.datePaiement));
}); });
setFactures(facturesEnRetard); setFactures(facturesEnRetard);
} catch (error) { } catch (error) {
@@ -155,11 +156,12 @@ const FacturesRetardPage = () => {
break; break;
case 'legal_notice': case 'legal_notice':
const delaiJours = Math.ceil((legalNoticeData.deadline.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
await factureActionsService.sendMiseEnDemeure({ await factureActionsService.sendMiseEnDemeure({
factureId: selectedFacture.id, factureId: selectedFacture.id,
delaiPaiement: legalNoticeData.delai, delaiPaiement: delaiJours,
mentionsLegales: legalNoticeData.mentions, mentionsLegales: legalNoticeData.content,
fraisDossier: legalNoticeData.frais fraisDossier: 0
}); });
message = 'Mise en demeure émise avec succès'; message = 'Mise en demeure émise avec succès';
break; break;
@@ -535,6 +537,7 @@ ACTIONS RECOMMANDÉES:
value={factures} value={factures}
selection={selectedFactures} selection={selectedFactures}
onSelectionChange={(e) => setSelectedFactures(e.value)} onSelectionChange={(e) => setSelectedFactures(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -315,9 +315,9 @@ const FactureTemplatesPage = () => {
); );
const typeBodyTemplate = (rowData: FactureTemplate) => ( const typeBodyTemplate = (rowData: FactureTemplate) => (
<Tag <Tag
value={rowData.type} value={rowData.type}
severity={rowData.type === 'FACTURE' ? 'primary' : 'info'} severity={rowData.type === 'FACTURE' ? 'success' : 'info'}
/> />
); );

View File

@@ -37,7 +37,7 @@ const GestionnaireDashboard = () => {
const { user: currentUser } = useAuth(); const { user: currentUser } = useAuth();
// Vérifier que l'utilisateur est connecté et est un gestionnaire // Vérifier que l'utilisateur est connecté et est un gestionnaire
if (!currentUser || currentUser.role !== 'GESTIONNAIRE_PROJET') { if (!currentUser || !currentUser.roles?.includes('GESTIONNAIRE_PROJET')) {
return ( return (
<div className="flex align-items-center justify-content-center min-h-screen"> <div className="flex align-items-center justify-content-center min-h-screen">
<div className="text-center"> <div className="text-center">
@@ -200,7 +200,7 @@ const GestionnaireDashboard = () => {
<div> <div>
<h2 className="text-primary m-0">Dashboard Gestionnaire</h2> <h2 className="text-primary m-0">Dashboard Gestionnaire</h2>
<p className="text-color-secondary m-0"> <p className="text-color-secondary m-0">
Bienvenue {currentUser.prenom} {currentUser.nom} Bienvenue {currentUser.fullName || currentUser.username}
</p> </p>
</div> </div>
</div> </div>

View File

@@ -439,6 +439,7 @@ const MaintenancePage = () => {
header={header} header={header}
selection={selectedMaintenances} selection={selectedMaintenances}
onSelectionChange={(e) => setSelectedMaintenances(e.value)} onSelectionChange={(e) => setSelectedMaintenances(e.value)}
selectionMode="checkbox"
responsiveLayout="scroll" responsiveLayout="scroll"
> >
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }} /> <Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />

View File

@@ -439,9 +439,9 @@ const PiecesDetacheesPage = () => {
filterDisplay="menu" filterDisplay="menu"
globalFilterFields={['nom', 'reference', 'description', 'fournisseur']} globalFilterFields={['nom', 'reference', 'description', 'fournisseur']}
header={header} header={header}
subHeader={renderHeader()}
selection={selectedPieces} selection={selectedPieces}
onSelectionChange={(e) => setSelectedPieces(e.value)} onSelectionChange={(e) => setSelectedPieces(e.value)}
selectionMode="checkbox"
responsiveLayout="scroll" responsiveLayout="scroll"
> >
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }} /> <Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />

View File

@@ -432,6 +432,7 @@ const PlanificationMaintenancePage = () => {
header={header} header={header}
selection={selectedMateriels} selection={selectedMateriels}
onSelectionChange={(e) => setSelectedMateriels(e.value)} onSelectionChange={(e) => setSelectedMateriels(e.value)}
selectionMode="checkbox"
responsiveLayout="scroll" responsiveLayout="scroll"
> >
<Column selectionMode="multiple" headerStyle={{ width: '3rem' }} /> <Column selectionMode="multiple" headerStyle={{ width: '3rem' }} />

View File

@@ -528,7 +528,6 @@ const MaintenanceUrgentePage = () => {
showTime showTime
showIcon showIcon
dateFormat="dd/mm/yy" dateFormat="dd/mm/yy"
timeFormat="24"
placeholder="Sélectionner date et heure" placeholder="Sélectionner date et heure"
/> />
</div> </div>

View File

@@ -281,6 +281,7 @@ const MaintenancesEnCoursPage = () => {
value={maintenances} value={maintenances}
selection={selectedMaintenances} selection={selectedMaintenances}
onSelectionChange={(e) => setSelectedMaintenances(e.value)} onSelectionChange={(e) => setSelectedMaintenances(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -75,7 +75,12 @@ const NouvelleMaintenancePage = () => {
if (maintenance.description?.trim() && maintenance.materiel) { if (maintenance.description?.trim() && maintenance.materiel) {
try { try {
setSaving(true); setSaving(true);
const savedMaintenance = await maintenanceService.create(maintenance); const maintenanceData = {
...maintenance,
datePrevue: maintenance.datePrevue.toISOString(),
dateRealisee: maintenance.dateRealisee?.toISOString() || null
};
const savedMaintenance = await maintenanceService.create(maintenanceData);
toast.current?.show({ toast.current?.show({
severity: 'success', severity: 'success',

View File

@@ -72,7 +72,7 @@ const MaintenancesPage = () => {
setMaintenance({ setMaintenance({
type: TypeMaintenance.PREVENTIVE, type: TypeMaintenance.PREVENTIVE,
statut: StatutMaintenance.PLANIFIEE, statut: StatutMaintenance.PLANIFIEE,
datePrevue: new Date(), datePrevue: new Date().toISOString(),
cout: 0 cout: 0
}); });
setSubmitted(false); setSubmitted(false);
@@ -223,7 +223,7 @@ const MaintenancesPage = () => {
}; };
const dateRealisationBodyTemplate = (rowData: MaintenanceMateriel) => { const dateRealisationBodyTemplate = (rowData: MaintenanceMateriel) => {
return formatDate(rowData.dateRealisation); return formatDate(rowData.dateRealisee);
}; };
const actionBodyTemplate = (rowData: MaintenanceMateriel) => { const actionBodyTemplate = (rowData: MaintenanceMateriel) => {
@@ -250,10 +250,12 @@ const MaintenancesPage = () => {
return 'success'; return 'success';
case TypeMaintenance.CORRECTIVE: case TypeMaintenance.CORRECTIVE:
return 'danger'; return 'danger';
case TypeMaintenance.PREDICTIVE: case TypeMaintenance.REVISION:
return 'info'; return 'info';
case TypeMaintenance.CURATIVE: case TypeMaintenance.CONTROLE_TECHNIQUE:
return 'warning'; return 'warning';
case TypeMaintenance.NETTOYAGE:
return 'secondary';
default: default:
return undefined; return undefined;
} }
@@ -366,6 +368,7 @@ const MaintenancesPage = () => {
value={maintenances} value={maintenances}
selection={selectedMaintenances} selection={selectedMaintenances}
onSelectionChange={(e) => setSelectedMaintenances(e.value)} onSelectionChange={(e) => setSelectedMaintenances(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}
@@ -450,11 +453,11 @@ const MaintenancesPage = () => {
</div> </div>
<div className="field col-12 md:col-6"> <div className="field col-12 md:col-6">
<label htmlFor="dateRealisation" className="font-bold">Date de réalisation</label> <label htmlFor="dateRealisee" className="font-bold">Date de réalisation</label>
<Calendar <Calendar
id="dateRealisation" id="dateRealisee"
value={maintenance.dateRealisation ? new Date(maintenance.dateRealisation) : null} value={maintenance.dateRealisee ? new Date(maintenance.dateRealisee) : null}
onChange={(e) => onDateChange(e, 'dateRealisation')} onChange={(e) => onDateChange(e, 'dateRealisee')}
dateFormat="dd/mm/yy" dateFormat="dd/mm/yy"
showIcon showIcon
/> />

View File

@@ -92,7 +92,7 @@ const MaintenancesPlanifieesPage = () => {
const updatedMaintenance = { const updatedMaintenance = {
...maintenance, ...maintenance,
datePrevue: nouvelleDate, datePrevue: nouvelleDate.toISOString(),
notes: `${maintenance.notes || ''}\nReportée le ${formatDate(new Date())}` notes: `${maintenance.notes || ''}\nReportée le ${formatDate(new Date())}`
}; };
@@ -311,7 +311,7 @@ const MaintenancesPlanifieesPage = () => {
<div> <div>
<div className="font-semibold">{m.materiel?.nom}</div> <div className="font-semibold">{m.materiel?.nom}</div>
<div className="text-sm text-500">{m.description}</div> <div className="text-sm text-500">{m.description}</div>
<Tag value={m.type?.replace('_', ' ')} severity={getTypeSeverity(m.type)} size="normal" className="mt-1" /> <Tag value={m.type?.replace('_', ' ')} severity={getTypeSeverity(m.type)} className="mt-1" />
</div> </div>
) )
})); }));
@@ -394,6 +394,7 @@ const MaintenancesPlanifieesPage = () => {
value={maintenances} value={maintenances}
selection={selectedMaintenances} selection={selectedMaintenances}
onSelectionChange={(e) => setSelectedMaintenances(e.value)} onSelectionChange={(e) => setSelectedMaintenances(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -142,14 +142,18 @@ const MaterielsDisponiblesPage = () => {
switch (type) { switch (type) {
case TypeMateriel.ENGIN_CHANTIER: case TypeMateriel.ENGIN_CHANTIER:
return 'danger'; return 'danger';
case TypeMateriel.OUTILLAGE: case TypeMateriel.OUTIL_ELECTRIQUE:
case TypeMateriel.OUTIL_MANUEL:
return 'warning'; return 'warning';
case TypeMateriel.EQUIPEMENT_SECURITE: case TypeMateriel.EQUIPEMENT_SECURITE:
return 'success'; return 'success';
case TypeMateriel.VEHICULE: case TypeMateriel.VEHICULE:
return 'info'; return 'info';
case TypeMateriel.GRUE:
case TypeMateriel.BETONIERE:
return 'danger';
default: default:
return undefined; return 'secondary';
} }
}; };
@@ -295,6 +299,7 @@ const MaterielsDisponiblesPage = () => {
value={materiels} value={materiels}
selection={selectedMateriels} selection={selectedMateriels}
onSelectionChange={(e) => setSelectedMateriels(e.value)} onSelectionChange={(e) => setSelectedMateriels(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -52,7 +52,7 @@ const MaintenancePrevuePage = () => {
materiel: materiel, materiel: materiel,
type: TypeMaintenance.PREVENTIVE, type: TypeMaintenance.PREVENTIVE,
description: `Maintenance préventive programmée pour ${materiel.nom}`, description: `Maintenance préventive programmée pour ${materiel.nom}`,
datePrevue: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // Dans 7 jours datePrevue: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() // Dans 7 jours
}; };
await maintenanceService.create(maintenanceData); await maintenanceService.create(maintenanceData);
@@ -98,7 +98,7 @@ const MaintenancePrevuePage = () => {
} }
const daysSinceLastMaintenance = Math.floor( const daysSinceLastMaintenance = Math.floor(
(Date.now() - new Date(derniereMaintenance.dateRealisation || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24) (Date.now() - new Date(derniereMaintenance.dateRealisee || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24)
); );
if (daysSinceLastMaintenance > 90) { if (daysSinceLastMaintenance > 90) {
@@ -115,7 +115,7 @@ const MaintenancePrevuePage = () => {
if (!derniereMaintenance) { if (!derniereMaintenance) {
return <span className="text-red-500">Aucune</span>; return <span className="text-red-500">Aucune</span>;
} }
return formatDate(derniereMaintenance.dateRealisation || derniereMaintenance.datePrevue); return formatDate(derniereMaintenance.dateRealisee || derniereMaintenance.datePrevue);
}; };
const actionBodyTemplate = (rowData: Materiel) => { const actionBodyTemplate = (rowData: Materiel) => {
@@ -146,7 +146,7 @@ const MaintenancePrevuePage = () => {
materiel: materiel, materiel: materiel,
type: TypeMaintenance.CORRECTIVE, type: TypeMaintenance.CORRECTIVE,
description: `Panne signalée sur ${materiel.nom}`, description: `Panne signalée sur ${materiel.nom}`,
datePrevue: new Date() // Immédiatement datePrevue: new Date().toISOString() // Immédiatement
}; };
await maintenanceService.create(maintenanceData); await maintenanceService.create(maintenanceData);
@@ -171,14 +171,18 @@ const MaintenancePrevuePage = () => {
switch (type) { switch (type) {
case TypeMateriel.ENGIN_CHANTIER: case TypeMateriel.ENGIN_CHANTIER:
return 'danger'; return 'danger';
case TypeMateriel.OUTILLAGE: case TypeMateriel.OUTIL_ELECTRIQUE:
case TypeMateriel.OUTIL_MANUEL:
return 'warning'; return 'warning';
case TypeMateriel.EQUIPEMENT_SECURITE: case TypeMateriel.EQUIPEMENT_SECURITE:
return 'success'; return 'success';
case TypeMateriel.VEHICULE: case TypeMateriel.VEHICULE:
return 'info'; return 'info';
case TypeMateriel.GRUE:
case TypeMateriel.BETONIERE:
return 'danger';
default: default:
return undefined; return 'secondary';
} }
}; };
@@ -237,7 +241,7 @@ const MaintenancePrevuePage = () => {
const derniereMaintenance = m.maintenances?.[0]; const derniereMaintenance = m.maintenances?.[0];
if (!derniereMaintenance) return true; if (!derniereMaintenance) return true;
const daysSince = Math.floor( const daysSince = Math.floor(
(Date.now() - new Date(derniereMaintenance.dateRealisation || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24) (Date.now() - new Date(derniereMaintenance.dateRealisee || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24)
); );
return daysSince > 60; return daysSince > 60;
}).length; }).length;
@@ -246,7 +250,7 @@ const MaintenancePrevuePage = () => {
const derniereMaintenance = m.maintenances?.[0]; const derniereMaintenance = m.maintenances?.[0];
if (!derniereMaintenance) return true; if (!derniereMaintenance) return true;
const daysSince = Math.floor( const daysSince = Math.floor(
(Date.now() - new Date(derniereMaintenance.dateRealisation || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24) (Date.now() - new Date(derniereMaintenance.dateRealisee || derniereMaintenance.datePrevue).getTime()) / (1000 * 60 * 60 * 24)
); );
return daysSince > 90; return daysSince > 90;
}).length; }).length;
@@ -311,6 +315,7 @@ const MaintenancePrevuePage = () => {
value={materiels} value={materiels}
selection={selectedMateriels} selection={selectedMateriels}
onSelectionChange={(e) => setSelectedMateriels(e.value)} onSelectionChange={(e) => setSelectedMateriels(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -65,9 +65,7 @@ const MaterielsPage = () => {
const openNew = () => { const openNew = () => {
setMateriel({ setMateriel({
statut: StatutMateriel.DISPONIBLE, statut: StatutMateriel.DISPONIBLE,
actif: true, actif: true
quantiteStock: 0,
seuilMinimum: 0
}); });
setSubmitted(false); setSubmitted(false);
setMaterielDialog(true); setMaterielDialog(true);
@@ -234,14 +232,18 @@ const MaterielsPage = () => {
switch (type) { switch (type) {
case TypeMateriel.ENGIN_CHANTIER: case TypeMateriel.ENGIN_CHANTIER:
return 'danger'; return 'danger';
case TypeMateriel.OUTILLAGE: case TypeMateriel.OUTIL_ELECTRIQUE:
case TypeMateriel.OUTIL_MANUEL:
return 'warning'; return 'warning';
case TypeMateriel.EQUIPEMENT_SECURITE: case TypeMateriel.EQUIPEMENT_SECURITE:
return 'success'; return 'success';
case TypeMateriel.VEHICULE: case TypeMateriel.VEHICULE:
return 'info'; return 'info';
case TypeMateriel.GRUE:
case TypeMateriel.BETONIERE:
return 'danger';
default: default:
return undefined; return 'secondary';
} }
}; };
@@ -249,12 +251,15 @@ const MaterielsPage = () => {
switch (statut) { switch (statut) {
case StatutMateriel.DISPONIBLE: case StatutMateriel.DISPONIBLE:
return 'success'; return 'success';
case StatutMateriel.EN_UTILISATION: case StatutMateriel.UTILISE:
return 'warning'; return 'warning';
case StatutMateriel.EN_MAINTENANCE: case StatutMateriel.MAINTENANCE:
case StatutMateriel.EN_REPARATION:
return 'info'; return 'info';
case StatutMateriel.HORS_SERVICE: case StatutMateriel.HORS_SERVICE:
return 'danger'; return 'danger';
case StatutMateriel.RESERVE:
return 'secondary';
default: default:
return undefined; return undefined;
} }
@@ -347,6 +352,7 @@ const MaterielsPage = () => {
value={materiels} value={materiels}
selection={selectedMateriels} selection={selectedMateriels}
onSelectionChange={(e) => setSelectedMateriels(e.value)} onSelectionChange={(e) => setSelectedMateriels(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}
@@ -505,17 +511,6 @@ const MaterielsPage = () => {
/> />
</div> </div>
<div className="field col-12 md:col-6">
<label htmlFor="quantiteStock" className="font-bold">Quantité en stock</label>
<InputNumber
id="quantiteStock"
value={materiel.quantiteStock}
onValueChange={(e) => onInputNumberChange(e.value, 'quantiteStock')}
min={0}
showButtons
/>
</div>
<div className="field col-12"> <div className="field col-12">
<label htmlFor="description" className="font-bold">Description</label> <label htmlFor="description" className="font-bold">Description</label>
<InputTextarea <InputTextarea

View File

@@ -133,7 +133,7 @@ const MaterielsStatsPage = () => {
const currentYear = new Date().getFullYear(); const currentYear = new Date().getFullYear();
maintenances.forEach(maintenance => { maintenances.forEach(maintenance => {
const date = new Date(maintenance.dateRealisation || maintenance.datePrevue); const date = new Date(maintenance.dateRealisee || maintenance.datePrevue);
if (date.getFullYear() === currentYear) { if (date.getFullYear() === currentYear) {
monthlyMaintenance[date.getMonth()]++; monthlyMaintenance[date.getMonth()]++;
} }
@@ -173,14 +173,18 @@ const MaterielsStatsPage = () => {
switch (type) { switch (type) {
case TypeMateriel.ENGIN_CHANTIER: case TypeMateriel.ENGIN_CHANTIER:
return 'danger'; return 'danger';
case TypeMateriel.OUTILLAGE: case TypeMateriel.OUTIL_ELECTRIQUE:
case TypeMateriel.OUTIL_MANUEL:
return 'warning'; return 'warning';
case TypeMateriel.EQUIPEMENT_SECURITE: case TypeMateriel.EQUIPEMENT_SECURITE:
return 'success'; return 'success';
case TypeMateriel.VEHICULE: case TypeMateriel.VEHICULE:
return 'info'; return 'info';
case TypeMateriel.GRUE:
case TypeMateriel.BETONIERE:
return 'danger';
default: default:
return undefined; return 'secondary';
} }
}; };
@@ -194,12 +198,12 @@ const MaterielsStatsPage = () => {
? (materiels.filter(m => m.statut === StatutMateriel.DISPONIBLE).length / materiels.length) * 100 ? (materiels.filter(m => m.statut === StatutMateriel.DISPONIBLE).length / materiels.length) * 100
: 0; : 0;
const tauxMaintenance = materiels.length > 0 const tauxMaintenance = materiels.length > 0
? (materiels.filter(m => m.statut === StatutMateriel.EN_MAINTENANCE).length / materiels.length) * 100 ? (materiels.filter(m => m.statut === StatutMateriel.MAINTENANCE || m.statut === StatutMateriel.EN_REPARATION).length / materiels.length) * 100
: 0; : 0;
const tauxUtilisation = materiels.length > 0 const tauxUtilisation = materiels.length > 0
? (materiels.filter(m => m.statut === StatutMateriel.EN_UTILISATION).length / materiels.length) * 100 ? (materiels.filter(m => m.statut === StatutMateriel.UTILISE).length / materiels.length) * 100
: 0; : 0;
return ( return (
@@ -302,7 +306,7 @@ const MaterielsStatsPage = () => {
</div> </div>
<ProgressBar value={tauxUtilisation} showValue={false} className="mb-3" /> <ProgressBar value={tauxUtilisation} showValue={false} className="mb-3" />
<div className="text-500"> <div className="text-500">
{materiels.filter(m => m.statut === StatutMateriel.EN_UTILISATION).length} / {materiels.length} en utilisation {materiels.filter(m => m.statut === StatutMateriel.UTILISE).length} / {materiels.length} en utilisation
</div> </div>
</div> </div>
</Card> </Card>
@@ -316,7 +320,7 @@ const MaterielsStatsPage = () => {
</div> </div>
<ProgressBar value={tauxMaintenance} showValue={false} className="mb-3" /> <ProgressBar value={tauxMaintenance} showValue={false} className="mb-3" />
<div className="text-500"> <div className="text-500">
{materiels.filter(m => m.statut === StatutMateriel.EN_MAINTENANCE).length} / {materiels.length} en maintenance {materiels.filter(m => m.statut === StatutMateriel.MAINTENANCE || m.statut === StatutMateriel.EN_REPARATION).length} / {materiels.length} en maintenance
</div> </div>
</div> </div>
</Card> </Card>

View File

@@ -233,6 +233,7 @@ const NotificationsPage = () => {
value={notifications} value={notifications}
selection={selectedNotifications} selection={selectedNotifications}
onSelectionChange={(e) => setSelectedNotifications(e.value)} onSelectionChange={(e) => setSelectedNotifications(e.value)}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}

View File

@@ -514,7 +514,7 @@ const LandingPage: Page = () => {
/> />
<span className="text-gray-700 font-bold ml-3">BTPXpress</span> <span className="text-gray-700 font-bold ml-3">BTPXpress</span>
<div style={{ marginLeft: '2.5rem' }}> <div style={{ marginLeft: '2.5rem' }}>
<LionsDevLogo size="normal" showText={true} /> <LionsDevLogo size="medium" showText={true} />
</div> </div>
</div> </div>
</div> </div>

View File

@@ -59,7 +59,8 @@ const PhasesChantierPage: Page = () => {
budgetPrevu: 0, budgetPrevu: 0,
statut: 'PLANIFIEE' as StatutPhase, statut: 'PLANIFIEE' as StatutPhase,
critique: false, critique: false,
notes: '' notes: '',
ordreExecution: 1
}); });
const statutOptions = [ const statutOptions = [
@@ -106,7 +107,8 @@ const PhasesChantierPage: Page = () => {
budgetPrevu: 0, budgetPrevu: 0,
statut: 'PLANIFIEE', statut: 'PLANIFIEE',
critique: false, critique: false,
notes: '' notes: '',
ordreExecution: 1
}); });
setSubmitted(false); setSubmitted(false);
setPhaseDialog(true); setPhaseDialog(true);
@@ -122,7 +124,8 @@ const PhasesChantierPage: Page = () => {
budgetPrevu: phase.budgetPrevu || 0, budgetPrevu: phase.budgetPrevu || 0,
statut: phase.statut, statut: phase.statut,
critique: phase.critique || false, critique: phase.critique || false,
notes: phase.notes || '' notes: phase.notes || '',
ordreExecution: phase.ordreExecution || 1
}); });
setSubmitted(false); setSubmitted(false);
setPhaseDialog(true); setPhaseDialog(true);
@@ -136,7 +139,7 @@ const PhasesChantierPage: Page = () => {
const deletePhase = async () => { const deletePhase = async () => {
try { try {
if (currentPhase?.id) { if (currentPhase?.id) {
await phaseChantierService.delete(currentPhase.id); await phaseChantierService.delete(Number(currentPhase.id));
await loadPhases(); await loadPhases();
toast.current?.show({ toast.current?.show({
severity: 'success', severity: 'success',
@@ -175,11 +178,12 @@ const PhasesChantierPage: Page = () => {
...formData, ...formData,
dateDebutPrevue: formData.dateDebutPrevue?.toISOString(), dateDebutPrevue: formData.dateDebutPrevue?.toISOString(),
dateFinPrevue: formData.dateFinPrevue?.toISOString(), dateFinPrevue: formData.dateFinPrevue?.toISOString(),
chantierId: 1 // ID exemple - en production, viendrait du contexte chantierId: '1', // ID exemple - en production, viendrait du contexte
ordreExecution: formData.ordreExecution || 1
}; };
if (currentPhase?.id) { if (currentPhase?.id) {
await phaseChantierService.update(currentPhase.id, phaseData); await phaseChantierService.update(Number(currentPhase.id), phaseData);
} else { } else {
await phaseChantierService.create(phaseData); await phaseChantierService.create(phaseData);
} }
@@ -224,7 +228,7 @@ const PhasesChantierPage: Page = () => {
const startPhase = async (phase: PhaseChantier) => { const startPhase = async (phase: PhaseChantier) => {
try { try {
if (phase.id) { if (phase.id) {
await phaseChantierService.start(phase.id); await phaseChantierService.start(Number(phase.id));
await loadPhases(); await loadPhases();
toast.current?.show({ toast.current?.show({
severity: 'success', severity: 'success',
@@ -246,7 +250,7 @@ const PhasesChantierPage: Page = () => {
const completePhase = async (phase: PhaseChantier) => { const completePhase = async (phase: PhaseChantier) => {
try { try {
if (phase.id) { if (phase.id) {
await phaseChantierService.complete(phase.id); await phaseChantierService.complete(Number(phase.id));
await loadPhases(); await loadPhases();
toast.current?.show({ toast.current?.show({
severity: 'success', severity: 'success',
@@ -268,7 +272,7 @@ const PhasesChantierPage: Page = () => {
const suspendPhase = async (phase: PhaseChantier) => { const suspendPhase = async (phase: PhaseChantier) => {
try { try {
if (phase.id) { if (phase.id) {
await phaseChantierService.suspend(phase.id); await phaseChantierService.suspend(Number(phase.id));
await loadPhases(); await loadPhases();
toast.current?.show({ toast.current?.show({
severity: 'success', severity: 'success',
@@ -371,10 +375,9 @@ const PhasesChantierPage: Page = () => {
const retard = phaseChantierService.calculateRetard(rowData); const retard = phaseChantierService.calculateRetard(rowData);
return ( return (
<Badge <Badge
value={`${retard}j`} value={`${retard}j`}
severity="danger" severity="danger"
tooltip="Jours de retard"
/> />
); );
}; };
@@ -492,6 +495,7 @@ const PhasesChantierPage: Page = () => {
value={phases} value={phases}
selection={selectedPhases} selection={selectedPhases}
onSelectionChange={(e) => setSelectedPhases(e.value as PhaseChantier[])} onSelectionChange={(e) => setSelectedPhases(e.value as PhaseChantier[])}
selectionMode="checkbox"
dataKey="id" dataKey="id"
paginator paginator
rows={10} rows={10}