feat: Drag-and-Drop-Reihenfolge, Station-Abschluss-Flow und UI-Verbesserungen

Lieferstationen-Dialog (Backend/Vaadin):
- Aufgaben per Drag & Drop neu anordnen, inkl. Drag-Handle, komprimierter
  Kachelansicht während des Drags und horizontaler Einfügelinie als Drop-Target
- Drop-Indikator wird unterdrückt, wenn der Drop keine Positionsänderung bewirken
  würde, und nach dem Abschluss clientseitig zuverlässig aufgeräumt
- Drag-Handle, Aufgabentyp-Label und Close-Button auf einheitlicher Position
  ausgerichtet; Abstände in der Kachel komprimiert

Station-Abschluss-Flow (Flutter-App + Backend):
- Neuer Button "Station abschließen" unter den Aufgaben; deaktiviert, solange
  Pflichtaufgaben offen sind, ansonsten aktiv (auch wenn nur optionale Aufgaben
  existieren)
- Hinweisdialog nach Erledigung der letzten Pflichtaufgabe sowie Warnung bei
  offenen optionalen Aufgaben vor dem Senden
- Neue station_completed-Nachricht (jobId, jobNumber, stationOrder,
  completedAt, hasIncompleteOptionalTasks) wird an den Server gesendet
- Backend: Auftrag wird nicht mehr automatisch beim Erledigen der letzten
  Pflichtaufgabe abgeschlossen, sondern erst beim Empfang der
  station_completed-Nachricht (neuer Handler in MessageController und
  MessagingConfig)

Aufgabenliste in der App:
- Farbcodierung optionaler Aufgaben entfernt; stattdessen vertikal zentrierter
  "Optional"-Chip am rechten Kartenrand

Weitere UI-Überarbeitungen über Login, Jobs, Chats, Settings, Aufgaben-Capture-
Screens, Offline-Banner und zugehörige Widgets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-13 11:26:30 +02:00
parent 1ac755bcbd
commit 6e8bedd9b4
19 changed files with 1458 additions and 548 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'app_theme.dart';
import 'l10n/app_localizations.dart';
import 'l10n/localization_helpers.dart';
import 'models/delivery_station.dart';
@@ -20,7 +21,7 @@ Color? deliveryStationCardBackgroundColor(
final isCompleted = station.tasks.every(
(task) => taskStatuses[task.id] ?? task.completed,
);
return isCompleted ? Colors.green[50] : null;
return isCompleted ? AppColors.successSoft : null;
}
class CargoItemsView extends StatefulWidget {
@@ -57,7 +58,6 @@ class _CargoItemsViewState extends State<CargoItemsView> {
return Scaffold(
appBar: AppBar(
title: Text(widget.job.jobNumber),
backgroundColor: Colors.deepPurple[100],
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
@@ -139,7 +139,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
Icon(
Icons.arrow_downward,
size: 16,
color: Colors.blue[600],
color: AppColors.primary,
),
const SizedBox(width: 4),
Text(
@@ -163,7 +163,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
Icon(
Icons.local_shipping_outlined,
size: 24,
color: Colors.deepPurple[600],
color: AppColors.primary,
),
const SizedBox(width: 8),
Text(
@@ -313,7 +313,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
vertical: 4,
),
decoration: BoxDecoration(
color: Colors.deepPurple[100],
color: AppColors.primarySoft,
borderRadius: BorderRadius.circular(12),
),
child: Text(
@@ -321,7 +321,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.deepPurple[700],
color: AppColors.primaryStrong,
),
),
),
@@ -359,7 +359,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
Icons.location_on_outlined,
AppLocalizations.of(context).location,
addressLines.join('\n'),
Colors.blue,
AppColors.primary,
),
if (station.phone.trim().isNotEmpty) ...[
const SizedBox(height: 12),
@@ -367,7 +367,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
Icons.phone_outlined,
l10n.phone,
station.phone,
Colors.green,
AppColors.success,
),
],
if (station.deliveryDate.trim().isNotEmpty ||
@@ -380,7 +380,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
station.deliveryDate,
station.deliveryTime,
].where((part) => part.trim().isNotEmpty).join(' '),
Colors.orange,
AppColors.warning,
),
],
const SizedBox(height: 12),
@@ -388,7 +388,7 @@ class _CargoItemsViewState extends State<CargoItemsView> {
Icons.task_alt,
AppLocalizations.of(context).tasks,
'${station.tasks.length}',
Colors.deepPurple,
AppColors.primaryStrong,
),
],
),