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:
@@ -4,6 +4,7 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image/image.dart' as img;
|
||||
import 'app_theme.dart';
|
||||
import 'l10n/app_localizations.dart';
|
||||
import 'l10n/localization_helpers.dart';
|
||||
import 'app_state.dart';
|
||||
@@ -257,13 +258,12 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
'Job-Nr: ${_activeChat.jobNumber}',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
color: AppColors.textMuted,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
backgroundColor: Colors.deepPurple[100],
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(isJobChat ? Icons.work : Icons.support_agent),
|
||||
@@ -281,7 +281,7 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
// Messages list
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(color: Colors.grey[50]),
|
||||
decoration: const BoxDecoration(color: AppColors.surfaceMuted),
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.fromLTRB(8, 8, 8, 96),
|
||||
@@ -325,7 +325,7 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
vertical: isImage ? 6 : 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: isOwn ? Colors.deepPurple[100] : Colors.white,
|
||||
color: isOwn ? AppColors.primarySoft : AppColors.surface,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: const Radius.circular(12),
|
||||
topRight: const Radius.circular(12),
|
||||
@@ -351,7 +351,10 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
children: [
|
||||
Text(
|
||||
_formatMessageTime(message.createdAt),
|
||||
style: TextStyle(fontSize: 11, color: Colors.grey[600]),
|
||||
style: const TextStyle(
|
||||
fontSize: 11,
|
||||
color: AppColors.textMuted,
|
||||
),
|
||||
),
|
||||
if (isOwn) ...[
|
||||
const SizedBox(width: 4),
|
||||
@@ -362,10 +365,10 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
size: 14,
|
||||
color:
|
||||
message.pendingSync
|
||||
? Colors.orange[700]
|
||||
? AppColors.warning
|
||||
: (message.read
|
||||
? Colors.deepPurple[400]
|
||||
: Colors.grey[600]),
|
||||
? AppColors.primary
|
||||
: AppColors.textMuted),
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -384,7 +387,7 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
if (!isImage) {
|
||||
return Text(
|
||||
message.content,
|
||||
style: TextStyle(fontSize: 15, color: Colors.grey[800]),
|
||||
style: const TextStyle(fontSize: 15, color: AppColors.textStrong),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -455,8 +458,8 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(top: BorderSide(color: Colors.grey[300]!)),
|
||||
color: AppColors.surface,
|
||||
border: const Border(top: BorderSide(color: AppColors.border)),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Row(
|
||||
@@ -466,12 +469,12 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[200],
|
||||
color: AppColors.surfaceMuted,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.attach_file,
|
||||
color: Colors.black87,
|
||||
color: AppColors.text,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
@@ -480,7 +483,7 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey[100],
|
||||
color: AppColors.surfaceMuted,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: TextField(
|
||||
@@ -508,7 +511,7 @@ class _ChatDetailsViewState extends State<ChatDetailsView> {
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.deepPurple,
|
||||
color: AppColors.primary,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: const Icon(Icons.send, color: Colors.white, size: 20),
|
||||
|
||||
Reference in New Issue
Block a user