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

View File

@ -66,3 +66,10 @@ class ImageUpdated extends NoteEvent {
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/presentation/delivery_sign.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_event.dart';
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_state.dart';
import 'package:hl_lieferservice/model/delivery.dart';
import 'package:hl_lieferservice/widget/operations/bloc/operation_bloc.dart';
class DeliveryDetail extends StatefulWidget {
final String deliveryId;
@ -118,9 +121,17 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
void _openSignatureView(Delivery delivery) {
Navigator.of(context).push(
MaterialPageRoute(
builder:
(context) =>
SignatureView(onSigned: _onSign, delivery: delivery),
builder: (context) {
return BlocProvider(
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),
child: FilledButton(
onPressed:
() => _step == _steps.length - 1
? _openSignatureView(delivery)
: _clickForward,
() =>
_step == _steps.length - 1
? _openSignatureView(delivery)
: _clickForward,
child:
_step == _steps.length - 1
? const Text("Unterschreiben")
@ -168,27 +180,31 @@ class _DeliveryDetailState extends State<DeliveryDetail> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Auslieferungsdetails")),
body: BlocBuilder<TourBloc, TourState>(builder: (context, state) {
final currentState = state;
body: BlocBuilder<TourBloc, TourState>(
builder: (context, state) {
final currentState = state;
if (currentState is TourLoaded) {
Delivery delivery = currentState.tour.deliveries.firstWhere((delivery) => delivery.id == widget.deliveryId);
return Column(
children: [
_stepInfo(),
const Divider(),
Expanded(
child:
StepFactory().make(_step, delivery) ??
_stepMissingWarning(),
),
_stepsNavigation(delivery),
],
);
}
if (currentState is TourLoaded) {
Delivery delivery = currentState.tour.deliveries.firstWhere(
(delivery) => delivery.id == widget.deliveryId,
);
return Column(
children: [
_stepInfo(),
const Divider(),
Expanded(
child:
StepFactory().make(_step, 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 'package:flutter_bloc/flutter_bloc.dart';
@ -71,11 +72,7 @@ class _SignatureViewState extends State<SignatureView> {
}
});
// only load notes if they are not already loaded
final noteState = context.read<NoteBloc>().state;
if (noteState is NoteInitial) {
context.read<NoteBloc>().add(LoadNote(delivery: widget.delivery));
}
context.read<NoteBloc>().add(LoadNote(delivery: widget.delivery));
}
@override
@ -122,7 +119,7 @@ class _SignatureViewState extends State<SignatureView> {
builder: (context, state) {
final current = state;
if (current is NoteLoadedBase) {
if (current is NoteLoaded) {
if (current.notes.isEmpty) {
return const SizedBox(
width: double.infinity,