PHASE 2 - FINALISATIONS FONCTIONNELLES TERMINÉES ✅ Pages Chantiers [id] créées: - /chantiers/[id]: Vue d'ensemble avec statistiques et navigation - /chantiers/[id]/budget: Suivi budgétaire détaillé avec graphiques - /chantiers/[id]/planning: Chronologie et planning des tâches - /chantiers/[id]/documents: Gestion des documents du chantier - /chantiers/[id]/equipe: Liste et gestion de l'équipe affectée ✅ Pages Clients [id] créées: - /clients/[id]: Fiche client complète avec coordonnées - Onglets: Chantiers, Factures, Documents - Statistiques et historique complet ✅ Pages Matériels [id] créées: - /materiels/[id]: Fiche matériel avec informations techniques - Calendrier de disponibilité - Onglets: Réservations, Maintenances, Documents - Timeline des maintenances Fonctionnalités implémentées: - Navigation fluide entre les pages - Boutons retour vers listes principales - DataTables avec tri et filtres - Graphiques budget (bar chart, doughnut) - Calendriers et timeline - Tags de statut colorés - Cards statistiques - Responsive design Technologies utilisées: - PrimeReact (DataTable, Chart, Calendar, Timeline, TabView) - Next.js App Router avec dynamic routes [id] - TypeScript avec interfaces typées - Integration API backend via fetch Prochaines étapes: - Connecter aux vraies APIs backend - Ajouter formulaires de modification - Implémenter actions (supprimer, modifier) - Ajouter toasts de confirmation 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import { useParams, useRouter } from 'next/navigation';
|
|
import { Card } from 'primereact/card';
|
|
import { Button } from 'primereact/button';
|
|
import { DataTable } from 'primereact/datatable';
|
|
import { Column } from 'primereact/column';
|
|
import { FileUpload } from 'primereact/fileupload';
|
|
import { Tag } from 'primereact/tag';
|
|
|
|
interface Document {
|
|
id: number;
|
|
nom: string;
|
|
type: string;
|
|
taille: number;
|
|
dateAjout: string;
|
|
ajoutePar: string;
|
|
categorie: string;
|
|
}
|
|
|
|
export default function ChantierDocumentsPage() {
|
|
const params = useParams();
|
|
const router = useRouter();
|
|
const id = params.id as string;
|
|
|
|
const [documents] = useState<Document[]>([
|
|
{
|
|
id: 1,
|
|
nom: 'Plan d\'architecte.pdf',
|
|
type: 'PDF',
|
|
taille: 2500000,
|
|
dateAjout: '2025-01-15',
|
|
ajoutePar: 'Jean Dupont',
|
|
categorie: 'Plans'
|
|
},
|
|
{
|
|
id: 2,
|
|
nom: 'Devis matériaux.xlsx',
|
|
type: 'Excel',
|
|
taille: 150000,
|
|
dateAjout: '2025-01-20',
|
|
ajoutePar: 'Marie Martin',
|
|
categorie: 'Devis'
|
|
}
|
|
]);
|
|
|
|
const formatTaille = (bytes: number) => {
|
|
if (bytes === 0) return '0 Bytes';
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
|
};
|
|
|
|
const typeBodyTemplate = (rowData: Document) => {
|
|
const icon = rowData.type === 'PDF' ? 'pi-file-pdf' :
|
|
rowData.type === 'Excel' ? 'pi-file-excel' : 'pi-file';
|
|
return <i className={`pi ${icon} text-2xl`}></i>;
|
|
};
|
|
|
|
const tailleBodyTemplate = (rowData: Document) => {
|
|
return formatTaille(rowData.taille);
|
|
};
|
|
|
|
const categorieBodyTemplate = (rowData: Document) => {
|
|
return <Tag value={rowData.categorie} />;
|
|
};
|
|
|
|
const actionsBodyTemplate = () => {
|
|
return (
|
|
<div className="flex gap-2">
|
|
<Button icon="pi pi-download" className="p-button-text p-button-sm" tooltip="Télécharger" />
|
|
<Button icon="pi pi-eye" className="p-button-text p-button-sm" tooltip="Prévisualiser" />
|
|
<Button icon="pi pi-trash" className="p-button-text p-button-sm p-button-danger" tooltip="Supprimer" />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="grid">
|
|
<div className="col-12">
|
|
<div className="flex justify-content-between align-items-center mb-3">
|
|
<div className="flex align-items-center">
|
|
<Button
|
|
icon="pi pi-arrow-left"
|
|
className="p-button-text mr-2"
|
|
onClick={() => router.push(`/chantiers/${id}`)}
|
|
tooltip="Retour"
|
|
/>
|
|
<h2 className="m-0">Documents du chantier</h2>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="col-12">
|
|
<Card>
|
|
<FileUpload
|
|
name="documents"
|
|
multiple
|
|
accept="*/*"
|
|
maxFileSize={10000000}
|
|
emptyTemplate={<p className="m-0">Glissez-déposez vos fichiers ici</p>}
|
|
chooseLabel="Choisir des fichiers"
|
|
uploadLabel="Téléverser"
|
|
cancelLabel="Annuler"
|
|
/>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="col-12">
|
|
<Card title="Liste des documents">
|
|
<DataTable
|
|
value={documents}
|
|
paginator
|
|
rows={10}
|
|
responsiveLayout="scroll"
|
|
>
|
|
<Column body={typeBodyTemplate} header="Type" style={{ width: '5rem' }} />
|
|
<Column field="nom" header="Nom" sortable filter />
|
|
<Column body={categorieBodyTemplate} header="Catégorie" sortable filter />
|
|
<Column body={tailleBodyTemplate} header="Taille" sortable />
|
|
<Column field="dateAjout" header="Date d'ajout" sortable />
|
|
<Column field="ajoutePar" header="Ajouté par" sortable />
|
|
<Column body={actionsBodyTemplate} header="Actions" />
|
|
</DataTable>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|