diff --git a/lib/application/table/table_form/table_form_bloc.dart b/lib/application/table/table_form/table_form_bloc.dart index 38c363a..6e65fd1 100644 --- a/lib/application/table/table_form/table_form_bloc.dart +++ b/lib/application/table/table_form/table_form_bloc.dart @@ -23,19 +23,44 @@ class TableFormBloc extends Bloc { Emitter emit, ) { return event.map( - updated: (e) async { + nameChanged: (e) async { + emit(state.copyWith(name: e.name)); + }, + capacityChanged: (e) async { + emit(state.copyWith(capacity: int.tryParse(e.capacity) ?? 0)); + }, + created: (e) async { Either failureOrTable; + emit(state.copyWith(isCreating: true, failureOrTable: none())); + + final isNameValid = state.name.isNotEmpty; + final isCapacityValid = state.capacity > 0; + + if (isNameValid && isCapacityValid) { + failureOrTable = await _repository.createTable( + name: state.name, + capacity: state.capacity, + ); + + emit( + state.copyWith( + failureOrTable: optionOf(failureOrTable), + isCreating: false, + ), + ); + } + + emit(state.copyWith(failureOrTable: none(), isCreating: false)); + }, + updated: (e) async { emit(state.copyWith(isUpdating: true, failureOrTable: none())); - failureOrTable = await _repository.updatePosition( - id: e.id, - position: e.position, - ); + await _repository.updatePosition(id: e.id, position: e.position); emit( state.copyWith( - failureOrTable: optionOf(failureOrTable), + // failureOrTable: optionOf(failureOrTable), isUpdating: false, ), ); diff --git a/lib/application/table/table_form/table_form_bloc.freezed.dart b/lib/application/table/table_form/table_form_bloc.freezed.dart index e3dd281..121e06a 100644 --- a/lib/application/table/table_form/table_form_bloc.freezed.dart +++ b/lib/application/table/table_form/table_form_bloc.freezed.dart @@ -17,40 +17,50 @@ final _privateConstructorUsedError = UnsupportedError( /// @nodoc mixin _$TableFormEvent { - String get id => throw _privateConstructorUsedError; - Offset get position => throw _privateConstructorUsedError; @optionalTypeArgs TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function(String capacity) capacityChanged, + required TResult Function() created, required TResult Function(String id, Offset position) updated, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function(String capacity)? capacityChanged, + TResult? Function()? created, TResult? Function(String id, Offset position)? updated, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function(String capacity)? capacityChanged, + TResult Function()? created, TResult Function(String id, Offset position)? updated, required TResult orElse(), }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_CapacityChanged value) capacityChanged, + required TResult Function(_Created value) created, required TResult Function(_Updated value) updated, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_CapacityChanged value)? capacityChanged, + TResult? Function(_Created value)? created, TResult? Function(_Updated value)? updated, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_CapacityChanged value)? capacityChanged, + TResult Function(_Created value)? created, TResult Function(_Updated value)? updated, required TResult orElse(), }) => throw _privateConstructorUsedError; - - /// Create a copy of TableFormEvent - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - $TableFormEventCopyWith get copyWith => - throw _privateConstructorUsedError; } /// @nodoc @@ -59,8 +69,6 @@ abstract class $TableFormEventCopyWith<$Res> { TableFormEvent value, $Res Function(TableFormEvent) then, ) = _$TableFormEventCopyWithImpl<$Res, TableFormEvent>; - @useResult - $Res call({String id, Offset position}); } /// @nodoc @@ -73,35 +81,447 @@ class _$TableFormEventCopyWithImpl<$Res, $Val extends TableFormEvent> // ignore: unused_field final $Res Function($Val) _then; + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$NameChangedImplCopyWith<$Res> { + factory _$$NameChangedImplCopyWith( + _$NameChangedImpl value, + $Res Function(_$NameChangedImpl) then, + ) = __$$NameChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String name}); +} + +/// @nodoc +class __$$NameChangedImplCopyWithImpl<$Res> + extends _$TableFormEventCopyWithImpl<$Res, _$NameChangedImpl> + implements _$$NameChangedImplCopyWith<$Res> { + __$$NameChangedImplCopyWithImpl( + _$NameChangedImpl _value, + $Res Function(_$NameChangedImpl) _then, + ) : super(_value, _then); + /// Create a copy of TableFormEvent /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override - $Res call({Object? id = null, Object? position = null}) { + $Res call({Object? name = null}) { return _then( - _value.copyWith( - id: null == id - ? _value.id - : id // ignore: cast_nullable_to_non_nullable - as String, - position: null == position - ? _value.position - : position // ignore: cast_nullable_to_non_nullable - as Offset, - ) - as $Val, + _$NameChangedImpl( + null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + ), ); } } /// @nodoc -abstract class _$$UpdatedImplCopyWith<$Res> - implements $TableFormEventCopyWith<$Res> { + +class _$NameChangedImpl implements _NameChanged { + const _$NameChangedImpl(this.name); + + @override + final String name; + + @override + String toString() { + return 'TableFormEvent.nameChanged(name: $name)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$NameChangedImpl && + (identical(other.name, name) || other.name == name)); + } + + @override + int get hashCode => Object.hash(runtimeType, name); + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$NameChangedImplCopyWith<_$NameChangedImpl> get copyWith => + __$$NameChangedImplCopyWithImpl<_$NameChangedImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function(String capacity) capacityChanged, + required TResult Function() created, + required TResult Function(String id, Offset position) updated, + }) { + return nameChanged(name); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function(String capacity)? capacityChanged, + TResult? Function()? created, + TResult? Function(String id, Offset position)? updated, + }) { + return nameChanged?.call(name); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function(String capacity)? capacityChanged, + TResult Function()? created, + TResult Function(String id, Offset position)? updated, + required TResult orElse(), + }) { + if (nameChanged != null) { + return nameChanged(name); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_CapacityChanged value) capacityChanged, + required TResult Function(_Created value) created, + required TResult Function(_Updated value) updated, + }) { + return nameChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_CapacityChanged value)? capacityChanged, + TResult? Function(_Created value)? created, + TResult? Function(_Updated value)? updated, + }) { + return nameChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_CapacityChanged value)? capacityChanged, + TResult Function(_Created value)? created, + TResult Function(_Updated value)? updated, + required TResult orElse(), + }) { + if (nameChanged != null) { + return nameChanged(this); + } + return orElse(); + } +} + +abstract class _NameChanged implements TableFormEvent { + const factory _NameChanged(final String name) = _$NameChangedImpl; + + String get name; + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$NameChangedImplCopyWith<_$NameChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$CapacityChangedImplCopyWith<$Res> { + factory _$$CapacityChangedImplCopyWith( + _$CapacityChangedImpl value, + $Res Function(_$CapacityChangedImpl) then, + ) = __$$CapacityChangedImplCopyWithImpl<$Res>; + @useResult + $Res call({String capacity}); +} + +/// @nodoc +class __$$CapacityChangedImplCopyWithImpl<$Res> + extends _$TableFormEventCopyWithImpl<$Res, _$CapacityChangedImpl> + implements _$$CapacityChangedImplCopyWith<$Res> { + __$$CapacityChangedImplCopyWithImpl( + _$CapacityChangedImpl _value, + $Res Function(_$CapacityChangedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({Object? capacity = null}) { + return _then( + _$CapacityChangedImpl( + null == capacity + ? _value.capacity + : capacity // ignore: cast_nullable_to_non_nullable + as String, + ), + ); + } +} + +/// @nodoc + +class _$CapacityChangedImpl implements _CapacityChanged { + const _$CapacityChangedImpl(this.capacity); + + @override + final String capacity; + + @override + String toString() { + return 'TableFormEvent.capacityChanged(capacity: $capacity)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$CapacityChangedImpl && + (identical(other.capacity, capacity) || + other.capacity == capacity)); + } + + @override + int get hashCode => Object.hash(runtimeType, capacity); + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$CapacityChangedImplCopyWith<_$CapacityChangedImpl> get copyWith => + __$$CapacityChangedImplCopyWithImpl<_$CapacityChangedImpl>( + this, + _$identity, + ); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function(String capacity) capacityChanged, + required TResult Function() created, + required TResult Function(String id, Offset position) updated, + }) { + return capacityChanged(capacity); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function(String capacity)? capacityChanged, + TResult? Function()? created, + TResult? Function(String id, Offset position)? updated, + }) { + return capacityChanged?.call(capacity); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function(String capacity)? capacityChanged, + TResult Function()? created, + TResult Function(String id, Offset position)? updated, + required TResult orElse(), + }) { + if (capacityChanged != null) { + return capacityChanged(capacity); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_CapacityChanged value) capacityChanged, + required TResult Function(_Created value) created, + required TResult Function(_Updated value) updated, + }) { + return capacityChanged(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_CapacityChanged value)? capacityChanged, + TResult? Function(_Created value)? created, + TResult? Function(_Updated value)? updated, + }) { + return capacityChanged?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_CapacityChanged value)? capacityChanged, + TResult Function(_Created value)? created, + TResult Function(_Updated value)? updated, + required TResult orElse(), + }) { + if (capacityChanged != null) { + return capacityChanged(this); + } + return orElse(); + } +} + +abstract class _CapacityChanged implements TableFormEvent { + const factory _CapacityChanged(final String capacity) = _$CapacityChangedImpl; + + String get capacity; + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + _$$CapacityChangedImplCopyWith<_$CapacityChangedImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$CreatedImplCopyWith<$Res> { + factory _$$CreatedImplCopyWith( + _$CreatedImpl value, + $Res Function(_$CreatedImpl) then, + ) = __$$CreatedImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$CreatedImplCopyWithImpl<$Res> + extends _$TableFormEventCopyWithImpl<$Res, _$CreatedImpl> + implements _$$CreatedImplCopyWith<$Res> { + __$$CreatedImplCopyWithImpl( + _$CreatedImpl _value, + $Res Function(_$CreatedImpl) _then, + ) : super(_value, _then); + + /// Create a copy of TableFormEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$CreatedImpl implements _Created { + const _$CreatedImpl(); + + @override + String toString() { + return 'TableFormEvent.created()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$CreatedImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function(String capacity) capacityChanged, + required TResult Function() created, + required TResult Function(String id, Offset position) updated, + }) { + return created(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function(String capacity)? capacityChanged, + TResult? Function()? created, + TResult? Function(String id, Offset position)? updated, + }) { + return created?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function(String capacity)? capacityChanged, + TResult Function()? created, + TResult Function(String id, Offset position)? updated, + required TResult orElse(), + }) { + if (created != null) { + return created(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_CapacityChanged value) capacityChanged, + required TResult Function(_Created value) created, + required TResult Function(_Updated value) updated, + }) { + return created(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_CapacityChanged value)? capacityChanged, + TResult? Function(_Created value)? created, + TResult? Function(_Updated value)? updated, + }) { + return created?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_CapacityChanged value)? capacityChanged, + TResult Function(_Created value)? created, + TResult Function(_Updated value)? updated, + required TResult orElse(), + }) { + if (created != null) { + return created(this); + } + return orElse(); + } +} + +abstract class _Created implements TableFormEvent { + const factory _Created() = _$CreatedImpl; +} + +/// @nodoc +abstract class _$$UpdatedImplCopyWith<$Res> { factory _$$UpdatedImplCopyWith( _$UpdatedImpl value, $Res Function(_$UpdatedImpl) then, ) = __$$UpdatedImplCopyWithImpl<$Res>; - @override @useResult $Res call({String id, Offset position}); } @@ -174,6 +594,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult when({ + required TResult Function(String name) nameChanged, + required TResult Function(String capacity) capacityChanged, + required TResult Function() created, required TResult Function(String id, Offset position) updated, }) { return updated(id, position); @@ -182,6 +605,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult? whenOrNull({ + TResult? Function(String name)? nameChanged, + TResult? Function(String capacity)? capacityChanged, + TResult? Function()? created, TResult? Function(String id, Offset position)? updated, }) { return updated?.call(id, position); @@ -190,6 +616,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult maybeWhen({ + TResult Function(String name)? nameChanged, + TResult Function(String capacity)? capacityChanged, + TResult Function()? created, TResult Function(String id, Offset position)? updated, required TResult orElse(), }) { @@ -202,6 +631,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult map({ + required TResult Function(_NameChanged value) nameChanged, + required TResult Function(_CapacityChanged value) capacityChanged, + required TResult Function(_Created value) created, required TResult Function(_Updated value) updated, }) { return updated(this); @@ -210,6 +642,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult? mapOrNull({ + TResult? Function(_NameChanged value)? nameChanged, + TResult? Function(_CapacityChanged value)? capacityChanged, + TResult? Function(_Created value)? created, TResult? Function(_Updated value)? updated, }) { return updated?.call(this); @@ -218,6 +653,9 @@ class _$UpdatedImpl implements _Updated { @override @optionalTypeArgs TResult maybeMap({ + TResult Function(_NameChanged value)? nameChanged, + TResult Function(_CapacityChanged value)? capacityChanged, + TResult Function(_Created value)? created, TResult Function(_Updated value)? updated, required TResult orElse(), }) { @@ -234,14 +672,11 @@ abstract class _Updated implements TableFormEvent { required final Offset position, }) = _$UpdatedImpl; - @override String get id; - @override Offset get position; /// Create a copy of TableFormEvent /// with the given fields replaced by the non-null parameter values. - @override @JsonKey(includeFromJson: false, includeToJson: false) _$$UpdatedImplCopyWith<_$UpdatedImpl> get copyWith => throw _privateConstructorUsedError; @@ -249,9 +684,12 @@ abstract class _Updated implements TableFormEvent { /// @nodoc mixin _$TableFormState { + String get name => throw _privateConstructorUsedError; + int get capacity => throw _privateConstructorUsedError; Option> get failureOrTable => throw _privateConstructorUsedError; bool get isUpdating => throw _privateConstructorUsedError; + bool get isCreating => throw _privateConstructorUsedError; /// Create a copy of TableFormState /// with the given fields replaced by the non-null parameter values. @@ -268,8 +706,11 @@ abstract class $TableFormStateCopyWith<$Res> { ) = _$TableFormStateCopyWithImpl<$Res, TableFormState>; @useResult $Res call({ + String name, + int capacity, Option> failureOrTable, bool isUpdating, + bool isCreating, }); } @@ -287,9 +728,23 @@ class _$TableFormStateCopyWithImpl<$Res, $Val extends TableFormState> /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override - $Res call({Object? failureOrTable = null, Object? isUpdating = null}) { + $Res call({ + Object? name = null, + Object? capacity = null, + Object? failureOrTable = null, + Object? isUpdating = null, + Object? isCreating = null, + }) { return _then( _value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + capacity: null == capacity + ? _value.capacity + : capacity // ignore: cast_nullable_to_non_nullable + as int, failureOrTable: null == failureOrTable ? _value.failureOrTable : failureOrTable // ignore: cast_nullable_to_non_nullable @@ -298,6 +753,10 @@ class _$TableFormStateCopyWithImpl<$Res, $Val extends TableFormState> ? _value.isUpdating : isUpdating // ignore: cast_nullable_to_non_nullable as bool, + isCreating: null == isCreating + ? _value.isCreating + : isCreating // ignore: cast_nullable_to_non_nullable + as bool, ) as $Val, ); @@ -314,8 +773,11 @@ abstract class _$$TableFormStateImplCopyWith<$Res> @override @useResult $Res call({ + String name, + int capacity, Option> failureOrTable, bool isUpdating, + bool isCreating, }); } @@ -332,9 +794,23 @@ class __$$TableFormStateImplCopyWithImpl<$Res> /// with the given fields replaced by the non-null parameter values. @pragma('vm:prefer-inline') @override - $Res call({Object? failureOrTable = null, Object? isUpdating = null}) { + $Res call({ + Object? name = null, + Object? capacity = null, + Object? failureOrTable = null, + Object? isUpdating = null, + Object? isCreating = null, + }) { return _then( _$TableFormStateImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + capacity: null == capacity + ? _value.capacity + : capacity // ignore: cast_nullable_to_non_nullable + as int, failureOrTable: null == failureOrTable ? _value.failureOrTable : failureOrTable // ignore: cast_nullable_to_non_nullable @@ -343,6 +819,10 @@ class __$$TableFormStateImplCopyWithImpl<$Res> ? _value.isUpdating : isUpdating // ignore: cast_nullable_to_non_nullable as bool, + isCreating: null == isCreating + ? _value.isCreating + : isCreating // ignore: cast_nullable_to_non_nullable + as bool, ), ); } @@ -351,17 +831,30 @@ class __$$TableFormStateImplCopyWithImpl<$Res> /// @nodoc class _$TableFormStateImpl implements _TableFormState { - _$TableFormStateImpl({required this.failureOrTable, this.isUpdating = false}); + _$TableFormStateImpl({ + required this.name, + required this.capacity, + required this.failureOrTable, + this.isUpdating = false, + this.isCreating = false, + }); + @override + final String name; + @override + final int capacity; @override final Option> failureOrTable; @override @JsonKey() final bool isUpdating; + @override + @JsonKey() + final bool isCreating; @override String toString() { - return 'TableFormState(failureOrTable: $failureOrTable, isUpdating: $isUpdating)'; + return 'TableFormState(name: $name, capacity: $capacity, failureOrTable: $failureOrTable, isUpdating: $isUpdating, isCreating: $isCreating)'; } @override @@ -369,14 +862,26 @@ class _$TableFormStateImpl implements _TableFormState { return identical(this, other) || (other.runtimeType == runtimeType && other is _$TableFormStateImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.capacity, capacity) || + other.capacity == capacity) && (identical(other.failureOrTable, failureOrTable) || other.failureOrTable == failureOrTable) && (identical(other.isUpdating, isUpdating) || - other.isUpdating == isUpdating)); + other.isUpdating == isUpdating) && + (identical(other.isCreating, isCreating) || + other.isCreating == isCreating)); } @override - int get hashCode => Object.hash(runtimeType, failureOrTable, isUpdating); + int get hashCode => Object.hash( + runtimeType, + name, + capacity, + failureOrTable, + isUpdating, + isCreating, + ); /// Create a copy of TableFormState /// with the given fields replaced by the non-null parameter values. @@ -392,14 +897,23 @@ class _$TableFormStateImpl implements _TableFormState { abstract class _TableFormState implements TableFormState { factory _TableFormState({ + required final String name, + required final int capacity, required final Option> failureOrTable, final bool isUpdating, + final bool isCreating, }) = _$TableFormStateImpl; + @override + String get name; + @override + int get capacity; @override Option> get failureOrTable; @override bool get isUpdating; + @override + bool get isCreating; /// Create a copy of TableFormState /// with the given fields replaced by the non-null parameter values. diff --git a/lib/application/table/table_form/table_form_event.dart b/lib/application/table/table_form/table_form_event.dart index bcbd296..86f4b24 100644 --- a/lib/application/table/table_form/table_form_event.dart +++ b/lib/application/table/table_form/table_form_event.dart @@ -2,6 +2,10 @@ part of 'table_form_bloc.dart'; @freezed class TableFormEvent with _$TableFormEvent { + const factory TableFormEvent.nameChanged(String name) = _NameChanged; + const factory TableFormEvent.capacityChanged(String capacity) = + _CapacityChanged; + const factory TableFormEvent.created() = _Created; const factory TableFormEvent.updated({ required String id, required Offset position, diff --git a/lib/application/table/table_form/table_form_state.dart b/lib/application/table/table_form/table_form_state.dart index ac33258..e9dbf88 100644 --- a/lib/application/table/table_form/table_form_state.dart +++ b/lib/application/table/table_form/table_form_state.dart @@ -3,9 +3,13 @@ part of 'table_form_bloc.dart'; @freezed class TableFormState with _$TableFormState { factory TableFormState({ + required String name, + required int capacity, required Option> failureOrTable, @Default(false) bool isUpdating, + @Default(false) bool isCreating, }) = _TableFormState; - factory TableFormState.initial() => TableFormState(failureOrTable: none()); + factory TableFormState.initial() => + TableFormState(failureOrTable: none(), name: '', capacity: 0); } diff --git a/lib/domain/table/repositories/i_table_repository.dart b/lib/domain/table/repositories/i_table_repository.dart index 6e53a28..d2dcb9c 100644 --- a/lib/domain/table/repositories/i_table_repository.dart +++ b/lib/domain/table/repositories/i_table_repository.dart @@ -6,6 +6,11 @@ abstract class ITableRepository { int limit = 50, }); + Future> createTable({ + required String name, + required int capacity, + }); + Future> updatePosition({ required String id, required Offset position, diff --git a/lib/infrastructure/outlet/repositories/outlet_repository.dart b/lib/infrastructure/outlet/repositories/outlet_repository.dart index dd62f4c..45170a5 100644 --- a/lib/infrastructure/outlet/repositories/outlet_repository.dart +++ b/lib/infrastructure/outlet/repositories/outlet_repository.dart @@ -52,6 +52,7 @@ class OutletRepository implements IOutletRepository { return left(result.error!); } + await _localDataProvider.saveCurrentOutlet(result.data!); final outlet = result.data!.toDomain(); return right(outlet); } catch (e, s) { diff --git a/lib/infrastructure/table/datasources/remote_data_provider.dart b/lib/infrastructure/table/datasources/remote_data_provider.dart index 835f6ee..db3114a 100644 --- a/lib/infrastructure/table/datasources/remote_data_provider.dart +++ b/lib/infrastructure/table/datasources/remote_data_provider.dart @@ -44,6 +44,38 @@ class TableRemoteDataProvider { } } + Future> storeTable({ + required String outletId, + required String name, + required int capacity, + }) async { + try { + final response = await _apiClient.post( + ApiPath.tables, + data: { + 'outlet_id': outletId, + 'table_name': name, + 'capacity': capacity, + 'position_x': 200, + 'position_y': 200, + }, + headers: getAuthorizationHeader(), + ); + + if (response.data['success'] == false) { + return DC.error(TableFailure.unexpectedError()); + } + + final table = TableDto.fromJson( + response.data['data'] as Map, + ); + return DC.data(table); + } on ApiFailure catch (e, s) { + log('storeTableError', name: _logName, error: e, stackTrace: s); + return DC.error(TableFailure.serverError(e)); + } + } + Future> updatePosition({ required String id, required Offset position, diff --git a/lib/infrastructure/table/repositories/table_repository.dart b/lib/infrastructure/table/repositories/table_repository.dart index 0ff90be..01477bb 100644 --- a/lib/infrastructure/table/repositories/table_repository.dart +++ b/lib/infrastructure/table/repositories/table_repository.dart @@ -5,14 +5,16 @@ import 'package:dartz/dartz.dart'; import 'package:injectable/injectable.dart'; import '../../../domain/table/table.dart'; +import '../../outlet/datasources/local_data_provider.dart'; import '../datasources/remote_data_provider.dart'; @Injectable(as: ITableRepository) class TableRepository implements ITableRepository { final TableRemoteDataProvider _remoteDataProvider; + final OutletLocalDatasource _outletLocalDatasource; final _logName = 'TableRepository'; - TableRepository(this._remoteDataProvider); + TableRepository(this._remoteDataProvider, this._outletLocalDatasource); @override Future> fetchTables({ @@ -38,6 +40,33 @@ class TableRepository implements ITableRepository { } } + @override + Future> createTable({ + required String name, + required int capacity, + }) async { + try { + final outlet = await _outletLocalDatasource.currentOutlet(); + + final result = await _remoteDataProvider.storeTable( + outletId: outlet.id, + name: name, + capacity: capacity, + ); + + if (result.hasError) { + return left(result.error!); + } + + final table = result.data!.toDomain(); + + return right(table); + } catch (e) { + log('fetchCreateTable', name: _logName, error: e); + return left(const TableFailure.unexpectedError()); + } + } + @override Future> updatePosition({ required String id, diff --git a/lib/injection.config.dart b/lib/injection.config.dart index 5a50c5b..7296fb6 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -149,6 +149,18 @@ extension GetItInjectableX on _i174.GetIt { gh<_i708.CategoryLocalDataProvider>(), ), ); + gh.factory<_i983.ITableRepository>( + () => _i824.TableRepository( + gh<_i95.TableRemoteDataProvider>(), + gh<_i693.OutletLocalDatasource>(), + ), + ); + gh.factory<_i424.TableLoaderBloc>( + () => _i424.TableLoaderBloc(gh<_i983.ITableRepository>()), + ); + gh.factory<_i248.TableFormBloc>( + () => _i248.TableFormBloc(gh<_i983.ITableRepository>()), + ); gh.factory<_i44.IProductRepository>( () => _i763.ProductRepository( gh<_i707.ProductRemoteDataProvider>(), @@ -167,9 +179,6 @@ extension GetItInjectableX on _i174.GetIt { gh.factory<_i1018.CategoryLoaderBloc>( () => _i1018.CategoryLoaderBloc(gh<_i502.ICategoryRepository>()), ); - gh.factory<_i983.ITableRepository>( - () => _i824.TableRepository(gh<_i95.TableRemoteDataProvider>()), - ); gh.factory<_i343.AuthBloc>( () => _i343.AuthBloc( gh<_i776.IAuthRepository>(), @@ -188,12 +197,6 @@ extension GetItInjectableX on _i174.GetIt { gh<_i502.ICategoryRepository>(), ), ); - gh.factory<_i424.TableLoaderBloc>( - () => _i424.TableLoaderBloc(gh<_i983.ITableRepository>()), - ); - gh.factory<_i248.TableFormBloc>( - () => _i248.TableFormBloc(gh<_i983.ITableRepository>()), - ); return this; } } diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index 76c5bf4..3af7498 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -6,6 +6,8 @@ import '../application/category/category_loader/category_loader_bloc.dart'; import '../application/checkout/checkout_form/checkout_form_bloc.dart'; import '../application/outlet/outlet_loader/outlet_loader_bloc.dart'; import '../application/product/product_loader/product_loader_bloc.dart'; +import '../application/table/table_form/table_form_bloc.dart'; +import '../application/table/table_loader/table_loader_bloc.dart'; import '../common/theme/theme.dart'; import '../common/constant/app_constant.dart'; import '../injection.dart'; @@ -31,6 +33,8 @@ class _AppWidgetState extends State { BlocProvider(create: (context) => getIt()), BlocProvider(create: (context) => getIt()), BlocProvider(create: (context) => getIt()), + BlocProvider(create: (context) => getIt()), + BlocProvider(create: (context) => getIt()), ], child: MaterialApp.router( debugShowCheckedModeBanner: false, diff --git a/lib/presentation/components/dialog/table/table_create_dialog.dart b/lib/presentation/components/dialog/table/table_create_dialog.dart new file mode 100644 index 0000000..4d8e036 --- /dev/null +++ b/lib/presentation/components/dialog/table/table_create_dialog.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../application/table/table_form/table_form_bloc.dart'; +import '../../button/button.dart'; +import '../../field/field.dart'; +import '../../spaces/space.dart'; +import '../dialog.dart'; + +class TableCreateDialog extends StatelessWidget { + const TableCreateDialog({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return CustomModalDialog( + title: 'Tambah Meja', + subtitle: 'Silahkan isi data meja', + contentPadding: const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 24.0, + ), + child: Column( + children: [ + AppTextFormField( + label: 'Nama Meja', + onChanged: (value) { + context.read().add( + TableFormEvent.nameChanged(value), + ); + }, + ), + SpaceHeight(16), + AppTextFormField( + label: 'Kapasitas', + keyboardType: TextInputType.number, + onChanged: (value) { + context.read().add( + TableFormEvent.capacityChanged(value), + ); + }, + ), + SpaceHeight(24), + AppElevatedButton.filled( + onPressed: () { + context.read().add( + const TableFormEvent.created(), + ); + }, + label: "Simpan", + isLoading: state.isCreating, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/presentation/components/toast/flushbar.dart b/lib/presentation/components/toast/flushbar.dart index 2141699..756f368 100644 --- a/lib/presentation/components/toast/flushbar.dart +++ b/lib/presentation/components/toast/flushbar.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/auth/auth.dart'; +import '../../../domain/table/table.dart'; class AppFlushbar { static void showSuccess(BuildContext context, String message) { @@ -50,4 +51,18 @@ class AppFlushbar { unexpectedError: (value) => 'Terjadi kesalahan, silahkan coba lagi', ), ); + + static void showTableFailureToast( + BuildContext context, + TableFailure failure, + ) => showError( + context, + failure.map( + serverError: (value) => value.failure.toStringFormatted(context), + dynamicErrorMessage: (value) => value.erroMessage, + unexpectedError: (value) => 'Terjadi kesalahan, silahkan coba lagi', + empty: (value) => 'Tidak ada data', + localStorageError: (value) => 'Terjadi kesalahan, silahkan coba lagi', + ), + ); } diff --git a/lib/presentation/pages/main/pages/table/table_page.dart b/lib/presentation/pages/main/pages/table/table_page.dart index 612c63d..56cde80 100644 --- a/lib/presentation/pages/main/pages/table/table_page.dart +++ b/lib/presentation/pages/main/pages/table/table_page.dart @@ -8,7 +8,9 @@ import '../../../../../common/extension/extension.dart'; import '../../../../../common/theme/theme.dart'; import '../../../../../domain/table/table.dart' as t; import '../../../../../injection.dart'; +import '../../../../components/dialog/table/table_create_dialog.dart'; import '../../../../components/loader/loader_with_text.dart'; +import '../../../../components/toast/flushbar.dart'; import 'widgets/floating_bottom_navbar.dart'; import 'widgets/table_card.dart'; @@ -27,7 +29,6 @@ class TablePage extends StatefulWidget implements AutoRouteWrapper { getIt() ..add(TableLoaderEvent.fetched(isRefresh: true)), ), - BlocProvider(create: (context) => getIt()), ], child: this, ); @@ -43,203 +44,227 @@ class _TablePageState extends State { final double mapWidth = context.deviceWidth * 2; final double mapHeight = context.deviceHeight * 1.5; - return Scaffold( - backgroundColor: AppColor.background, - appBar: AppBar( - title: const Text("Layout Meja"), - backgroundColor: Colors.white, - foregroundColor: Colors.black, - elevation: 0.5, - actions: [ - IconButton( - icon: const Icon(Icons.refresh), - onPressed: () { + return BlocListener( + listenWhen: (previous, current) => + previous.failureOrTable != current.failureOrTable, + listener: (context, state) { + state.failureOrTable.fold(() {}, (either) { + either.fold((f) => AppFlushbar.showTableFailureToast(context, f), ( + success, + ) { + if (context.mounted) { + context.router.maybePop(); context.read().add( - const TableLoaderEvent.fetched(isRefresh: true), + TableLoaderEvent.fetched(isRefresh: true), ); - }, - ), - IconButton( - icon: const Icon(Icons.add), - onPressed: () { - // showDialog( - // context: context, - // builder: (context) => FormTableNewDialog(), - // ); - }, - ), - ], - bottom: PreferredSize( - preferredSize: const Size.fromHeight(20), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), - child: Row( - children: [ - _buildLegendDot(Colors.blue[200]!, "Available"), - const SizedBox(width: 16), - _buildLegendDot(Colors.orange[200]!, "Occupied"), - ], + } + }); + }); + }, + child: Scaffold( + backgroundColor: AppColor.background, + appBar: AppBar( + title: const Text("Layout Meja"), + backgroundColor: Colors.white, + foregroundColor: Colors.black, + elevation: 0.5, + actions: [ + IconButton( + icon: const Icon(Icons.refresh), + onPressed: () { + context.read().add( + const TableLoaderEvent.fetched(isRefresh: true), + ); + }, + ), + IconButton( + icon: const Icon(Icons.add), + onPressed: () { + showDialog( + context: context, + builder: (context) => TableCreateDialog(), + ); + }, + ), + ], + bottom: PreferredSize( + preferredSize: const Size.fromHeight(20), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Row( + children: [ + _buildLegendDot(Colors.blue[200]!, "Available"), + const SizedBox(width: 16), + _buildLegendDot(Colors.orange[200]!, "Occupied"), + ], + ), ), ), ), - ), - body: BlocBuilder( - builder: (context, state) { - if (state.isFetching) { - return const Center(child: LoaderWithText()); - } - return SafeArea( - child: Stack( - children: [ - Row( - children: [ - Expanded( - flex: 5, - child: InteractiveViewer( - panEnabled: true, - scaleEnabled: true, - constrained: false, - boundaryMargin: const EdgeInsets.all(80), - minScale: 0.3, - maxScale: 3.0, - alignment: Alignment.topLeft, - child: Container( - width: mapWidth, - height: mapHeight, - decoration: BoxDecoration( - color: const Color(0xFFF7F8FA), - border: Border.all( - color: Colors.grey[300]!, - width: 2, + body: BlocBuilder( + builder: (context, state) { + if (state.isFetching) { + return const Center(child: LoaderWithText()); + } + return SafeArea( + child: Stack( + children: [ + Row( + children: [ + Expanded( + flex: 5, + child: InteractiveViewer( + panEnabled: true, + scaleEnabled: true, + constrained: false, + boundaryMargin: const EdgeInsets.all(80), + minScale: 0.3, + maxScale: 3.0, + alignment: Alignment.topLeft, + child: Container( + width: mapWidth, + height: mapHeight, + decoration: BoxDecoration( + color: const Color(0xFFF7F8FA), + border: Border.all( + color: Colors.grey[300]!, + width: 2, + ), ), - ), - child: Stack( - children: [ - ...List.generate( - 20, - (i) => Positioned( - left: i * 100.0, - top: 0, - bottom: 0, - child: Container( - width: 1, - color: Colors.grey[200], + child: Stack( + children: [ + ...List.generate( + 20, + (i) => Positioned( + left: i * 100.0, + top: 0, + bottom: 0, + child: Container( + width: 1, + color: Colors.grey[200], + ), ), ), - ), - ...List.generate( - 15, - (i) => Positioned( - top: i * 100.0, - left: 0, - right: 0, - child: Container( - height: 1, - color: Colors.grey[200], + ...List.generate( + 15, + (i) => Positioned( + top: i * 100.0, + left: 0, + right: 0, + child: Container( + height: 1, + color: Colors.grey[200], + ), ), ), - ), - ...state.tables.map((table) { - final isSelected = state.selectedTable == table; - return Positioned( - left: table.positionX, - top: table.positionY, - child: Draggable( - data: table, - feedback: Material( - color: Colors.transparent, - child: TableCard( - table: table, - isSelected: isSelected, - ), - ), - childWhenDragging: Opacity( - opacity: 0.5, - child: TableCard( - table: table, - isSelected: isSelected, - ), - ), - onDragStarted: () { - setState(() { - draggingTable = table; - }); - }, - onDraggableCanceled: (velocity, offset) { - setState(() { - draggingTable = null; - }); - }, - onDragEnd: (details) { - final RenderBox box = - context.findRenderObject() - as RenderBox; - final Offset local = box.globalToLocal( - details.offset, - ); - - final newX = local.dx.clamp( - 0.0, - mapWidth - 120, - ); - final newY = local.dy.clamp( - 0.0, - mapHeight - 80, - ); - - setState(() { - draggingTable = null; - }); - - // Update position locally in bloc state - context.read().add( - TableLoaderEvent.updatedPostion( - id: table.id, - position: Offset(newX, newY), + ...state.tables.map((table) { + final isSelected = + state.selectedTable == table; + return Positioned( + left: table.positionX, + top: table.positionY, + child: Draggable( + data: table, + feedback: Material( + color: Colors.transparent, + child: TableCard( + table: table, + isSelected: isSelected, ), - ); - context.read().add( - TableFormEvent.updated( - id: table.id, - position: Offset(newX, newY), + ), + childWhenDragging: Opacity( + opacity: 0.5, + child: TableCard( + table: table, + isSelected: isSelected, ), - ); - }, - child: GestureDetector( - onTap: () { + ), + onDragStarted: () { + setState(() { + draggingTable = table; + }); + }, + onDraggableCanceled: (velocity, offset) { + setState(() { + draggingTable = null; + }); + }, + onDragEnd: (details) { + final RenderBox box = + context.findRenderObject() + as RenderBox; + final Offset local = box.globalToLocal( + details.offset, + ); + + final newX = local.dx.clamp( + 0.0, + mapWidth - 120, + ); + final newY = local.dy.clamp( + 0.0, + mapHeight - 80, + ); + + setState(() { + draggingTable = null; + }); + + // Update position locally in bloc state context.read().add( - TableLoaderEvent.setSelectedTable( - table, + TableLoaderEvent.updatedPostion( + id: table.id, + position: Offset(newX, newY), + ), + ); + context.read().add( + TableFormEvent.updated( + id: table.id, + position: Offset(newX, newY), ), ); }, - onTapDown: (details) => - tapPosition = details.globalPosition, - onLongPress: () { - if (table.status.isOccupied) { - _showPopupMenu(context, table); - } - }, - child: TableCard( - table: table, - isSelected: isSelected, + child: GestureDetector( + onTap: () { + context.read().add( + TableLoaderEvent.setSelectedTable( + table, + ), + ); + }, + onTapDown: (details) => tapPosition = + details.globalPosition, + onLongPress: () { + if (table.status.isOccupied) { + context.read().add( + TableLoaderEvent.setSelectedTable( + null, + ), + ); + _showPopupMenu(context, table); + } + }, + child: TableCard( + table: table, + isSelected: isSelected, + ), ), ), - ), - ); - }), - ], + ); + }), + ], + ), ), ), ), - ), - ], - ), - TableFloatingBottomNavbar(selectedTable: state.selectedTable), - ], - ), - ); - }, + ], + ), + TableFloatingBottomNavbar(selectedTable: state.selectedTable), + ], + ), + ); + }, + ), ), ); }