Initial commit

This commit is contained in:
dahoud
2025-10-01 01:39:07 +00:00
commit b430bf3b96
826 changed files with 255287 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
/**
* Bouton d'action distinctif avec couleurs et animations personnalisées
*/
import React from 'react';
import { Button } from 'primereact/button';
import { Tooltip } from 'primereact/tooltip';
import {
ACTION_BUTTON_THEMES,
BUTTON_SIZES,
BUTTON_VARIANTS,
ActionButtonType
} from './ActionButtonStyles';
import ChantierMenuActions from './ChantierMenuActions';
import { ChantierActif } from '../../hooks/useDashboard';
interface ActionButtonProps {
type: ActionButtonType;
onClick?: () => void;
disabled?: boolean;
loading?: boolean;
size?: 'xs' | 'sm' | 'md' | 'lg';
showLabel?: boolean;
className?: string;
style?: React.CSSProperties;
tooltipPosition?: 'top' | 'bottom' | 'left' | 'right';
// Propriétés pour le menu
chantier?: ChantierActif;
onMenuAction?: (action: string, chantier: ChantierActif) => void;
}
const ActionButton: React.FC<ActionButtonProps> = ({
type,
onClick,
disabled = false,
loading = false,
size = 'md',
showLabel = false,
className = '',
style = {},
tooltipPosition = 'top',
chantier,
onMenuAction
}) => {
const theme = ACTION_BUTTON_THEMES[type];
// ID unique pour le tooltip
const buttonId = `action-btn-${type.toLowerCase()}-${Math.random().toString(36).substr(2, 9)}`;
// Style minimal Atlantis Rounded Text - pas de styles custom
const getButtonStyles = () => {
return {
...style // Seulement les styles passés en props
};
};
// Classes CSS strictes Atlantis Rounded Text
const buttonClasses = [
'p-button-text p-button-rounded p-button-sm', // Strict Atlantis + taille compacte
disabled ? 'p-disabled' : '',
className
].filter(Boolean).join(' ');
// Rendu minimal Atlantis
const buttonContent = (
<>
<i className={theme.icon} style={{ color: theme.colors.primary }} />
{showLabel && <span className="ml-1">{theme.name}</span>}
</>
);
// Si c'est le bouton MENU et qu'on a un chantier, utiliser le composant menu
if (type === 'MENU' && chantier && onMenuAction) {
return (
<ChantierMenuActions
chantier={chantier}
onAction={onMenuAction}
/>
);
}
return (
<>
<Button
id={buttonId}
className={buttonClasses}
style={getButtonStyles()}
onClick={onClick}
disabled={disabled}
loading={loading}
aria-label={theme.name}
>
{buttonContent}
</Button>
<Tooltip
target={`#${buttonId}`}
content={theme.name}
position={tooltipPosition}
showDelay={300}
hideDelay={100}
/>
</>
);
};
export default ActionButton;

View File

@@ -0,0 +1,73 @@
/**
* Groupe de boutons d'action avec animations et espacement optimisé
*/
import React from 'react';
import ActionButton from './ActionButton';
import { ActionButtonType } from './ActionButtonStyles';
import { ChantierActif } from '../../hooks/useDashboard';
interface ActionButtonGroupProps {
chantier: ChantierActif;
actions: ActionButtonType[];
onAction: (action: ActionButtonType, chantier: ChantierActif) => void;
size?: 'xs' | 'sm' | 'md' | 'lg';
orientation?: 'horizontal' | 'vertical';
spacing?: 'none' | 'sm' | 'md' | 'lg';
showLabels?: boolean;
className?: string;
}
const ActionButtonGroup: React.FC<ActionButtonGroupProps> = ({
chantier,
actions,
onAction,
size = 'md',
orientation = 'horizontal',
spacing = 'sm',
showLabels = false,
className = ''
}) => {
// Classes pour l'espacement - plus compact
const spacingClasses = {
none: 'gap-0',
sm: 'gap-1',
md: 'gap-1',
lg: 'gap-2'
};
// Classes pour l'orientation
const orientationClasses = {
horizontal: 'flex-row',
vertical: 'flex-column'
};
const containerClasses = [
'flex',
'align-items-center',
orientationClasses[orientation],
spacingClasses[spacing],
'action-button-group',
className
].filter(Boolean).join(' ');
return (
<div className={containerClasses}>
{actions.map((actionType, index) => (
<ActionButton
key={`${actionType}-${chantier.id}-${index}`}
type={actionType}
size={size}
showLabel={showLabels}
onClick={() => onAction(actionType, chantier)}
className="action-button-group-item"
// Props pour le menu
chantier={chantier}
onMenuAction={actionType === 'MENU' ? onAction : undefined}
/>
))}
</div>
);
};
export default ActionButtonGroup;

