- 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>
391 lines
12 KiB
Markdown
Executable File
391 lines
12 KiB
Markdown
Executable File
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Instructions générales pour Claude
|
|
|
|
### Langue de communication
|
|
- **TOUJOURS répondre en français** sauf si explicitement demandé autrement
|
|
- Utiliser un langage technique approprié en français
|
|
|
|
### Méthodologie de travail
|
|
- **Travailler par étapes** : Ne jamais se lancer directement dans la modification du code
|
|
- **Présenter et proposer** : Toujours expliquer ce que je compte faire AVANT de le faire
|
|
- **Demander validation** : Attendre l'accord de l'utilisateur avant de procéder aux modifications
|
|
- **Structure de réponse** :
|
|
1. Analyser la demande
|
|
2. Proposer une solution détaillée
|
|
3. Lister les fichiers qui seront modifiés
|
|
4. Attendre la validation
|
|
5. Implémenter les changements
|
|
|
|
## Build Commands
|
|
- **Run app**: `flutter run` - start the Flutter app in debug mode
|
|
- **Build for release**: `flutter build apk` (Android), `flutter build ios` (iOS), `flutter build web` (Web)
|
|
- **Run tests**: `flutter test` - run all unit tests
|
|
- **Run specific test**: `flutter test test/widget_test.dart` - run a specific test file
|
|
- **Analyze code**: `flutter analyze` - check for errors, warnings, and lints
|
|
- **Format code**: `flutter format lib/` - format all Dart files
|
|
- **Generate code**: `flutter packages pub run build_runner build` - generate Hive adapters and JSON serialization
|
|
- **Clean build**: `flutter clean && flutter pub get` - clean and reinstall dependencies
|
|
- **Update dependencies**: `flutter pub upgrade` - update all packages
|
|
- **Launcher icons**: `flutter pub run flutter_launcher_icons:main` - generate app icons
|
|
|
|
## Code Architecture
|
|
|
|
### Core Architecture Pattern
|
|
The app follows a **Repository Pattern** with singleton services and reactive UI updates:
|
|
|
|
```
|
|
UI Layer (ValueListenableBuilder)
|
|
↓
|
|
Repository Layer (Business Logic)
|
|
↓
|
|
Service Layer (API + Hive Storage)
|
|
```
|
|
|
|
### Key Architectural Components
|
|
|
|
#### **Singleton Services** (lib/core/services/)
|
|
- `ApiService` - HTTP client with environment auto-detection (DEV/REC/PROD)
|
|
- `HiveService` - Local database management with typed Box handling
|
|
- `CurrentUserService` - User session and authentication state
|
|
- `CurrentAmicaleService` - Current organization context
|
|
- `DataLoadingService` - Orchestrates API data synchronization to Hive
|
|
|
|
#### **Repository Pattern** (lib/core/repositories/)
|
|
- `UserRepository` - User management and authentication
|
|
- `OperationRepository` - Operations and campaigns
|
|
- `MembreRepository` - Team member management
|
|
- `PassageRepository` - Distribution tracking
|
|
- `SectorRepository` - Geographic sectors
|
|
- `AmicaleRepository` - Organization management
|
|
|
|
#### **Reactive UI Pattern**
|
|
Uses `ValueListenableBuilder` with Hive boxes for automatic UI updates:
|
|
```dart
|
|
ValueListenableBuilder<Box<UserModel>>(
|
|
valueListenable: userRepository.getUsersBox().listenable(),
|
|
builder: (context, box, child) {
|
|
// UI automatically updates when data changes
|
|
},
|
|
)
|
|
```
|
|
|
|
### Data Flow Architecture
|
|
|
|
#### **"API First" Principle**
|
|
1. UI action triggers repository method
|
|
2. Repository attempts API call first
|
|
3. On success → Save to Hive → UI auto-updates via ValueListenableBuilder
|
|
4. On error → Show error message, no local changes
|
|
|
|
#### **Hive Storage Strategy**
|
|
- **TypeId Management**: Models use specific typeIds (UserModel: 0, OperationModel: 1, etc.)
|
|
- **Typed Boxes**: Each model has its own strongly-typed Hive box
|
|
- **Auto-sync**: Data automatically syncs between API and local storage
|
|
- **Offline-ready**: App functions with cached data when offline
|
|
- **Box Caching Optimization**: Repositories use cached Box references to prevent repeated access checks
|
|
|
|
### Error Handling Architecture
|
|
|
|
#### **Centralized Error Management**
|
|
- `ApiException` class extracts meaningful error messages from API responses
|
|
- `showError()` and `showSuccess()` methods provide consistent user feedback
|
|
- Repository methods propagate exceptions to UI layer for handling
|
|
|
|
#### **Error Flow Pattern**
|
|
```dart
|
|
try {
|
|
final result = await repository.updateUser(user);
|
|
ApiException.showSuccess(context, "User updated successfully");
|
|
} catch (e) {
|
|
ApiException.showError(context, e); // Handles all error types
|
|
}
|
|
```
|
|
|
|
#### **Smart Dialog Detection**
|
|
ApiException automatically detects when called from within a Dialog and adjusts message positioning:
|
|
|
|
- **Normal context**: Uses standard SnackBar
|
|
- **Dialog context**: Uses overlay SnackBar positioned above the Dialog
|
|
- **Mobile/Web aware**: Automatically adapts presentation for each platform
|
|
- **Consistent styling**: Unified colors, icons, and behavior across all contexts
|
|
|
|
```dart
|
|
// Same API works everywhere - smart context detection
|
|
if (validationFails) {
|
|
ApiException.showError(context, Exception("Validation failed"));
|
|
return; // Dialog stays open for corrections
|
|
}
|
|
|
|
// Success handling with auto-close
|
|
if (success) {
|
|
Navigator.pop(context); // Close dialog first
|
|
ApiException.showSuccess(context, "Operation completed");
|
|
}
|
|
```
|
|
|
|
### State Management Strategy
|
|
|
|
#### **No Provider/Bloc** - Direct Reactive Pattern
|
|
- Uses `ValueListenableBuilder` directly with Hive boxes
|
|
- Singleton services maintain global state
|
|
- `ChangeNotifier` only for specific repository loading states
|
|
|
|
#### **Dialog Auto-Management Pattern**
|
|
Dialogs handle their own submission and closing:
|
|
```dart
|
|
// Dialog manages its own lifecycle
|
|
void _handleSubmit() async {
|
|
try {
|
|
await repository.saveData(data);
|
|
Navigator.pop(context); // Auto-close on success
|
|
widget.onSuccess?.call(); // Simple callback
|
|
} catch (e) {
|
|
ApiException.showError(context, e); // Error without closing
|
|
}
|
|
}
|
|
```
|
|
|
|
### Multi-Role Permission System
|
|
|
|
#### **Role Hierarchy**
|
|
- **Role 1** (Membre): Field operations, distribution tracking
|
|
- **Role 2** (Admin Amicale): Organization management, member administration
|
|
- **Role 3+** (Super Admin): Global system administration
|
|
|
|
#### **Permission Checks**
|
|
```dart
|
|
final currentUser = CurrentUserService.instance;
|
|
if (currentUser.canAccessAdmin) {
|
|
// Show admin features
|
|
}
|
|
if (currentUser.isSuperAdmin) {
|
|
// Show super admin features
|
|
}
|
|
```
|
|
|
|
### Code Generation Requirements
|
|
|
|
#### **Hive Adapters**
|
|
Models require code generation for Hive serialization:
|
|
```bash
|
|
flutter packages pub run build_runner build
|
|
```
|
|
|
|
Run this after modifying any `@HiveType` models in `lib/core/data/models/`.
|
|
|
|
#### **Model Structure**
|
|
```dart
|
|
@HiveType(typeId: X)
|
|
class MyModel extends HiveObject {
|
|
@HiveField(0)
|
|
final int id;
|
|
|
|
@HiveField(1)
|
|
final String name;
|
|
}
|
|
```
|
|
|
|
### Development Workflow
|
|
|
|
#### **Working with Repositories**
|
|
1. Always inject repositories via constructor or global instances from `app.dart`
|
|
2. Use `try/catch` blocks for all repository calls
|
|
3. Show loading states during async operations
|
|
4. Handle errors with `ApiException.showError()`
|
|
5. Implement Hive box caching to avoid repeated access checks during high-frequency operations
|
|
|
|
#### **Adding New Features**
|
|
1. Create/modify models in `lib/core/data/models/`
|
|
2. Run `build_runner` to generate Hive adapters
|
|
3. Add repository methods in `lib/core/repositories/`
|
|
4. Create UI widgets in `lib/presentation/widgets/`
|
|
5. Wire up with `ValueListenableBuilder` for reactivity
|
|
|
|
#### **Testing Strategy**
|
|
- Unit tests for repositories and services
|
|
- Widget tests for UI components
|
|
- Integration tests for complete user flows
|
|
- Use `flutter test` for running tests
|
|
|
|
### Environment Configuration
|
|
|
|
#### **Auto-Detection**
|
|
The app automatically detects environment based on URL:
|
|
- `dapp.geosector.fr` → DEV environment
|
|
- `rapp.geosector.fr` → REC environment
|
|
- Production → PROD environment
|
|
- Non-web platforms → DEV by default
|
|
|
|
#### **API Configuration**
|
|
Environment-specific API endpoints are configured in `ApiService` automatically.
|
|
|
|
### Common Patterns to Follow
|
|
|
|
#### **Repository Method Pattern**
|
|
```dart
|
|
Future<bool> updateUser(UserModel user) async {
|
|
try {
|
|
final response = await ApiService.instance.put('/users/${user.id}', user.toJson());
|
|
final updatedUser = UserModel.fromJson(response.data);
|
|
await _saveUserToHive(updatedUser);
|
|
return true;
|
|
} catch (e) {
|
|
throw ApiException.fromDioException(e);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### **Hive Box Caching Pattern**
|
|
```dart
|
|
class MyRepository {
|
|
// Cache de la box pour éviter les vérifications répétées
|
|
Box<MyModel>? _cachedBox;
|
|
|
|
// Getter lazy pour n'accéder à la boîte que lorsque nécessaire
|
|
Box<MyModel> get _myBox {
|
|
if (_cachedBox == null) {
|
|
if (!Hive.isBoxOpen(AppKeys.myBoxName)) {
|
|
throw Exception('La boîte n\'est pas ouverte');
|
|
}
|
|
_cachedBox = Hive.box<MyModel>(AppKeys.myBoxName);
|
|
}
|
|
return _cachedBox!;
|
|
}
|
|
|
|
// Méthode pour réinitialiser le cache après modification
|
|
void _resetCache() {
|
|
_cachedBox = null;
|
|
}
|
|
|
|
// Sauvegarder avec réinitialisation du cache
|
|
Future<void> saveItem(MyModel item) async {
|
|
await _myBox.put(item.id, item);
|
|
_resetCache(); // Crucial pour ValueListenableBuilder
|
|
notifyListeners();
|
|
}
|
|
}
|
|
```
|
|
|
|
#### **Widget Error Handling**
|
|
```dart
|
|
Future<void> _handleSave() async {
|
|
try {
|
|
setState(() => _isLoading = true);
|
|
await repository.saveData(data);
|
|
ApiException.showSuccess(context, "Saved successfully");
|
|
} catch (e) {
|
|
ApiException.showError(context, e);
|
|
} finally {
|
|
setState(() => _isLoading = false);
|
|
}
|
|
}
|
|
```
|
|
|
|
#### **ValueListenableBuilder Usage**
|
|
```dart
|
|
ValueListenableBuilder<Box<ModelType>>(
|
|
valueListenable: repository.getBox().listenable(),
|
|
builder: (context, box, child) {
|
|
final items = box.values.where((item) => filterCondition).toList();
|
|
return ListView.builder(
|
|
itemCount: items.length,
|
|
itemBuilder: (context, index) => ItemWidget(item: items[index]),
|
|
);
|
|
},
|
|
)
|
|
```
|
|
|
|
### Hive Box Performance Management
|
|
|
|
#### **Box Caching Strategy**
|
|
|
|
Repositories implement a caching pattern to optimize Hive box access and prevent performance issues during high-frequency operations:
|
|
|
|
**Problems Solved:**
|
|
- Eliminates repeated `Hive.isBoxOpen()` checks (up to 848 checks per page load)
|
|
- Improves performance during list rendering and filtering operations
|
|
- Maintains thread-safe access to Hive boxes
|
|
|
|
**Implementation Pattern:**
|
|
```dart
|
|
class ExampleRepository {
|
|
// Private cached box reference
|
|
Box<ExampleModel>? _cachedBox;
|
|
|
|
// Lazy getter with caching
|
|
Box<ExampleModel> get _exampleBox {
|
|
if (_cachedBox == null) {
|
|
if (!Hive.isBoxOpen(AppKeys.exampleBoxName)) {
|
|
throw Exception('Box not open: ${AppKeys.exampleBoxName}');
|
|
}
|
|
_cachedBox = Hive.box<ExampleModel>(AppKeys.exampleBoxName);
|
|
debugPrint('Repository: Box ${AppKeys.exampleBoxName} cached');
|
|
}
|
|
return _cachedBox!;
|
|
}
|
|
|
|
// Cache reset for ValueListenableBuilder notifications
|
|
void _resetCache() {
|
|
_cachedBox = null;
|
|
}
|
|
}
|
|
```
|
|
|
|
#### **When to Reset Cache**
|
|
|
|
Cache reset is **essential** after any database modification to ensure ValueListenableBuilder and other Hive listeners detect changes:
|
|
|
|
```dart
|
|
// REQUIRED: After individual saves
|
|
Future<void> saveItem(ExampleModel item) async {
|
|
await _exampleBox.put(item.id, item);
|
|
_resetCache(); // ← Essential for UI reactivity
|
|
notifyListeners();
|
|
}
|
|
|
|
// REQUIRED: After deletions
|
|
Future<void> deleteItem(int id) async {
|
|
await _exampleBox.delete(id);
|
|
_resetCache(); // ← Essential for UI reactivity
|
|
notifyListeners();
|
|
}
|
|
|
|
// REQUIRED: After bulk operations
|
|
Future<void> clearAll() async {
|
|
await _exampleBox.clear();
|
|
_resetCache(); // ← Essential for UI reactivity
|
|
notifyListeners();
|
|
}
|
|
|
|
// REQUIRED: After API data processing
|
|
Future<void> processApiData(List<dynamic> data) async {
|
|
await _exampleBox.clear();
|
|
for (final item in data) {
|
|
await _exampleBox.put(item.id, ExampleModel.fromJson(item));
|
|
}
|
|
_resetCache(); // ← Essential for UI reactivity
|
|
notifyListeners();
|
|
}
|
|
```
|
|
|
|
#### **Performance Impact**
|
|
|
|
| Scenario | Without Caching | With Caching |
|
|
|----------|-----------------|--------------|
|
|
| Loading 848 passages | 848 box checks | 1 box access |
|
|
| List filtering | Check per item | Cached access |
|
|
| ValueListenableBuilder | Repeated verification | Optimized access |
|
|
| Memory usage | Minimal overhead | Negligible cache |
|
|
|
|
#### **Best Practices**
|
|
|
|
1. **Always cache** in repositories that handle frequently accessed data
|
|
2. **Always reset cache** after any modification operation
|
|
3. **Use lazy getters** to avoid unnecessary box access
|
|
4. **Include debug prints** to monitor caching behavior during development
|
|
5. **Apply pattern consistently** across all repositories for maintainability
|
|
|
|
This architecture ensures type safety, reactivity, offline capability, and maintainable code structure across the entire application. |