'use client'; export const dynamic = 'force-dynamic'; 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 { Checkbox } from 'primereact/checkbox'; import { factureService } from '../../../../services/api'; import { formatDate } from '../../../../utils/formatters'; interface FactureTemplate { id: string; nom: string; description: string; type: string; categorie: string; lignes: Array<{ designation: string; quantite: number; unite: string; prixUnitaire: number; }>; tauxTVA: number; conditionsPaiement: string; actif: boolean; dateCreation: Date; utilisations: number; } const FactureTemplatesPage = () => { 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: '', type: 'FACTURE', categorie: '', lignes: [], tauxTVA: 20, conditionsPaiement: 'Paiement à 30 jours', actif: true }); const typeOptions = [ { label: 'Facture', value: 'FACTURE' }, { label: 'Acompte', value: 'ACOMPTE' }, { label: 'Facture de situation', value: 'SITUATION' }, { label: 'Facture de solde', value: 'SOLDE' } ]; 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 factureService.getTemplates(); // Données simulées pour la démonstration const mockTemplates: FactureTemplate[] = [ { id: '1', nom: 'Facture Rénovation Standard', description: 'Template pour factures de rénovation complète', type: 'FACTURE', categorie: 'RENOVATION', lignes: [ { designation: 'Main d\'œuvre', quantite: 1, unite: 'forfait', prixUnitaire: 2500 }, { designation: 'Matériaux', quantite: 1, unite: 'forfait', prixUnitaire: 1800 }, { designation: 'Évacuation déchets', quantite: 1, unite: 'forfait', prixUnitaire: 300 } ], tauxTVA: 20, conditionsPaiement: 'Paiement à 30 jours', actif: true, dateCreation: new Date('2024-01-15'), utilisations: 45 }, { id: '2', nom: 'Acompte Gros Œuvre', description: 'Template pour acomptes sur travaux de gros œuvre', type: 'ACOMPTE', categorie: 'GROS_OEUVRE', lignes: [ { designation: 'Acompte 30% - Fondations', quantite: 1, unite: 'forfait', prixUnitaire: 0 } ], tauxTVA: 20, conditionsPaiement: 'Paiement à réception', actif: true, dateCreation: new Date('2024-02-10'), utilisations: 28 }, { id: '3', nom: 'Facture Maintenance Préventive', description: 'Template pour factures de maintenance préventive', type: 'FACTURE', categorie: 'MAINTENANCE', lignes: [ { designation: 'Contrôle technique', quantite: 1, unite: 'forfait', prixUnitaire: 150 }, { designation: 'Remplacement pièces', quantite: 1, unite: 'forfait', prixUnitaire: 200 }, { designation: 'Rapport de maintenance', quantite: 1, unite: 'forfait', prixUnitaire: 50 } ], tauxTVA: 20, conditionsPaiement: 'Paiement à 15 jours', actif: true, dateCreation: new Date('2024-03-05'), utilisations: 67 } ]; 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: '', type: 'FACTURE', categorie: '', lignes: [], tauxTVA: 20, conditionsPaiement: 'Paiement à 30 jours', actif: true }); setShowDialog(true); }; const handleEdit = (template: FactureTemplate) => { setEditingTemplate(template); setFormData({ ...template }); setShowDialog(true); }; const handleSave = async () => { try { if (editingTemplate) { // TODO: Appel API pour mise à jour // await factureService.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 factureService.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: FactureTemplate) => { try { // TODO: Appel API pour suppression // await factureService.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: FactureTemplate) => { try { // TODO: Créer une nouvelle facture basée sur le template toast.current?.show({ severity: 'info', summary: 'Info', detail: 'Redirection vers la création de facture...' }); // Simuler la redirection setTimeout(() => { window.location.href = `/factures/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: FactureTemplate) => [ { 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: FactureTemplate) => (
); const typeBodyTemplate = (rowData: FactureTemplate) => ( ); const categorieBodyTemplate = (rowData: FactureTemplate) => { const categorie = categorieOptions.find(opt => opt.value === rowData.categorie); return ( ); }; const statutBodyTemplate = (rowData: FactureTemplate) => ( ); const utilisationsBodyTemplate = (rowData: FactureTemplate) => ( ); const toolbarStartTemplate = () => (

Templates de Factures

); 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
Types
{new Set(templates.map(t => t.type)).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, type: e.value }))} className="w-full" placeholder="Sélectionner un type" />
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} />
setFormData(prev => ({ ...prev, tauxTVA: parseFloat(e.target.value) || 0 }))} className="w-full" />
setFormData(prev => ({ ...prev, conditionsPaiement: e.target.value }))} className="w-full" />
setFormData(prev => ({ ...prev, actif: e.checked || false }))} />
Lignes du template

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

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

Aucune ligne définie

)}
); }; export default FactureTemplatesPage;