View File

@@ -0,0 +1,115 @@
/**
* Styles distinctifs pour chaque bouton d'action
* Couleurs spécifiques et animations pour une UX premium
*/
export const ACTION_BUTTON_THEMES = {
VIEW: {
name: 'Vue Rapide',
icon: 'pi pi-eye',
colors: {
primary: '#3B82F6', // Bleu moderne
light: '#DBEAFE', // Bleu très clair
dark: '#1D4ED8', // Bleu foncé
text: '#1E40AF' // Texte bleu
},
className: ''
},
PHASES: {
name: 'Phases',
icon: 'pi pi-sitemap',
colors: {
primary: '#10B981', // Vert émeraude
light: '#D1FAE5', // Vert très clair
dark: '#059669', // Vert foncé
text: '#047857' // Texte vert
},
className: ''
},
PLANNING: {
name: 'Planning',
icon: 'pi pi-calendar',
colors: {
primary: '#8B5CF6', // Violet moderne
light: '#EDE9FE', // Violet très clair
dark: '#7C3AED', // Violet foncé
text: '#6D28D9' // Texte violet
},
className: ''
},
STATS: {
name: 'Statistiques',
icon: 'pi pi-chart-bar',
colors: {
primary: '#06B6D4', // Cyan moderne
light: '#CFFAFE', // Cyan très clair
dark: '#0891B2', // Cyan foncé
text: '#0E7490' // Texte cyan
},
className: ''
},
MENU: {
name: 'Plus d\'actions',
icon: 'pi pi-ellipsis-v',
colors: {
primary: '#6B7280', // Gris moderne
light: '#F3F4F6', // Gris très clair
dark: '#4B5563', // Gris foncé
text: '#374151' // Texte gris
},
className: ''
},
EDIT: {
name: 'Modifier',
icon: 'pi pi-pencil',
colors: {
primary: '#F59E0B', // Orange/Ambre
light: '#FEF3C7', // Orange très clair
dark: '#D97706', // Orange foncé
text: '#B45309' // Texte orange
},
className: ''
},
DELETE: {
name: 'Supprimer',
icon: 'pi pi-trash',
colors: {
primary: '#EF4444', // Rouge moderne
light: '#FEE2E2', // Rouge très clair
dark: '#DC2626', // Rouge foncé
text: '#B91C1C' // Texte rouge
},
className: ''
}
} as const;
export type ActionButtonType = keyof typeof ACTION_BUTTON_THEMES;
// Tailles compactes pour DataTable optimisée
export const BUTTON_SIZES = {
xs: {
padding: 'p-1',
iconSize: 'text-xs',
width: 'w-5 h-5' // Extra compact
},
sm: {
padding: 'p-1',
iconSize: 'text-sm',
width: 'w-6 h-6' // Compact
},
md: {
padding: 'p-2',
iconSize: 'text-base',
width: 'w-8 h-8'
},
lg: {
padding: 'p-2',
iconSize: 'text-lg',
width: 'w-10 h-10'
}
} as const;
// Style Rounded Text uniquement - autres variantes supprimées
export const BUTTON_VARIANTS = {
roundedText: 'p-button-text p-button-rounded'
} as const;

View File

