diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/lib/application/sync/sync_setting/sync_setting_bloc.dart b/lib/application/sync/sync_setting/sync_setting_bloc.dart new file mode 100644 index 0000000..89cbd47 --- /dev/null +++ b/lib/application/sync/sync_setting/sync_setting_bloc.dart @@ -0,0 +1,234 @@ +import 'package:bloc/bloc.dart'; +import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:injectable/injectable.dart'; + +import '../../../domain/category/category.dart'; +import '../../../domain/product/product.dart'; + +part 'sync_setting_event.dart'; +part 'sync_setting_state.dart'; +part 'sync_setting_bloc.freezed.dart'; + +@injectable +class SyncSettingBloc extends Bloc { + final IProductRepository _productRepository; + final ICategoryRepository _categoryRepository; + + SyncSettingBloc(this._productRepository, this._categoryRepository) + : super(SyncSettingState.initial()) { + on(_onSyncSettingEvent); + } + + Future _onSyncSettingEvent( + SyncSettingEvent event, + Emitter emit, + ) { + return event.map( + loadStats: (e) => _onLoadStats(emit), + syncAllData: (e) => _onSyncAllData(emit), + clearAllData: (e) => _onClearAllData(emit), + syncProducts: (e) => _onSyncProducts(emit), + syncCategories: (e) => _onSyncCategories(emit), + clearCategories: (e) => _onClearCategories(emit), + clearProducts: (e) => _onClearProducts(emit), + ); + } + + Future _onLoadStats(Emitter emit) async { + emit( + state.copyWith( + isLoading: true, + failureOptionProduct: none(), + failureOptionCategory: none(), + ), + ); + + final productStats = await _productRepository.getDatabaseStats(); + final categoryStats = await _categoryRepository.getDatabaseStats(); + + productStats.fold( + (failure) { + emit( + state.copyWith( + isLoading: false, + failureOptionProduct: optionOf(failure), + ), + ); + }, + (data) { + emit( + state.copyWith( + isLoading: false, + productStats: data, + failureOptionProduct: none(), + ), + ); + }, + ); + + categoryStats.fold( + (failure) { + emit( + state.copyWith( + isLoading: false, + failureOptionCategory: optionOf(failure), + ), + ); + }, + (data) { + emit( + state.copyWith( + isLoading: false, + categoryStats: data, + failureOptionCategory: none(), + ), + ); + }, + ); + } + + Future _onSyncAllData(Emitter emit) async { + emit( + state.copyWith( + isSyncing: true, + failureOptionSyncCategory: none(), + failureOptionSyncProduct: none(), + ), + ); + + // Sync categories first + final categoryResult = await _categoryRepository.syncAllCategories(); + + bool categorySuccess = false; + categoryResult.fold( + (failure) { + emit( + state.copyWith(failureOptionSyncCategory: optionOf(left(failure))), + ); + }, + (success) { + categorySuccess = true; + emit( + state.copyWith(failureOptionSyncCategory: optionOf(right(success))), + ); + }, + ); + + // Only sync products if categories synced successfully + if (categorySuccess) { + final productResult = await _productRepository.syncAllProducts(); + + productResult.fold( + (failure) { + emit( + state.copyWith( + isSyncing: false, + failureOptionSyncProduct: optionOf(left(failure)), + ), + ); + }, + (success) { + emit( + state.copyWith( + isSyncing: false, + failureOptionSyncProduct: optionOf(right(success)), + ), + ); + }, + ); + } else { + emit(state.copyWith(isSyncing: false)); + } + + // Reload stats after sync + add(const SyncSettingEvent.loadStats()); + } + + Future _onClearAllData(Emitter emit) async { + emit(state.copyWith(isLoading: true)); + + try { + // Clear products and categories + await _productRepository.clearAllProducts(); + await _categoryRepository.clearAllCategories(); + + // Clear caches + _productRepository.clearCache(); + _categoryRepository.clearCache(); + + emit(state.copyWith(isLoading: false)); + + // Reload stats after clearing + add(const SyncSettingEvent.loadStats()); + } catch (e) { + emit(state.copyWith(isLoading: false)); + } + } + + Future _onSyncProducts(Emitter emit) async { + emit(state.copyWith(isLoading: true, failureOptionSyncProduct: none())); + + final result = await _productRepository.syncAllProducts(); + + result.fold( + (failure) { + emit( + state.copyWith( + isLoading: false, + failureOptionSyncProduct: optionOf(left(failure)), + ), + ); + }, + (success) { + emit( + state.copyWith( + isLoading: false, + failureOptionSyncProduct: optionOf(right(success)), + ), + ); + }, + ); + + // Reload stats after sync + add(const SyncSettingEvent.loadStats()); + } + + Future _onSyncCategories(Emitter emit) async { + emit(state.copyWith(isLoading: true, failureOptionSyncCategory: none())); + + final result = await _categoryRepository.syncAllCategories(); + + result.fold( + (failure) { + emit( + state.copyWith( + isLoading: false, + failureOptionSyncCategory: optionOf(left(failure)), + ), + ); + }, + (success) { + emit( + state.copyWith( + isLoading: false, + failureOptionSyncCategory: optionOf(right(success)), + ), + ); + }, + ); + + // Reload stats after sync + add(const SyncSettingEvent.loadStats()); + } + + Future _onClearCategories(Emitter emit) async { + await _categoryRepository.clearAllCategories(); + _categoryRepository.clearCache(); + } + + Future _onClearProducts(Emitter emit) async { + await _productRepository.clearAllProducts(); + _productRepository.clearCache(); + } +} diff --git a/lib/application/sync/sync_setting/sync_setting_bloc.freezed.dart b/lib/application/sync/sync_setting/sync_setting_bloc.freezed.dart new file mode 100644 index 0000000..e9d04c1 --- /dev/null +++ b/lib/application/sync/sync_setting/sync_setting_bloc.freezed.dart @@ -0,0 +1,1399 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'sync_setting_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models', +); + +/// @nodoc +mixin _$SyncSettingEvent { + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) => throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SyncSettingEventCopyWith<$Res> { + factory $SyncSettingEventCopyWith( + SyncSettingEvent value, + $Res Function(SyncSettingEvent) then, + ) = _$SyncSettingEventCopyWithImpl<$Res, SyncSettingEvent>; +} + +/// @nodoc +class _$SyncSettingEventCopyWithImpl<$Res, $Val extends SyncSettingEvent> + implements $SyncSettingEventCopyWith<$Res> { + _$SyncSettingEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc +abstract class _$$LoadStatsImplCopyWith<$Res> { + factory _$$LoadStatsImplCopyWith( + _$LoadStatsImpl value, + $Res Function(_$LoadStatsImpl) then, + ) = __$$LoadStatsImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$LoadStatsImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$LoadStatsImpl> + implements _$$LoadStatsImplCopyWith<$Res> { + __$$LoadStatsImplCopyWithImpl( + _$LoadStatsImpl _value, + $Res Function(_$LoadStatsImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$LoadStatsImpl implements _LoadStats { + const _$LoadStatsImpl(); + + @override + String toString() { + return 'SyncSettingEvent.loadStats()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$LoadStatsImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return loadStats(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return loadStats?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (loadStats != null) { + return loadStats(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return loadStats(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return loadStats?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (loadStats != null) { + return loadStats(this); + } + return orElse(); + } +} + +abstract class _LoadStats implements SyncSettingEvent { + const factory _LoadStats() = _$LoadStatsImpl; +} + +/// @nodoc +abstract class _$$SyncAllDataImplCopyWith<$Res> { + factory _$$SyncAllDataImplCopyWith( + _$SyncAllDataImpl value, + $Res Function(_$SyncAllDataImpl) then, + ) = __$$SyncAllDataImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SyncAllDataImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$SyncAllDataImpl> + implements _$$SyncAllDataImplCopyWith<$Res> { + __$$SyncAllDataImplCopyWithImpl( + _$SyncAllDataImpl _value, + $Res Function(_$SyncAllDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SyncAllDataImpl implements _SyncAllData { + const _$SyncAllDataImpl(); + + @override + String toString() { + return 'SyncSettingEvent.syncAllData()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SyncAllDataImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return syncAllData(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return syncAllData?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (syncAllData != null) { + return syncAllData(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return syncAllData(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return syncAllData?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (syncAllData != null) { + return syncAllData(this); + } + return orElse(); + } +} + +abstract class _SyncAllData implements SyncSettingEvent { + const factory _SyncAllData() = _$SyncAllDataImpl; +} + +/// @nodoc +abstract class _$$ClearAllDataImplCopyWith<$Res> { + factory _$$ClearAllDataImplCopyWith( + _$ClearAllDataImpl value, + $Res Function(_$ClearAllDataImpl) then, + ) = __$$ClearAllDataImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ClearAllDataImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$ClearAllDataImpl> + implements _$$ClearAllDataImplCopyWith<$Res> { + __$$ClearAllDataImplCopyWithImpl( + _$ClearAllDataImpl _value, + $Res Function(_$ClearAllDataImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$ClearAllDataImpl implements _ClearAllData { + const _$ClearAllDataImpl(); + + @override + String toString() { + return 'SyncSettingEvent.clearAllData()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$ClearAllDataImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return clearAllData(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return clearAllData?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (clearAllData != null) { + return clearAllData(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return clearAllData(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return clearAllData?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (clearAllData != null) { + return clearAllData(this); + } + return orElse(); + } +} + +abstract class _ClearAllData implements SyncSettingEvent { + const factory _ClearAllData() = _$ClearAllDataImpl; +} + +/// @nodoc +abstract class _$$SyncProductsImplCopyWith<$Res> { + factory _$$SyncProductsImplCopyWith( + _$SyncProductsImpl value, + $Res Function(_$SyncProductsImpl) then, + ) = __$$SyncProductsImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SyncProductsImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$SyncProductsImpl> + implements _$$SyncProductsImplCopyWith<$Res> { + __$$SyncProductsImplCopyWithImpl( + _$SyncProductsImpl _value, + $Res Function(_$SyncProductsImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SyncProductsImpl implements _SyncProducts { + const _$SyncProductsImpl(); + + @override + String toString() { + return 'SyncSettingEvent.syncProducts()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SyncProductsImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return syncProducts(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return syncProducts?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (syncProducts != null) { + return syncProducts(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return syncProducts(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return syncProducts?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (syncProducts != null) { + return syncProducts(this); + } + return orElse(); + } +} + +abstract class _SyncProducts implements SyncSettingEvent { + const factory _SyncProducts() = _$SyncProductsImpl; +} + +/// @nodoc +abstract class _$$SyncCategoriesImplCopyWith<$Res> { + factory _$$SyncCategoriesImplCopyWith( + _$SyncCategoriesImpl value, + $Res Function(_$SyncCategoriesImpl) then, + ) = __$$SyncCategoriesImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$SyncCategoriesImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$SyncCategoriesImpl> + implements _$$SyncCategoriesImplCopyWith<$Res> { + __$$SyncCategoriesImplCopyWithImpl( + _$SyncCategoriesImpl _value, + $Res Function(_$SyncCategoriesImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$SyncCategoriesImpl implements _SyncCategories { + const _$SyncCategoriesImpl(); + + @override + String toString() { + return 'SyncSettingEvent.syncCategories()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$SyncCategoriesImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return syncCategories(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return syncCategories?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (syncCategories != null) { + return syncCategories(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return syncCategories(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return syncCategories?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (syncCategories != null) { + return syncCategories(this); + } + return orElse(); + } +} + +abstract class _SyncCategories implements SyncSettingEvent { + const factory _SyncCategories() = _$SyncCategoriesImpl; +} + +/// @nodoc +abstract class _$$ClearCategoriesImplCopyWith<$Res> { + factory _$$ClearCategoriesImplCopyWith( + _$ClearCategoriesImpl value, + $Res Function(_$ClearCategoriesImpl) then, + ) = __$$ClearCategoriesImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ClearCategoriesImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$ClearCategoriesImpl> + implements _$$ClearCategoriesImplCopyWith<$Res> { + __$$ClearCategoriesImplCopyWithImpl( + _$ClearCategoriesImpl _value, + $Res Function(_$ClearCategoriesImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$ClearCategoriesImpl implements _ClearCategories { + const _$ClearCategoriesImpl(); + + @override + String toString() { + return 'SyncSettingEvent.clearCategories()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$ClearCategoriesImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return clearCategories(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return clearCategories?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (clearCategories != null) { + return clearCategories(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return clearCategories(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return clearCategories?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (clearCategories != null) { + return clearCategories(this); + } + return orElse(); + } +} + +abstract class _ClearCategories implements SyncSettingEvent { + const factory _ClearCategories() = _$ClearCategoriesImpl; +} + +/// @nodoc +abstract class _$$ClearProductsImplCopyWith<$Res> { + factory _$$ClearProductsImplCopyWith( + _$ClearProductsImpl value, + $Res Function(_$ClearProductsImpl) then, + ) = __$$ClearProductsImplCopyWithImpl<$Res>; +} + +/// @nodoc +class __$$ClearProductsImplCopyWithImpl<$Res> + extends _$SyncSettingEventCopyWithImpl<$Res, _$ClearProductsImpl> + implements _$$ClearProductsImplCopyWith<$Res> { + __$$ClearProductsImplCopyWithImpl( + _$ClearProductsImpl _value, + $Res Function(_$ClearProductsImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingEvent + /// with the given fields replaced by the non-null parameter values. +} + +/// @nodoc + +class _$ClearProductsImpl implements _ClearProducts { + const _$ClearProductsImpl(); + + @override + String toString() { + return 'SyncSettingEvent.clearProducts()'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && other is _$ClearProductsImpl); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() loadStats, + required TResult Function() syncAllData, + required TResult Function() clearAllData, + required TResult Function() syncProducts, + required TResult Function() syncCategories, + required TResult Function() clearCategories, + required TResult Function() clearProducts, + }) { + return clearProducts(); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function()? loadStats, + TResult? Function()? syncAllData, + TResult? Function()? clearAllData, + TResult? Function()? syncProducts, + TResult? Function()? syncCategories, + TResult? Function()? clearCategories, + TResult? Function()? clearProducts, + }) { + return clearProducts?.call(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? loadStats, + TResult Function()? syncAllData, + TResult Function()? clearAllData, + TResult Function()? syncProducts, + TResult Function()? syncCategories, + TResult Function()? clearCategories, + TResult Function()? clearProducts, + required TResult orElse(), + }) { + if (clearProducts != null) { + return clearProducts(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(_LoadStats value) loadStats, + required TResult Function(_SyncAllData value) syncAllData, + required TResult Function(_ClearAllData value) clearAllData, + required TResult Function(_SyncProducts value) syncProducts, + required TResult Function(_SyncCategories value) syncCategories, + required TResult Function(_ClearCategories value) clearCategories, + required TResult Function(_ClearProducts value) clearProducts, + }) { + return clearProducts(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(_LoadStats value)? loadStats, + TResult? Function(_SyncAllData value)? syncAllData, + TResult? Function(_ClearAllData value)? clearAllData, + TResult? Function(_SyncProducts value)? syncProducts, + TResult? Function(_SyncCategories value)? syncCategories, + TResult? Function(_ClearCategories value)? clearCategories, + TResult? Function(_ClearProducts value)? clearProducts, + }) { + return clearProducts?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(_LoadStats value)? loadStats, + TResult Function(_SyncAllData value)? syncAllData, + TResult Function(_ClearAllData value)? clearAllData, + TResult Function(_SyncProducts value)? syncProducts, + TResult Function(_SyncCategories value)? syncCategories, + TResult Function(_ClearCategories value)? clearCategories, + TResult Function(_ClearProducts value)? clearProducts, + required TResult orElse(), + }) { + if (clearProducts != null) { + return clearProducts(this); + } + return orElse(); + } +} + +abstract class _ClearProducts implements SyncSettingEvent { + const factory _ClearProducts() = _$ClearProductsImpl; +} + +/// @nodoc +mixin _$SyncSettingState { + Map get productStats => throw _privateConstructorUsedError; + Map get categoryStats => throw _privateConstructorUsedError; + Option get failureOptionCategory => + throw _privateConstructorUsedError; + Option get failureOptionProduct => + throw _privateConstructorUsedError; + Option> get failureOptionSyncProduct => + throw _privateConstructorUsedError; + Option> get failureOptionSyncCategory => + throw _privateConstructorUsedError; + bool get isSyncing => throw _privateConstructorUsedError; + bool get isLoading => throw _privateConstructorUsedError; + + /// Create a copy of SyncSettingState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $SyncSettingStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $SyncSettingStateCopyWith<$Res> { + factory $SyncSettingStateCopyWith( + SyncSettingState value, + $Res Function(SyncSettingState) then, + ) = _$SyncSettingStateCopyWithImpl<$Res, SyncSettingState>; + @useResult + $Res call({ + Map productStats, + Map categoryStats, + Option failureOptionCategory, + Option failureOptionProduct, + Option> failureOptionSyncProduct, + Option> failureOptionSyncCategory, + bool isSyncing, + bool isLoading, + }); +} + +/// @nodoc +class _$SyncSettingStateCopyWithImpl<$Res, $Val extends SyncSettingState> + implements $SyncSettingStateCopyWith<$Res> { + _$SyncSettingStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of SyncSettingState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productStats = null, + Object? categoryStats = null, + Object? failureOptionCategory = null, + Object? failureOptionProduct = null, + Object? failureOptionSyncProduct = null, + Object? failureOptionSyncCategory = null, + Object? isSyncing = null, + Object? isLoading = null, + }) { + return _then( + _value.copyWith( + productStats: null == productStats + ? _value.productStats + : productStats // ignore: cast_nullable_to_non_nullable + as Map, + categoryStats: null == categoryStats + ? _value.categoryStats + : categoryStats // ignore: cast_nullable_to_non_nullable + as Map, + failureOptionCategory: null == failureOptionCategory + ? _value.failureOptionCategory + : failureOptionCategory // ignore: cast_nullable_to_non_nullable + as Option, + failureOptionProduct: null == failureOptionProduct + ? _value.failureOptionProduct + : failureOptionProduct // ignore: cast_nullable_to_non_nullable + as Option, + failureOptionSyncProduct: null == failureOptionSyncProduct + ? _value.failureOptionSyncProduct + : failureOptionSyncProduct // ignore: cast_nullable_to_non_nullable + as Option>, + failureOptionSyncCategory: null == failureOptionSyncCategory + ? _value.failureOptionSyncCategory + : failureOptionSyncCategory // ignore: cast_nullable_to_non_nullable + as Option>, + isSyncing: null == isSyncing + ? _value.isSyncing + : isSyncing // ignore: cast_nullable_to_non_nullable + as bool, + isLoading: null == isLoading + ? _value.isLoading + : isLoading // ignore: cast_nullable_to_non_nullable + as bool, + ) + as $Val, + ); + } +} + +/// @nodoc +abstract class _$$SyncSettingStateImplCopyWith<$Res> + implements $SyncSettingStateCopyWith<$Res> { + factory _$$SyncSettingStateImplCopyWith( + _$SyncSettingStateImpl value, + $Res Function(_$SyncSettingStateImpl) then, + ) = __$$SyncSettingStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({ + Map productStats, + Map categoryStats, + Option failureOptionCategory, + Option failureOptionProduct, + Option> failureOptionSyncProduct, + Option> failureOptionSyncCategory, + bool isSyncing, + bool isLoading, + }); +} + +/// @nodoc +class __$$SyncSettingStateImplCopyWithImpl<$Res> + extends _$SyncSettingStateCopyWithImpl<$Res, _$SyncSettingStateImpl> + implements _$$SyncSettingStateImplCopyWith<$Res> { + __$$SyncSettingStateImplCopyWithImpl( + _$SyncSettingStateImpl _value, + $Res Function(_$SyncSettingStateImpl) _then, + ) : super(_value, _then); + + /// Create a copy of SyncSettingState + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? productStats = null, + Object? categoryStats = null, + Object? failureOptionCategory = null, + Object? failureOptionProduct = null, + Object? failureOptionSyncProduct = null, + Object? failureOptionSyncCategory = null, + Object? isSyncing = null, + Object? isLoading = null, + }) { + return _then( + _$SyncSettingStateImpl( + productStats: null == productStats + ? _value._productStats + : productStats // ignore: cast_nullable_to_non_nullable + as Map, + categoryStats: null == categoryStats + ? _value._categoryStats + : categoryStats // ignore: cast_nullable_to_non_nullable + as Map, + failureOptionCategory: null == failureOptionCategory + ? _value.failureOptionCategory + : failureOptionCategory // ignore: cast_nullable_to_non_nullable + as Option, + failureOptionProduct: null == failureOptionProduct + ? _value.failureOptionProduct + : failureOptionProduct // ignore: cast_nullable_to_non_nullable + as Option, + failureOptionSyncProduct: null == failureOptionSyncProduct + ? _value.failureOptionSyncProduct + : failureOptionSyncProduct // ignore: cast_nullable_to_non_nullable + as Option>, + failureOptionSyncCategory: null == failureOptionSyncCategory + ? _value.failureOptionSyncCategory + : failureOptionSyncCategory // ignore: cast_nullable_to_non_nullable + as Option>, + isSyncing: null == isSyncing + ? _value.isSyncing + : isSyncing // ignore: cast_nullable_to_non_nullable + as bool, + isLoading: null == isLoading + ? _value.isLoading + : isLoading // ignore: cast_nullable_to_non_nullable + as bool, + ), + ); + } +} + +/// @nodoc + +class _$SyncSettingStateImpl implements _SyncSettingState { + _$SyncSettingStateImpl({ + required final Map productStats, + required final Map categoryStats, + required this.failureOptionCategory, + required this.failureOptionProduct, + required this.failureOptionSyncProduct, + required this.failureOptionSyncCategory, + this.isSyncing = false, + this.isLoading = false, + }) : _productStats = productStats, + _categoryStats = categoryStats; + + final Map _productStats; + @override + Map get productStats { + if (_productStats is EqualUnmodifiableMapView) return _productStats; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_productStats); + } + + final Map _categoryStats; + @override + Map get categoryStats { + if (_categoryStats is EqualUnmodifiableMapView) return _categoryStats; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(_categoryStats); + } + + @override + final Option failureOptionCategory; + @override + final Option failureOptionProduct; + @override + final Option> failureOptionSyncProduct; + @override + final Option> failureOptionSyncCategory; + @override + @JsonKey() + final bool isSyncing; + @override + @JsonKey() + final bool isLoading; + + @override + String toString() { + return 'SyncSettingState(productStats: $productStats, categoryStats: $categoryStats, failureOptionCategory: $failureOptionCategory, failureOptionProduct: $failureOptionProduct, failureOptionSyncProduct: $failureOptionSyncProduct, failureOptionSyncCategory: $failureOptionSyncCategory, isSyncing: $isSyncing, isLoading: $isLoading)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$SyncSettingStateImpl && + const DeepCollectionEquality().equals( + other._productStats, + _productStats, + ) && + const DeepCollectionEquality().equals( + other._categoryStats, + _categoryStats, + ) && + (identical(other.failureOptionCategory, failureOptionCategory) || + other.failureOptionCategory == failureOptionCategory) && + (identical(other.failureOptionProduct, failureOptionProduct) || + other.failureOptionProduct == failureOptionProduct) && + (identical( + other.failureOptionSyncProduct, + failureOptionSyncProduct, + ) || + other.failureOptionSyncProduct == failureOptionSyncProduct) && + (identical( + other.failureOptionSyncCategory, + failureOptionSyncCategory, + ) || + other.failureOptionSyncCategory == failureOptionSyncCategory) && + (identical(other.isSyncing, isSyncing) || + other.isSyncing == isSyncing) && + (identical(other.isLoading, isLoading) || + other.isLoading == isLoading)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + const DeepCollectionEquality().hash(_productStats), + const DeepCollectionEquality().hash(_categoryStats), + failureOptionCategory, + failureOptionProduct, + failureOptionSyncProduct, + failureOptionSyncCategory, + isSyncing, + isLoading, + ); + + /// Create a copy of SyncSettingState + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$SyncSettingStateImplCopyWith<_$SyncSettingStateImpl> get copyWith => + __$$SyncSettingStateImplCopyWithImpl<_$SyncSettingStateImpl>( + this, + _$identity, + ); +} + +abstract class _SyncSettingState implements SyncSettingState { + factory _SyncSettingState({ + required final Map productStats, + required final Map categoryStats, + required final Option failureOptionCategory, + required final Option failureOptionProduct, + required final Option> + failureOptionSyncProduct, + required final Option> + failureOptionSyncCategory, + final bool isSyncing, + final bool isLoading, + }) = _$SyncSettingStateImpl; + + @override + Map get productStats; + @override + Map get categoryStats; + @override + Option get failureOptionCategory; + @override + Option get failureOptionProduct; + @override + Option> get failureOptionSyncProduct; + @override + Option> get failureOptionSyncCategory; + @override + bool get isSyncing; + @override + bool get isLoading; + + /// Create a copy of SyncSettingState + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$SyncSettingStateImplCopyWith<_$SyncSettingStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/application/sync/sync_setting/sync_setting_event.dart b/lib/application/sync/sync_setting/sync_setting_event.dart new file mode 100644 index 0000000..728a33f --- /dev/null +++ b/lib/application/sync/sync_setting/sync_setting_event.dart @@ -0,0 +1,12 @@ +part of 'sync_setting_bloc.dart'; + +@freezed +class SyncSettingEvent with _$SyncSettingEvent { + const factory SyncSettingEvent.loadStats() = _LoadStats; + const factory SyncSettingEvent.syncAllData() = _SyncAllData; + const factory SyncSettingEvent.clearAllData() = _ClearAllData; + const factory SyncSettingEvent.syncProducts() = _SyncProducts; + const factory SyncSettingEvent.syncCategories() = _SyncCategories; + const factory SyncSettingEvent.clearCategories() = _ClearCategories; + const factory SyncSettingEvent.clearProducts() = _ClearProducts; +} diff --git a/lib/application/sync/sync_setting/sync_setting_state.dart b/lib/application/sync/sync_setting/sync_setting_state.dart new file mode 100644 index 0000000..1129ee3 --- /dev/null +++ b/lib/application/sync/sync_setting/sync_setting_state.dart @@ -0,0 +1,24 @@ +part of 'sync_setting_bloc.dart'; + +@freezed +class SyncSettingState with _$SyncSettingState { + factory SyncSettingState({ + required Map productStats, + required Map categoryStats, + required Option failureOptionCategory, + required Option failureOptionProduct, + required Option> failureOptionSyncProduct, + required Option> failureOptionSyncCategory, + @Default(false) bool isSyncing, + @Default(false) bool isLoading, + }) = _SyncSettingState; + + factory SyncSettingState.initial() => SyncSettingState( + productStats: {}, + categoryStats: {}, + failureOptionCategory: none(), + failureOptionProduct: none(), + failureOptionSyncProduct: none(), + failureOptionSyncCategory: none(), + ); +} diff --git a/lib/injection.config.dart b/lib/injection.config.dart index 64feb5a..a9899fc 100644 --- a/lib/injection.config.dart +++ b/lib/injection.config.dart @@ -63,6 +63,8 @@ import 'package:apskel_pos_flutter_v2/application/report/report_bloc.dart' import 'package:apskel_pos_flutter_v2/application/split_bill/split_bill_form/split_bill_form_bloc.dart' as _i334; import 'package:apskel_pos_flutter_v2/application/sync/sync_bloc.dart' as _i741; +import 'package:apskel_pos_flutter_v2/application/sync/sync_setting/sync_setting_bloc.dart' + as _i729; import 'package:apskel_pos_flutter_v2/application/table/table_form/table_form_bloc.dart' as _i248; import 'package:apskel_pos_flutter_v2/application/table/table_loader/table_loader_bloc.dart' @@ -348,6 +350,12 @@ extension GetItInjectableX on _i174.GetIt { gh<_i502.ICategoryRepository>(), ), ); + gh.factory<_i729.SyncSettingBloc>( + () => _i729.SyncSettingBloc( + gh<_i44.IProductRepository>(), + gh<_i502.ICategoryRepository>(), + ), + ); gh.factory<_i268.ProductAnalyticLoaderBloc>( () => _i268.ProductAnalyticLoaderBloc(gh<_i346.IAnalyticRepository>()), ); diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index 7f562ee..bf43d8c 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -15,6 +15,7 @@ import '../application/printer/print_struck/print_struck_bloc.dart'; import '../application/printer/printer_form/printer_form_bloc.dart'; import '../application/printer/printer_loader/printer_loader_bloc.dart'; import '../application/product/product_loader/product_loader_bloc.dart'; +import '../application/sync/sync_setting/sync_setting_bloc.dart'; import '../application/table/table_form/table_form_bloc.dart'; import '../application/table/table_loader/table_loader_bloc.dart'; import '../application/void/void_form/void_form_bloc.dart'; @@ -55,6 +56,7 @@ class _AppWidgetState extends State { 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/pages/main/pages/setting/sections/setting_sync_section.dart b/lib/presentation/pages/main/pages/setting/sections/setting_sync_section.dart new file mode 100644 index 0000000..2c69e32 --- /dev/null +++ b/lib/presentation/pages/main/pages/setting/sections/setting_sync_section.dart @@ -0,0 +1,511 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import '../../../../../../application/sync/sync_setting/sync_setting_bloc.dart'; +import '../../../../../../common/theme/theme.dart'; +import '../../../../../../injection.dart'; +import '../../../../../components/button/button.dart'; +import '../../../../../components/loader/loader_with_text.dart'; +import '../../../../../components/page/page_title.dart'; +import '../../../../../components/spaces/space.dart'; +import '../../../../../components/toast/flushbar.dart'; + +class SettingSyncSection extends StatelessWidget { + const SettingSyncSection({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => + getIt()..add(const SyncSettingEvent.loadStats()), + child: const _SettingSyncPageContent(), + ); + } +} + +class _SettingSyncPageContent extends StatelessWidget { + const _SettingSyncPageContent(); + + @override + Widget build(BuildContext context) { + return BlocConsumer( + listener: (context, state) { + // Handle product stats failure + state.failureOptionProduct.fold(() {}, (failure) { + AppFlushbar.showError( + context, + 'Gagal memuat stats produk: ${failure.toString()}', + ); + }); + + // Handle category stats failure + state.failureOptionCategory.fold(() {}, (failure) { + AppFlushbar.showError( + context, + 'Gagal memuat stats kategori: ${failure.toString()}', + ); + }); + + // Handle sync product result + state.failureOptionSyncProduct.fold(() {}, (result) { + result.fold( + (failure) { + AppFlushbar.showError( + context, + 'Gagal sync produk: ${failure.toString()}', + ); + }, + (success) { + AppFlushbar.showSuccess(context, success); + }, + ); + }); + + // Handle sync category result + state.failureOptionSyncCategory.fold(() {}, (result) { + result.fold( + (failure) { + AppFlushbar.showError( + context, + 'Gagal sync kategori: ${failure.toString()}', + ); + }, + (success) { + AppFlushbar.showSuccess(context, success); + }, + ); + }); + }, + builder: (context, state) { + return Column( + children: [ + PageTitle( + title: 'Sinkronisasi', + subtitle: 'Sinkronisasi data dengan server', + isBack: false, + ), + Expanded( + child: Material( + color: AppColor.background, + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + children: [ + SpaceHeight(24), + _buildQuickActions(context, state), + SpaceHeight(24), + _buildSyncTables(context, state), + SpaceHeight(24), + _buildDatabaseStats(context, state), + ], + ), + ), + ), + ), + ], + ); + }, + ); + } + + Widget _buildQuickActions(BuildContext context, SyncSettingState state) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade200), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Aksi Cepat', + style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600), + ), + SpaceHeight(16), + Row( + children: [ + Expanded( + child: AppElevatedButton.filled( + onPressed: state.isSyncing || state.isLoading + ? null + : () => _syncAllData(context), + label: state.isSyncing + ? 'Menyinkronkan...' + : 'Sync Semua Data', + ), + ), + SpaceWidth(12), + Expanded( + child: AppElevatedButton.outlined( + onPressed: state.isLoading || state.isSyncing + ? null + : () => _clearAllData(context), + label: 'Hapus Semua Data', + textColor: Colors.red, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildSyncTables(BuildContext context, SyncSettingState state) { + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade200), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Sinkronisasi per Tabel', + style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600), + ), + SpaceHeight(16), + _buildSyncTableItem( + context: context, + state: state, + title: 'Kategori', + subtitle: 'Sinkronkan data kategori produk', + icon: Icons.category, + color: Colors.blue, + count: state.categoryStats['total_categories'] ?? 0, + onSync: () { + context.read().add( + const SyncSettingEvent.syncCategories(), + ); + }, + onClear: () => _clearCategories(context), + ), + SpaceHeight(12), + const Divider(), + SpaceHeight(12), + _buildSyncTableItem( + context: context, + state: state, + title: 'Produk', + subtitle: 'Sinkronkan data produk dan variant', + icon: Icons.inventory_2, + color: Colors.green, + count: state.productStats['total_products'] ?? 0, + onSync: () { + context.read().add( + const SyncSettingEvent.syncProducts(), + ); + }, + onClear: () => _clearProducts(context), + ), + ], + ), + ); + } + + Widget _buildSyncTableItem({ + required BuildContext context, + required SyncSettingState state, + required String title, + required String subtitle, + required IconData icon, + required Color color, + required int count, + required VoidCallback onSync, + required VoidCallback onClear, + }) { + return Row( + children: [ + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Icon(icon, color: color, size: 24), + ), + SpaceWidth(12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + title, + style: AppStyle.md.copyWith(fontWeight: FontWeight.w600), + ), + SpaceWidth(8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 2, + ), + decoration: BoxDecoration( + color: color.withOpacity(0.1), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + '$count', + style: AppStyle.sm.copyWith( + fontWeight: FontWeight.w600, + color: color, + ), + ), + ), + ], + ), + Text( + subtitle, + style: AppStyle.sm.copyWith(color: Colors.grey.shade600), + ), + ], + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: state.isLoading || state.isSyncing ? null : onSync, + icon: const Icon(Icons.sync, size: 20), + tooltip: 'Sync $title', + style: IconButton.styleFrom( + backgroundColor: color.withOpacity(0.1), + foregroundColor: color, + ), + ), + SpaceWidth(4), + IconButton( + onPressed: state.isLoading || state.isSyncing ? null : onClear, + icon: const Icon(Icons.delete_outline, size: 20), + tooltip: 'Hapus $title', + style: IconButton.styleFrom( + backgroundColor: Colors.red.withOpacity(0.1), + foregroundColor: Colors.red, + ), + ), + ], + ), + ], + ); + } + + Widget _buildDatabaseStats(BuildContext context, SyncSettingState state) { + final totalCacheEntries = + (state.productStats['cache_entries'] ?? 0) + + (state.categoryStats['cache_entries'] ?? 0); + final totalDatabaseSize = + (state.productStats['database_size_mb'] ?? 0.0) + + (state.categoryStats['database_size_mb'] ?? 0.0); + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: Colors.grey.shade200), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + 'Statistik Database', + style: AppStyle.lg.copyWith(fontWeight: FontWeight.w600), + ), + const Spacer(), + if (state.isLoading) + Center(child: LoaderWithText()) + else + IconButton( + onPressed: () { + context.read().add( + const SyncSettingEvent.loadStats(), + ); + }, + icon: const Icon(Icons.refresh, size: 20), + tooltip: 'Refresh Stats', + ), + ], + ), + SpaceHeight(16), + if (state.isLoading) + const Center(child: LoaderWithText()) + else + Column( + children: [ + _buildStatRow( + 'Kategori', + state.categoryStats['total_categories']?.toString() ?? '0', + Icons.category, + Colors.blue, + ), + SpaceHeight(8), + _buildStatRow( + 'Produk', + state.productStats['total_products']?.toString() ?? '0', + Icons.inventory_2, + Colors.green, + ), + SpaceHeight(8), + _buildStatRow( + 'Variant', + state.productStats['total_variants']?.toString() ?? '0', + Icons.tune, + Colors.orange, + ), + SpaceHeight(8), + _buildStatRow( + 'Cache Entries', + '$totalCacheEntries', + Icons.memory, + Colors.purple, + ), + SpaceHeight(8), + _buildStatRow( + 'Ukuran Database', + '${totalDatabaseSize.toStringAsFixed(2)} MB', + Icons.storage, + Colors.grey.shade600, + ), + ], + ), + ], + ), + ); + } + + Widget _buildStatRow(String label, String value, IconData icon, Color color) { + return Row( + children: [ + Icon(icon, size: 16, color: color), + SpaceWidth(8), + Expanded( + child: Text( + label, + style: AppStyle.md.copyWith(color: Colors.grey.shade700), + ), + ), + Text( + value, + style: AppStyle.md.copyWith( + fontWeight: FontWeight.w600, + color: color, + ), + ), + ], + ); + } + + Future _syncAllData(BuildContext context) async { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => const AlertDialog( + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CircularProgressIndicator(), + SpaceHeight(16), + Text('Sinkronisasi semua data...'), + ], + ), + ), + ); + + context.read().add(const SyncSettingEvent.syncAllData()); + + // Wait a bit for the sync to complete, then close dialog + await Future.delayed(const Duration(milliseconds: 500)); + if (context.mounted) { + Navigator.of(context).pop(); + } + } + + Future _clearAllData(BuildContext context) async { + final confirmed = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Hapus Semua Data'), + content: const Text( + 'Apakah Anda yakin ingin menghapus semua data lokal? Tindakan ini tidak dapat dibatalkan.', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text('Batal'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text( + 'Hapus', + style: AppStyle.md.copyWith(color: Colors.red), + ), + ), + ], + ), + ); + + if (confirmed == true && context.mounted) { + context.read().add( + const SyncSettingEvent.clearAllData(), + ); + } + } + + Future _clearCategories(BuildContext context) async { + final confirmed = await _showClearConfirmation(context, 'kategori'); + if (confirmed && context.mounted) { + context.read().add( + const SyncSettingEvent.clearCategories(), + ); + AppFlushbar.showSuccess(context, 'Data kategori berhasil dihapus'); + context.read().add(const SyncSettingEvent.loadStats()); + } + } + + Future _clearProducts(BuildContext context) async { + final confirmed = await _showClearConfirmation(context, 'produk'); + if (confirmed && context.mounted) { + context.read().add( + const SyncSettingEvent.clearProducts(), + ); + AppFlushbar.showSuccess(context, 'Data produk berhasil dihapus'); + context.read().add(const SyncSettingEvent.loadStats()); + } + } + + Future _showClearConfirmation( + BuildContext context, + String dataType, + ) async { + return await showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Hapus Data $dataType'), + content: Text( + 'Apakah Anda yakin ingin menghapus semua data $dataType?', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: const Text('Batal'), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text( + 'Hapus', + style: AppStyle.md.copyWith(color: Colors.red), + ), + ), + ], + ), + ) ?? + false; + } +} diff --git a/lib/presentation/pages/main/pages/setting/setting_page.dart b/lib/presentation/pages/main/pages/setting/setting_page.dart index 0d5ceff..47a40f6 100644 --- a/lib/presentation/pages/main/pages/setting/setting_page.dart +++ b/lib/presentation/pages/main/pages/setting/setting_page.dart @@ -6,6 +6,7 @@ import '../../../../../application/printer/printer_bloc.dart'; import '../../../../../common/theme/theme.dart'; import '../../../../../injection.dart'; import 'sections/setting_printer_section.dart'; +import 'sections/setting_sync_section.dart'; import 'widgets/setting_left_panel.dart'; @RoutePage() @@ -25,7 +26,7 @@ class SettingPage extends StatelessWidget implements AutoRouteWrapper { flex: 4, child: switch (state.index) { 0 => SettingPrinterSection(), - 1 => Container(), + 1 => SettingSyncSection(), _ => Container(), }, ),