Files
geo/flutt/lib/presentation/widgets/sector_distribution_card.dart

207 lines
6.3 KiB
Dart

import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:geosector_app/core/data/models/passage_model.dart';
import 'package:geosector_app/core/data/models/sector_model.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/shared/app_theme.dart';
class SectorDistributionCard extends StatefulWidget {
final String title;
final double? height;
final EdgeInsetsGeometry? padding;
const SectorDistributionCard({
Key? key,
this.title = 'Répartition par secteur',
this.height,
this.padding,
}) : super(key: key);
@override
State<SectorDistributionCard> createState() => _SectorDistributionCardState();
}
class _SectorDistributionCardState extends State<SectorDistributionCard> {
List<Map<String, dynamic>> sectorStats = [];
bool isLoading = true;
@override
void initState() {
super.initState();
_loadSectorData();
}
Future<void> _loadSectorData() async {
setState(() {
isLoading = true;
});
try {
// S'assurer que les boîtes Hive sont ouvertes
if (!Hive.isBoxOpen(AppKeys.sectorsBoxName)) {
await Hive.openBox<SectorModel>(AppKeys.sectorsBoxName);
}
if (!Hive.isBoxOpen(AppKeys.passagesBoxName)) {
await Hive.openBox<PassageModel>(AppKeys.passagesBoxName);
}
// Récupérer tous les secteurs
final sectorsBox = Hive.box<SectorModel>(AppKeys.sectorsBoxName);
final List<SectorModel> sectors = sectorsBox.values.toList();
// Récupérer tous les passages
final passagesBox = Hive.box<PassageModel>(AppKeys.passagesBoxName);
final List<PassageModel> passages = passagesBox.values.toList();
// Compter les passages par secteur (en excluant ceux où fkType==2)
final Map<int, int> sectorCounts = {};
for (final passage in passages) {
// Exclure les passages où fkType==2
if (passage.fkSector != null && passage.fkType != 2) {
sectorCounts[passage.fkSector!] =
(sectorCounts[passage.fkSector!] ?? 0) + 1;
}
}
// Préparer les données pour l'affichage
List<Map<String, dynamic>> stats = [];
for (final sector in sectors) {
final count = sectorCounts[sector.id] ?? 0;
if (count > 0) {
stats.add({
'name': sector.libelle,
'count': count,
'color': sector.color.isEmpty
? 0xFF4B77BE
: int.tryParse(sector.color.replaceAll('#', '0xFF')) ??
0xFF4B77BE,
});
}
}
setState(() {
sectorStats = stats;
isLoading = false;
});
} catch (e) {
debugPrint('Erreur lors du chargement des données de secteur: $e');
setState(() {
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Container(
height: widget.height,
padding: widget.padding ?? const EdgeInsets.all(AppTheme.spacingM),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
boxShadow: AppTheme.cardShadow,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.title,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
if (isLoading)
const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
else
IconButton(
icon: const Icon(Icons.refresh, size: 20),
onPressed: _loadSectorData,
tooltip: 'Rafraîchir',
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
),
],
),
const SizedBox(height: AppTheme.spacingM),
Expanded(
child: isLoading
? const Center(child: CircularProgressIndicator())
: sectorStats.isEmpty
? const Center(
child: Text('Aucune donnée de secteur disponible'))
: ListView.builder(
itemCount: sectorStats.length,
itemBuilder: (context, index) {
final sector = sectorStats[index];
return _buildSectorItem(
context,
sector['name'],
sector['count'],
Color(sector['color']),
);
},
),
),
],
),
);
}
Widget _buildSectorItem(
BuildContext context,
String name,
int count,
Color color,
) {
final totalCount =
sectorStats.fold(0, (sum, item) => sum + (item['count'] as int));
final percentage = totalCount > 0 ? (count / totalCount) * 100 : 0;
return Padding(
padding: const EdgeInsets.only(bottom: AppTheme.spacingS),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(
name,
style: const TextStyle(fontSize: 14),
overflow: TextOverflow.ellipsis,
),
),
Text(
'$count (${percentage.toInt()}%)',
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
],
),
const SizedBox(height: 4),
LinearProgressIndicator(
value: percentage / 100,
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation<Color>(color),
minHeight: 8,
borderRadius: BorderRadius.circular(4),
),
],
),
);
}
}