import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hl_lieferservice/domain/entity/delivery.dart'; import 'package:hl_lieferservice/domain/entity/delivery_item.dart'; import 'package:hl_lieferservice/domain/entity/tour_details.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_bloc.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_state.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/phase_bloc.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/phase_event.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart'; import 'package:hl_lieferservice/feature/delivery/model/delivery_phase.dart'; import 'package:hl_lieferservice/feature/delivery/overview/presentation/delivery_fail_page.dart'; import 'package:hl_lieferservice/feature/loading/presentation/loading_customer_page.dart'; import 'package:hl_lieferservice/widget/home/presentation/home_drawer.dart'; import 'package:hl_lieferservice/widget/phase_stepper/phase_stepper.dart'; /// Übersichts-Ansicht für die Beladen-Phase: alle Kunden mit ihren /// Artikeln und Soll/Ist-Mengen. /// /// Scans werden in der `LoadingCustomerPage` (Vollbild pro Kunde) /// ausgelöst; diese Übersicht ist reines Status-Display und Navigation. /// Der Button „Auslieferungs-Phase starten" unten erlaubt dem Fahrer, /// jederzeit in die nächste Phase zu wechseln — die App erzwingt /// bewusst keine 100%-Auslieferung (z. B. wenn ein Artikel fehlt und /// der Fahrer das später hold/cancel-en will). class LoadingOverviewPage extends StatelessWidget { const LoadingOverviewPage({super.key}); String? _plateFor(BuildContext context, String? carId) { if (carId == null) return null; final state = context.read().state; if (state is! CarsLoaded) return null; for (final c in state.cars) { if (c.id == carId) return c.plate; } return null; } /// Beladereihenfolge = umgekehrte Sortier-Reihenfolge: wer zuletzt /// ausgeliefert wird, wird zuerst beladen (kommt unten in den LKW). List _ownDeliveriesInLoadingOrder( TourDetails details, String carId, bool multiCarTeam, ) { final relevant = multiCarTeam ? details.deliveriesSorted .where((d) => d.assignedCarId == carId) .toList() : details.deliveriesSorted; return relevant.reversed.toList(); } @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, carState) { final carId = carState is CarSelectComplete ? carState.selectedCar.id : ''; return BlocBuilder( builder: (context, tourState) { if (tourState is TourLoadFailed) { return const DeliveryLoadingFailedPage(); } if (tourState is TourEmpty) { return Scaffold( drawer: const HomeAppDrawer(), appBar: AppBar(title: const Text('Beladung')), body: const _EmptyOverview(), ); } if (tourState is! TourLoaded) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } final carsState = context.read().state; final multiCarTeam = carsState is CarsLoaded && carsState.cars.length >= 2; final ordered = _ownDeliveriesInLoadingOrder( tourState.details, carId, multiCarTeam, ); // Gate für „Auslieferungs-Phase starten": jede aktive Lieferung // muss im Standardlager fertig beladen sein. Pausierte/abgebrochene // zählen nicht; offene Filial-Items dürfen bleiben (werden unterwegs // geholt — siehe Status-Logik). Keine aktive Lieferung ⇒ kein Block. final canStart = ordered .where((d) => d.state == DeliveryState.active) .every(tourState.details.standardWarehouseLoadingDone); return Scaffold( drawer: const HomeAppDrawer(), appBar: PreferredSize( preferredSize: const Size.fromHeight(140), child: PhaseStepper( currentPhase: DeliveryPhase.beladen, carId: carId, ), ), body: SafeArea( top: false, child: ordered.isEmpty ? const _EmptyOverview() : _OverviewList( deliveries: ordered, details: tourState.details, plateResolver: (id) => _plateFor(context, id), ), ), bottomNavigationBar: _BottomBar(carId: carId, canStart: canStart), ); }, ); }, ); } } class _OverviewList extends StatelessWidget { const _OverviewList({ required this.deliveries, required this.details, required this.plateResolver, }); final List deliveries; final TourDetails details; final String? Function(String?) plateResolver; /// Klassifiziert eine Lieferung in einen UX-Bucket. Bucket bestimmt, /// in welcher Sektion das Tile in der Übersicht landet. /// /// Lifecycle-Zustände (`held` / `canceled`) gewinnen vor der /// Standardlager-/Filial-Logik: eine pausierte oder abgebrochene /// Lieferung soll nicht versehentlich als „nächste Lieferung" oder /// „offen" auftauchen, auch wenn ihr Standardlager-Counter Items /// hätte. _OverviewBucket _bucketOf(Delivery delivery) { if (delivery.state == DeliveryState.canceled) { return _OverviewBucket.canceled; } if (delivery.state == DeliveryState.held) { return _OverviewBucket.paused; } final standardDone = details.standardWarehouseLoadingDone(delivery); final hasExternal = details.hasExternalWarehouseItems(delivery); if (standardDone && hasExternal) return _OverviewBucket.later; if (standardDone) return _OverviewBucket.done; return _OverviewBucket.open; } @override Widget build(BuildContext context) { // Standardlager-Items pro Lieferung — Basis für den Fortschritts- // Counter („X / Y Artikel" am Kunden). Filial-Items zählen hier // nicht; sie werden separat geladen und sollen den Fortschritt im // Hauptlager nicht verwässern. final standardItemsPerDelivery = >{}; for (final d in deliveries) { standardItemsPerDelivery[d.id] = d.items.where((it) { if (it.isRemoved) return false; if (!details.isArticleScannable(it.articleId)) return false; final w = details.warehouseOf(it.warehouseId); return w?.isStandard ?? false; }).toList(); } // Lieferungen in drei Buckets sortieren. Innerhalb der Buckets // bleibt die Belade-Reihenfolge erhalten (Original-Index), damit der // Fahrer „Kunde Nr. 3 in der Reihenfolge" jederzeit identifizieren // kann — auch wenn die Karte gerade in „Später abholen" einsortiert // ist. final open = <_OverviewEntry>[]; final later = <_OverviewEntry>[]; final paused = <_OverviewEntry>[]; final done = <_OverviewEntry>[]; final canceled = <_OverviewEntry>[]; for (int i = 0; i < deliveries.length; i++) { final d = deliveries[i]; final entry = _OverviewEntry( originalIndex: i, delivery: d, standardItems: standardItemsPerDelivery[d.id] ?? const [], ); switch (_bucketOf(d)) { case _OverviewBucket.open: open.add(entry); case _OverviewBucket.later: later.add(entry); case _OverviewBucket.paused: paused.add(entry); case _OverviewBucket.done: done.add(entry); case _OverviewBucket.canceled: canceled.add(entry); } } // „Nächste Lieferung" zieht den ersten Offen-Eintrag heraus und // präsentiert ihn in einer eigenen Sektion ganz oben — der Fahrer // sieht damit immer sofort, was als nächstes anliegt, statt aus // einer Liste die Position-Nr. 1 selbst rauszusuchen. Sobald die // Lieferung beladen ist, rutscht sie in „Später abholen" oder // „Fertig" und der Eintrag auf Position 2 wird zur neuen // „Nächsten" — automatisch, da diese Logik bei jedem Build neu // läuft. final _OverviewEntry? nextUp = open.isEmpty ? null : open.removeAt(0); final totalActive = deliveries .where((d) => d.state != DeliveryState.canceled) .length; // „Fertig beladen" = Standardlager fertig. Filial-Items // blockieren den Übergang in die Auslieferungs-Phase nicht. final doneActive = deliveries .where((d) => d.state != DeliveryState.canceled && details.standardWarehouseLoadingDone(d)) .length; return Column( children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Beladereihenfolge', style: Theme.of(context).textTheme.titleMedium, ), Text( '$doneActive / $totalActive Kunden', style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 4), // Macht den Bezugsrahmen der Phase explizit: Es wird im // Standardlager beladen. Filial-Artikel sind die Ausnahme // und werden separat geholt — sonst entsteht der Eindruck, // man müsse für jede Lieferung mehrere Lager ansteuern. Row( children: [ Icon( Icons.inventory_2_outlined, size: 14, color: Theme.of(context).colorScheme.onSurfaceVariant, ), const SizedBox(width: 4), Expanded( child: Text( 'Beladung im Standardlager · Filial-Artikel werden separat geholt', style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.onSurfaceVariant, ), ), ), ], ), const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular(4), child: LinearProgressIndicator( value: totalActive == 0 ? 0.0 : doneActive / totalActive, minHeight: 6, backgroundColor: Theme.of(context) .colorScheme .surfaceContainerHighest, ), ), ], ), ), const Divider(height: 1), Expanded( child: ListView( padding: const EdgeInsets.only(top: 4, bottom: 16), children: [ if (nextUp != null) _BucketSection( title: 'Nächste Lieferung', count: 1, color: Theme.of(context).colorScheme.primary, icon: Icons.local_shipping_outlined, entries: [nextUp], details: details, ), if (open.isNotEmpty) _BucketSection( title: 'Offen', count: open.length, color: Theme.of(context) .colorScheme .primary .withValues(alpha: 0.55), entries: open, details: details, ), if (later.isNotEmpty) _BucketSection( title: 'Später abholen', count: later.length, color: Colors.amber.shade800, entries: later, details: details, ), if (paused.isNotEmpty) _BucketSection( title: 'Pausiert', count: paused.length, color: Colors.orange.shade800, icon: Icons.pause_circle_outline, entries: paused, details: details, ), if (done.isNotEmpty) _BucketSection( title: 'Fertig', count: done.length, color: Colors.green.shade700, entries: done, details: details, ), if (canceled.isNotEmpty) _BucketSection( title: 'Abgebrochen', count: canceled.length, color: Colors.red.shade700, icon: Icons.cancel_outlined, entries: canceled, details: details, ), ], ), ), ], ); } } class _OverviewTile extends StatelessWidget { const _OverviewTile({ required this.position, required this.delivery, required this.standardItems, required this.details, required this.onTap, }); final int position; final Delivery delivery; /// Scanbare, nicht-entfernte Items aus dem Standardlager. Basis für /// den Beladen-Fortschritt — Filial-Items werden separat geladen /// und zählen hier nicht mit. final List standardItems; final TourDetails details; final VoidCallback onTap; @override Widget build(BuildContext context) { final theme = Theme.of(context); final canceled = delivery.state == DeliveryState.canceled; final held = delivery.state == DeliveryState.held; final standardDone = details.standardWarehouseLoadingDone(delivery); final hasExternal = details.hasExternalWarehouseItems(delivery); final externalLabels = details.externalWarehouseLabels(delivery); final scannedStandardCount = standardItems.where((it) => it.isDone).length; final scannedAnyStandard = standardItems.any((it) => it.scanProgress.scannedQuantity > 0); final customer = details.customerOf(delivery); Color cardColor; Color borderColor; Color titleColor; String statusText; IconData statusIcon; // Lifecycle-States gewinnen vor der Beladen-Logik: pausiert / // abgebrochen sollen visuell sofort als solche erkennbar sein — // egal wie weit der Standardlager-Counter war. if (canceled) { cardColor = Colors.red.withValues(alpha: 0.06); borderColor = Colors.red.withValues(alpha: 0.35); titleColor = Colors.red.shade700; statusText = 'Abgebrochen'; statusIcon = Icons.cancel_outlined; } else if (held) { cardColor = Colors.orange.withValues(alpha: 0.07); borderColor = Colors.orange.withValues(alpha: 0.45); titleColor = Colors.orange.shade800; statusText = 'Pausiert'; statusIcon = Icons.pause_circle_outline; } else if (standardDone && hasExternal) { // Sonderfall, fachlich wichtig: Standardlager ist durch, aber im // Filiale wartet noch was. Der Fahrer kann technisch in die // Auslieferungs-Phase, muss aber wissen, dass er zwischendurch // ein zweites Lager ansteuert. cardColor = Colors.amber.withValues(alpha: 0.18); borderColor = Colors.amber.withValues(alpha: 0.55); titleColor = Colors.amber.shade800; statusText = 'Standardlager fertig — Filiale offen'; statusIcon = Icons.warehouse_outlined; } else if (standardDone) { cardColor = Colors.green.withValues(alpha: 0.07); borderColor = Colors.green.withValues(alpha: 0.35); titleColor = Colors.green.shade700; statusText = 'Fertig beladen'; statusIcon = Icons.check_circle_outline; } else if (scannedAnyStandard) { cardColor = Colors.orange.withValues(alpha: 0.07); borderColor = Colors.orange.withValues(alpha: 0.35); titleColor = Colors.orange.shade800; statusText = 'Beladung läuft'; statusIcon = Icons.pending_outlined; } else { cardColor = theme.colorScheme.surfaceContainerLow; borderColor = Colors.transparent; titleColor = theme.colorScheme.onSurface; statusText = 'Offen'; statusIcon = Icons.radio_button_unchecked; } // Bewusst KEIN Filial-Card-Highlight, solange das Standardlager // noch offen ist: eine Lieferung mit Standard- UND Filial-Items // soll sich nicht von einer reinen Standardlager-Lieferung // unterscheiden — der Fahrer belädt zuerst das Standardlager, und eine // orange Karte würde fälschlich einen Sonderzustand suggerieren // (irreführend besonders in der „Nächste Lieferung"-Sektion). Den // Hinweis aufs Filiale trägt allein das `_ExternalWarehouseBadge` // weiter unten. Der echte Sonderfall „Standardlager fertig — Filiale // offen" wird oben in der Status-Kette eigenständig amber gefärbt. // Fortschritts-Label rechts in der Status-Zeile. // // „X / Y Artikel" bezieht sich bewusst nur auf das Standardlager (siehe // `standardItems`). Hat eine Lieferung dort GAR KEINE Position, ergäbe das // ein irreführendes „0 / 0 Artikel" — die Card sähe leer aus, obwohl die // Ware nur aus einer Filiale kommt (später abholen) oder es sich um eine // reine Dienstleistung handelt. In diesen Fällen zeigen wir statt des // Zählers einen sprechenden Hinweis. So wirkt keine Card mehr „verloren". final String progressLabel; if (canceled || held) { progressLabel = '—'; } else if (standardItems.isNotEmpty) { progressLabel = '$scannedStandardCount / ${standardItems.length} Artikel'; } else if (hasExternal) { // Keine Standardlager-Ware, aber Filial-Items → wird separat geholt. // Das Filial-Badge unten trägt die Details; hier nur der Kurz-Hinweis. progressLabel = 'Nur Filiale'; } else if (details.hasServiceItems(delivery)) { // Weder Standardlager- noch Filial-Ware, aber eine nicht-scanbare // Position → reine Dienstleistung. Rechtfertigt trotzdem die Anfahrt. progressLabel = 'Nur Dienstleistung'; } else { // Defensive: keinerlei relevante Positionen — sollte praktisch nicht // vorkommen. Kein „0 / 0", sondern neutraler Strich. progressLabel = '—'; } // Avatar-Hintergrund spiegelt den Lifecycle-State wider, damit die // Nummer-Bubble nicht weiterhin primary leuchtet, obwohl die // Lieferung pausiert/abgebrochen ist. final Color avatarColor; if (canceled) { avatarColor = Colors.red.shade700; } else if (held) { avatarColor = Colors.orange.shade800; } else { avatarColor = theme.colorScheme.primary; } final reason = delivery.stateReason; final showReason = (canceled || held) && reason != null && reason.isNotEmpty; return Opacity( opacity: canceled ? 0.65 : 1.0, child: Card( margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), elevation: 0, color: cardColor, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: borderColor), ), child: InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Padding( padding: const EdgeInsets.all(12), child: Row( children: [ CircleAvatar( backgroundColor: avatarColor, foregroundColor: theme.colorScheme.onPrimary, radius: 18, child: Text( '$position', style: const TextStyle(fontWeight: FontWeight.bold), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( customer?.name ?? '⟨Unbekannter Kunde⟩', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: titleColor, decoration: canceled ? TextDecoration.lineThrough : TextDecoration.none, ), ), const SizedBox(height: 2), Text( delivery.deliveryAddressSnapshot.oneLine, style: TextStyle( fontSize: 12, color: theme.colorScheme.onSurfaceVariant, ), ), const SizedBox(height: 4), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(top: 2), child: Icon(statusIcon, size: 14, color: titleColor), ), const SizedBox(width: 4), Expanded( child: Text( statusText, style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: titleColor, ), softWrap: true, ), ), const SizedBox(width: 10), Text( progressLabel, style: TextStyle( fontSize: 12, color: theme.colorScheme.onSurfaceVariant, ), ), ], ), if (showReason) Padding( padding: const EdgeInsets.only(left: 18, top: 2), child: Text( 'Grund: $reason', style: TextStyle( fontSize: 11, color: titleColor, ), ), ), // Filial-Badge nur sichtbar, wenn die Lieferung // im aktiven Workflow ist. Pausiert / abgebrochen // soll keine zusätzliche Filial-Aufmerksamkeit // ziehen — die Aktion ist gerade unterbrochen oder // beendet. if (!canceled && !held && hasExternal) ...[ const SizedBox(height: 6), _ExternalWarehouseBadge(labels: externalLabels), ], ], ), ), const Icon(Icons.chevron_right), ], ), ), ), ), ); } } class _BottomBar extends StatelessWidget { const _BottomBar({required this.carId, required this.canStart}); final String carId; /// Nur wenn alle aktiven Lieferungen im Standardlager fertig beladen sind, /// darf der Fahrer in die Auslieferungs-Phase wechseln. final bool canStart; @override Widget build(BuildContext context) { if (carId.isEmpty) return const SizedBox.shrink(); final theme = Theme.of(context); return SafeArea( child: Padding( padding: const EdgeInsets.all(12), child: Column( mainAxisSize: MainAxisSize.min, children: [ if (!canStart) Padding( padding: const EdgeInsets.only(bottom: 8), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.info_outline, size: 16, color: theme.colorScheme.onSurfaceVariant, ), const SizedBox(width: 6), Flexible( child: Text( 'Erst alle Artikel des Standardlagers beladen', style: TextStyle( fontSize: 12, color: theme.colorScheme.onSurfaceVariant, ), ), ), ], ), ), SizedBox( width: double.infinity, child: OutlinedButton.icon( onPressed: canStart ? () { context.read().add( PhaseSet( carId: carId, phase: DeliveryPhase.ausliefern, ), ); } : null, icon: const Icon(Icons.arrow_forward), label: const Text('Auslieferungs-Phase starten'), ), ), ], ), ), ); } } /// UX-Bucket der Übersicht. Bestimmt, in welche Sektion eine Lieferung /// einsortiert wird: /// * `open` — Standardlager nicht fertig (= jetzt zu beladen) /// * `later` — Standardlager fertig, aber Filial-Items offen /// * `paused` — Lieferung explizit pausiert (`held`) /// * `done` — komplett fertig (Standardlager fertig & kein Filiale) /// * `canceled` — endgültig abgebrochen enum _OverviewBucket { open, later, paused, done, canceled } /// Bündelt eine Lieferung mit ihrer Beladereihenfolge-Position für die /// Übersicht — der `originalIndex` bleibt über die Sektions-Umsortierung /// hinweg sichtbar im Tile-Avatar. class _OverviewEntry { const _OverviewEntry({ required this.originalIndex, required this.delivery, required this.standardItems, }); final int originalIndex; final Delivery delivery; final List standardItems; } /// Sektion in der Übersicht mit eigenem Header + zugehörigen Tiles. /// Header zeigt Titel, farbigen Pill mit Anzahl und nimmt die Section- /// Farbe als Akzent — Fahrer erkennt auf einen Blick, „was kommt jetzt". class _BucketSection extends StatelessWidget { const _BucketSection({ required this.title, required this.count, required this.color, required this.entries, required this.details, this.icon, }); final String title; final int count; final Color color; final List<_OverviewEntry> entries; final TourDetails details; /// Optionales Icon vor dem Titel — wird aktuell nur für „Nächste /// Lieferung" verwendet, damit diese Sektion auf einen Blick als /// „aktiv jetzt" erkennbar ist. Bei den restlichen Sektionen reichen /// Farb-Balken + Pill als visueller Anker. final IconData? icon; @override Widget build(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Padding( padding: const EdgeInsets.fromLTRB(16, 16, 16, 4), child: Row( children: [ Container( width: 4, height: 18, decoration: BoxDecoration( color: color, borderRadius: BorderRadius.circular(2), ), ), const SizedBox(width: 8), if (icon != null) ...[ Icon(icon, size: 16, color: color), const SizedBox(width: 6), ], Text( title, style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: color, letterSpacing: 0.4, ), ), const SizedBox(width: 8), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 1), decoration: BoxDecoration( color: color.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(12), ), child: Text( '$count', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w600, color: color, ), ), ), ], ), ), for (final entry in entries) _OverviewTile( position: entry.originalIndex + 1, delivery: entry.delivery, standardItems: entry.standardItems, details: details, onTap: () { Navigator.of(context).push( MaterialPageRoute( builder: (_) => LoadingCustomerPage( initialIndex: entry.originalIndex, ), ), ); }, ), ], ); } } /// Hinweis-Badge unterhalb der Status-Zeile einer Lieferung mit Artikeln /// aus einem oder mehreren Filialen. /// /// Formuliert bewusst „Enthält auch … zum späteren Abholen": Die Lieferung /// wird JETZT normal (im Standardlager) beladen — das Filial-Item ist /// nur ein zusätzlicher Bestandteil. Das „auch" signalisiert den Zusatz, /// und „zum späteren Abholen" hängt den Zeitbezug klar an den ARTIKEL, nicht /// an die Lieferung (die sonst fälschlich als nach-hinten-geschoben wirkt). class _ExternalWarehouseBadge extends StatelessWidget { const _ExternalWarehouseBadge({required this.labels}); final List labels; @override Widget build(BuildContext context) { final lagerText = labels.isEmpty ? 'Artikel zum späteren Abholen aus der Filiale' : 'Artikel zum späteren Abholen aus Filiale: ${labels.join(", ")}'; return Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 5), decoration: BoxDecoration( color: Colors.amber.withValues(alpha: 0.22), borderRadius: BorderRadius.circular(6), border: Border.all(color: Colors.amber.withValues(alpha: 0.7)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( Icons.warehouse_outlined, size: 14, color: Colors.amber.shade800, ), const SizedBox(width: 4), Flexible( child: RichText( maxLines: 2, overflow: TextOverflow.ellipsis, text: TextSpan( style: TextStyle( fontSize: 11, fontWeight: FontWeight.w600, color: Colors.amber.shade800, ), children: [ const TextSpan( text: 'Enthält auch ', style: TextStyle(fontWeight: FontWeight.w800), ), TextSpan(text: lagerText), ], ), ), ), ], ), ); } } class _EmptyOverview extends StatelessWidget { const _EmptyOverview(); @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.inbox_outlined, size: 64, color: scheme.onSurfaceVariant), const SizedBox(height: 12), Text( 'Keine Lieferungen zum Beladen', style: Theme.of(context).textTheme.titleMedium, ), ], ), ); } }