refactor: Projektstruktur in app/ und backend/ aufgeteilt

This commit is contained in:
2026-03-24 15:06:44 +01:00
parent 5f5d5995c5
commit 2673ef658d
449 changed files with 28551 additions and 167 deletions

429
app/AGENTS.md Normal file
View File

@@ -0,0 +1,429 @@
# Votian LT App - Agent Guidelines
## Project Overview
**Votian LT** is a Flutter-based mobile application for logistics and transport management. The app enables drivers to manage transport jobs, complete tasks (photos, signatures, barcodes), communicate via real-time chat, and navigate to pickup/delivery locations.
### Key Features
- **Job Management**: View and manage assigned transport jobs with cargo items
- **Task System**: Complete various task types (confirmation, photo capture, signature, barcode scanning, todo lists, comments)
- **Real-time Chat**: Job-specific and general chat via WebSocket
- **Offline Support**: Full offline functionality with local ObjectBox database
- **Navigation**: Integration with external maps and embedded WebView routing
- **Push Notifications**: Local notifications for new jobs and messages
- **Implementation**: When making changes, be careful not to damage existing functionalities.
---
## Technology Stack
| Layer | Technology |
|-------|------------|
| Framework | Flutter 3.7+ with Dart |
| State Management | Singleton pattern + Custom DartMQ pub/sub |
| Local Database | ObjectBox (NoSQL) |
| Real-time Communication | WebSocket (STOMP-style protocol) |
| Backend Integration | WebSocket to `ws://localhost:8082/ws/messaging` |
| UI Design | Material Design 3 |
### Key Dependencies (pubspec.yaml)
- `web_socket_channel: ^3.0.0` - WebSocket client
- `objectbox: ^4.0.3` + `objectbox_flutter_libs` - Local database
- `camera: ^0.10.5+9` - Photo capture
- `mobile_scanner: ^5.0.0` - Barcode scanning
- `signature: ^5.5.0` - Signature capture canvas
- `flutter_local_notifications: ^18.0.0` - Local notifications
- `url_launcher: ^6.3.0` - External navigation
- `webview_flutter: ^4.8.0` - Embedded maps
- `image: ^4.2.0` - Image processing
- `package_info_plus: ^8.0.0` - App version info
---
## Project Structure
```
lib/
├── main.dart # App entry point, MaterialApp setup
├── app_state.dart # Global app state singleton (jobs, login)
├── navigation_observer.dart # Route observer for analytics
├── routing_view.dart # Embedded navigation WebView
├── models/ # Domain models (JSON serializable)
│ ├── job.dart # Transport job with cargo items and tasks
│ ├── cargo_item.dart # Cargo/load items
│ ├── task.dart # Abstract task base class
│ ├── tasks/ # Concrete task implementations
│ │ ├── confirmation_task.dart
│ │ ├── photo_task.dart
│ │ ├── signature_task.dart
│ │ ├── barcode_task.dart
│ │ ├── todolist_task.dart
│ │ ├── comment_task.dart
│ │ └── generic_task.dart
│ ├── chat.dart # Chat conversation
│ ├── chat_message.dart # Individual message
│ ├── message_envelope.dart # WebSocket message wrapper
│ ├── acknowledgment_message.dart
│ └── queued_message.dart # Offline message queue
├── entities/ # ObjectBox database entities
│ ├── job_entity.dart
│ ├── task_status_entity.dart
│ ├── user_data_entity.dart
│ ├── photo_entity.dart
│ ├── queued_message_entity.dart
│ └── chat_message_entity.dart
├── services/ # Business logic services (singletons)
│ ├── websocket_service.dart # WebSocket connection & messaging
│ ├── database_service.dart # ObjectBox database operations
│ ├── chat_service.dart # Chat management
│ ├── dart_mq.dart # In-app pub/sub message bus
│ ├── notification_service.dart # Local notifications
│ ├── message_handler.dart # Incoming message processing
│ ├── ack_tracker.dart # Message acknowledgment tracking
│ └── developer.dart # Developer utilities/logging
├── views/ # Main UI screens
│ ├── login_view.dart # Authentication screen
│ ├── jobs_view.dart # Job list screen
│ ├── cargo_items_view.dart # Cargo details for a job
│ ├── chats_view.dart # Chat list screen
│ ├── chat_details_view.dart # Individual chat conversation
│ └── task_view.dart # Task completion screen
├── tasks/ # Task-specific UI screens
│ ├── photo_capture_screen.dart
│ ├── signature_capture_screen.dart
│ └── barcode_capture_screen.dart
└── widgets/ # Reusable UI components
├── chat_photo_dialog.dart
└── offline_banner.dart
test/ # Unit and widget tests
├── models/
│ ├── job_parsing_test.dart
│ ├── message_envelope_test.dart
│ └── acknowledgment_message_test.dart
└── services/
├── ack_tracker_test.dart
├── message_handler_test.dart
└── mqtt_integration_test.dart
android/, ios/, macos/, linux/, windows/ # Platform-specific code
```
---
## Build, Test, and Development Commands
### Setup
```bash
# Install dependencies
flutter pub get
# Generate ObjectBox code (after entity changes)
flutter pub run build_runner build
```
### Development
```bash
# Run static analysis
flutter analyze
# Format code (CI expects formatted code)
dart format lib/ test/
# Run the app
flutter run
# Run on specific device
flutter run -d <device_id>
```
### Testing
```bash
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Run specific test file
flutter test test/models/job_parsing_test.dart
```
---
## Architecture Patterns
### Singleton Services
All major services use the singleton pattern for app-wide state:
```dart
// Accessing services
final appState = AppState();
final chatService = ChatService();
final wsService = WebSocketService();
final dbService = DatabaseService();
```
### DartMQ Pub/Sub
Custom lightweight message bus for decoupled communication:
```dart
// Subscribe to topics
final sub = DartMQ().subscribe<Map<String, dynamic>>(
MQTopics.authResponse,
(data) => handleAuth(data),
);
// Publish messages
DartMQ().publish<bool>(MQTopics.connectionStatus, true);
// Cleanup
sub.cancel();
```
**Common Topics** (`lib/services/dart_mq.dart`):
- `connection/status` - WebSocket connection state (bool)
- `auth/response` - Authentication responses (Map)
- `jobs/response` - Job list updates (List)
- `jobsUpdated` - Job data changed notification (void)
- `job/deleted` - Job deletion event (Map)
- `job/created` - New job created (Map)
- `chat/incoming` - New chat message (ChatMessage)
### Task System
Tasks are polymorphic based on `taskType` field:
| Task Type | Description |
|-----------|-------------|
| `CONFIRMATION` | Button tap confirmation |
| `PHOTO` | Capture photos (min/max count) |
| `SIGNATURE` | Capture signature as SVG |
| `BARCODE` | Scan barcodes/QR codes |
| `TODOLIST` | Checklist of items |
| `COMMENT` | Text input field |
| `GENERIC` | Fallback type |
---
## Coding Style Guidelines
### Dart/Flutter Conventions
- **Indentation**: 2 spaces
- **Trailing Commas**: Use trailing commas to encourage proper auto-formatting
- **Naming**:
- Classes: `UpperCamelCase`
- Methods/variables: `lowerCamelCase`
- Private members: `_leadingUnderscore`
- Constants: `camelCase` or `UPPER_SNAKE_CASE` for static const
### Code Style Examples
```dart
// Good: trailing commas for multi-line
final job = Job(
id: '123',
jobNumber: 'JOB-001',
status: 'ASSIGNED',
// ...
);
// Good: private helper methods
String _formatAddress(String street, String city) {
return '$street, $city';
}
// Good: type annotations for public APIs
Future<List<Job>> loadJobs() async {
// ...
}
```
### Imports
- Order: Dart SDK → Flutter → Third-party → Project (alphabetical within groups)
- Use `package:votianlt_app/` prefix for project imports
---
## Testing Guidelines
### Test Structure
```dart
import 'package:flutter_test/flutter_test.dart';
import 'package:votianlt_app/models/job.dart';
void main() {
group('Job Parsing', () {
test('parses basic fields correctly', () {
// Arrange
final json = {'job': {'id': '123', ...}};
// Act
final job = Job.fromJson(json);
// Assert
expect(job.id, '123');
});
});
}
```
### Testing Patterns
- Mirror the `lib/` directory structure in `test/`
- Name tests after the unit: `job_parsing_test.dart`
- Use `group()` for related assertions
- Test both success and edge cases
- Test round-trip serialization (`fromJson``toJson``fromJson`)
### Mocking
Use `mocktail` for mocking dependencies in service tests.
---
## Database (ObjectBox)
### Entity Definition Example
```dart
@Entity()
class JobEntity {
@Id()
int id = 0;
@Unique()
String jobId;
String jobData; // JSON-encoded
@Property(type: PropertyType.date)
DateTime createdAt;
@Property(type: PropertyType.date)
DateTime updatedAt;
JobEntity({...});
}
```
### Regenerating Code
After modifying entities in `lib/entities/`:
```bash
flutter pub run build_runner build
```
This generates `lib/objectbox.g.dart`.
---
## WebSocket Protocol
### Connection
- URL: `ws://localhost:8082/ws/messaging` (desktop)
- Android Emulator: `ws://10.0.2.2:8082/ws/messaging`
### Message Format
```json
{
"topic": "/client/auth",
"payload": { ... }
}
```
### Client → Server Topics
- `/server/login` - Authentication
- `/server/jobs/assigned` - Request job list
- `/server/message` - Send chat message
- `/server/task_completed` - Mark task complete
### Server → Client Topics
- `/client/{userId}/auth` - Auth response
- `/client/{userId}/jobs` - Job list
- `/client/{userId}/message` - Incoming chat
- `/client/{userId}/job_deleted` - Job deleted
- `/client/{userId}/job_created` - New job
---
## Security Considerations
### Credentials
- Email/password stored in ObjectBox (encrypted at rest by OS)
- Credentials cleared on logout
- Auto-login with saved credentials
### WebSocket
- Reconnection with 15-second interval
- Message buffering when offline
- Unique App ID per installation for client identification
### Secrets
- Do not commit API keys or credentials
- Server endpoint configurable in `WebSocketService._buildWebSocketUrl()`
---
## Platform-Specific Notes
### Android
- Minimum SDK: Defined in `android/app/build.gradle`
- Permissions in `AndroidManifest.xml`:
- `INTERNET` - WebSocket communication
- `CAMERA` - Photo/barcode capture
- `WRITE_EXTERNAL_STORAGE` - Photo storage
- `POST_NOTIFICATIONS` - Push notifications
- `VIBRATE` - Notification vibration
### iOS
- Camera and photo permissions in `ios/Runner/Info.plist`
- Notification permissions configured
---
## Common Development Tasks
### Adding a New Task Type
1. Create model in `lib/models/tasks/new_task_type.dart`
2. Add to `Task.fromJson()` factory in `lib/models/task.dart`
3. Add UI screen in `lib/tasks/` if needed
4. Update `task_view.dart` to handle the new type
5. Add tests in `test/models/`
### Adding a New Database Entity
1. Create entity class in `lib/entities/`
2. Run `flutter pub run build_runner build`
3. Add CRUD operations in `DatabaseService`
### Modifying WebSocket Messages
1. Update message handler in `WebSocketService._handleMessage()`
2. Add topic constant to `MQTopics` if needed
3. Update `MessageHandler` for processing logic
---
## Localization
The app uses German for UI text:
- Job status: "Erstellt", "Zugewiesen", "In Bearbeitung", "Abgeschlossen"
- Notifications: "Neue Jobs", "Neue Nachricht"
- Chat: "Allgemeine Nachrichten"
---
## Debugging
### Logging
Use the developer log utility:
```dart
import 'package:votianlt_app/services/developer.dart' as developer;
developer.log('Debug message', name: 'ComponentName');
```
### Common Issues
1. **WebSocket not connecting**: Check server is running on port 8082
2. **Database errors**: Run `flutter clean` and `flutter pub get`
3. **ObjectBox issues**: Regenerate with `build_runner`
4. **Camera not working**: Check platform permissions