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,136 @@
import React from 'react';
import { Button } from 'primereact/button';
interface ActionButtonProps {
icon: string;
tooltip: string;
onClick: () => void;
color?: 'default' | 'green' | 'blue' | 'orange' | 'red' | 'purple' | 'teal';
disabled?: boolean;
size?: 'small' | 'normal' | 'large';
}
/**
* Composant de bouton d'action standardisé pour toute l'application
* Utilise le style p-button-text avec des couleurs personnalisées
*/
export const ActionButton: React.FC<ActionButtonProps> = ({
icon,
tooltip,
onClick,
color = 'default',
disabled = false,
size = 'small'
}) => {
// Classes de couleur pour les icônes
const colorClasses = {
default: '',
green: 'text-green-500',
blue: 'text-blue-500',
orange: 'text-orange-500',
red: 'text-red-500',
purple: 'text-purple-500',
teal: 'text-teal-500'
};
// Classes de taille
const sizeClasses = {
small: 'p-button-sm',
normal: '',
large: 'p-button-lg'
};
const buttonClasses = [
'p-button-rounded',
'p-button-text',
sizeClasses[size],
colorClasses[color]
].filter(Boolean).join(' ');
return (
<Button
icon={icon}
className={buttonClasses}
tooltip={tooltip}
tooltipOptions={{ position: 'top' }}
onClick={onClick}
disabled={disabled}
/>
);
};
// Boutons d'actions prédéfinis pour les cas d'usage courants
export const ViewButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-eye" color="default" {...props} />
);
export const EditButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-pencil" color="orange" {...props} />
);
export const DeleteButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-trash" color="red" {...props} />
);
export const StartButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-play" color="green" {...props} />
);
export const CompleteButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-check" color="green" {...props} />
);
export const ProgressButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-percentage" color="blue" {...props} />
);
export const PauseButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-pause" color="orange" {...props} />
);
export const ResumeButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-play" color="teal" {...props} />
);
export const DownloadButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-download" color="blue" {...props} />
);
export const PrintButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-print" color="purple" {...props} />
);
export const BudgetPlanButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-calculator" color="purple" {...props} />
);
export const BudgetTrackButton: React.FC<Omit<ActionButtonProps, 'icon' | 'color'>> = (props) => (
<ActionButton icon="pi pi-chart-line" color="teal" {...props} />
);
/**
* Container pour grouper les boutons d'actions
*/
interface ActionButtonGroupProps {
children: React.ReactNode;
align?: 'left' | 'center' | 'right';
gap?: '1' | '2' | '3';
}
export const ActionButtonGroup: React.FC<ActionButtonGroupProps> = ({
children,
align = 'center',
gap = '1'
}) => {
const alignClasses = {
left: 'justify-content-start',
center: 'justify-content-center',
right: 'justify-content-end'
};
return (
<div className={`flex ${alignClasses[align]} gap-${gap}`}>
{children}
</div>
);
};

View File

@@ -0,0 +1,41 @@
'use client';
import React from 'react';
interface CFASymbolProps {
size?: 'small' | 'medium' | 'large';
className?: string;
style?: React.CSSProperties;
}
const CFASymbol: React.FC<CFASymbolProps> = ({
size = 'medium',
className = '',
style = {}
}) => {
const sizeMap = {
small: '16px',
medium: '20px',
large: '24px'
};
const symbolStyle = {
height: sizeMap[size],
width: 'auto',
display: 'inline-block',
verticalAlign: 'middle',
...style
};
return (
<img
src="/layout/images/logo/logo-cfa.png"
alt="CFA"
className={`cfa-symbol ${className}`}
style={symbolStyle}
title="Franc CFA"
/>
);
};
export default CFASymbol;

View File

@@ -0,0 +1,66 @@
'use client';
import React from 'react';
interface LionsDevLogoProps {
size?: 'small' | 'medium' | 'large';
className?: string;
style?: React.CSSProperties;
showText?: boolean;
}
const LionsDevLogo: React.FC<LionsDevLogoProps> = ({
size = 'medium',
className = '',
style = {},
showText = false
}) => {
const sizeMap = {
small: '20px',
medium: '32px',
large: '48px'
};
const logoStyle = {
height: sizeMap[size],
width: 'auto',
display: 'inline-block',
verticalAlign: 'middle',
...style
};
return (
<div className={`lions-dev-logo flex align-items-center ${className}`}>
<div
style={{
height: sizeMap[size],
width: sizeMap[size],
backgroundColor: '#1a1a1a',
borderRadius: '4px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginRight: showText ? '8px' : '0',
border: '1px solid #fbbf24',
...style
}}
title="Développé par Lions Dev"
>
<span style={{
color: '#fbbf24',
fontWeight: 'bold',
fontSize: size === 'small' ? '8px' : size === 'medium' ? '12px' : '16px'
}}>
🦁
</span>
</div>
{showText && (
<span className="text-sm text-600">
Développé par Lions Dev
</span>
)}
</div>
);
};
export default LionsDevLogo;

View File

@@ -0,0 +1,46 @@
'use client';
import React from 'react';
interface LoadingSpinnerProps {
size?: 'small' | 'medium' | 'large';
color?: 'primary' | 'secondary' | 'white';
className?: string;
}
const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
size = 'medium',
color = 'primary',
className = '',
}) => {
// Tailles du spinner
const sizeClasses = {
small: 'w-4 h-4',
medium: 'w-8 h-8',
large: 'w-12 h-12',
};
// Couleurs du spinner
const colorClasses = {
primary: 'border-blue-600',
secondary: 'border-gray-600',
white: 'border-white',
};
return (
<div
className={`
inline-block animate-spin rounded-full border-2 border-solid border-current border-r-transparent
${sizeClasses[size]}
${colorClasses[color]}
${className}
`}
role="status"
aria-label="Chargement..."
>
<span className="sr-only">Chargement...</span>
</div>
);
};
export default LoadingSpinner;

