Refactor: Centralisation des labels et icônes pour les enums

Centralise la gestion des libellés, couleurs et icônes pour `EquipmentStatus`, `EquipmentCategory`, et `ContainerType` en utilisant des extensions Dart.

- Ajout de nouvelles icônes SVG pour `flight-case`, `truss` et `tape`.
- Refactorisation des vues pour utiliser les nouvelles extensions, supprimant ainsi la logique d'affichage dupliquée.
- Mise à jour des `ChoiceChip` et des listes de filtres pour afficher les icônes à côté des labels.
This commit is contained in:
ElPoyo
2025-10-29 18:43:24 +01:00
parent 3fab69cb00
commit df6d54a007
16 changed files with 441 additions and 307 deletions

View File

@@ -167,7 +167,7 @@ class _ContainerDetailPageState extends State<ContainerDetailPage> {
Expanded(
child: _buildInfoItem(
'Type',
containerTypeLabel(_container.type),
_container.type.label,
Icons.category,
),
),

View File

@@ -177,7 +177,7 @@ class _ContainerFormPageState extends State<ContainerFormPage> {
items: ContainerType.values.map((type) {
return DropdownMenuItem(
value: type,
child: Text(containerTypeLabel(type)),
child: Text(type.label),
);
}).toList(),
onChanged: (value) {

View File

@@ -190,7 +190,7 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
...ContainerType.values.map((type) {
return Padding(
padding: const EdgeInsets.only(right: 8),
child: _buildTypeChip(type, containerTypeLabel(type)),
child: _buildTypeChip(type, type.label),
);
}),
],
@@ -201,8 +201,19 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
Widget _buildTypeChip(ContainerType? type, String label) {
final isSelected = _selectedType == type;
final color = isSelected ? Colors.white : AppColors.noir;
return ChoiceChip(
label: Text(label),
label: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (type != null) ...[
type.getIcon(size: 16, color: color),
const SizedBox(width: 8),
],
Text(label),
],
),
selected: isSelected,
onSelected: (selected) {
setState(() {
@@ -212,7 +223,7 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
},
selectedColor: AppColors.rouge,
labelStyle: TextStyle(
color: isSelected ? Colors.white : AppColors.noir,
color: color,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
);
@@ -244,7 +255,7 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
const SizedBox(height: 8),
_buildFilterOption(null, 'Tous les types'),
...ContainerType.values.map((type) {
return _buildFilterOption(type, containerTypeLabel(type));
return _buildFilterOption(type, type.label);
}),
const Divider(height: 32),
@@ -403,8 +414,7 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
),
// Icône du type de container
Icon(
_getTypeIcon(container.type),
container.type.getIcon(
size: 40,
color: AppColors.rouge,
),
@@ -434,7 +444,7 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
Row(
children: [
_buildInfoChip(
containerTypeLabel(container.type),
container.type.label,
Icons.category,
),
const SizedBox(width: 8),
@@ -534,42 +544,17 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
}
Widget _buildStatusBadge(EquipmentStatus status) {
Color color;
String label;
switch (status) {
case EquipmentStatus.available:
color = Colors.green;
label = 'Disponible';
break;
case EquipmentStatus.inUse:
color = Colors.orange;
label = 'En prestation';
break;
case EquipmentStatus.maintenance:
color = Colors.blue;
label = 'Maintenance';
break;
case EquipmentStatus.outOfService:
color = Colors.red;
label = 'Hors service';
break;
default:
color = Colors.grey;
label = 'Autre';
}
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
color: status.color.withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: color),
border: Border.all(color: status.color),
),
child: Text(
label,
status.label,
style: TextStyle(
color: color,
color: status.color,
fontWeight: FontWeight.bold,
fontSize: 12,
),
@@ -577,21 +562,6 @@ class _ContainerManagementPageState extends State<ContainerManagementPage>
);
}
IconData _getTypeIcon(ContainerType type) {
switch (type) {
case ContainerType.flightCase:
return Icons.work;
case ContainerType.pelicase:
return Icons.work_outline;
case ContainerType.bag:
return Icons.shopping_bag;
case ContainerType.openCrate:
return Icons.inventory_2;
case ContainerType.toolbox:
return Icons.handyman;
}
}
void _handleMenuAction(String action, ContainerModel container) {
switch (action) {

View File

@@ -7,7 +7,6 @@ import 'package:em2rp/providers/local_user_provider.dart';
import 'package:em2rp/services/equipment_service.dart';
import 'package:em2rp/services/qr_code_service.dart';
import 'package:em2rp/utils/colors.dart';
import 'package:em2rp/utils/permission_gate.dart';
import 'package:em2rp/views/widgets/nav/custom_app_bar.dart';
import 'package:em2rp/views/equipment_form_page.dart';
import 'package:em2rp/views/widgets/equipment/equipment_parent_containers.dart';
@@ -144,10 +143,9 @@ class _EquipmentDetailPageState extends State<EquipmentDetailPage> {
CircleAvatar(
backgroundColor: Colors.white,
radius: 30,
child: Icon(
_getCategoryIcon(widget.equipment.category),
color: AppColors.rouge,
child: widget.equipment.category.getIcon(
size: 32,
color: AppColors.rouge,
),
),
const SizedBox(width: 16),
@@ -187,7 +185,7 @@ class _EquipmentDetailPageState extends State<EquipmentDetailPage> {
}
Widget _buildStatusBadge() {
final statusInfo = _getStatusInfo(widget.equipment.status);
final status = widget.equipment.status;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
@@ -201,17 +199,17 @@ class _EquipmentDetailPageState extends State<EquipmentDetailPage> {
width: 8,
height: 8,
decoration: BoxDecoration(
color: statusInfo.$2,
color: status.color,
shape: BoxShape.circle,
),
),
const SizedBox(width: 8),
Text(
statusInfo.$1,
status.label,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: statusInfo.$2,
color: status.color,
),
),
],
@@ -240,14 +238,14 @@ class _EquipmentDetailPageState extends State<EquipmentDetailPage> {
],
),
const Divider(height: 24),
_buildInfoRow('Catégorie', _getCategoryName(widget.equipment.category)),
_buildInfoRow('Catégorie', widget.equipment.category.label),
if (widget.equipment.brand != null && widget.equipment.brand!.isNotEmpty)
_buildInfoRow('Marque', widget.equipment.brand!),
if (widget.equipment.model != null && widget.equipment.model!.isNotEmpty)
_buildInfoRow('Modèle', widget.equipment.model!),
if (widget.equipment.category != EquipmentCategory.consumable &&
widget.equipment.category != EquipmentCategory.cable)
_buildInfoRow('Statut', _getStatusInfo(widget.equipment.status).$1),
_buildInfoRow('Statut', widget.equipment.status.label),
],
),
),
@@ -808,65 +806,6 @@ class _EquipmentDetailPageState extends State<EquipmentDetailPage> {
);
}
IconData _getCategoryIcon(EquipmentCategory category) {
switch (category) {
case EquipmentCategory.lighting:
return Icons.light_mode;
case EquipmentCategory.sound:
return Icons.volume_up;
case EquipmentCategory.video:
return Icons.videocam;
case EquipmentCategory.effect:
return Icons.auto_awesome;
case EquipmentCategory.structure:
return Icons.construction;
case EquipmentCategory.consumable:
return Icons.inventory_2;
case EquipmentCategory.cable:
return Icons.cable;
case EquipmentCategory.other:
return Icons.more_horiz;
}
}
String _getCategoryName(EquipmentCategory category) {
switch (category) {
case EquipmentCategory.lighting:
return 'Lumière';
case EquipmentCategory.sound:
return 'Son';
case EquipmentCategory.video:
return 'Vidéo';
case EquipmentCategory.effect:
return 'Effets';
case EquipmentCategory.structure:
return 'Structure';
case EquipmentCategory.consumable:
return 'Consommable';
case EquipmentCategory.cable:
return 'Câble';
case EquipmentCategory.other:
return 'Autre';
}
}
(String, Color) _getStatusInfo(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return ('Disponible', Colors.green);
case EquipmentStatus.inUse:
return ('En prestation', Colors.blue);
case EquipmentStatus.rented:
return ('Loué', Colors.orange);
case EquipmentStatus.lost:
return ('Perdu', Colors.red);
case EquipmentStatus.outOfService:
return ('HS', Colors.red[900]!);
case EquipmentStatus.maintenance:
return ('Maintenance', Colors.amber);
}
}
(String, IconData) _getMaintenanceTypeInfo(MaintenanceType type) {
switch (type) {
case MaintenanceType.preventive:

View File

@@ -275,7 +275,7 @@ class _EquipmentFormPageState extends State<EquipmentFormPage> {
items: EquipmentCategory.values.map((category) {
return DropdownMenuItem(
value: category,
child: Text(_getCategoryLabel(category)),
child: Text(category.label),
);
}).toList(),
onChanged: (value) {
@@ -301,7 +301,7 @@ class _EquipmentFormPageState extends State<EquipmentFormPage> {
items: EquipmentStatus.values.map((status) {
return DropdownMenuItem(
value: status,
child: Text(_getStatusLabel(status)),
child: Text(status.label),
);
}).toList(),
onChanged: (value) {
@@ -654,47 +654,4 @@ class _EquipmentFormPageState extends State<EquipmentFormPage> {
if (mounted) setState(() => _isLoading = false);
}
}
// Correction des enums dans _getCategoryLabel
String _getCategoryLabel(EquipmentCategory category) {
switch (category) {
case EquipmentCategory.lighting:
return 'Lumière';
case EquipmentCategory.sound:
return 'Son';
case EquipmentCategory.video:
return 'Vidéo';
case EquipmentCategory.effect:
return 'Effet';
case EquipmentCategory.structure:
return 'Structure';
case EquipmentCategory.consumable:
return 'Consommable';
case EquipmentCategory.cable:
return 'Câble';
case EquipmentCategory.other:
default:
return 'Autre';
}
}
// Correction des enums dans _getStatusLabel
String _getStatusLabel(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return 'Disponible';
case EquipmentStatus.inUse:
return 'En prestation';
case EquipmentStatus.rented:
return 'Loué';
case EquipmentStatus.lost:
return 'Perdu';
case EquipmentStatus.outOfService:
return 'HS';
case EquipmentStatus.maintenance:
return 'Maintenance';
default:
return 'Autre';
}
}
}

View File

@@ -293,7 +293,6 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
},
),
),
const Divider(),
// Filtres par catégorie
Padding(
padding:
@@ -353,44 +352,34 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
}
List<Widget> _buildCategoryChips() {
final categories = [
(EquipmentCategory.lighting, Icons.light_mode, 'Lumière'),
(EquipmentCategory.sound, Icons.volume_up, 'Son'),
(EquipmentCategory.video, Icons.videocam, 'Vidéo'),
(EquipmentCategory.effect, Icons.auto_awesome, 'Effets'),
(EquipmentCategory.structure, Icons.construction, 'Structure'),
(EquipmentCategory.consumable, Icons.inventory_2, 'Consommable'),
(EquipmentCategory.cable, Icons.cable, 'Câble'),
(EquipmentCategory.other, Icons.more_horiz, 'Autre'),
];
return EquipmentCategory.values.map((category) {
final isSelected = _selectedCategory == category;
final color = isSelected ? Colors.white : AppColors.rouge;
return categories.map((cat) {
final isSelected = _selectedCategory == cat.$1;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: ChoiceChip(
label: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
cat.$2,
category.getIcon(
size: 16,
color: isSelected ? Colors.white : AppColors.rouge,
color: color,
),
const SizedBox(width: 8),
Text(cat.$3),
Text(category.label),
],
),
selected: isSelected,
onSelected: (selected) {
if (selected) {
setState(() => _selectedCategory = cat.$1);
context.read<EquipmentProvider>().setSelectedCategory(cat.$1);
setState(() => _selectedCategory = category);
context.read<EquipmentProvider>().setSelectedCategory(category);
}
},
selectedColor: AppColors.rouge,
labelStyle: TextStyle(
color: isSelected ? Colors.white : AppColors.rouge,
color: color,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
),
),
@@ -399,26 +388,17 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
}
List<Widget> _buildCategoryListTiles() {
final categories = [
(EquipmentCategory.lighting, Icons.light_mode, 'Lumière'),
(EquipmentCategory.sound, Icons.volume_up, 'Son'),
(EquipmentCategory.video, Icons.videocam, 'Vidéo'),
(EquipmentCategory.effect, Icons.auto_awesome, 'Effets'),
(EquipmentCategory.structure, Icons.construction, 'Structure'),
(EquipmentCategory.consumable, Icons.inventory_2, 'Consommable'),
(EquipmentCategory.cable, Icons.cable, 'Câble'),
(EquipmentCategory.other, Icons.more_horiz, 'Autre'),
];
return EquipmentCategory.values.map((category) {
final isSelected = _selectedCategory == category;
final color = isSelected ? AppColors.rouge : Colors.grey[600]!;
return categories.map((cat) {
final isSelected = _selectedCategory == cat.$1;
return ListTile(
leading: Icon(
cat.$2,
color: isSelected ? AppColors.rouge : Colors.grey[600],
leading: category.getIcon(
size: 24,
color: color,
),
title: Text(
cat.$3,
category.label,
style: TextStyle(
color: isSelected ? AppColors.rouge : Colors.black87,
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
@@ -427,8 +407,8 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
selected: isSelected,
selectedTileColor: AppColors.rouge.withOpacity(0.1),
onTap: () {
setState(() => _selectedCategory = cat.$1);
context.read<EquipmentProvider>().setSelectedCategory(cat.$1);
setState(() => _selectedCategory = category);
context.read<EquipmentProvider>().setSelectedCategory(category);
},
);
}).toList();
@@ -506,10 +486,10 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
)
: CircleAvatar(
backgroundColor:
_getStatusColor(equipment.status).withOpacity(0.2),
child: Icon(
_getCategoryIcon(equipment.category),
color: _getStatusColor(equipment.status),
equipment.status.color.withOpacity(0.2),
child: equipment.category.getIcon(
size: 20,
color: Colors.black,
),
),
title: Row(
@@ -659,67 +639,24 @@ class _EquipmentManagementPageState extends State<EquipmentManagementPage>
}
Widget _buildStatusBadge(EquipmentStatus status) {
final statusInfo = _getStatusInfo(status);
return Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: statusInfo.$2.withOpacity(0.2),
color: status.color.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: statusInfo.$2),
border: Border.all(color: status.color),
),
child: Text(
statusInfo.$1,
status.label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: statusInfo.$2,
color: status.color,
),
),
);
}
(String, Color) _getStatusInfo(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return ('Disponible', Colors.green);
case EquipmentStatus.inUse:
return ('En prestation', Colors.blue);
case EquipmentStatus.rented:
return ('Loué', Colors.orange);
case EquipmentStatus.lost:
return ('Perdu', Colors.red);
case EquipmentStatus.outOfService:
return ('HS', Colors.red[900]!);
case EquipmentStatus.maintenance:
return ('Maintenance', Colors.amber);
}
}
Color _getStatusColor(EquipmentStatus status) {
return _getStatusInfo(status).$2;
}
IconData _getCategoryIcon(EquipmentCategory category) {
switch (category) {
case EquipmentCategory.lighting:
return Icons.light_mode;
case EquipmentCategory.sound:
return Icons.volume_up;
case EquipmentCategory.video:
return Icons.videocam;
case EquipmentCategory.effect:
return Icons.auto_awesome;
case EquipmentCategory.structure:
return Icons.construction;
case EquipmentCategory.consumable:
return Icons.inventory_2;
case EquipmentCategory.cable:
return Icons.cable;
case EquipmentCategory.other:
return Icons.more_horiz;
}
}
// Actions
void _createNewEquipment() {
Navigator.push(

View File

@@ -25,8 +25,7 @@ class ContainerHeaderCard extends StatelessWidget {
children: [
Row(
children: [
Icon(
_getTypeIcon(container.type),
container.type.getIcon(
size: 60,
color: AppColors.rouge,
),
@@ -62,7 +61,7 @@ class ContainerHeaderCard extends StatelessWidget {
child: _buildInfoItem(
context,
'Type',
containerTypeLabel(container.type),
container.type.label,
Icons.category,
),
),
@@ -70,9 +69,9 @@ class ContainerHeaderCard extends StatelessWidget {
child: _buildInfoItem(
context,
'Statut',
_getStatusLabel(container.status),
container.status.label,
Icons.info,
statusColor: _getStatusColor(container.status),
statusColor: container.status.color,
),
),
],
@@ -148,50 +147,5 @@ class ContainerHeaderCard extends StatelessWidget {
final totalWeight = container.calculateTotalWeight(equipmentList);
return '${totalWeight.toStringAsFixed(1)} kg';
}
IconData _getTypeIcon(ContainerType type) {
switch (type) {
case ContainerType.flightCase:
return Icons.work;
case ContainerType.pelicase:
return Icons.work_outline;
case ContainerType.bag:
return Icons.shopping_bag;
case ContainerType.openCrate:
return Icons.inventory_2;
case ContainerType.toolbox:
return Icons.handyman;
}
}
String _getStatusLabel(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return 'Disponible';
case EquipmentStatus.inUse:
return 'En prestation';
case EquipmentStatus.maintenance:
return 'Maintenance';
case EquipmentStatus.outOfService:
return 'Hors service';
default:
return 'Autre';
}
}
Color _getStatusColor(EquipmentStatus status) {
switch (status) {
case EquipmentStatus.available:
return Colors.green;
case EquipmentStatus.inUse:
return Colors.orange;
case EquipmentStatus.maintenance:
return Colors.blue;
case EquipmentStatus.outOfService:
return Colors.red;
default:
return Colors.grey;
}
}
}