'use client'; import React, { useState, useEffect } from 'react'; import { Card } from 'primereact/card'; import { Button } from 'primereact/button'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { InputText } from 'primereact/inputtext'; import { InputNumber } from 'primereact/inputnumber'; import { Dropdown } from 'primereact/dropdown'; import { Tag } from 'primereact/tag'; import { Badge } from 'primereact/badge'; import { Toolbar } from 'primereact/toolbar'; import { Dialog } from 'primereact/dialog'; import { ProgressBar } from 'primereact/progressbar'; import { FilterMatchMode } from 'primereact/api'; import { useRouter } from 'next/navigation'; import { apiClient } from '../../../../services/api-client'; interface PieceDetachee { id: number; nom: string; reference: string; description: string; categorie: string; fournisseur: string; coutUnitaire: number; quantiteStock: number; seuilAlerte: number; seuilCritique: number; uniteStock: string; localisation: string; dateAchat?: string; garantie?: number; // en mois materielsCompatibles: string[]; frequenceUtilisation: number; derniereMaintenance?: string; prochainCommande?: string; statut: 'DISPONIBLE' | 'RUPTURE' | 'ALERTE' | 'COMMANDE'; historiqueUtilisation: Array<{ date: string; quantite: number; maintenanceId: number; technicien: string; }>; } interface NouvellePiece { nom: string; reference: string; description: string; categorie: string; fournisseur: string; coutUnitaire: number; quantiteStock: number; seuilAlerte: number; seuilCritique: number; uniteStock: string; localisation: string; garantie?: number; materielsCompatibles: string[]; } const PiecesDetacheesPage = () => { const [pieces, setPieces] = useState([]); const [loading, setLoading] = useState(true); const [pieceDialog, setPieceDialog] = useState(false); const [nouvellePiece, setNouvellePiece] = useState({ nom: '', reference: '', description: '', categorie: '', fournisseur: '', coutUnitaire: 0, quantiteStock: 0, seuilAlerte: 10, seuilCritique: 5, uniteStock: 'unité', localisation: '', materielsCompatibles: [] }); const [selectedPieces, setSelectedPieces] = useState([]); const [globalFilterValue, setGlobalFilterValue] = useState(''); const [filters, setFilters] = useState({ global: { value: null, matchMode: FilterMatchMode.CONTAINS }, nom: { value: null, matchMode: FilterMatchMode.STARTS_WITH }, reference: { value: null, matchMode: FilterMatchMode.CONTAINS }, categorie: { value: null, matchMode: FilterMatchMode.EQUALS }, fournisseur: { value: null, matchMode: FilterMatchMode.CONTAINS }, statut: { value: null, matchMode: FilterMatchMode.EQUALS } }); const router = useRouter(); const categorieOptions = [ { label: 'Moteur', value: 'MOTEUR' }, { label: 'Hydraulique', value: 'HYDRAULIQUE' }, { label: 'Électrique', value: 'ELECTRIQUE' }, { label: 'Mécanique', value: 'MECANIQUE' }, { label: 'Pneumatique', value: 'PNEUMATIQUE' }, { label: 'Filtres', value: 'FILTRES' }, { label: 'Lubrifiants', value: 'LUBRIFIANTS' }, { label: 'Consommables', value: 'CONSOMMABLES' } ]; const uniteOptions = [ { label: 'Unité', value: 'unité' }, { label: 'Litre', value: 'litre' }, { label: 'Kilogramme', value: 'kg' }, { label: 'Mètre', value: 'mètre' }, { label: 'Boîte', value: 'boîte' }, { label: 'Lot', value: 'lot' } ]; const statutOptions = [ { label: 'Tous', value: null }, { label: 'Disponible', value: 'DISPONIBLE' }, { label: 'Alerte', value: 'ALERTE' }, { label: 'Rupture', value: 'RUPTURE' }, { label: 'En commande', value: 'COMMANDE' } ]; useEffect(() => { loadPieces(); }, []); const loadPieces = async () => { try { setLoading(true); console.log('🔄 Chargement des pièces détachées...'); const response = await apiClient.get('/api/maintenance/pieces-detachees'); console.log('✅ Pièces chargées:', response.data); setPieces(response.data || []); } catch (error) { console.error('❌ Erreur lors du chargement des pièces:', error); setPieces([]); } finally { setLoading(false); } }; const ajouterPiece = async () => { try { console.log('🔄 Ajout d\'une nouvelle pièce...', nouvellePiece); const response = await apiClient.post('/api/maintenance/pieces-detachees', nouvellePiece); console.log('✅ Pièce ajoutée avec succès:', response.data); setPieceDialog(false); setNouvellePiece({ nom: '', reference: '', description: '', categorie: '', fournisseur: '', coutUnitaire: 0, quantiteStock: 0, seuilAlerte: 10, seuilCritique: 5, uniteStock: 'unité', localisation: '', materielsCompatibles: [] }); loadPieces(); } catch (error) { console.error('❌ Erreur lors de l\'ajout de la pièce:', error); } }; const supprimerPieces = async () => { try { console.log('🔄 Suppression des pièces sélectionnées...'); await Promise.all( selectedPieces.map(piece => apiClient.delete(`/api/maintenance/pieces-detachees/${piece.id}`) ) ); console.log('✅ Pièces supprimées avec succès'); setSelectedPieces([]); loadPieces(); } catch (error) { console.error('❌ Erreur lors de la suppression:', error); } }; const commanderPieces = async () => { try { console.log('🔄 Commande des pièces sélectionnées...'); const pieceIds = selectedPieces.map(p => p.id); await apiClient.post('/api/maintenance/pieces-detachees/commander', { pieceIds }); console.log('✅ Commande créée avec succès'); setSelectedPieces([]); loadPieces(); } catch (error) { console.error('❌ Erreur lors de la commande:', error); } }; const onGlobalFilterChange = (e: React.ChangeEvent) => { const value = e.target.value; let _filters = { ...filters }; _filters['global'].value = value; setFilters(_filters); setGlobalFilterValue(value); }; const pieceBodyTemplate = (rowData: PieceDetachee) => { return (
{rowData.nom} Réf: {rowData.reference} {rowData.description}
); }; const stockBodyTemplate = (rowData: PieceDetachee) => { const pourcentageStock = (rowData.quantiteStock / (rowData.seuilAlerte * 2)) * 100; const couleur = rowData.quantiteStock <= rowData.seuilCritique ? 'danger' : rowData.quantiteStock <= rowData.seuilAlerte ? 'warning' : 'success'; return (
{rowData.quantiteStock} {rowData.uniteStock}
Alerte: {rowData.seuilAlerte} | Critique: {rowData.seuilCritique}
); }; const statutBodyTemplate = (rowData: PieceDetachee) => { const getStatutSeverity = (statut: string) => { switch (statut) { case 'DISPONIBLE': return 'success'; case 'ALERTE': return 'warning'; case 'RUPTURE': return 'danger'; case 'COMMANDE': return 'info'; default: return 'secondary'; } }; return ; }; const coutBodyTemplate = (rowData: PieceDetachee) => { const valeurStock = rowData.quantiteStock * rowData.coutUnitaire; return (
{rowData.coutUnitaire.toLocaleString('fr-FR')} € Stock: {valeurStock.toLocaleString('fr-FR')} €
); }; const materielsBodyTemplate = (rowData: PieceDetachee) => { return (
{rowData.materielsCompatibles.slice(0, 3).map((materiel, index) => ( ))} {rowData.materielsCompatibles.length > 3 && ( )}
); }; const actionBodyTemplate = (rowData: PieceDetachee) => { return (
); }; const leftToolbarTemplate = () => { return (
); }; const rightToolbarTemplate = () => { return (
); }; const header = (

Gestion des Pièces Détachées

p.statut === 'RUPTURE').length} severity="danger" /> Ruptures p.statut === 'ALERTE').length} severity="warning" /> Alertes p.statut === 'COMMANDE').length} severity="info" /> Commandes
); const renderHeader = () => { return (
{ let _filters = { ...filters }; _filters.statut.value = e.value; setFilters(_filters); }} placeholder="Filtrer par statut" showClear /> { let _filters = { ...filters }; _filters.categorie.value = e.value; setFilters(_filters); }} placeholder="Filtrer par catégorie" showClear />
); }; return (
setSelectedPieces(e.value)} selectionMode="checkbox" responsiveLayout="scroll" >
{/* Dialog Nouvelle Pièce */} setPieceDialog(false)} footer={
} >
setNouvellePiece({ ...nouvellePiece, nom: e.target.value })} placeholder="Nom de la pièce" />
setNouvellePiece({ ...nouvellePiece, reference: e.target.value })} placeholder="Référence fabricant" />
setNouvellePiece({ ...nouvellePiece, description: e.target.value })} placeholder="Description de la pièce" />
setNouvellePiece({ ...nouvellePiece, categorie: e.value })} placeholder="Sélectionner une catégorie" />
setNouvellePiece({ ...nouvellePiece, fournisseur: e.target.value })} placeholder="Nom du fournisseur" />
setNouvellePiece({ ...nouvellePiece, coutUnitaire: e.value || 0 })} min={0} mode="currency" currency="EUR" locale="fr-FR" />
setNouvellePiece({ ...nouvellePiece, quantiteStock: e.value || 0 })} min={0} />
setNouvellePiece({ ...nouvellePiece, uniteStock: e.value })} placeholder="Unité de mesure" />
setNouvellePiece({ ...nouvellePiece, seuilAlerte: e.value || 10 })} min={1} />
setNouvellePiece({ ...nouvellePiece, seuilCritique: e.value || 5 })} min={1} />
setNouvellePiece({ ...nouvellePiece, localisation: e.target.value })} placeholder="Emplacement de stockage" />
setNouvellePiece({ ...nouvellePiece, garantie: e.value || undefined })} min={0} max={120} />
); }; export default PiecesDetacheesPage;