# 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