@@ -0,0 +1,215 @@
/**
* Composant réutilisable pour les actions sur les chantiers
*/
import React, { useRef } from 'react';
import { Button } from 'primereact/button';
import { Menu } from 'primereact/menu';
import { MenuItem } from 'primereact/menuitem';
import { ACTION_BUTTONS, COMMON_CLASSES, ActionButtonType } from './ChantierStyles';
import { ChantierActif } from '../../hooks/useDashboard';
interface ChantierActionsProps {
chantier: ChantierActif;
onQuickView?: (chantier: ChantierActif) => void;
onManagePhases?: (chantier: ChantierActif) => void;
onViewPlanning?: (chantier: ChantierActif) => void;
onViewStats?: (chantier: ChantierActif) => void;
onMenuAction?: (action: string, chantier: ChantierActif) => void;
showLabels?: boolean;
size?: 'small' | 'normal' | 'large';
layout?: 'horizontal' | 'vertical';
buttons?: ActionButtonType[];
className?: string;
}
const ChantierActions: React.FC<ChantierActionsProps> = ({
chantier,
onQuickView,
onManagePhases,
onViewPlanning,
onViewStats,
onMenuAction,
showLabels = false,
size = 'normal',
layout = 'horizontal',
buttons = ['VIEW', 'PHASES', 'PLANNING', 'STATS', 'MENU'],
className = ''
}) => {
const menuRef = useRef<Menu>(null);
const sizeClasses = {
small: 'p-button-sm',
normal: '',
large: 'p-button-lg'
};
const layoutClasses = {
horizontal: COMMON_CLASSES.BUTTON_GROUP,
vertical: 'flex flex-column gap-2'
};
// Configuration du menu contextuel
const menuItems: MenuItem[] = [
{
label: 'Navigation',
items: [
{
label: 'Détails complets',
icon: 'pi pi-external-link',
command: () => onMenuAction?.('details', chantier)
},
{
label: 'Documents',
icon: 'pi pi-file',
command: () => onMenuAction?.('documents', chantier)
},
{
label: 'Photos',
icon: 'pi pi-images',
command: () => onMenuAction?.('photos', chantier)
}
]
},
{ separator: true },
{
label: 'Ressources',
items: [
{
label: 'Équipe assignée',
icon: 'pi pi-users',
command: () => onMenuAction?.('team', chantier)
},
{
label: 'Matériel utilisé',
icon: 'pi pi-cog',
command: () => onMenuAction?.('equipment', chantier)
}
]
},
{ separator: true },
{
label: 'Rapports',
items: [
{
label: 'Générer rapport',
icon: 'pi pi-chart-bar',
command: () => onMenuAction?.('report', chantier)
},
{
label: 'Export PDF',
icon: 'pi pi-file-pdf',
command: () => onMenuAction?.('export-pdf', chantier)
},
{
label: 'Export Excel',
icon: 'pi pi-file-excel',
command: () => onMenuAction?.('export-excel', chantier)
}
]
},
{ separator: true },
{
label: 'Actions',
items: [
{
label: chantier.statut === 'SUSPENDU' ? 'Reprendre' : 'Suspendre',
icon: chantier.statut === 'SUSPENDU' ? 'pi pi-play' : 'pi pi-pause',
command: () => onMenuAction?.('toggle-suspend', chantier),
className: 'text-orange-500'
},
{
label: 'Clôturer',
icon: 'pi pi-check-circle',
command: () => onMenuAction?.('close', chantier),
disabled: chantier.statut === 'TERMINE',
className: 'text-green-500'
},
{
label: 'Archiver',
icon: 'pi pi-inbox',
command: () => onMenuAction?.('archive', chantier),
className: 'text-gray-500'
}
]
}
];
const handleMenuClick = (e: React.MouseEvent) => {
menuRef.current?.toggle(e);
};
const renderButton = (buttonType: ActionButtonType) => {
const config = ACTION_BUTTONS[buttonType];
const baseClassName = `${config.className} ${sizeClasses[size]}`;
const buttonProps = {
icon: config.icon,
tooltip: config.tooltip,
tooltipOptions: { position: 'top' as const, showDelay: 500 },
className: baseClassName,
'aria-label': config.tooltip
};
switch (buttonType) {
case 'VIEW':
return (
<Button
key="view"
{...buttonProps}
onClick={() => onQuickView?.(chantier)}
/>
);
case 'PHASES':
return (
<Button
key="phases"
{...buttonProps}
onClick={() => onManagePhases?.(chantier)}
/>
);
case 'PLANNING':
return (
<Button
key="planning"
{...buttonProps}
onClick={() => onViewPlanning?.(chantier)}
/>
);
case 'STATS':
return (
<Button
key="stats"
{...buttonProps}
onClick={() => onViewStats?.(chantier)}
/>
);
case 'MENU':
return (
<Button
key="menu"
{...buttonProps}
onClick={handleMenuClick}
/>
);
default:
return null;
}
};
return (
<>
<div className={`${layoutClasses[layout]} ${className}`}>
{buttons.map(buttonType => renderButton(buttonType))}
</div>
<Menu ref={menuRef} model={menuItems} popup />
</>
);
};
export default ChantierActions;

