'use client'; import React, { useState, useEffect, useRef } 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 { InputTextarea } from 'primereact/inputtextarea'; import { Dropdown } from 'primereact/dropdown'; import { Tag } from 'primereact/tag'; import { Toast } from 'primereact/toast'; import { Toolbar } from 'primereact/toolbar'; import { Dialog } from 'primereact/dialog'; import { ConfirmDialog } from 'primereact/confirmdialog'; import { Menu } from 'primereact/menu'; import { Badge } from 'primereact/badge'; import { devisService } from '../../../../services/api'; import { formatDate } from '../../../../utils/formatters'; interface DevisTemplate { id: string; nom: string; description: string; categorie: string; lignes: Array<{ designation: string; quantite: number; unite: string; prixUnitaire: number; }>; tauxTVA: number; actif: boolean; dateCreation: Date; utilisations: number; } const DevisTemplatesPage = () => { const toast = useRef(null); const menuRef = useRef(null); const [templates, setTemplates] = useState([]); const [loading, setLoading] = useState(true); const [showDialog, setShowDialog] = useState(false); const [editingTemplate, setEditingTemplate] = useState(null); const [selectedTemplate, setSelectedTemplate] = useState(null); const [globalFilter, setGlobalFilter] = useState(''); const [formData, setFormData] = useState>({ nom: '', description: '', categorie: '', lignes: [], tauxTVA: 20, actif: true }); const categorieOptions = [ { label: 'Gros œuvre', value: 'GROS_OEUVRE' }, { label: 'Second œuvre', value: 'SECOND_OEUVRE' }, { label: 'Finitions', value: 'FINITIONS' }, { label: 'Plomberie', value: 'PLOMBERIE' }, { label: 'Électricité', value: 'ELECTRICITE' }, { label: 'Chauffage', value: 'CHAUFFAGE' }, { label: 'Rénovation', value: 'RENOVATION' }, { label: 'Maintenance', value: 'MAINTENANCE' } ]; useEffect(() => { loadTemplates(); }, []); const loadTemplates = async () => { try { setLoading(true); // TODO: Remplacer par un vrai appel API // const response = await devisService.getTemplates(); // Données simulées pour la démonstration const mockTemplates: DevisTemplate[] = [ { id: '1', nom: 'Rénovation Salle de Bain Standard', description: 'Template pour rénovation complète salle de bain 6m²', categorie: 'RENOVATION', lignes: [ { designation: 'Démolition existant', quantite: 1, unite: 'forfait', prixUnitaire: 800 }, { designation: 'Carrelage sol', quantite: 6, unite: 'm²', prixUnitaire: 45 }, { designation: 'Carrelage mural', quantite: 20, unite: 'm²', prixUnitaire: 35 }, { designation: 'Sanitaires standard', quantite: 1, unite: 'forfait', prixUnitaire: 1200 } ], tauxTVA: 20, actif: true, dateCreation: new Date('2024-01-15'), utilisations: 23 }, { id: '2', nom: 'Extension Maison 20m²', description: 'Template pour extension plain-pied 20m²', categorie: 'GROS_OEUVRE', lignes: [ { designation: 'Fondations', quantite: 20, unite: 'm²', prixUnitaire: 120 }, { designation: 'Murs parpaings', quantite: 40, unite: 'm²', prixUnitaire: 85 }, { designation: 'Charpente', quantite: 20, unite: 'm²', prixUnitaire: 95 }, { designation: 'Couverture', quantite: 22, unite: 'm²', prixUnitaire: 65 } ], tauxTVA: 20, actif: true, dateCreation: new Date('2024-02-10'), utilisations: 15 }, { id: '3', nom: 'Installation Électrique Complète', description: 'Template pour installation électrique maison 100m²', categorie: 'ELECTRICITE', lignes: [ { designation: 'Tableau électrique', quantite: 1, unite: 'unité', prixUnitaire: 450 }, { designation: 'Prises de courant', quantite: 25, unite: 'unité', prixUnitaire: 35 }, { designation: 'Points lumineux', quantite: 15, unite: 'unité', prixUnitaire: 45 }, { designation: 'Câblage', quantite: 1, unite: 'forfait', prixUnitaire: 1200 } ], tauxTVA: 20, actif: true, dateCreation: new Date('2024-03-05'), utilisations: 31 } ]; setTemplates(mockTemplates); } catch (error) { console.error('Erreur lors du chargement des templates:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les templates' }); } finally { setLoading(false); } }; const handleNew = () => { setEditingTemplate(null); setFormData({ nom: '', description: '', categorie: '', lignes: [], tauxTVA: 20, actif: true }); setShowDialog(true); }; const handleEdit = (template: DevisTemplate) => { setEditingTemplate(template); setFormData({ ...template }); setShowDialog(true); }; const handleSave = async () => { try { if (editingTemplate) { // TODO: Appel API pour mise à jour // await devisService.updateTemplate(editingTemplate.id, formData); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Template modifié avec succès' }); } else { // TODO: Appel API pour création // await devisService.createTemplate(formData); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Template créé avec succès' }); } setShowDialog(false); loadTemplates(); } catch (error) { console.error('Erreur lors de la sauvegarde:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la sauvegarde' }); } }; const handleDelete = async (template: DevisTemplate) => { try { // TODO: Appel API pour suppression // await devisService.deleteTemplate(template.id); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Template supprimé avec succès' }); loadTemplates(); } catch (error) { console.error('Erreur lors de la suppression:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la suppression' }); } }; const handleUseTemplate = async (template: DevisTemplate) => { try { // TODO: Créer un nouveau devis basé sur le template toast.current?.show({ severity: 'info', summary: 'Info', detail: 'Redirection vers la création de devis...' }); // Simuler la redirection setTimeout(() => { window.location.href = `/devis/nouveau?template=${template.id}`; }, 1000); } catch (error) { console.error('Erreur lors de l\'utilisation du template:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de l\'utilisation du template' }); } }; const getMenuItems = (template: DevisTemplate) => [ { label: 'Utiliser', icon: 'pi pi-plus', command: () => handleUseTemplate(template) }, { label: 'Modifier', icon: 'pi pi-pencil', command: () => handleEdit(template) }, { label: 'Dupliquer', icon: 'pi pi-copy', command: () => { setEditingTemplate(null); setFormData({ ...template, nom: `${template.nom} (Copie)`, id: undefined }); setShowDialog(true); } }, { separator: true }, { label: 'Supprimer', icon: 'pi pi-trash', className: 'text-red-500', command: () => { setSelectedTemplate(template); // TODO: Afficher dialog de confirmation } } ]; const actionBodyTemplate = (rowData: DevisTemplate) => (
); const categorieBodyTemplate = (rowData: DevisTemplate) => { const categorie = categorieOptions.find(opt => opt.value === rowData.categorie); return ( ); }; const statutBodyTemplate = (rowData: DevisTemplate) => ( ); const utilisationsBodyTemplate = (rowData: DevisTemplate) => ( ); const toolbarStartTemplate = () => (

Templates de Devis

); const toolbarEndTemplate = () => (
setGlobalFilter(e.target.value)} placeholder="Rechercher..." />
); return (
{/* Statistiques rapides */}
Total Templates
{templates.length}
Templates Actifs
{templates.filter(t => t.actif).length}
Plus Utilisé
{Math.max(...templates.map(t => t.utilisations), 0)} fois
Catégories
{new Set(templates.map(t => t.categorie)).size}
{/* Table des templates */}
Liste des Templates {templates.length} template(s)
} > rowData.lignes?.length || 0} style={{ width: '100px' }} /> formatDate(rowData.dateCreation)} sortable style={{ width: '120px' }} />
{/* Dialog de création/modification */} setShowDialog(false)} style={{ width: '800px' }} footer={
} >
setFormData(prev => ({ ...prev, nom: e.target.value }))} className="w-full" required />
setFormData(prev => ({ ...prev, categorie: e.value }))} className="w-full" placeholder="Sélectionner une catégorie" />
setFormData(prev => ({ ...prev, description: e.target.value }))} className="w-full" rows={3} />
Prestations du template

Les prestations seront automatiquement ajoutées lors de l'utilisation du template.

{formData.lignes && formData.lignes.length > 0 ? ( `${rowData.prixUnitaire}€`} /> ) : (

Aucune prestation définie

)}
); }; export default DevisTemplatesPage;