You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
7.8KB

  1. import 'package:cached_network_image/cached_network_image.dart';
  2. import 'package:farm_tpf/models/item_dropdown.dart';
  3. import 'package:farm_tpf/presentation/screens/codes/models/stamp_type.dart';
  4. import 'package:farm_tpf/presentation/screens/codes/widgets/item_column.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:flutter/scheduler.dart';
  7. import 'package:flutter/services.dart';
  8. import 'package:flutter/src/widgets/framework.dart';
  9. import 'package:flutter/src/widgets/placeholder.dart';
  10. import 'package:flutter_bloc/flutter_bloc.dart';
  11. import 'package:get/get.dart';
  12. import 'package:keyboard_dismisser/keyboard_dismisser.dart';
  13. import '../../../utils/utils.dart';
  14. import '../../custom_widgets/app_bar_widget.dart';
  15. import '../../custom_widgets/button_widget.dart';
  16. import '../../custom_widgets/date_picker/date_picker_widget.dart';
  17. import '../../custom_widgets/dropdown/dropdown_bottom_sheet.dart';
  18. import '../../custom_widgets/textfield/text_field_normal.dart';
  19. import 'cubit/create_stamp_cubit.dart';
  20. class CreateStampPage extends StatefulWidget {
  21. const CreateStampPage({
  22. super.key,
  23. });
  24. @override
  25. State<CreateStampPage> createState() => _CreateStampPageState();
  26. }
  27. class _CreateStampPageState extends State<CreateStampPage> {
  28. final bloc = CreateStampCubit();
  29. @override
  30. void initState() {
  31. super.initState();
  32. bloc.preparedData();
  33. }
  34. @override
  35. void dispose() {
  36. bloc.dispose();
  37. super.dispose();
  38. }
  39. @override
  40. Widget build(BuildContext context) {
  41. return Scaffold(
  42. appBar: AppBarWidget(),
  43. body: BlocListener<CreateStampCubit, CreateStampState>(
  44. bloc: bloc,
  45. listener: ((context, state) {
  46. if (state is CreateStampLoading) {
  47. SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
  48. UtilWidget.showLoading();
  49. });
  50. } else if (state is CreateStampFailure) {
  51. SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
  52. UtilWidget.hideLoading();
  53. // UtilWidget.showToastError(state.errorMessage);
  54. });
  55. } else if (state is CreateStampPrepareDataSuccessful) {
  56. SchedulerBinding.instance.addPostFrameCallback((timeStamp) {
  57. UtilWidget.hideLoading();
  58. });
  59. }
  60. }),
  61. child: KeyboardDismisser(
  62. child: Container(
  63. child: Form(
  64. key: bloc.formKey,
  65. child: Column(
  66. children: [
  67. Expanded(
  68. child: _widgetBody(),
  69. ),
  70. Padding(
  71. padding: const EdgeInsets.all(8.0),
  72. child: ButtonWidget(
  73. title: 'Cập nhật',
  74. onPressed: () {
  75. bloc.onSubmit();
  76. },
  77. ),
  78. ),
  79. ],
  80. ),
  81. ),
  82. ),
  83. ),
  84. ),
  85. );
  86. }
  87. Widget _widgetBody() {
  88. return Container(
  89. padding: const EdgeInsets.all(16),
  90. child: SingleChildScrollView(
  91. child: Column(
  92. crossAxisAlignment: CrossAxisAlignment.start,
  93. children: [
  94. ItemColumnWidget(
  95. title: 'Lô',
  96. child: ValueListenableBuilder<String>(
  97. valueListenable: bloc.selectedPlot,
  98. builder: (context, selected, _) {
  99. return ValueListenableBuilder<List<ItemDropDown>>(
  100. valueListenable: bloc.plots,
  101. builder: (context, plots, _) {
  102. return DropdownBottomSheet(
  103. dataSources: plots,
  104. initValue: selected,
  105. onSelected: (val) {
  106. bloc.selectedPlot.value = val.key ?? '';
  107. },
  108. hint: 'Lô',
  109. );
  110. },
  111. );
  112. },
  113. ),
  114. ),
  115. const SizedBox(
  116. height: 8,
  117. ),
  118. ItemColumnWidget(
  119. title: 'Tên sản phẩm',
  120. child: TextFieldNormal(
  121. controller: bloc.productNameCtl,
  122. maxLines: 1,
  123. hint: 'Tên sản phẩm',
  124. ),
  125. ),
  126. const SizedBox(
  127. height: 8,
  128. ),
  129. ItemColumnWidget(
  130. title: 'Mô tả',
  131. child: TextFieldNormal(
  132. controller: bloc.descriptionCtl,
  133. maxLines: 1,
  134. hint: 'Mô tả',
  135. ),
  136. ),
  137. const SizedBox(
  138. height: 8,
  139. ),
  140. ItemColumnWidget(
  141. title: 'Số lượng tem',
  142. child: TextFieldNormal(
  143. controller: bloc.quantityCtl,
  144. keyboardType: TextInputType.number,
  145. inputFormatters: [
  146. FilteringTextInputFormatter.digitsOnly,
  147. ],
  148. maxLines: 1,
  149. hint: 'Số lượng tem',
  150. ),
  151. ),
  152. const SizedBox(
  153. height: 8,
  154. ),
  155. ItemColumnWidget(
  156. title: 'Hạn sử dụng (ngày)',
  157. child: TextFieldNormal(
  158. controller: bloc.expiredDateCtl,
  159. maxLines: 1,
  160. keyboardType: TextInputType.number,
  161. inputFormatters: [
  162. FilteringTextInputFormatter.digitsOnly,
  163. ],
  164. hint: 'Hạn sử dụng (ngày)',
  165. ),
  166. ),
  167. const SizedBox(
  168. height: 8,
  169. ),
  170. ItemColumnWidget(
  171. title: 'Mẫu tem',
  172. child: ValueListenableBuilder<String>(
  173. valueListenable: bloc.selectedStampType,
  174. builder: (context, selected, _) {
  175. return ValueListenableBuilder<List<ItemDropDown>>(
  176. valueListenable: bloc.stampTypes,
  177. builder: (context, types, _) {
  178. return DropdownBottomSheet(
  179. dataSources: types,
  180. initValue: selected,
  181. onSelected: (val) {
  182. bloc.selectedStampType.value = val.key ?? '';
  183. },
  184. hint: 'Mẫu tem',
  185. );
  186. },
  187. );
  188. },
  189. ),
  190. ),
  191. const SizedBox(
  192. height: 8,
  193. ),
  194. ValueListenableBuilder<String>(
  195. valueListenable: bloc.selectedStampType,
  196. builder: (context, selected, _) {
  197. if (selected.isEmpty) {
  198. return const SizedBox.shrink();
  199. }
  200. var stamp = bloc.stampTypeRaws.firstWhere(
  201. (e) => selected == e.id?.toString(),
  202. orElse: () => StampType(),
  203. );
  204. return Container(
  205. child: CachedNetworkImage(
  206. imageUrl: stamp.exampleStampImage ?? '',
  207. width: Get.width,
  208. height: Get.width / 2,
  209. fit: BoxFit.contain,
  210. placeholder: (context, url) => Icon(
  211. Icons.image,
  212. size: 100,
  213. color: Colors.grey[200],
  214. ),
  215. errorWidget: (context, url, _) => Icon(
  216. Icons.image_not_supported,
  217. size: 100,
  218. color: Colors.grey[200],
  219. ),
  220. ),
  221. );
  222. },
  223. ),
  224. const SizedBox(
  225. height: 16,
  226. ),
  227. ],
  228. ),
  229. ),
  230. );
  231. }
  232. }