Final commit.
This commit is contained in:
@ -1,6 +1,9 @@
|
||||
import 'package:collection/collection.dart';
|
||||
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/tour_details.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';
|
||||
@ -8,8 +11,6 @@ import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.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/model/delivery.dart';
|
||||
import 'package:hl_lieferservice/model/tour.dart';
|
||||
import 'package:hl_lieferservice/widget/home/presentation/home_drawer.dart';
|
||||
import 'package:hl_lieferservice/widget/phase_stepper/phase_stepper.dart';
|
||||
|
||||
@ -20,18 +21,11 @@ import 'package:hl_lieferservice/widget/phase_stepper/phase_stepper.dart';
|
||||
/// * Tab "Verfügbar" — alle Lieferungen, die noch keinem Fahrzeug
|
||||
/// zugeordnet sind. Multiselect, Bulk-Bestätigung per BottomBar-Button.
|
||||
/// * Tab "Vergeben" — Lieferungen, die bereits zugeordnet sind. Tap auf
|
||||
/// eigene Lieferung → Freigabe-Dialog; Tap auf fremde → Umlade-Dialog.
|
||||
/// * Persistent untere BottomBar: "Weiter zum Sortieren" — wechselt die
|
||||
/// Phase. Es gibt bewusst keinen Zwang, dass alle Lieferungen verteilt
|
||||
/// sein müssen; der Fahrer entscheidet wann er weiterzieht.
|
||||
/// eigene → Freigabe-Dialog; Tap auf fremde → Umlade-Dialog.
|
||||
/// * Persistente BottomBar: "Weiter zum Sortieren" — wechselt die Phase.
|
||||
class DeliverySelectionPage extends StatefulWidget {
|
||||
const DeliverySelectionPage({
|
||||
super.key,
|
||||
required this.selectedCarId,
|
||||
});
|
||||
const DeliverySelectionPage({super.key, required this.selectedCarId});
|
||||
|
||||
/// ID des aktuell gewählten Fahrzeugs (Eigene Lieferungen / Ziel von
|
||||
/// Übernahmen).
|
||||
final String selectedCarId;
|
||||
|
||||
@override
|
||||
@ -39,86 +33,63 @@ class DeliverySelectionPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
/// Lokale Multi-Selektion im Tab "Verfügbar". Wird nach erfolgreichem
|
||||
/// Bulk-Assign geleert.
|
||||
final Set<String> _selectedIds = <String>{};
|
||||
|
||||
/// True während sequentieller Assign-Calls — schaltet den
|
||||
/// Bestätigungs-Button auf Spinner und disabled.
|
||||
bool _isAssigning = false;
|
||||
|
||||
String get _carIdString => widget.selectedCarId.toString();
|
||||
|
||||
/// Sucht das Plate eines Autos in der Tour-Driver-Liste. Liefert "?" als
|
||||
/// Fallback, falls die Zuordnung nicht (mehr) im Team enthalten ist —
|
||||
/// z. B. nach Personalwechsel zwischen Tour-Synchronisationen.
|
||||
String _plateFor(String? carId, Tour tour) {
|
||||
if (carId == null) return "?";
|
||||
final car = tour.driver.cars.firstWhereOrNull((c) => c.id == carId);
|
||||
return car?.plate ?? "?";
|
||||
/// Sucht das Kennzeichen eines Fahrzeugs in der aktuell geladenen
|
||||
/// CarsBloc-Liste. Liefert "?" als Fallback, wenn das Auto nicht (mehr)
|
||||
/// im Account ist — z. B. nach Personalwechsel zwischen Tour-Syncs.
|
||||
String _plateFor(String? carId) {
|
||||
if (carId == null) return '?';
|
||||
final carsState = context.read<CarsBloc>().state;
|
||||
if (carsState is! CarsLoaded) return '?';
|
||||
for (final c in carsState.cars) {
|
||||
if (c.id == carId) return c.plate;
|
||||
}
|
||||
return '?';
|
||||
}
|
||||
|
||||
/// Bulk-Assign der aktuell selektierten Lieferungen an das eigene Auto.
|
||||
/// Sequentiell, damit der lokale Tour-Stream nach jedem Schritt
|
||||
/// konsistent ist und die Listen-Filter live mitwandern. Bei Fehlern
|
||||
/// wird eine SnackBar gezeigt und die Selektion bleibt erhalten.
|
||||
Future<void> _confirmSelection() async {
|
||||
if (_selectedIds.isEmpty || _isAssigning) return;
|
||||
|
||||
setState(() => _isAssigning = true);
|
||||
final tourBloc = context.read<TourBloc>();
|
||||
void _confirmSelection() {
|
||||
if (_selectedIds.isEmpty) return;
|
||||
final ids = List<String>.from(_selectedIds);
|
||||
|
||||
try {
|
||||
for (final id in ids) {
|
||||
tourBloc.add(
|
||||
AssignCarEvent(deliveryId: id, carId: _carIdString),
|
||||
);
|
||||
}
|
||||
// Hinweis: TourBloc verarbeitet die Events asynchron; lokale
|
||||
// Tour-Updates erfolgen über den Stream. Wir leeren die Selektion
|
||||
// optimistisch, damit der Fahrer ein klares Feedback bekommt.
|
||||
if (!mounted) return;
|
||||
setState(_selectedIds.clear);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("Fehler beim Übernehmen: $e")),
|
||||
);
|
||||
} finally {
|
||||
if (mounted) setState(() => _isAssigning = false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Wechselt in die nächste Phase (Sortieren). Der Fahrer kann jederzeit
|
||||
/// zurückspringen — die persistierte Phase wird über den Stepper-Tap
|
||||
/// zurückgesetzt.
|
||||
void _goToSorting() {
|
||||
context.read<PhaseBloc>().add(
|
||||
PhaseSet(
|
||||
carId: _carIdString,
|
||||
phase: DeliveryPhase.sortieren,
|
||||
// EIN Bulk-Event statt N parallel laufender Single-Events: vermeidet
|
||||
// die Race-Condition, bei der `flutter_bloc`s default-concurrent
|
||||
// Event-Processing parallele Handler den Initial-State lesen lässt
|
||||
// und sich am Ende beim `emit` gegenseitig überschreiben.
|
||||
context.read<TourBloc>().add(
|
||||
AssignCarToDeliveries(
|
||||
deliveryIds: ids,
|
||||
carId: widget.selectedCarId,
|
||||
),
|
||||
);
|
||||
|
||||
setState(_selectedIds.clear);
|
||||
}
|
||||
|
||||
Future<void> _showReleaseDialog(Delivery delivery) async {
|
||||
void _goToSorting() {
|
||||
context.read<PhaseBloc>().add(
|
||||
PhaseSet(carId: widget.selectedCarId, phase: DeliveryPhase.sortieren),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showReleaseDialog(Delivery delivery, TourDetails details) async {
|
||||
final customer = details.customerOf(delivery);
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: const Text("Lieferung freigeben"),
|
||||
title: const Text('Lieferung freigeben'),
|
||||
content: Text(
|
||||
"${delivery.customer.name} wurde Ihrem Fahrzeug zugeordnet. "
|
||||
"Möchten Sie diese Lieferung wieder freigeben?",
|
||||
'${customer?.name ?? 'Diese Lieferung'} wurde Ihrem Fahrzeug '
|
||||
'zugeordnet. Möchten Sie sie wieder freigeben?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(false),
|
||||
child: const Text("Abbrechen"),
|
||||
child: const Text('Abbrechen'),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(true),
|
||||
child: const Text("Freigeben"),
|
||||
child: const Text('Freigeben'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -126,54 +97,57 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
|
||||
if (result != true || !mounted) return;
|
||||
context.read<TourBloc>().add(
|
||||
UnassignDeliveryEvent(deliveryId: delivery.id),
|
||||
AssignCarToDelivery(deliveryId: delivery.id, carId: null),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showTakeoverDialog(Delivery delivery, Tour tour) async {
|
||||
final foreignPlate = _plateFor(delivery.carId, tour);
|
||||
final ownPlate = _plateFor(widget.selectedCarId, tour);
|
||||
Future<void> _showTakeoverDialog(
|
||||
Delivery delivery,
|
||||
TourDetails details,
|
||||
) async {
|
||||
final customer = details.customerOf(delivery);
|
||||
final foreignPlate = _plateFor(delivery.assignedCarId);
|
||||
final ownPlate = _plateFor(widget.selectedCarId);
|
||||
final theme = Theme.of(context);
|
||||
|
||||
final result = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
title: const Text("Lieferung umladen"),
|
||||
title: const Text('Lieferung umladen'),
|
||||
content: RichText(
|
||||
text: TextSpan(
|
||||
style: theme.textTheme.bodyMedium,
|
||||
children: [
|
||||
TextSpan(text: "${delivery.customer.name} ist aktuell "),
|
||||
TextSpan(
|
||||
text: '${customer?.name ?? 'Diese Lieferung'} ist aktuell ',
|
||||
),
|
||||
TextSpan(
|
||||
text: foreignPlate,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const TextSpan(text: " zugeordnet. Möchten Sie diese "
|
||||
"Lieferung auf "),
|
||||
const TextSpan(
|
||||
text: ' zugeordnet. Möchten Sie diese Lieferung auf ',
|
||||
),
|
||||
TextSpan(
|
||||
text: ownPlate,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
const TextSpan(text: " umladen?"),
|
||||
const TextSpan(text: ' umladen?'),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(false),
|
||||
child: const Text("Abbrechen"),
|
||||
child: const Text('Abbrechen'),
|
||||
),
|
||||
FilledButton(
|
||||
// Warnfarbe, da das Umladen eine bestehende Zuordnung
|
||||
// überschreibt — last write wins. `colorScheme.error` ist
|
||||
// bewusst hart gewählt, damit der Fahrer den Eingriff in
|
||||
// fremde Disposition bewusst bestätigt.
|
||||
style: FilledButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.error,
|
||||
foregroundColor: theme.colorScheme.onError,
|
||||
),
|
||||
onPressed: () => Navigator.of(ctx).pop(true),
|
||||
child: const Text("Übernehmen"),
|
||||
child: const Text('Übernehmen'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -181,16 +155,14 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
|
||||
if (result != true || !mounted) return;
|
||||
context.read<TourBloc>().add(
|
||||
AssignCarEvent(
|
||||
AssignCarToDelivery(
|
||||
deliveryId: delivery.id,
|
||||
carId: _carIdString,
|
||||
carId: widget.selectedCarId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Widgets
|
||||
// ---------------------------------------------------------------------------
|
||||
// ─── Widgets ─────────────────────────────────────────────────────────
|
||||
|
||||
Widget _plateBadge(BuildContext context, String plate, {bool own = false}) {
|
||||
final theme = Theme.of(context);
|
||||
@ -213,11 +185,7 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
plate,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: fg,
|
||||
),
|
||||
style: TextStyle(fontSize: 11, fontWeight: FontWeight.bold, color: fg),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -257,13 +225,13 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _availableTab(List<Delivery> available) {
|
||||
Widget _availableTab(List<Delivery> available, TourDetails details) {
|
||||
if (available.isEmpty) {
|
||||
return _emptyState(
|
||||
icon: Icons.inbox_outlined,
|
||||
title: "Alle Lieferungen sind verteilt.",
|
||||
subtitle: "Im Tab \"Vergeben\" können Sie eigene Lieferungen "
|
||||
"freigeben oder fremde übernehmen.",
|
||||
title: 'Alle Lieferungen sind verteilt.',
|
||||
subtitle: 'Im Tab "Vergeben" können Sie eigene Lieferungen '
|
||||
'freigeben oder fremde übernehmen.',
|
||||
);
|
||||
}
|
||||
|
||||
@ -272,27 +240,29 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
itemCount: available.length,
|
||||
itemBuilder: (context, index) {
|
||||
final delivery = available[index];
|
||||
final customer = details.customerOf(delivery);
|
||||
final isSelected = _selectedIds.contains(delivery.id);
|
||||
return CheckboxListTile(
|
||||
key: ValueKey("available-${delivery.id}"),
|
||||
key: ValueKey('available-${delivery.id}'),
|
||||
value: isSelected,
|
||||
onChanged: _isAssigning
|
||||
? null
|
||||
: (checked) {
|
||||
setState(() {
|
||||
if (checked == true) {
|
||||
_selectedIds.add(delivery.id);
|
||||
} else {
|
||||
_selectedIds.remove(delivery.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
onChanged: (checked) {
|
||||
// Während ein Bulk-Zuweisung läuft, blockiert der
|
||||
// OperationViewEnforcer die Eingabe global; ein separates
|
||||
// `_isAssigning`-Lock ist hier nicht mehr nötig.
|
||||
setState(() {
|
||||
if (checked == true) {
|
||||
_selectedIds.add(delivery.id);
|
||||
} else {
|
||||
_selectedIds.remove(delivery.id);
|
||||
}
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
delivery.customer.name,
|
||||
customer?.name ?? '⟨Unbekannter Kunde⟩',
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
subtitle: Text(
|
||||
delivery.customer.address.toString(),
|
||||
delivery.deliveryAddressSnapshot.oneLine,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
@ -301,11 +271,11 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _assignedTab(List<Delivery> assigned, Tour tour) {
|
||||
Widget _assignedTab(List<Delivery> assigned, TourDetails details) {
|
||||
if (assigned.isEmpty) {
|
||||
return _emptyState(
|
||||
icon: Icons.local_shipping_outlined,
|
||||
title: "Noch keine Lieferungen verteilt.",
|
||||
title: 'Noch keine Lieferungen verteilt.',
|
||||
);
|
||||
}
|
||||
|
||||
@ -316,20 +286,21 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
itemCount: assigned.length,
|
||||
itemBuilder: (context, index) {
|
||||
final delivery = assigned[index];
|
||||
final isOwn = delivery.carId == widget.selectedCarId;
|
||||
final plate = _plateFor(delivery.carId, tour);
|
||||
final isOwn = delivery.assignedCarId == widget.selectedCarId;
|
||||
final plate = _plateFor(delivery.assignedCarId);
|
||||
final customer = details.customerOf(delivery);
|
||||
|
||||
return Material(
|
||||
color: isOwn
|
||||
? theme.colorScheme.primaryContainer.withValues(alpha: 0.35)
|
||||
: null,
|
||||
child: ListTile(
|
||||
key: ValueKey("assigned-${delivery.id}"),
|
||||
key: ValueKey('assigned-${delivery.id}'),
|
||||
onTap: () {
|
||||
if (isOwn) {
|
||||
_showReleaseDialog(delivery);
|
||||
_showReleaseDialog(delivery, details);
|
||||
} else {
|
||||
_showTakeoverDialog(delivery, tour);
|
||||
_showTakeoverDialog(delivery, details);
|
||||
}
|
||||
},
|
||||
leading: Icon(
|
||||
@ -339,14 +310,14 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
title: Text(
|
||||
delivery.customer.name,
|
||||
customer?.name ?? '⟨Unbekannter Kunde⟩',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isOwn ? theme.colorScheme.primary : null,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
delivery.customer.address.toString(),
|
||||
delivery.deliveryAddressSnapshot.oneLine,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
trailing: _plateBadge(context, plate, own: isOwn),
|
||||
@ -356,13 +327,12 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
);
|
||||
}
|
||||
|
||||
/// BottomBar mit Bulk-Confirm (kontextabhängig) + Phasen-Wechsel.
|
||||
/// Confirm-Button ist nur sichtbar, wenn etwas selektiert ist —
|
||||
/// "Weiter zum Sortieren" bleibt immer sichtbar.
|
||||
Widget _buildBottomBar() {
|
||||
final theme = Theme.of(context);
|
||||
final hasSelection = _selectedIds.isNotEmpty;
|
||||
|
||||
// Disabled-State und Spinner während des Bulk-Zuweisens übernimmt
|
||||
// global der `OperationViewEnforcer` (StartOperation/FinishOperation
|
||||
// aus dem TourBloc) — daher hier keine lokale Lock-Variable mehr.
|
||||
return SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
@ -373,20 +343,10 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: FilledButton.icon(
|
||||
onPressed:
|
||||
_isAssigning ? null : _confirmSelection,
|
||||
icon: _isAssigning
|
||||
? SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: theme.colorScheme.onPrimary,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.check),
|
||||
onPressed: _confirmSelection,
|
||||
icon: const Icon(Icons.check),
|
||||
label: Text(
|
||||
"Auswahl bestätigen (${_selectedIds.length})",
|
||||
'Auswahl bestätigen (${_selectedIds.length})',
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -394,9 +354,9 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: _isAssigning ? null : _goToSorting,
|
||||
onPressed: _goToSorting,
|
||||
icon: const Icon(Icons.arrow_forward),
|
||||
label: const Text("Weiter zum Sortieren"),
|
||||
label: const Text('Weiter zum Sortieren'),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -409,24 +369,38 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<TourBloc, TourState>(
|
||||
builder: (context, state) {
|
||||
if (state is TourLoadingFailed) {
|
||||
if (state is TourLoadFailed) {
|
||||
return const DeliveryLoadingFailedPage();
|
||||
}
|
||||
if (state is TourEmpty) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Lieferungen auswählen')),
|
||||
body: const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Text(
|
||||
'Für heute ist keine Tour zugewiesen.',
|
||||
style: TextStyle(fontSize: 16),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (state is! TourLoaded) {
|
||||
return const Scaffold(
|
||||
body: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
final available = state.tour.deliveries
|
||||
.where((d) => d.carId == null)
|
||||
final details = state.details;
|
||||
final available = details.deliveries
|
||||
.where((d) => d.assignedCarId == null)
|
||||
.toList();
|
||||
final assigned = state.tour.deliveries
|
||||
.where((d) => d.carId != null)
|
||||
final assigned = details.deliveries
|
||||
.where((d) => d.assignedCarId != null)
|
||||
.toList();
|
||||
|
||||
// Falls eine selektierte Lieferung in der Zwischenzeit zugeordnet
|
||||
// wurde (z. B. durch einen parallelen Vorgang), Selektion bereinigen.
|
||||
_selectedIds.removeWhere(
|
||||
(id) => !available.any((d) => d.id == id),
|
||||
);
|
||||
@ -442,22 +416,20 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
children: [
|
||||
PhaseStepper(
|
||||
currentPhase: DeliveryPhase.auswaehlen,
|
||||
carId: _carIdString,
|
||||
carId: widget.selectedCarId,
|
||||
),
|
||||
Material(
|
||||
color: Theme.of(context).primaryColor,
|
||||
child: TabBar(
|
||||
labelColor:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
labelColor: Theme.of(context).colorScheme.onPrimary,
|
||||
unselectedLabelColor: Theme.of(context)
|
||||
.colorScheme
|
||||
.onPrimary
|
||||
.withValues(alpha: 0.6),
|
||||
indicatorColor:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
indicatorColor: Theme.of(context).colorScheme.onPrimary,
|
||||
tabs: [
|
||||
Tab(text: "Verfügbar (${available.length})"),
|
||||
Tab(text: "Vergeben (${assigned.length})"),
|
||||
Tab(text: 'Verfügbar (${available.length})'),
|
||||
Tab(text: 'Vergeben (${assigned.length})'),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -466,8 +438,8 @@ class _DeliverySelectionPageState extends State<DeliverySelectionPage> {
|
||||
),
|
||||
body: TabBarView(
|
||||
children: [
|
||||
_availableTab(available),
|
||||
_assignedTab(assigned, state.tour),
|
||||
_availableTab(available, details),
|
||||
_assignedTab(assigned, details),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: _buildBottomBar(),
|
||||
|
||||
Reference in New Issue
Block a user