View File

@@ -0,0 +1,67 @@
/**
* Version simplifiée du composant ChantierActions pour debug
*/
import React from 'react';
import { Button } from 'primereact/button';
import { ChantierActif } from '../../hooks/useDashboard';
interface ChantierActionsSimpleProps {
chantier: ChantierActif;
onQuickView?: (chantier: ChantierActif) => void;
onManagePhases?: (chantier: ChantierActif) => void;
onViewPlanning?: (chantier: ChantierActif) => void;
onViewStats?: (chantier: ChantierActif) => void;
onMenuAction?: (action: string, chantier: ChantierActif) => void;
}
const ChantierActionsSimple: React.FC<ChantierActionsSimpleProps> = ({
chantier,
onQuickView,
onManagePhases,
onViewPlanning,
onViewStats,
onMenuAction
}) => {
return (
<div className="flex gap-2">
<Button
icon="pi pi-eye"
className="p-button-rounded p-button-text"
tooltip="Vue rapide"
onClick={() => onQuickView?.(chantier)}
size="small"
/>
<Button
icon="pi pi-sitemap"
className="p-button-rounded p-button-text"
tooltip="Gérer les phases"
onClick={() => onManagePhases?.(chantier)}
size="small"
/>
<Button
icon="pi pi-calendar"
className="p-button-rounded p-button-text"
tooltip="Planning"
onClick={() => onViewPlanning?.(chantier)}
size="small"
/>
<Button
icon="pi pi-chart-bar"
className="p-button-rounded p-button-text"
tooltip="Statistiques"
onClick={() => onViewStats?.(chantier)}
size="small"
/>
<Button
icon="pi pi-ellipsis-v"
className="p-button-rounded p-button-text"
tooltip="Plus d'actions"
onClick={() => onMenuAction?.('details', chantier)}
size="small"
/>
</div>
);
};
export default ChantierActionsSimple;

View File

@@ -0,0 +1,100 @@
/**
* Menu d'actions pour les chantiers - Actions prioritaires BTP
*/
import React, { useRef } from 'react';
import { Button } from 'primereact/button';
import { Menu } from 'primereact/menu';
import { MenuItem } from 'primereact/menuitem';
import { ChantierActif } from '../../hooks/useDashboard';
interface ChantierMenuActionsProps {
chantier: ChantierActif;
onAction: (action: string, chantier: ChantierActif) => void;
}
const ChantierMenuActions: React.FC<ChantierMenuActionsProps> = ({
chantier,
onAction
}) => {
const menuRef = useRef<Menu>(null);
// Actions prioritaires pour le workflow BTP
const menuItems: MenuItem[] = [
{
label: 'Gestion chantier',
items: [
{
label: 'Suspendre le chantier',
icon: 'pi pi-pause',
command: () => onAction('suspend', chantier)
},
{
label: 'Clôturer le chantier',
icon: 'pi pi-check-circle',
command: () => onAction('close', chantier)
}
]
},
{
separator: true
},
{
label: 'Communication',
items: [
{
label: 'Notification client',
icon: 'pi pi-send',
command: () => onAction('notify-client', chantier)
},
{
label: 'Rapport de synthèse',
icon: 'pi pi-file-pdf',
command: () => onAction('generate-report', chantier)
}
]
},
{
separator: true
},
{
label: 'Financier',
items: [
{
label: 'Facture intermédiaire',
icon: 'pi pi-euro',
command: () => onAction('generate-invoice', chantier)
},
{
label: 'Créer un avenant',
icon: 'pi pi-file-plus',
command: () => onAction('create-amendment', chantier)
}
]
}
];
const toggleMenu = (event: React.MouseEvent) => {
menuRef.current?.toggle(event);
};
return (
<>
<Button
icon="pi pi-ellipsis-v"
className="p-button-text p-button-rounded p-button-sm"
onClick={toggleMenu}
aria-label="Plus d'actions"
style={{ color: '#6B7280' }}
/>
<Menu
ref={menuRef}
model={menuItems}
popup
style={{ minWidth: '250px' }}
/>
</>
);
};
export default ChantierMenuActions;

View File

