feat: Pages de détails complètes pour chantiers, clients et matériels
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>
This commit is contained in:
131
app/(main)/chantiers/[id]/documents/page.tsx
Normal file
131
app/(main)/chantiers/[id]/documents/page.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user