Initial commit
This commit is contained in:
314
app/(main)/maintenances/nouvelle/page.tsx
Normal file
314
app/(main)/maintenances/nouvelle/page.tsx
Normal file
@@ -0,0 +1,314 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Card } from 'primereact/card';
|
||||
import { Button } from 'primereact/button';
|
||||
import { InputNumber } from 'primereact/inputnumber';
|
||||
import { Dropdown } from 'primereact/dropdown';
|
||||
import { Calendar } from 'primereact/calendar';
|
||||
import { InputTextarea } from 'primereact/inputtextarea';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { maintenanceService, materielService } from '../../../../services/api';
|
||||
import { Materiel, TypeMaintenance, StatutMaintenance } from '../../../../types/btp';
|
||||
|
||||
const NouvelleMaintenancePage = () => {
|
||||
const router = useRouter();
|
||||
const [maintenance, setMaintenance] = useState({
|
||||
materiel: null as Materiel | null,
|
||||
type: TypeMaintenance.PREVENTIVE,
|
||||
statut: StatutMaintenance.PLANIFIEE,
|
||||
description: '',
|
||||
datePrevue: new Date(),
|
||||
dateRealisee: null as Date | null,
|
||||
cout: 0,
|
||||
notes: ''
|
||||
});
|
||||
const [materiels, setMateriels] = useState<Materiel[]>([]);
|
||||
const [submitted, setSubmitted] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const toast = useRef<Toast>(null);
|
||||
|
||||
const typeOptions = Object.values(TypeMaintenance).map(type => ({
|
||||
label: type.replace('_', ' '),
|
||||
value: type
|
||||
}));
|
||||
|
||||
const statutOptions = Object.values(StatutMaintenance).map(statut => ({
|
||||
label: statut.replace('_', ' '),
|
||||
value: statut
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
loadMateriels();
|
||||
}, []);
|
||||
|
||||
const loadMateriels = async () => {
|
||||
try {
|
||||
const data = await materielService.getAll();
|
||||
setMateriels(data);
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du chargement des matériels:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const onInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>, name: string) => {
|
||||
const val = (e.target && e.target.value) || '';
|
||||
setMaintenance(prev => ({ ...prev, [name]: val }));
|
||||
};
|
||||
|
||||
const onInputNumberChange = (value: number | null, name: string) => {
|
||||
setMaintenance(prev => ({ ...prev, [name]: value || 0 }));
|
||||
};
|
||||
|
||||
const onDropdownChange = (e: any, name: string) => {
|
||||
setMaintenance(prev => ({ ...prev, [name]: e.value }));
|
||||
};
|
||||
|
||||
const onDateChange = (e: any, name: string) => {
|
||||
setMaintenance(prev => ({ ...prev, [name]: e.value }));
|
||||
};
|
||||
|
||||
const saveMaintenance = async () => {
|
||||
setSubmitted(true);
|
||||
|
||||
if (maintenance.description?.trim() && maintenance.materiel) {
|
||||
try {
|
||||
setSaving(true);
|
||||
const savedMaintenance = await maintenanceService.create(maintenance);
|
||||
|
||||
toast.current?.show({
|
||||
severity: 'success',
|
||||
summary: 'Succès',
|
||||
detail: 'Maintenance créée avec succès',
|
||||
life: 3000
|
||||
});
|
||||
|
||||
// Rediriger vers la liste après 2 secondes
|
||||
setTimeout(() => {
|
||||
router.push('/maintenances');
|
||||
}, 2000);
|
||||
|
||||
} catch (error: any) {
|
||||
toast.current?.show({
|
||||
severity: 'error',
|
||||
summary: 'Erreur',
|
||||
detail: error?.userMessage || 'Erreur lors de la création',
|
||||
life: 3000
|
||||
});
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const annuler = () => {
|
||||
router.back();
|
||||
};
|
||||
|
||||
const materielOptions = materiels.map(materiel => ({
|
||||
label: `${materiel.nom} - ${materiel.marque} ${materiel.modele}`,
|
||||
value: materiel
|
||||
}));
|
||||
|
||||
// Templates prédéfinis selon le type
|
||||
const onTypeChange = (newType: TypeMaintenance) => {
|
||||
let description = '';
|
||||
let cout = 0;
|
||||
|
||||
switch (newType) {
|
||||
case TypeMaintenance.PREVENTIVE:
|
||||
description = 'Maintenance préventive programmée selon planning';
|
||||
cout = 100;
|
||||
break;
|
||||
case TypeMaintenance.CORRECTIVE:
|
||||
description = 'Réparation suite à dysfonctionnement';
|
||||
cout = 300;
|
||||
break;
|
||||
case TypeMaintenance.REVISION:
|
||||
description = 'Révision complète du matériel';
|
||||
cout = 200;
|
||||
break;
|
||||
case TypeMaintenance.CONTROLE_TECHNIQUE:
|
||||
description = 'Contrôle technique réglementaire';
|
||||
cout = 150;
|
||||
break;
|
||||
case TypeMaintenance.NETTOYAGE:
|
||||
description = 'Nettoyage et entretien courant';
|
||||
cout = 50;
|
||||
break;
|
||||
}
|
||||
|
||||
setMaintenance(prev => ({ ...prev, type: newType, description, cout }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="grid">
|
||||
<div className="col-12">
|
||||
<Toast ref={toast} />
|
||||
|
||||
<div className="flex align-items-center justify-content-between mb-4">
|
||||
<h2 className="m-0">Nouvelle Maintenance</h2>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
label="Annuler"
|
||||
icon="pi pi-times"
|
||||
className="p-button-text p-button-rounded"
|
||||
onClick={annuler}
|
||||
/>
|
||||
<Button
|
||||
label="Sauvegarder"
|
||||
icon="pi pi-check"
|
||||
className="p-button-text p-button-rounded"
|
||||
onClick={saveMaintenance}
|
||||
loading={saving}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card>
|
||||
<div className="p-fluid formgrid grid">
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="materiel" className="font-bold">
|
||||
Matériel <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<Dropdown
|
||||
id="materiel"
|
||||
value={maintenance.materiel}
|
||||
onChange={(e) => onDropdownChange(e, 'materiel')}
|
||||
options={materielOptions}
|
||||
placeholder="Sélectionner un matériel"
|
||||
filter
|
||||
className={submitted && !maintenance.materiel ? 'p-invalid' : ''}
|
||||
/>
|
||||
{submitted && !maintenance.materiel && <small className="p-error">Le matériel est obligatoire.</small>}
|
||||
</div>
|
||||
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="type" className="font-bold">Type</label>
|
||||
<Dropdown
|
||||
id="type"
|
||||
value={maintenance.type}
|
||||
onChange={(e) => onTypeChange(e.value)}
|
||||
options={typeOptions}
|
||||
placeholder="Sélectionner un type"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="statut" className="font-bold">Statut</label>
|
||||
<Dropdown
|
||||
id="statut"
|
||||
value={maintenance.statut}
|
||||
onChange={(e) => onDropdownChange(e, 'statut')}
|
||||
options={statutOptions}
|
||||
placeholder="Sélectionner un statut"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="datePrevue" className="font-bold">Date prévue</label>
|
||||
<Calendar
|
||||
id="datePrevue"
|
||||
value={maintenance.datePrevue}
|
||||
onChange={(e) => onDateChange(e, 'datePrevue')}
|
||||
dateFormat="dd/mm/yy"
|
||||
showIcon
|
||||
showTime
|
||||
hourFormat="24"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="dateRealisee" className="font-bold">Date de réalisation</label>
|
||||
<Calendar
|
||||
id="dateRealisee"
|
||||
value={maintenance.dateRealisee}
|
||||
onChange={(e) => onDateChange(e, 'dateRealisee')}
|
||||
dateFormat="dd/mm/yy"
|
||||
showIcon
|
||||
showTime
|
||||
hourFormat="24"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field col-12 md:col-6">
|
||||
<label htmlFor="cout" className="font-bold">Coût estimé</label>
|
||||
<InputNumber
|
||||
id="cout"
|
||||
value={maintenance.cout}
|
||||
onValueChange={(e) => onInputNumberChange(e.value, 'cout')}
|
||||
mode="currency"
|
||||
currency="EUR"
|
||||
locale="fr-FR"
|
||||
min={0}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="field col-12">
|
||||
<label htmlFor="description" className="font-bold">
|
||||
Description <span className="text-red-500">*</span>
|
||||
</label>
|
||||
<InputTextarea
|
||||
id="description"
|
||||
value={maintenance.description}
|
||||
onChange={(e) => onInputChange(e, 'description')}
|
||||
rows={3}
|
||||
cols={20}
|
||||
placeholder="Description détaillée de la maintenance..."
|
||||
className={submitted && !maintenance.description ? 'p-invalid' : ''}
|
||||
/>
|
||||
{submitted && !maintenance.description && <small className="p-error">La description est obligatoire.</small>}
|
||||
</div>
|
||||
|
||||
<div className="field col-12">
|
||||
<label htmlFor="notes" className="font-bold">Notes</label>
|
||||
<InputTextarea
|
||||
id="notes"
|
||||
value={maintenance.notes}
|
||||
onChange={(e) => onInputChange(e, 'notes')}
|
||||
rows={2}
|
||||
cols={20}
|
||||
placeholder="Notes et observations..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 p-3 surface-100 border-round">
|
||||
<h5>Informations sur le matériel sélectionné</h5>
|
||||
{maintenance.materiel ? (
|
||||
<div className="grid">
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Nom:</strong> {maintenance.materiel.nom}
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Marque:</strong> {maintenance.materiel.marque}
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Modèle:</strong> {maintenance.materiel.modele}
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Statut:</strong> {maintenance.materiel.statut?.replace('_', ' ')}
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Localisation:</strong> {maintenance.materiel.localisation}
|
||||
</div>
|
||||
<div className="col-12 md:col-6">
|
||||
<strong>Dernière maintenance:</strong>
|
||||
{maintenance.materiel.maintenances?.length ?
|
||||
new Date(maintenance.materiel.maintenances[0].dateRealisee || maintenance.materiel.maintenances[0].datePrevue).toLocaleDateString('fr-FR') :
|
||||
'Aucune'
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-500">Sélectionnez un matériel pour voir ses informations</p>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NouvelleMaintenancePage;
|
||||
Reference in New Issue
Block a user