@@ -0,0 +1,70 @@
/**
* Composant réutilisable pour afficher l'avancement d'un chantier
*/
import React from 'react';
import { ProgressBar } from 'primereact/progressbar';
import { AVANCEMENT_CONFIG, COMMON_CLASSES } from './ChantierStyles';
interface ChantierProgressBarProps {
value: number;
showValue?: boolean;
showPercentage?: boolean;
size?: 'small' | 'normal' | 'large';
showCompletionIcon?: boolean;
className?: string;
style?: React.CSSProperties;
}
const ChantierProgressBar: React.FC<ChantierProgressBarProps> = ({
value,
showValue = false,
showPercentage = true,
size = 'normal',
showCompletionIcon = true,
className = '',
style = {}
}) => {
// Déterminer la configuration couleur selon l'avancement
const getProgressConfig = () => {
if (value < AVANCEMENT_CONFIG.CRITIQUE.threshold) return AVANCEMENT_CONFIG.CRITIQUE;
if (value < AVANCEMENT_CONFIG.ATTENTION.threshold) return AVANCEMENT_CONFIG.ATTENTION;
if (value < AVANCEMENT_CONFIG.PROGRES.threshold) return AVANCEMENT_CONFIG.PROGRES;
return AVANCEMENT_CONFIG.TERMINE;
};
const config = getProgressConfig();
const sizeConfig = {
small: { height: '8px', fontSize: 'text-xs' },
normal: { height: '16px', fontSize: 'text-sm' },
large: { height: '20px', fontSize: 'text-base' }
};
const currentSize = sizeConfig[size];
return (
<div className={`${COMMON_CLASSES.PROGRESS_CONTAINER} ${className}`} style={style}>
<div className="w-full">
<ProgressBar
value={value}
showValue={showValue}
style={{ height: currentSize.height }}
className={`progress-${size}`}
/>
</div>
{showPercentage && (
<span className={`ml-2 font-bold ${currentSize.fontSize} ${config.textColor}`}>
{value}%
</span>
)}
{showCompletionIcon && value === 100 && (
<i className="pi pi-check-circle text-green-500 text-xl ml-2" />
)}
</div>
);
};
export default ChantierProgressBar;

View File

@@ -0,0 +1,41 @@
/**
* Composant réutilisable pour afficher le statut d'un chantier
*/
import React from 'react';
import { Tag } from 'primereact/tag';
import { CHANTIER_STATUTS, ChantierStatut } from './ChantierStyles';
interface ChantierStatusBadgeProps {
statut: string;
showIcon?: boolean;
size?: 'small' | 'normal' | 'large';
className?: string;
}
const ChantierStatusBadge: React.FC<ChantierStatusBadgeProps> = ({
statut,
showIcon = true,
size = 'normal',
className = ''
}) => {
const statutKey = statut as ChantierStatut;
const config = CHANTIER_STATUTS[statutKey] || CHANTIER_STATUTS.PLANIFIE;
const sizeClasses = {
small: 'text-xs px-2 py-1',
normal: '',
large: 'text-lg px-3 py-2'
};
return (
<Tag
value={config.label}
severity={config.severity}
icon={showIcon ? config.icon : undefined}
className={`${sizeClasses[size]} ${className}`}
/>
);
};
export default ChantierStatusBadge;

View File

