| import 'package:farm_tpf/data/api/dio_provider.dart'; | import 'package:farm_tpf/data/api/dio_provider.dart'; | ||||
| import 'package:farm_tpf/data/api/rest_client.dart'; | import 'package:farm_tpf/data/api/rest_client.dart'; | ||||
| import 'package:farm_tpf/models/PagedResult.dart'; | import 'package:farm_tpf/models/PagedResult.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp_request.dart'; | |||||
| import 'package:farm_tpf/utils/const_common.dart'; | import 'package:farm_tpf/utils/const_common.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import '../../presentation/screens/codes/models/stamp_type.dart'; | |||||
| import '../../presentation/screens/login/models/request_user.dart'; | import '../../presentation/screens/login/models/request_user.dart'; | ||||
| import '../../presentation/screens/login/models/response_user.dart'; | import '../../presentation/screens/login/models/response_user.dart'; | ||||
| import '../api/app_exception.dart'; | |||||
| class Repository { | class Repository { | ||||
| final dio = DioProvider(); | final dio = DioProvider(); | ||||
| final client = RestClient(dio); | final client = RestClient(dio); | ||||
| return client.getDetailActivityCommon(activityType, activityId); | return client.getDetailActivityCommon(activityType, activityId); | ||||
| } | } | ||||
| // Stamp | |||||
| Future<List<Stamp>> stamps({int page = 0, int size = 20}) async { | |||||
| try { | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-codes/list?page=$page&size=$size&sort=id,desc'; | |||||
| var res = await dio.post(url, data: {}); | |||||
| return (res.data as List).map((e) => Stamp.fromJson(e)).toList(); | |||||
| } catch (e) { | |||||
| rethrow; | |||||
| } | |||||
| } | |||||
| Future<List<StampType>> stampTypes() async { | |||||
| try { | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-example-stamp/dropdown-list'; | |||||
| var res = await dio.get( | |||||
| url, | |||||
| ); | |||||
| return (res.data as List).map((e) => StampType.fromJson(e)).toList(); | |||||
| } catch (e) { | |||||
| rethrow; | |||||
| } | |||||
| } | |||||
| Future<void> createStamp( | |||||
| Function(dynamic) onSuccess, | |||||
| Function(String) onError, { | |||||
| required RequestStamp item, | |||||
| }) async { | |||||
| try { | |||||
| var url = '${ConstCommon.baseUrl}/api/tb-codes'; | |||||
| await dio.post(url, data: item).then( | |||||
| (value) { | |||||
| onSuccess(value); | |||||
| }, | |||||
| ).catchError((e) { | |||||
| onError(AppException.handleError(e)); | |||||
| }); | |||||
| } catch (e) { | |||||
| onError(AppException.handleError(e)); | |||||
| } | |||||
| } | |||||
| } | } |
| // import 'package:barcode_scan/barcode_scan.dart'; | // import 'package:barcode_scan/barcode_scan.dart'; | ||||
| import 'dart:io'; | import 'dart:io'; | ||||
| import 'package:farm_tpf/data/repository/repository.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/bloc/stamp_bloc.dart'; | |||||
| import 'package:firebase_core/firebase_core.dart'; | import 'package:firebase_core/firebase_core.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:flutter/services.dart'; | import 'package:flutter/services.dart'; | ||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
| import 'package:hive/hive.dart'; | import 'package:hive/hive.dart'; | ||||
| import 'package:path_provider/path_provider.dart'; | import 'package:path_provider/path_provider.dart'; | ||||
| import 'app.dart'; | import 'app.dart'; | ||||
| final appDocumentDirectory = await getApplicationDocumentsDirectory(); | final appDocumentDirectory = await getApplicationDocumentsDirectory(); | ||||
| Hive..init(appDocumentDirectory.path); | Hive..init(appDocumentDirectory.path); | ||||
| await Hive.openBox('LocalDBName'); | await Hive.openBox('LocalDBName'); | ||||
| runApp(App( | |||||
| authenticationRepository: AuthenticationRepository(), | |||||
| )); | |||||
| runApp( | |||||
| MultiBlocProvider( | |||||
| providers: [ | |||||
| BlocProvider( | |||||
| create: (_) => StampBloc( | |||||
| Repository(), | |||||
| ), | |||||
| ), | |||||
| ], | |||||
| child: App( | |||||
| authenticationRepository: AuthenticationRepository(), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | } |
| import 'package:bloc/bloc.dart'; | |||||
| import 'package:equatable/equatable.dart'; | |||||
| import '../../../../data/api/app_exception.dart'; | |||||
| import '../../../../data/repository/repository.dart'; | |||||
| part 'stamp_event.dart'; | |||||
| part 'stamp_state.dart'; | |||||
| class StampBloc extends Bloc<StampEvent, StampState> { | |||||
| final Repository repository; | |||||
| int pageSize = 20; | |||||
| StampBloc(this.repository) : super(StampInitial()); | |||||
| @override | |||||
| Stream<StampState> mapEventToState( | |||||
| StampEvent event, | |||||
| ) async* { | |||||
| if (event is DataFetched && !(state is StampSuccess && ((state as StampSuccess).hasReachedMax ?? false))) { | |||||
| try { | |||||
| if (state is StampInitial) { | |||||
| yield (StampLoading()); | |||||
| final response = await repository.stamps(page: 0); | |||||
| yield StampSuccess( | |||||
| items: response, | |||||
| page: 0, | |||||
| hasReachedMax: response.length < pageSize ? true : false, | |||||
| ); | |||||
| } | |||||
| if (state is StampSuccess) { | |||||
| final currentState = state as StampSuccess; | |||||
| int page = (currentState.page ?? 0) + 1; | |||||
| final response = await repository.stamps(page: page); | |||||
| yield response.isEmpty | |||||
| ? currentState.copyWith(hasReachedMax: true) | |||||
| : StampSuccess( | |||||
| items: (currentState.items ?? []) + response, | |||||
| page: (currentState.page ?? 0) + 1, | |||||
| hasReachedMax: false, | |||||
| ); | |||||
| } | |||||
| } catch (e) { | |||||
| var errorString = AppException.handleError(e); | |||||
| yield (StampFailure(errorString: errorString)); | |||||
| } | |||||
| } | |||||
| if (event is OnRefresh) { | |||||
| try { | |||||
| yield (StampLoading()); | |||||
| final response = await repository.stamps(page: 0); | |||||
| yield StampSuccess( | |||||
| items: response, | |||||
| page: 0, | |||||
| hasReachedMax: response.length < pageSize ? true : false, | |||||
| ); | |||||
| } catch (e) { | |||||
| yield (StampFailure(errorString: AppException.handleError(e))); | |||||
| } | |||||
| } else if (event is OnSearch) { | |||||
| try { | |||||
| yield (StampLoading()); | |||||
| final response = await repository.stamps(page: 0); | |||||
| yield StampSuccess(items: response, page: 0, hasReachedMax: response.length < pageSize ? true : false); | |||||
| } catch (e) { | |||||
| yield (StampFailure(errorString: AppException.handleError(e))); | |||||
| } | |||||
| } | |||||
| } | |||||
| } |
| part of 'stamp_bloc.dart'; | |||||
| abstract class StampEvent extends Equatable { | |||||
| const StampEvent(); | |||||
| @override | |||||
| List<Object> get props => []; | |||||
| } | |||||
| class DataFetched extends StampEvent {} | |||||
| class OnRefresh extends StampEvent {} | |||||
| class OnSearch extends StampEvent { | |||||
| final String searchString; | |||||
| OnSearch({required this.searchString}); | |||||
| } |
| part of 'stamp_bloc.dart'; | |||||
| abstract class StampState extends Equatable { | |||||
| const StampState(); | |||||
| @override | |||||
| List<Object> get props => []; | |||||
| } | |||||
| class StampInitial extends StampState {} | |||||
| class StampLoading extends StampState {} | |||||
| class StampFailure extends StampState { | |||||
| final String errorString; | |||||
| StampFailure({required this.errorString}); | |||||
| } | |||||
| class StampSuccess<T> extends StampState { | |||||
| final List<T>? items; | |||||
| final int? page; | |||||
| final bool? hasReachedMax; | |||||
| const StampSuccess({this.items, this.page, this.hasReachedMax}); | |||||
| StampSuccess copyWith({List<T>? items, int? page, bool? hasReachedMax}) { | |||||
| return StampSuccess( | |||||
| items: items ?? this.items, | |||||
| page: page ?? this.page, | |||||
| hasReachedMax: hasReachedMax ?? this.hasReachedMax, | |||||
| ); | |||||
| } | |||||
| } |
| import 'package:farm_tpf/data/repository/repository.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/button/button_2_icon.dart'; | import 'package:farm_tpf/presentation/custom_widgets/button/button_2_icon.dart'; | ||||
| import 'package:farm_tpf/presentation/custom_widgets/button/second_button.dart'; | import 'package:farm_tpf/presentation/custom_widgets/button/second_button.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/codes/code_detail_page.dart'; | import 'package:farm_tpf/presentation/screens/codes/code_detail_page.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/codes/create_stamp_page.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/widgets/item_code.dart'; | import 'package:farm_tpf/presentation/screens/codes/widgets/item_code.dart'; | ||||
| import 'package:farm_tpf/themes/app_colors.dart'; | import 'package:farm_tpf/themes/app_colors.dart'; | ||||
| import 'package:flutter/cupertino.dart'; | import 'package:flutter/cupertino.dart'; | ||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
| import 'package:get/get.dart'; | import 'package:get/get.dart'; | ||||
| import '../../../themes/styles_text.dart'; | import '../../../themes/styles_text.dart'; | ||||
| import '../../../utils/const_string.dart'; | |||||
| import '../../custom_widgets/bottom_loader.dart'; | |||||
| import '../../custom_widgets/loading_list_page.dart'; | |||||
| import '../plot/widget_search.dart'; | import '../plot/widget_search.dart'; | ||||
| import 'bloc/stamp_bloc.dart'; | |||||
| class CodePage extends StatefulWidget { | class CodePage extends StatefulWidget { | ||||
| const CodePage({super.key}); | const CodePage({super.key}); | ||||
| class _CodePageState extends State<CodePage> { | class _CodePageState extends State<CodePage> { | ||||
| final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>(); | ||||
| StampBloc bloc = StampBloc(Repository()); | |||||
| final _scrollController = ScrollController(); | |||||
| final _scrollThreshold = 250.0; | |||||
| @override | |||||
| void initState() { | |||||
| bloc.add(DataFetched()); | |||||
| _scrollController.addListener(() { | |||||
| final maxScroll = _scrollController.position.maxScrollExtent; | |||||
| final currentScroll = _scrollController.position.pixels; | |||||
| if (maxScroll - currentScroll < _scrollThreshold) { | |||||
| bloc.add(DataFetched()); | |||||
| } | |||||
| }); | |||||
| super.initState(); | |||||
| } | |||||
| @override | |||||
| void dispose() { | |||||
| _scrollController.dispose(); | |||||
| super.dispose(); | |||||
| } | |||||
| @override | @override | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| return Scaffold( | return Scaffold( | ||||
| ), | ), | ||||
| const Spacer(), | const Spacer(), | ||||
| SecondButton( | SecondButton( | ||||
| onPressed: () {}, | |||||
| onPressed: () { | |||||
| Get.to(() => CreateStampPage())?.then((value) { | |||||
| if (value != null) { | |||||
| bloc.add(OnRefresh()); | |||||
| } | |||||
| }); | |||||
| }, | |||||
| title: 'Tạo tem', | title: 'Tạo tem', | ||||
| leftIcon: CupertinoIcons.add, | leftIcon: CupertinoIcons.add, | ||||
| color: AppColors.primary1, | color: AppColors.primary1, | ||||
| ], | ], | ||||
| ), | ), | ||||
| Expanded( | Expanded( | ||||
| child: ListView.builder( | |||||
| itemBuilder: ((context, index) { | |||||
| return ItemCode( | |||||
| onPressed: () { | |||||
| Get.to(() => CodeDetailPage()); | |||||
| }, | |||||
| ); | |||||
| }), | |||||
| itemCount: 100, | |||||
| ), | |||||
| child: mainBody(), | |||||
| ), | ), | ||||
| ], | ], | ||||
| ), | ), | ||||
| ), | ), | ||||
| ); | ); | ||||
| } | } | ||||
| Widget mainBody() { | |||||
| return BlocBuilder<StampBloc, StampState>( | |||||
| bloc: bloc, | |||||
| builder: (context, state) { | |||||
| if (state is StampFailure) { | |||||
| return Center(child: Text(state.errorString)); | |||||
| } | |||||
| if (state is StampSuccess) { | |||||
| if ((state.items ?? []).isEmpty) { | |||||
| return Center(child: Text(label_list_empty)); | |||||
| } | |||||
| return RefreshIndicator( | |||||
| child: ListView.builder( | |||||
| physics: AlwaysScrollableScrollPhysics(), | |||||
| itemBuilder: (BuildContext context, int index) { | |||||
| return index >= (state.items ?? []).length | |||||
| ? BottomLoader() | |||||
| : ItemCode( | |||||
| item: state.items?[index], | |||||
| onPressed: () { | |||||
| Get.to(() => CodeDetailPage()); | |||||
| }, | |||||
| ); | |||||
| }, | |||||
| itemCount: (state.hasReachedMax ?? false) ? (state.items ?? []).length : (state.items ?? []).length + 1, | |||||
| controller: _scrollController, | |||||
| ), | |||||
| onRefresh: () async { | |||||
| bloc.add(OnRefresh()); | |||||
| }); | |||||
| } | |||||
| return Center( | |||||
| child: LoadingListPage(), | |||||
| ); | |||||
| }, | |||||
| ); | |||||
| } | |||||
| } | } |
| import 'package:cached_network_image/cached_network_image.dart'; | |||||
| import 'package:farm_tpf/models/item_dropdown.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/widgets/item_column.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:flutter/scheduler.dart'; | |||||
| import 'package:flutter/services.dart'; | |||||
| import 'package:flutter/src/widgets/framework.dart'; | |||||
| import 'package:flutter/src/widgets/placeholder.dart'; | |||||
| import 'package:flutter_bloc/flutter_bloc.dart'; | |||||
| import 'package:get/get.dart'; | |||||
| import 'package:keyboard_dismisser/keyboard_dismisser.dart'; | |||||
| import '../../../utils/utils.dart'; | |||||
| import '../../custom_widgets/app_bar_widget.dart'; | |||||
| import '../../custom_widgets/button_widget.dart'; | |||||
| import '../../custom_widgets/date_picker/date_picker_widget.dart'; | |||||
| import '../../custom_widgets/dropdown/dropdown_bottom_sheet.dart'; | |||||
| import '../../custom_widgets/textfield/text_field_normal.dart'; | |||||
| import 'cubit/create_stamp_cubit.dart'; | |||||
| class CreateStampPage extends StatefulWidget { | |||||
| const CreateStampPage({ | |||||
| super.key, | |||||
| }); | |||||
| @override | |||||
| State<CreateStampPage> createState() => _CreateStampPageState(); | |||||
| } | |||||
| class _CreateStampPageState extends State<CreateStampPage> { | |||||
| final bloc = CreateStampCubit(); | |||||
| @override | |||||
| void initState() { | |||||
| super.initState(); | |||||
| bloc.preparedData(); | |||||
| } | |||||
| @override | |||||
| void dispose() { | |||||
| bloc.dispose(); | |||||
| super.dispose(); | |||||
| } | |||||
| @override | |||||
| Widget build(BuildContext context) { | |||||
| return Scaffold( | |||||
| appBar: AppBarWidget(), | |||||
| body: BlocListener<CreateStampCubit, CreateStampState>( | |||||
| bloc: bloc, | |||||
| listener: ((context, state) { | |||||
| if (state is CreateStampLoading) { | |||||
| SchedulerBinding.instance.addPostFrameCallback((timeStamp) { | |||||
| UtilWidget.showLoading(); | |||||
| }); | |||||
| } else if (state is CreateStampFailure) { | |||||
| SchedulerBinding.instance.addPostFrameCallback((timeStamp) { | |||||
| UtilWidget.hideLoading(); | |||||
| // UtilWidget.showToastError(state.errorMessage); | |||||
| }); | |||||
| } else if (state is CreateStampPrepareDataSuccessful) { | |||||
| SchedulerBinding.instance.addPostFrameCallback((timeStamp) { | |||||
| UtilWidget.hideLoading(); | |||||
| }); | |||||
| } | |||||
| }), | |||||
| child: KeyboardDismisser( | |||||
| child: Container( | |||||
| child: Form( | |||||
| key: bloc.formKey, | |||||
| child: Column( | |||||
| children: [ | |||||
| Expanded( | |||||
| child: _widgetBody(), | |||||
| ), | |||||
| Padding( | |||||
| padding: const EdgeInsets.all(8.0), | |||||
| child: ButtonWidget( | |||||
| title: 'Cập nhật', | |||||
| onPressed: () { | |||||
| bloc.onSubmit(); | |||||
| }, | |||||
| ), | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| Widget _widgetBody() { | |||||
| return Container( | |||||
| padding: const EdgeInsets.all(16), | |||||
| child: SingleChildScrollView( | |||||
| child: Column( | |||||
| crossAxisAlignment: CrossAxisAlignment.start, | |||||
| children: [ | |||||
| ItemColumnWidget( | |||||
| title: 'Mô tả', | |||||
| child: TextFieldNormal( | |||||
| controller: bloc.descriptionCtl, | |||||
| maxLines: 1, | |||||
| hint: 'Mô tả', | |||||
| ), | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 8, | |||||
| ), | |||||
| ItemColumnWidget( | |||||
| title: 'Số lượng tem', | |||||
| child: TextFieldNormal( | |||||
| controller: bloc.quantityCtl, | |||||
| maxLines: 1, | |||||
| hint: 'Số lượng tem', | |||||
| ), | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 8, | |||||
| ), | |||||
| ItemColumnWidget( | |||||
| title: 'Hạn sử dụng (ngày)', | |||||
| child: TextFieldNormal( | |||||
| controller: bloc.expiredDateCtl, | |||||
| maxLines: 1, | |||||
| keyboardType: TextInputType.number, | |||||
| inputFormatters: [ | |||||
| FilteringTextInputFormatter.digitsOnly, | |||||
| ], | |||||
| hint: 'Hạn sử dụng (ngày)', | |||||
| ), | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 8, | |||||
| ), | |||||
| ItemColumnWidget( | |||||
| title: 'Mẫu tem', | |||||
| child: ValueListenableBuilder<String>( | |||||
| valueListenable: bloc.selectedStampType, | |||||
| builder: (context, selected, _) { | |||||
| return ValueListenableBuilder<List<ItemDropDown>>( | |||||
| valueListenable: bloc.stampTypes, | |||||
| builder: (context, types, _) { | |||||
| return DropdownBottomSheet( | |||||
| dataSources: types, | |||||
| initValue: selected, | |||||
| onSelected: (val) { | |||||
| bloc.selectedStampType.value = val.key ?? ''; | |||||
| }, | |||||
| hint: 'Mẫu tem', | |||||
| ); | |||||
| }, | |||||
| ); | |||||
| }, | |||||
| ), | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 8, | |||||
| ), | |||||
| ValueListenableBuilder<String>( | |||||
| valueListenable: bloc.selectedStampType, | |||||
| builder: (context, selected, _) { | |||||
| if (selected.isEmpty) { | |||||
| return const SizedBox.shrink(); | |||||
| } | |||||
| var stamp = bloc.stampTypeRaws.firstWhere( | |||||
| (e) => selected == e.id?.toString(), | |||||
| orElse: () => StampType(), | |||||
| ); | |||||
| return Container( | |||||
| child: CachedNetworkImage( | |||||
| imageUrl: stamp.exampleStampImage ?? '', | |||||
| width: Get.width, | |||||
| height: Get.width / 2, | |||||
| fit: BoxFit.contain, | |||||
| placeholder: (context, url) => Icon( | |||||
| Icons.image, | |||||
| size: 100, | |||||
| color: Colors.grey[200], | |||||
| ), | |||||
| errorWidget: (context, url, _) => Icon( | |||||
| Icons.image_not_supported, | |||||
| size: 100, | |||||
| color: Colors.grey[200], | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| }, | |||||
| ), | |||||
| const SizedBox( | |||||
| height: 16, | |||||
| ), | |||||
| ], | |||||
| ), | |||||
| ), | |||||
| ); | |||||
| } | |||||
| } |
| import 'package:bloc/bloc.dart'; | |||||
| import 'package:equatable/equatable.dart'; | |||||
| import 'package:farm_tpf/presentation/custom_widgets/widget_utils.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp_request.dart'; | |||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart'; | |||||
| import 'package:farm_tpf/utils/formatter.dart'; | |||||
| import 'package:flutter/material.dart'; | |||||
| import 'package:get/get.dart'; | |||||
| import '../../../../data/api/app_exception.dart'; | |||||
| import '../../../../data/repository/repository.dart'; | |||||
| import '../../../../models/item_dropdown.dart'; | |||||
| import '../../../../utils/utils.dart'; | |||||
| part 'create_stamp_state.dart'; | |||||
| class CreateStampCubit extends Cubit<CreateStampState> { | |||||
| CreateStampCubit() : super(CreateStampInitial()); | |||||
| final repository = Repository(); | |||||
| final formKey = GlobalKey<FormState>(); | |||||
| final descriptionCtl = TextEditingController(); | |||||
| final quantityCtl = TextEditingController(); | |||||
| final expiredDateCtl = TextEditingController(); | |||||
| var stampTypeRaws = <StampType>[]; | |||||
| var stampTypes = ValueNotifier(<ItemDropDown>[]); | |||||
| var selectedStampType = ValueNotifier(''); | |||||
| // var existedCreateStamp = UpdateCreateStamp(); | |||||
| void dispose() { | |||||
| descriptionCtl.dispose(); | |||||
| quantityCtl.dispose(); | |||||
| expiredDateCtl.dispose(); | |||||
| } | |||||
| Future<void> preparedData() async { | |||||
| try { | |||||
| await Future.delayed(const Duration(seconds: 0)); | |||||
| emit(CreateStampLoading()); | |||||
| stampTypeRaws = await repository.stampTypes(); | |||||
| stampTypes.value = stampTypeRaws | |||||
| .map( | |||||
| (e) => ItemDropDown(key: e.id?.toString(), value: e.exampleStampName), | |||||
| ) | |||||
| .toList(); | |||||
| emit(CreateStampPrepareDataSuccessful()); | |||||
| } catch (e) { | |||||
| emit(CreateStampFailure(AppException.handleError(e))); | |||||
| } | |||||
| } | |||||
| Future<void> onSubmit() async { | |||||
| if (formKey.currentState!.validate()) { | |||||
| var requestStamp = RequestStamp(); | |||||
| var stamp = stampTypeRaws.firstWhere( | |||||
| (e) => selectedStampType.value == e.id?.toString(), | |||||
| orElse: () => StampType(), | |||||
| ); | |||||
| var expiredDate = DateTime.now().add(Duration(days: int.tryParse(expiredDateCtl.text) ?? 0)); | |||||
| requestStamp | |||||
| ..description = descriptionCtl.text | |||||
| ..quantity = int.tryParse(quantityCtl.text) ?? 0 | |||||
| ..expiredDate = expiredDate.convertLocalDateTimeToStringUtcDateTime() | |||||
| ..tbExampleStampId = int.tryParse(selectedStampType.value); | |||||
| print(requestStamp.toJson()); | |||||
| UtilWidget.showLoading(); | |||||
| await repository.createStamp( | |||||
| (success) { | |||||
| UtilWidget.hideDialog(); | |||||
| Get.back(result: 'ok'); | |||||
| Utils.showSnackBarSuccess(); | |||||
| }, | |||||
| (errorMessage) { | |||||
| UtilWidget.hideDialog(); | |||||
| Utils.showSnackBarError(); | |||||
| }, | |||||
| item: requestStamp, | |||||
| ); | |||||
| } | |||||
| } | |||||
| } |
| part of 'create_stamp_cubit.dart'; | |||||
| class CreateStampState extends Equatable { | |||||
| const CreateStampState(); | |||||
| @override | |||||
| List<Object> get props => []; | |||||
| } | |||||
| class CreateStampInitial extends CreateStampState {} | |||||
| class CreateStampLoading extends CreateStampState {} | |||||
| class CreateStampFailure extends CreateStampState { | |||||
| final String errorMessage; | |||||
| CreateStampFailure(this.errorMessage); | |||||
| } | |||||
| class CreateStampPrepareDataSuccessful extends CreateStampState { | |||||
| CreateStampPrepareDataSuccessful(); | |||||
| } |
| import '../../../../custom_model/TbCropDTO.dart'; | |||||
| class Stamp { | |||||
| int? id; | |||||
| TbCropDTO? tbCropDTO; | |||||
| String? code; | |||||
| num? quantity; | |||||
| String? description; | |||||
| String? pathImage; | |||||
| String? status; | |||||
| String? expiredDate; | |||||
| String? createdDate; | |||||
| Stamp({ | |||||
| this.id, | |||||
| this.tbCropDTO, | |||||
| this.code, | |||||
| this.quantity, | |||||
| this.description, | |||||
| this.pathImage, | |||||
| this.status, | |||||
| this.expiredDate, | |||||
| this.createdDate, | |||||
| }); | |||||
| Stamp.fromJson(Map<String, dynamic> json) { | |||||
| id = json['id']; | |||||
| tbCropDTO = json['TbCropDTO'] != null ? new TbCropDTO.fromJson(json['TbCropDTO']) : null; | |||||
| code = json['code']; | |||||
| quantity = json['quantity']; | |||||
| description = json['description']; | |||||
| pathImage = json['pathImage']; | |||||
| status = json['status']; | |||||
| expiredDate = json['expiredDate']; | |||||
| createdDate = json['createdDate']; | |||||
| } | |||||
| Map<String, dynamic> toJson() { | |||||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
| data['id'] = this.id; | |||||
| if (this.tbCropDTO != null) { | |||||
| data['TbCropDTO'] = this.tbCropDTO?.toJson(); | |||||
| } | |||||
| data['code'] = this.code; | |||||
| data['quantity'] = this.quantity; | |||||
| data['description'] = this.description; | |||||
| data['pathImage'] = this.pathImage; | |||||
| data['status'] = this.status; | |||||
| data['expiredDate'] = this.expiredDate; | |||||
| data['createdDate'] = this.createdDate; | |||||
| return data; | |||||
| } | |||||
| } |
| class RequestStamp { | |||||
| int? tBCropId; | |||||
| int? tbExampleStampId; | |||||
| int? quantity; | |||||
| String? description; | |||||
| String? expiredDate; | |||||
| RequestStamp({ | |||||
| this.tBCropId, | |||||
| this.tbExampleStampId, | |||||
| this.quantity, | |||||
| this.description, | |||||
| this.expiredDate, | |||||
| }); | |||||
| RequestStamp.fromJson(Map<String, dynamic> json) { | |||||
| tBCropId = json['tBCropId']; | |||||
| tbExampleStampId = json['tbExampleStampId']; | |||||
| quantity = json['quantity']; | |||||
| description = json['description']; | |||||
| expiredDate = json['expiredDate']; | |||||
| } | |||||
| Map<String, dynamic> toJson() { | |||||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
| data['tBCropId'] = this.tBCropId; | |||||
| data['tbExampleStampId'] = this.tbExampleStampId; | |||||
| data['quantity'] = this.quantity; | |||||
| data['description'] = this.description; | |||||
| data['expiredDate'] = this.expiredDate; | |||||
| return data; | |||||
| } | |||||
| } |
| class StampType { | |||||
| int? id; | |||||
| String? exampleStampName; | |||||
| String? exampleStampImage; | |||||
| StampType({this.id, this.exampleStampName, this.exampleStampImage}); | |||||
| StampType.fromJson(Map<String, dynamic> json) { | |||||
| id = json['id']; | |||||
| exampleStampName = json['exampleStampName']; | |||||
| exampleStampImage = json['exampleStampImage']; | |||||
| } | |||||
| Map<String, dynamic> toJson() { | |||||
| final Map<String, dynamic> data = new Map<String, dynamic>(); | |||||
| data['id'] = this.id; | |||||
| data['exampleStampName'] = this.exampleStampName; | |||||
| data['exampleStampImage'] = this.exampleStampImage; | |||||
| return data; | |||||
| } | |||||
| } |
| // ignore_for_file: public_member_api_docs, sort_constructors_first | |||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||
| import 'package:farm_tpf/presentation/screens/codes/models/stamp.dart'; | |||||
| import '../../../../themes/app_colors.dart'; | import '../../../../themes/app_colors.dart'; | ||||
| import '../../../../themes/styles_text.dart'; | import '../../../../themes/styles_text.dart'; | ||||
| import 'package:farm_tpf/utils/formatter.dart'; | |||||
| class ItemCode extends StatelessWidget { | class ItemCode extends StatelessWidget { | ||||
| final Stamp item; | |||||
| final Function onPressed; | final Function onPressed; | ||||
| const ItemCode({ | |||||
| super.key, | |||||
| ItemCode({ | |||||
| Key? key, | |||||
| required this.item, | |||||
| required this.onPressed, | required this.onPressed, | ||||
| }); | |||||
| }) : super(key: key); | |||||
| @override | @override | ||||
| Widget build(BuildContext context) { | Widget build(BuildContext context) { | ||||
| var expiredDate = item.expiredDate?.format_DDMMYY().toString() ?? ''; | |||||
| var quantity = item.quantity; | |||||
| var status = 'mới'; | |||||
| switch (item.status) { | |||||
| case 'NEW': | |||||
| status = 'mới'; | |||||
| break; | |||||
| default: | |||||
| } | |||||
| return GestureDetector( | return GestureDetector( | ||||
| onTap: () { | onTap: () { | ||||
| onPressed(); | onPressed(); | ||||
| crossAxisAlignment: CrossAxisAlignment.start, | crossAxisAlignment: CrossAxisAlignment.start, | ||||
| children: [ | children: [ | ||||
| Text( | Text( | ||||
| 'Cà chua đợt 1 5/2023', | |||||
| item.description ?? '', | |||||
| style: StylesText.body1, | style: StylesText.body1, | ||||
| ), | ), | ||||
| const SizedBox( | const SizedBox( | ||||
| height: 8, | height: 8, | ||||
| ), | ), | ||||
| Text( | Text( | ||||
| '06/05/2023 - 1500 tem - mới', | |||||
| '$expiredDate - $quantity tem - $status', | |||||
| style: StylesText.body6, | style: StylesText.body6, | ||||
| ), | ), | ||||
| ], | ], |
| final changeTabbar = Get.put(TabbarSelected()); | final changeTabbar = Get.put(TabbarSelected()); | ||||
| List<TabbarItem> itemsTabbar = [ | List<TabbarItem> itemsTabbar = [ | ||||
| TabbarItem(icon: AppIcons.icPlot, title: 'Lô trồng', index: TabBarIndex.plot), | TabbarItem(icon: AppIcons.icPlot, title: 'Lô trồng', index: TabBarIndex.plot), | ||||
| TabbarItem(icon: AppIcons.icDevice, title: 'Thiết bị', index: TabBarIndex.device), | |||||
| // TabbarItem(icon: AppIcons.icQrManage, title: 'Quản lý QR', index: TabBarIndex.qrManage), | |||||
| // TabbarItem(icon: AppIcons.icDevice, title: 'Thiết bị', index: TabBarIndex.device), | |||||
| TabbarItem(icon: AppIcons.icQrManage, title: 'Quản lý QR', index: TabBarIndex.qrManage), | |||||
| TabbarItem(icon: AppIcons.icQr, title: 'Quét QR', index: TabBarIndex.qr), | TabbarItem(icon: AppIcons.icQr, title: 'Quét QR', index: TabBarIndex.qr), | ||||
| TabbarItem(icon: AppIcons.icNotification, title: 'Thông báo', index: TabBarIndex.notification), | TabbarItem(icon: AppIcons.icNotification, title: 'Thông báo', index: TabBarIndex.notification), | ||||
| TabbarItem(icon: AppIcons.icPerson, title: 'Cá nhân', index: TabBarIndex.account) | TabbarItem(icon: AppIcons.icPerson, title: 'Cá nhân', index: TabBarIndex.account) | ||||
| case TabBarIndex.plot: | case TabBarIndex.plot: | ||||
| return PlotListScreen(); | return PlotListScreen(); | ||||
| break; | break; | ||||
| case TabBarIndex.device: | |||||
| return ControlDeviceScreen(); | |||||
| break; | |||||
| // case TabBarIndex.qrManage: | |||||
| // return CodePage(); | |||||
| // case TabBarIndex.device: | |||||
| // return ControlDeviceScreen(); | |||||
| // break; | // break; | ||||
| case TabBarIndex.qrManage: | |||||
| return CodePage(); | |||||
| break; | |||||
| case TabBarIndex.qr: | case TabBarIndex.qr: | ||||
| return Container(); | return Container(); | ||||
| break; | break; | ||||
| enum TabBarIndex { | enum TabBarIndex { | ||||
| plot, | plot, | ||||
| device, | |||||
| // qrManage, | |||||
| // device, | |||||
| qrManage, | |||||
| qr, | qr, | ||||
| notification, | notification, | ||||
| account, | account, |
| } | } | ||||
| } | } | ||||
| String format_DDMMYY() { | |||||
| try { | |||||
| final str = this.toString(); | |||||
| var dateFromString = DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(str, true).toLocal(); | |||||
| return DateFormat("dd/MM/yyyy").format(dateFromString); | |||||
| } catch (_) { | |||||
| return ""; | |||||
| } | |||||
| } | |||||
| DateTime convertStringServerDateTimeToLocalDateTime() { | DateTime convertStringServerDateTimeToLocalDateTime() { | ||||
| try { | try { | ||||
| return DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(this, true).toLocal(); | return DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(this, true).toLocal(); |