- Configuration complète Stripe pour les 3 environnements (DEV/REC/PROD) * DEV: Clés TEST Pierre (mode test) * REC: Clés TEST Client (mode test) * PROD: Clés LIVE Client (mode live) - Ajout de la gestion des bases de données immeubles/bâtiments * Configuration buildings_database pour DEV/REC/PROD * Service BuildingService pour enrichissement des adresses - Optimisations pages et améliorations ergonomie - Mises à jour des dépendances Composer - Nettoyage des fichiers obsolètes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
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 :
- Analyser la demande
- Proposer une solution détaillée
- Lister les fichiers qui seront modifiés
- Attendre la validation
- 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 handlingCurrentUserService- User session and authentication stateCurrentAmicaleService- Current organization contextDataLoadingService- Orchestrates API data synchronization to Hive
Repository Pattern (lib/core/repositories/)
UserRepository- User management and authenticationOperationRepository- Operations and campaignsMembreRepository- Team member managementPassageRepository- Distribution trackingSectorRepository- Geographic sectorsAmicaleRepository- Organization management
Reactive UI Pattern
Uses ValueListenableBuilder with Hive boxes for automatic UI updates:
ValueListenableBuilder<Box<UserModel>>(
valueListenable: userRepository.getUsersBox().listenable(),
builder: (context, box, child) {
// UI automatically updates when data changes
},
)
Data Flow Architecture
"API First" Principle
- UI action triggers repository method
- Repository attempts API call first
- On success → Save to Hive → UI auto-updates via ValueListenableBuilder
- 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
ApiExceptionclass extracts meaningful error messages from API responsesshowError()andshowSuccess()methods provide consistent user feedback- Repository methods propagate exceptions to UI layer for handling
Error Flow Pattern
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
// 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
ValueListenableBuilderdirectly with Hive boxes - Singleton services maintain global state
ChangeNotifieronly for specific repository loading states
Dialog Auto-Management Pattern
Dialogs handle their own submission and closing:
// 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
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:
flutter packages pub run build_runner build
Run this after modifying any @HiveType models in lib/core/data/models/.
Model Structure
@HiveType(typeId: X)
class MyModel extends HiveObject {
@HiveField(0)
final int id;
@HiveField(1)
final String name;
}
Development Workflow
Working with Repositories
- Always inject repositories via constructor or global instances from
app.dart - Use
try/catchblocks for all repository calls - Show loading states during async operations
- Handle errors with
ApiException.showError() - Implement Hive box caching to avoid repeated access checks during high-frequency operations
Adding New Features
- Create/modify models in
lib/core/data/models/ - Run
build_runnerto generate Hive adapters - Add repository methods in
lib/core/repositories/ - Create UI widgets in
lib/presentation/widgets/ - Wire up with
ValueListenableBuilderfor reactivity
Testing Strategy
- Unit tests for repositories and services
- Widget tests for UI components
- Integration tests for complete user flows
- Use
flutter testfor running tests
Environment Configuration
Auto-Detection
The app automatically detects environment based on URL:
dapp.geosector.fr→ DEV environmentrapp.geosector.fr→ REC environmentapp3.geosector.fr→ 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
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
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
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
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:
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:
// 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
- Always cache in repositories that handle frequently accessed data
- Always reset cache after any modification operation
- Use lazy getters to avoid unnecessary box access
- Include debug prints to monitor caching behavior during development
- Apply pattern consistently across all repositories for maintainability
This architecture ensures type safety, reactivity, offline capability, and maintainable code structure across the entire application.