feat: Gestion des secteurs et migration v3.0.4+304

- Ajout système complet de gestion des secteurs avec contours géographiques
- Import des contours départementaux depuis GeoJSON
- API REST pour la gestion des secteurs (/api/sectors)
- Service de géolocalisation pour déterminer les secteurs
- Migration base de données avec tables x_departements_contours et sectors_adresses
- Interface Flutter pour visualisation et gestion des secteurs
- Ajout thème sombre dans l'application
- Corrections diverses et optimisations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
pierre
2025-08-07 11:01:45 +02:00
parent 6a609fb467
commit 599b9fcda0
662 changed files with 213221 additions and 174243 deletions

View File

@@ -0,0 +1,76 @@
import 'package:flutter/material.dart';
/// Widget pour créer des sections de formulaire avec titre flottant
/// Compatible avec le design du passage_form_dialog
class FormSection extends StatelessWidget {
final String title;
final IconData? icon;
final List<Widget> children;
final EdgeInsets? padding;
final EdgeInsets? margin;
final bool showBorder;
const FormSection({
super.key,
required this.title,
this.icon,
required this.children,
this.padding,
this.margin,
this.showBorder = true,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Stack(
children: [
Container(
margin: margin ?? const EdgeInsets.only(top: 8),
padding: padding ?? const EdgeInsets.fromLTRB(16, 20, 16, 16),
decoration: showBorder ? BoxDecoration(
border: Border.all(color: theme.colorScheme.outline),
borderRadius: BorderRadius.circular(8),
) : null,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
),
),
if (title.isNotEmpty)
Positioned(
top: 0,
left: 16,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(4),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
Icon(
icon,
color: theme.colorScheme.primary,
size: 16,
),
const SizedBox(width: 6),
],
Text(
title,
style: theme.textTheme.labelMedium?.copyWith(
fontWeight: FontWeight.bold,
color: theme.colorScheme.primary,
),
),
],
),
),
),
],
);
}
}