Enhanced signature step and adjusted note bloc

This commit is contained in:
Dennis Nemec
2026-01-07 16:07:24 +01:00
parent 622967e5c1
commit 6a53d2d716
4 changed files with 81 additions and 61 deletions

View File

@ -1,11 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart'; import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_event.dart'; import 'package:hl_lieferservice/widget/operations/bloc/operation_event.dart';
import 'package:rxdart/rxdart.dart';
import '../../../../model/delivery.dart';
import 'note_event.dart'; import 'note_event.dart';
import 'note_state.dart'; import 'note_state.dart';
import 'package:hl_lieferservice/feature/delivery/detail/repository/note_repository.dart'; import 'package:hl_lieferservice/feature/delivery/detail/repository/note_repository.dart';
@ -15,20 +18,25 @@ class NoteBloc extends Bloc<NoteEvent, NoteState> {
final OperationBloc opBloc; final OperationBloc opBloc;
final String deliveryId; final String deliveryId;
StreamSubscription? _noteSubscription; StreamSubscription? _combinedSubscription;
StreamSubscription? _imageSubscription;
NoteBloc({required this.repository, required this.opBloc, required this.deliveryId}) NoteBloc({
: super(NoteInitial()) { required this.repository,
repository.loadNotes(deliveryId); required this.opBloc,
required this.deliveryId,
_noteSubscription = repository.notes.listen((notes) { }) : super(NoteInitial()) {
add(NotesUpdated(notes: notes)); _combinedSubscription = CombineLatestStream.combine2(
}); repository.notes,
repository.images,
_imageSubscription = repository.images.listen((images) { (note, image) => {"note": note, "image": image},
add(ImageUpdated(images: images)); ).listen(
}); (data) => add(
DataUpdated(
images: data["image"] as List<ImageNote>,
notes: data["note"] as List<Note>,
),
),
);
on<LoadNote>(_load); on<LoadNote>(_load);
on<AddNote>(_add); on<AddNote>(_add);
@ -37,36 +45,28 @@ class NoteBloc extends Bloc<NoteEvent, NoteState> {
on<AddImageNote>(_upload); on<AddImageNote>(_upload);
on<RemoveImageNote>(_removeImage); on<RemoveImageNote>(_removeImage);
on<ResetNotes>(_reset); on<ResetNotes>(_reset);
on<NotesUpdated>(_noteUpdated); on<DataUpdated>(_dataUpdated);
on<ImageUpdated>(_imageUpdated);
} }
@override @override
Future<void> close() { Future<void> close() {
_noteSubscription?.cancel(); _combinedSubscription?.cancel();
_imageSubscription?.cancel();
return super.close(); return super.close();
} }
Future<void> _imageUpdated(ImageUpdated event, Emitter<NoteState> emit) async { Future<void> _dataUpdated(DataUpdated event, Emitter<NoteState> emit) async {
final currentState = state; emit(NoteLoaded(notes: event.notes, images: event.images));
if (currentState is NoteLoaded) {
emit.call(currentState.copyWith(images: event.images));
}
}
Future<void> _noteUpdated(NotesUpdated event, Emitter<NoteState> emit) async {
emit(NoteLoaded(notes: event.notes));
} }
Future<void> _reset(ResetNotes event, Emitter<NoteState> emit) async { Future<void> _reset(ResetNotes event, Emitter<NoteState> emit) async {
emit.call(NoteInitial()); emit.call(NoteInitial());
} }
Future<void> _removeImage(RemoveImageNote event, Future<void> _removeImage(
Emitter<NoteState> emit,) async { RemoveImageNote event,
Emitter<NoteState> emit,
) async {
opBloc.add(LoadOperation()); opBloc.add(LoadOperation());
try { try {
@ -101,7 +101,7 @@ class NoteBloc extends Bloc<NoteEvent, NoteState> {
try { try {
List<String> urls = List<String> urls =
event.delivery.images.map((image) => image.url).toList(); event.delivery.images.map((image) => image.url).toList();
debugPrint("IMAGE URLS : $urls"); debugPrint("IMAGE URLS : $urls");

View File

@ -66,3 +66,10 @@ class ImageUpdated extends NoteEvent {
ImageUpdated({required this.images}); ImageUpdated({required this.images});
} }
class DataUpdated extends NoteEvent {
final List<ImageNote> images;
final List<Note> notes;
DataUpdated({required this.images, required this.notes});
}

View File

@ -7,10 +7,13 @@ import 'package:hl_lieferservice/feature/delivery/detail/bloc/note_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/detail/bloc/note_event.dart'; import 'package:hl_lieferservice/feature/delivery/detail/bloc/note_event.dart';
import 'package:hl_lieferservice/feature/delivery/detail/presentation/delivery_sign.dart'; import 'package:hl_lieferservice/feature/delivery/detail/presentation/delivery_sign.dart';
import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step.dart'; import 'package:hl_lieferservice/feature/delivery/detail/presentation/steps/step.dart';
import 'package:hl_lieferservice/feature/delivery/detail/repository/note_repository.dart';
import 'package:hl_lieferservice/feature/delivery/detail/service/notes_service.dart';
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_bloc.dart'; import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_bloc.dart';
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_event.dart'; import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_event.dart';
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_state.dart'; import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_state.dart';
import 'package:hl_lieferservice/model/delivery.dart'; import 'package:hl_lieferservice/model/delivery.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
class DeliveryDetail extends StatefulWidget { class DeliveryDetail extends StatefulWidget {
final String deliveryId; final String deliveryId;
@ -118,9 +121,17 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
void _openSignatureView(Delivery delivery) { void _openSignatureView(Delivery delivery) {
Navigator.of(context).push( Navigator.of(context).push(
MaterialPageRoute( MaterialPageRoute(
builder: builder: (context) {
(context) => return BlocProvider(
SignatureView(onSigned: _onSign, delivery: delivery), create:
(context) => NoteBloc(
repository: NoteRepository(service: NoteService()),
opBloc: context.read<OperationBloc>(),
deliveryId: delivery.id,
),
child: SignatureView(onSigned: _onSign, delivery: delivery),
);
},
), ),
); );
} }
@ -150,9 +161,10 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
padding: const EdgeInsets.only(left: 20), padding: const EdgeInsets.only(left: 20),
child: FilledButton( child: FilledButton(
onPressed: onPressed:
() => _step == _steps.length - 1 () =>
? _openSignatureView(delivery) _step == _steps.length - 1
: _clickForward, ? _openSignatureView(delivery)
: _clickForward,
child: child:
_step == _steps.length - 1 _step == _steps.length - 1
? const Text("Unterschreiben") ? const Text("Unterschreiben")
@ -168,27 +180,31 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: const Text("Auslieferungsdetails")), appBar: AppBar(title: const Text("Auslieferungsdetails")),
body: BlocBuilder<TourBloc, TourState>(builder: (context, state) { body: BlocBuilder<TourBloc, TourState>(
final currentState = state; builder: (context, state) {
final currentState = state;
if (currentState is TourLoaded) { if (currentState is TourLoaded) {
Delivery delivery = currentState.tour.deliveries.firstWhere((delivery) => delivery.id == widget.deliveryId); Delivery delivery = currentState.tour.deliveries.firstWhere(
return Column( (delivery) => delivery.id == widget.deliveryId,
children: [ );
_stepInfo(), return Column(
const Divider(), children: [
Expanded( _stepInfo(),
child: const Divider(),
StepFactory().make(_step, delivery) ?? Expanded(
_stepMissingWarning(), child:
), StepFactory().make(_step, delivery) ??
_stepsNavigation(delivery), _stepMissingWarning(),
], ),
); _stepsNavigation(delivery),
} ],
);
}
return const Center(child: CircularProgressIndicator(),); return const Center(child: CircularProgressIndicator());
}), },
),
); );
} }
} }

View File

@ -1,3 +1,4 @@
import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -71,11 +72,7 @@ class _SignatureViewState extends State<SignatureView> {
} }
}); });
// only load notes if they are not already loaded context.read<NoteBloc>().add(LoadNote(delivery: widget.delivery));
final noteState = context.read<NoteBloc>().state;
if (noteState is NoteInitial) {
context.read<NoteBloc>().add(LoadNote(delivery: widget.delivery));
}
} }
@override @override
@ -122,7 +119,7 @@ class _SignatureViewState extends State<SignatureView> {
builder: (context, state) { builder: (context, state) {
final current = state; final current = state;
if (current is NoteLoadedBase) { if (current is NoteLoaded) {
if (current.notes.isEmpty) { if (current.notes.isEmpty) {
return const SizedBox( return const SizedBox(
width: double.infinity, width: double.infinity,