151
components/ui/README.md Normal file
View File

@@ -0,0 +1,151 @@
# Composants UI Standardisés - BTPXpress
## ActionButton - Boutons d'Actions Standardisés
### Vue d'ensemble
Les composants `ActionButton` fournissent une approche cohérente pour tous les boutons d'actions dans l'application BTPXpress. Ils utilisent le style `p-button-text` pour un rendu subtil et professionnel, similaire au template Atlantis React.
### Utilisation de base
```tsx
import { ActionButton, ActionButtonGroup } from '../../components/ui/ActionButton';
// Bouton personnalisé
<ActionButton
icon="pi pi-eye"
tooltip="Voir détails"
onClick={() => handleView()}
color="blue"
/>
// Groupe de boutons
<ActionButtonGroup>
<ViewButton tooltip="Voir" onClick={() => handleView()} />
<EditButton tooltip="Modifier" onClick={() => handleEdit()} />
<DeleteButton tooltip="Supprimer" onClick={() => handleDelete()} />
</ActionButtonGroup>
```
### Boutons prédéfinis disponibles
- **ViewButton**: `pi pi-eye` - Couleur par défaut (gris)
- **EditButton**: `pi pi-pencil` - Orange
- **DeleteButton**: `pi pi-trash` - Rouge
- **StartButton**: `pi pi-play` - Vert
- **CompleteButton**: `pi pi-check` - Vert
- **ProgressButton**: `pi pi-percentage` - Bleu
- **PauseButton**: `pi pi-pause` - Orange
- **ResumeButton**: `pi pi-play` - Teal
- **DownloadButton**: `pi pi-download` - Bleu
- **PrintButton**: `pi pi-print` - Violet
### Props ActionButton
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| icon | string | - | Icône PrimeIcons (ex: "pi pi-eye") |
| tooltip | string | - | Texte du tooltip |
| onClick | function | - | Fonction appelée au clic |
| color | string | 'default' | Couleur: 'default', 'green', 'blue', 'orange', 'red', 'purple', 'teal' |
| disabled | boolean | false | Désactiver le bouton |
| size | string | 'small' | Taille: 'small', 'normal', 'large' |
### Props ActionButtonGroup
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| children | ReactNode | - | Boutons enfants |
| align | string | 'center' | Alignement: 'left', 'center', 'right' |
| gap | string | '1' | Espacement: '1', '2', '3' |
### Exemples d'utilisation dans les tableaux
#### DataTable avec actions contextuelles
```tsx
const actionBodyTemplate = (rowData: any) => {
return (
<ActionButtonGroup>
<ViewButton
tooltip="Voir détails"
onClick={() => viewDetails(rowData)}
/>
{rowData.status === 'DRAFT' && (
<EditButton
tooltip="Modifier"
onClick={() => editItem(rowData)}
/>
)}
{rowData.canDelete && (
<DeleteButton
tooltip="Supprimer"
onClick={() => confirmDelete(rowData)}
/>
)}
</ActionButtonGroup>
);
};
```
#### Actions en en-tête de page
```tsx
<ActionButtonGroup align="right" gap="2">
<DownloadButton
tooltip="Exporter PDF"
onClick={handleExportPDF}
/>
<PrintButton
tooltip="Imprimer"
onClick={handlePrint}
/>
</ActionButtonGroup>
```
### Standards visuels
- **Style**: Tous les boutons utilisent `p-button-text` pour un rendu subtil
- **Forme**: Boutons ronds (`p-button-rounded`)
- **Taille**: Par défaut petite (`p-button-sm`)
- **Tooltips**: Toujours positionnés en haut
- **Couleurs**: Système cohérent basé sur l'action
- Actions neutres: Gris par défaut
- Actions positives: Vert (démarrer, valider, compléter)
- Actions d'information: Bleu (voir, télécharger)
- Actions de modification: Orange (éditer, pauser)
- Actions destructives: Rouge (supprimer)
- Actions spéciales: Violet (imprimer), Teal (reprendre)
### Intégration dans les pages existantes
Pour appliquer ces standards dans vos pages :
1. **Importez les composants nécessaires**
```tsx
import { ActionButtonGroup, ViewButton, EditButton, DeleteButton } from '../../components/ui/ActionButton';
```
2. **Remplacez les boutons existants**
```tsx
// Ancien style
<Button icon="pi pi-eye" className="p-button-text" onClick={handleView} />
<Button icon="pi pi-pencil" className="p-button-warning" onClick={handleEdit} />
// Nouveau style standardisé
<ActionButtonGroup>
<ViewButton tooltip="Voir" onClick={handleView} />
<EditButton tooltip="Modifier" onClick={handleEdit} />
</ActionButtonGroup>
```
3. **Adaptez selon le contexte**
- Utilisez les boutons prédéfinis quand possible
- Créez des boutons personnalisés avec `ActionButton` si nécessaire
- Groupez les actions logiquement avec `ActionButtonGroup`
### Maintenance et évolution
- **Cohérence**: Tous les boutons d'actions de l'application doivent utiliser ces composants
- **Extensibilité**: Ajoutez de nouveaux boutons prédéfinis selon les besoins
- **Accessibilité**: Les tooltips et l'état disabled sont automatiquement gérés
- **Responsive**: Les boutons s'adaptent automatiquement aux différentes tailles d'écran