10 KiB
🧩 COMPOSANTS - BTPXPRESS FRONTEND
📋 Table des matières
- Vue d'ensemble
- Composants Layout
- Composants Formulaires
- Composants Tableaux
- Composants Graphiques
- Composants Communs
- PrimeReact
- Création de composants
🎯 Vue d'ensemble
L'application utilise PrimeReact 10.2.1 comme bibliothèque de composants UI principale, complétée par des composants personnalisés.
Organisation
components/
├── layout/ # Composants de mise en page
├── forms/ # Formulaires
├── tables/ # Tableaux de données
├── charts/ # Graphiques
└── common/ # Composants réutilisables
🏗️ Composants Layout
Header
En-tête de l'application avec navigation et profil utilisateur.
Fichier : components/layout/Header.tsx
'use client';
import { Menubar } from 'primereact/menubar';
import { Avatar } from 'primereact/avatar';
import { useAuth } from '@/hooks/useAuth';
export const Header = () => {
const { user, logout } = useAuth();
const items = [
{ label: 'Dashboard', icon: 'pi pi-home', url: '/dashboard' },
{ label: 'Chantiers', icon: 'pi pi-building', url: '/chantiers' },
{ label: 'Clients', icon: 'pi pi-users', url: '/clients' },
{ label: 'Matériel', icon: 'pi pi-wrench', url: '/materiels' },
];
const end = (
<div className="flex align-items-center gap-2">
<Avatar label={user?.initials} shape="circle" />
<span>{user?.name}</span>
</div>
);
return <Menubar model={items} end={end} />;
};
Props : Aucune
Utilisation :
import { Header } from '@/components/layout/Header';
<Header />
Sidebar
Menu latéral de navigation.
Fichier : components/layout/Sidebar.tsx
'use client';
import { PanelMenu } from 'primereact/panelmenu';
import { MenuItem } from 'primereact/menuitem';
export const Sidebar = () => {
const items: MenuItem[] = [
{
label: 'Dashboard',
icon: 'pi pi-home',
url: '/dashboard',
},
{
label: 'Chantiers',
icon: 'pi pi-building',
items: [
{ label: 'Liste', url: '/chantiers' },
{ label: 'Nouveau', url: '/chantiers/nouveau' },
{ label: 'Planning', url: '/chantiers/planning' },
],
},
{
label: 'Clients',
icon: 'pi pi-users',
items: [
{ label: 'Liste', url: '/clients' },
{ label: 'Nouveau', url: '/clients/nouveau' },
],
},
];
return (
<div className="sidebar">
<PanelMenu model={items} />
</div>
);
};
Breadcrumb
Fil d'Ariane pour la navigation.
Fichier : components/layout/Breadcrumb.tsx
'use client';
import { BreadCrumb } from 'primereact/breadcrumb';
import { MenuItem } from 'primereact/menuitem';
interface BreadcrumbProps {
items: MenuItem[];
}
export const AppBreadcrumb: React.FC<BreadcrumbProps> = ({ items }) => {
const home = { icon: 'pi pi-home', url: '/dashboard' };
return <BreadCrumb model={items} home={home} />;
};
Utilisation :
const items = [
{ label: 'Chantiers', url: '/chantiers' },
{ label: 'Villa Moderne' },
];
<AppBreadcrumb items={items} />
📝 Composants Formulaires
ChantierForm
Formulaire de création/modification de chantier.
Fichier : components/forms/ChantierForm.tsx
'use client';
import { useForm, Controller } from 'react-hook-form';
import { InputText } from 'primereact/inputtext';
import { Dropdown } from 'primereact/dropdown';
import { Calendar } from 'primereact/calendar';
import { Button } from 'primereact/button';
import type { ChantierDTO } from '@/types/models/Chantier';
interface ChantierFormProps {
chantier?: ChantierDTO;
onSubmit: (data: ChantierDTO) => void;
onCancel: () => void;
}
export const ChantierForm: React.FC<ChantierFormProps> = ({
chantier,
onSubmit,
onCancel,
}) => {
const { control, handleSubmit, formState: { errors } } = useForm<ChantierDTO>({
defaultValues: chantier || {},
});
const statutOptions = [
{ label: 'Planifié', value: 'PLANIFIE' },
{ label: 'En cours', value: 'EN_COURS' },
{ label: 'Terminé', value: 'TERMINE' },
];
return (
<form onSubmit={handleSubmit(onSubmit)} className="p-fluid">
<div className="field">
<label htmlFor="nom">Nom *</label>
<Controller
name="nom"
control={control}
rules={{ required: 'Le nom est obligatoire' }}
render={({ field }) => (
<InputText
id="nom"
{...field}
className={errors.nom ? 'p-invalid' : ''}
/>
)}
/>
{errors.nom && <small className="p-error">{errors.nom.message}</small>}
</div>
<div className="field">
<label htmlFor="statut">Statut</label>
<Controller
name="statut"
control={control}
render={({ field }) => (
<Dropdown
id="statut"
{...field}
options={statutOptions}
placeholder="Sélectionner un statut"
/>
)}
/>
</div>
<div className="field">
<label htmlFor="dateDebut">Date de début</label>
<Controller
name="dateDebut"
control={control}
render={({ field }) => (
<Calendar
id="dateDebut"
{...field}
dateFormat="dd/mm/yy"
showIcon
/>
)}
/>
</div>
<div className="flex gap-2 justify-content-end">
<Button
label="Annuler"
icon="pi pi-times"
className="p-button-text"
onClick={onCancel}
type="button"
/>
<Button
label="Enregistrer"
icon="pi pi-check"
type="submit"
/>
</div>
</form>
);
};
📊 Composants Tableaux
DataTableWrapper
Wrapper pour DataTable de PrimeReact avec fonctionnalités communes.
Fichier : components/tables/DataTableWrapper.tsx
'use client';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { Button } from 'primereact/button';
interface DataTableWrapperProps<T> {
data: T[];
columns: ColumnConfig[];
onEdit?: (item: T) => void;
onDelete?: (item: T) => void;
loading?: boolean;
}
interface ColumnConfig {
field: string;
header: string;
sortable?: boolean;
body?: (rowData: any) => React.ReactNode;
}
export function DataTableWrapper<T>({
data,
columns,
onEdit,
onDelete,
loading = false,
}: DataTableWrapperProps<T>) {
const actionBodyTemplate = (rowData: T) => {
return (
<div className="flex gap-2">
{onEdit && (
<Button
icon="pi pi-pencil"
className="p-button-rounded p-button-text"
onClick={() => onEdit(rowData)}
/>
)}
{onDelete && (
<Button
icon="pi pi-trash"
className="p-button-rounded p-button-text p-button-danger"
onClick={() => onDelete(rowData)}
/>
)}
</div>
);
};
return (
<DataTable
value={data}
paginator
rows={10}
loading={loading}
emptyMessage="Aucune donnée disponible"
>
{columns.map((col) => (
<Column
key={col.field}
field={col.field}
header={col.header}
sortable={col.sortable}
body={col.body}
/>
))}
{(onEdit || onDelete) && (
<Column
body={actionBodyTemplate}
header="Actions"
style={{ width: '10rem' }}
/>
)}
</DataTable>
);
}
Utilisation :
const columns = [
{ field: 'nom', header: 'Nom', sortable: true },
{ field: 'code', header: 'Code', sortable: true },
{ field: 'statut', header: 'Statut' },
];
<DataTableWrapper
data={chantiers}
columns={columns}
onEdit={handleEdit}
onDelete={handleDelete}
loading={loading}
/>
📈 Composants Graphiques
ChartBar
Graphique en barres avec Chart.js.
Fichier : components/charts/ChartBar.tsx
'use client';
import { Chart } from 'primereact/chart';
interface ChartBarProps {
data: {
labels: string[];
datasets: {
label: string;
data: number[];
backgroundColor?: string;
}[];
};
title?: string;
}
export const ChartBar: React.FC<ChartBarProps> = ({ data, title }) => {
const options = {
responsive: true,
plugins: {
legend: {
position: 'top' as const,
},
title: {
display: !!title,
text: title,
},
},
};
return <Chart type="bar" data={data} options={options} />;
};
Utilisation :
const data = {
labels: ['Jan', 'Fév', 'Mar', 'Avr'],
datasets: [
{
label: 'Chantiers',
data: [12, 19, 8, 15],
backgroundColor: 'rgba(54, 162, 235, 0.5)',
},
],
};
<ChartBar data={data} title="Chantiers par mois" />
🔧 Composants Communs
LoadingSpinner
Indicateur de chargement.
'use client';
import { ProgressSpinner } from 'primereact/progressspinner';
export const LoadingSpinner = () => {
return (
<div className="flex justify-content-center align-items-center" style={{ height: '400px' }}>
<ProgressSpinner />
</div>
);
};
ErrorMessage
Message d'erreur.
'use client';
import { Message } from 'primereact/message';
interface ErrorMessageProps {
message: string;
}
export const ErrorMessage: React.FC<ErrorMessageProps> = ({ message }) => {
return <Message severity="error" text={message} />;
};
🎨 PrimeReact
Composants utilisés
| Composant | Usage |
|---|---|
| DataTable | Tableaux de données |
| Button | Boutons |
| InputText | Champs texte |
| Dropdown | Listes déroulantes |
| Calendar | Sélecteur de date |
| Dialog | Modales |
| Toast | Notifications |
| Chart | Graphiques |
| Menubar | Menu principal |
| PanelMenu | Menu latéral |
Documentation
Dernière mise à jour : 2025-09-30
Version : 1.0
Auteur : Équipe BTPXpress