@@ -0,0 +1,111 @@
/**
* Constantes de style pour les composants Chantier
* Facilite la maintenance et la cohérence visuelle
*/
// Configuration des statuts avec couleurs et icônes
export const CHANTIER_STATUTS = {
EN_COURS: {
label: 'En cours',
severity: 'success' as const,
icon: 'pi pi-play-circle',
color: 'text-green-500',
bgColor: 'bg-green-100'
},
PLANIFIE: {
label: 'Planifié',
severity: 'info' as const,
icon: 'pi pi-calendar',
color: 'text-blue-500',
bgColor: 'bg-blue-100'
},
EN_RETARD: {
label: 'En retard',
severity: 'danger' as const,
icon: 'pi pi-exclamation-triangle',
color: 'text-red-500',
bgColor: 'bg-red-100'
},
TERMINE: {
label: 'Terminé',
severity: 'success' as const,
icon: 'pi pi-check-circle',
color: 'text-green-600',
bgColor: 'bg-green-100'
},
SUSPENDU: {
label: 'Suspendu',
severity: 'warning' as const,
icon: 'pi pi-pause-circle',
color: 'text-orange-500',
bgColor: 'bg-orange-100'
}
} as const;
// Configuration des niveaux d'avancement
export const AVANCEMENT_CONFIG = {
CRITIQUE: { threshold: 30, color: 'bg-red-500', textColor: 'text-red-600' },
ATTENTION: { threshold: 60, color: 'bg-orange-500', textColor: 'text-orange-600' },
PROGRES: { threshold: 90, color: 'bg-blue-500', textColor: 'text-blue-600' },
TERMINE: { threshold: 100, color: 'bg-green-500', textColor: 'text-green-600' }
} as const;
// Configuration des boutons d'action
export const ACTION_BUTTONS = {
VIEW: {
icon: 'pi pi-eye',
tooltip: 'Vue rapide',
className: 'p-button-rounded p-button-text p-button-plain',
color: 'text-blue-500'
},
PHASES: {
icon: 'pi pi-sitemap',
tooltip: 'Gérer les phases',
className: 'p-button-rounded p-button-text p-button-plain',
color: 'text-green-500'
},
PLANNING: {
icon: 'pi pi-calendar',
tooltip: 'Planning',
className: 'p-button-rounded p-button-text p-button-plain',
color: 'text-purple-500'
},
STATS: {
icon: 'pi pi-chart-bar',
tooltip: 'Statistiques',
className: 'p-button-rounded p-button-text p-button-plain',
color: 'text-cyan-500'
},
MENU: {
icon: 'pi pi-ellipsis-v',
tooltip: 'Plus d\'actions',
className: 'p-button-rounded p-button-text p-button-plain',
color: 'text-gray-600'
}
} as const;
// Configuration des indicateurs d'urgence
export const URGENCE_INDICATORS = {
RETARD: {
icon: 'pi pi-exclamation-circle',
color: 'text-red-500',
tooltip: 'En retard'
},
BIENTOT_TERMINE: {
icon: 'pi pi-flag-fill',
color: 'text-green-500',
tooltip: 'Bientôt terminé'
}
} as const;
// Classes CSS communes
export const COMMON_CLASSES = {
BUTTON_GROUP: 'flex gap-2',
CARD_ICON: 'flex align-items-center justify-content-center border-round',
PROGRESS_CONTAINER: 'flex align-items-center',
STATUS_TAG: 'inline-flex align-items-center gap-2'
} as const;
// Types pour TypeScript
export type ChantierStatut = keyof typeof CHANTIER_STATUTS;
export type ActionButtonType = keyof typeof ACTION_BUTTONS;

View File

@@ -0,0 +1,52 @@
/**
* Composant pour les indicateurs d'urgence des chantiers
*/
import React from 'react';
import { URGENCE_INDICATORS } from './ChantierStyles';
import { ChantierActif } from '../../hooks/useDashboard';
interface ChantierUrgencyIndicatorProps {
chantier: ChantierActif;
size?: 'small' | 'normal' | 'large';
className?: string;
}
const ChantierUrgencyIndicator: React.FC<ChantierUrgencyIndicatorProps> = ({
chantier,
size = 'normal',
className = ''
}) => {
const sizeClasses = {
small: 'text-sm',
normal: 'text-base',
large: 'text-xl'
};
const getUrgencyType = () => {
if (chantier.statut === 'EN_RETARD') {
return 'RETARD';
}
if (chantier.avancement >= 90) {
return 'BIENTOT_TERMINE';
}
return null;
};
const urgencyType = getUrgencyType();
if (!urgencyType) {
return null;
}
const indicator = URGENCE_INDICATORS[urgencyType];
return (
<i
className={`${indicator.icon} ${indicator.color} ${sizeClasses[size]} ${className}`}
title={indicator.tooltip}
/>
);
};
export default ChantierUrgencyIndicator;

View File

@@ -0,0 +1,13 @@
/**
* Export des composants Chantier réutilisables
*/
export { default as ChantierActions } from './ChantierActions';
export { default as ChantierStatusBadge } from './ChantierStatusBadge';
export { default as ChantierProgressBar } from './ChantierProgressBar';
export { default as ChantierUrgencyIndicator } from './ChantierUrgencyIndicator';
export * from './ChantierStyles';
// Types communs
export type { ChantierStatut, ActionButtonType } from './ChantierStyles';