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:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'l10n/app_localizations.dart';
|
||||
import 'app_state.dart';
|
||||
import 'app_theme.dart';
|
||||
|
||||
/// Supported languages with their display names and flag emojis
|
||||
class LanguageOption {
|
||||
@@ -36,17 +37,17 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
setState(() {
|
||||
_selectedLanguageCode = languageCode;
|
||||
});
|
||||
|
||||
|
||||
// Save language preference
|
||||
await _appState.setLanguage(languageCode);
|
||||
|
||||
|
||||
// Show confirmation snackbar
|
||||
_showLanguageChangedSnackBar(languageCode);
|
||||
}
|
||||
|
||||
void _showLanguageChangedSnackBar(String languageCode) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
|
||||
|
||||
// Get the language name from the corresponding localization
|
||||
String languageName;
|
||||
String flagEmoji;
|
||||
@@ -98,11 +99,9 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'${l10n.languageChanged}: $flagEmoji $languageName',
|
||||
),
|
||||
content: Text('${l10n.languageChanged}: $flagEmoji $languageName'),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.green,
|
||||
backgroundColor: AppColors.success,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -129,10 +128,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
final languageOptions = _getLanguageOptions();
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(l10n.settings),
|
||||
backgroundColor: Colors.deepPurple[100],
|
||||
),
|
||||
appBar: AppBar(title: Text(l10n.settings)),
|
||||
body: ListView(
|
||||
children: [
|
||||
// Language Selection Section
|
||||
@@ -143,7 +139,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
color: AppColors.textMuted,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
@@ -160,7 +156,7 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
color: AppColors.surfaceMuted,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Center(
|
||||
@@ -173,22 +169,27 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
title: Text(
|
||||
language.name,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
color: isSelected ? Colors.deepPurple : Colors.black87,
|
||||
fontWeight:
|
||||
isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
color:
|
||||
isSelected
|
||||
? AppColors.primaryStrong
|
||||
: AppColors.textStrong,
|
||||
),
|
||||
),
|
||||
trailing: isSelected
|
||||
? const Icon(
|
||||
Icons.check_circle,
|
||||
color: Colors.deepPurple,
|
||||
)
|
||||
: const Icon(
|
||||
Icons.circle_outlined,
|
||||
color: Colors.grey,
|
||||
),
|
||||
trailing:
|
||||
isSelected
|
||||
? const Icon(
|
||||
Icons.check_circle,
|
||||
color: AppColors.primary,
|
||||
)
|
||||
: const Icon(
|
||||
Icons.circle_outlined,
|
||||
color: AppColors.textMuted,
|
||||
),
|
||||
onTap: () => _onLanguageSelected(language.code),
|
||||
selected: isSelected,
|
||||
selectedTileColor: Colors.deepPurple.withValues(alpha: 0.05),
|
||||
selectedTileColor: AppColors.primarySoft,
|
||||
),
|
||||
const Divider(height: 1, indent: 72),
|
||||
],
|
||||
@@ -203,17 +204,14 @@ class _SettingsViewState extends State<SettingsView> {
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey,
|
||||
color: AppColors.textMuted,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(height: 1),
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.info_outline,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
leading: Icon(Icons.info_outline, color: AppColors.textMuted),
|
||||
title: Text(l10n.version),
|
||||
subtitle: const Text('0.9.2'),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user