Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 
 
 

297 linhas
11 KiB

  1. // ignore_for_file: public_member_api_docs, sort_constructors_first
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_gen/gen_l10n/app_localizations.dart';
  4. import 'package:font_awesome_flutter/font_awesome_flutter.dart';
  5. import 'package:go_router/go_router.dart';
  6. import 'package:provider/provider.dart';
  7. import 'package:qadirneyriz/config/config.dart';
  8. import 'package:qadirneyriz/screens/meeting/diolog_meetings_filters.dart';
  9. import 'package:qadirneyriz/screens/meeting/state.dart';
  10. import 'package:qadirneyriz/utils/enums/status.dart';
  11. import 'package:qadirneyriz/utils/tools/tools.dart';
  12. import 'package:qadirneyriz/widgets/card_meeting.dart';
  13. import 'package:qadirneyriz/widgets/custom_appbar.dart';
  14. import 'package:qadirneyriz/widgets/empty_widget.dart';
  15. import 'package:qadirneyriz/widgets/error_widget.dart';
  16. import 'package:qadirneyriz/widgets/icon_button.dart';
  17. import 'package:qadirneyriz/widgets/loading_widget.dart';
  18. import 'package:qadirneyriz/widgets/today_widget.dart';
  19. import 'package:shamsi_date/shamsi_date.dart';
  20. class MeetingsScreen extends StatefulWidget {
  21. const MeetingsScreen({super.key});
  22. @override
  23. State<MeetingsScreen> createState() => _MeetingsScreenState();
  24. }
  25. class _MeetingsScreenState extends State<MeetingsScreen> {
  26. late ScrollController _scrollController;
  27. late MeetingsState meetingsState;
  28. @override
  29. void initState() {
  30. _scrollController = ScrollController();
  31. _scrollController.addListener(_scrollListener);
  32. meetingsState = Provider.of<MeetingsState>(context, listen: false);
  33. Future.delayed(Duration.zero, () async {
  34. await meetingsState.getMeetings();
  35. meetingsState.clearFilters();
  36. });
  37. super.initState();
  38. }
  39. @override
  40. void dispose() {
  41. _scrollController.dispose();
  42. super.dispose();
  43. }
  44. _scrollListener() async {
  45. if (_scrollController.offset >=
  46. _scrollController.position.maxScrollExtent &&
  47. !_scrollController.position.outOfRange) {
  48. if (!meetingsState.pageEndedMeetings) {
  49. await meetingsState.nextPageMeetings(
  50. toDate: meetingsState.toDate,
  51. fromDate: meetingsState.fromDate,
  52. location: meetingsState.selectedLocationId,
  53. subject: meetingsState.selectedSubjectId,
  54. meetingManager: meetingsState.selectedManagersId,
  55. meetingStatus: meetingsState.selectedStatusId);
  56. }
  57. }
  58. }
  59. @override
  60. Widget build(BuildContext context) {
  61. Jalali nowShamsi = Jalali.now();
  62. String todayDateForShow =
  63. '${nowShamsi.day} ${Tools.getMonthName(nowShamsi.month)} ${nowShamsi.year}';
  64. return Consumer<MeetingsState>(
  65. builder: (context, value, child) {
  66. return CustomScrollView(
  67. controller: _scrollController,
  68. slivers: <Widget>[
  69. const CustomAppbar(),
  70. SliverToBoxAdapter(
  71. child: TodayWidget(formattedDate: todayDateForShow),
  72. ),
  73. SliverToBoxAdapter(
  74. child: Padding(
  75. padding:
  76. const EdgeInsets.symmetric(vertical: 30, horizontal: 15),
  77. child: Row(
  78. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  79. crossAxisAlignment: CrossAxisAlignment.center,
  80. children: [
  81. Text(
  82. style: const TextStyle(fontSize: 14),
  83. AppLocalizations.of(context)!.meetings,
  84. ),
  85. IconButtonCustom(
  86. iconColor: value.hasActiveFilters()
  87. ? Colors.white
  88. : config.ui.secendGreen,
  89. backColor: value.hasActiveFilters()
  90. ? config.ui.secendGreen
  91. : Colors.white,
  92. icon: FontAwesomeIcons.sliders,
  93. onTap: () {
  94. showModalBottomSheet(
  95. isScrollControlled: true,
  96. useSafeArea: true,
  97. context: context,
  98. builder: (context) {
  99. return DiologMeetingsFilters();
  100. },
  101. );
  102. },
  103. )
  104. ],
  105. ),
  106. ),
  107. ),
  108. meetingsList(value),
  109. (value.paginationMeetings == Status.ready ||
  110. value.paginationMeetings == Status.empty)
  111. ? const SliverToBoxAdapter()
  112. : const SliverToBoxAdapter(
  113. child: Center(
  114. child: LoadingWidget(
  115. size: 10,
  116. ),
  117. ),
  118. )
  119. ],
  120. );
  121. },
  122. );
  123. }
  124. Widget meetingsList(MeetingsState state) {
  125. switch (state.statusMeetings) {
  126. case Status.ready:
  127. return SliverList.builder(
  128. itemBuilder: (context, index) {
  129. final items = state.meetingsModel!.data![index];
  130. return Padding(
  131. padding: const EdgeInsets.all(8.0),
  132. child: CustomCardMeeting(
  133. titel: items.subject!.subject ?? '',
  134. fromTime: items.azHour ?? '',
  135. toTime: items.taHour ?? "",
  136. location: items.location!.address ?? '',
  137. date: items.dateJalali ?? '',
  138. cardId: items.id ?? 0,
  139. onSelectedMoreButton: (value) async {
  140. switch (value) {
  141. case 'edit':
  142. await context.pushNamed('meetingedit',
  143. pathParameters: {'id': items.id.toString()});
  144. meetingsState.getMeetings(refresh: true);
  145. case 'confirm':
  146. acceptMeeting(state, context, items.id ?? -1);
  147. case 'cancel':
  148. cancelMeeting(state, context, items.id ?? -1);
  149. case 'report':
  150. await context.pushNamed(
  151. 'meetinsammary',
  152. extra: items, // `items` should be a Datum instance
  153. );
  154. default:
  155. }
  156. },
  157. itemBuilderMoreButton: (context) => [
  158. PopupMenuItem(
  159. value: 'edit',
  160. child: Row(
  161. children: const [
  162. Icon(
  163. Icons.edit,
  164. color: Colors.green,
  165. size: 17,
  166. ),
  167. SizedBox(width: 8),
  168. Text(
  169. 'ویرایش قرار',
  170. style: TextStyle(fontSize: 12),
  171. ),
  172. ],
  173. ),
  174. ),
  175. PopupMenuItem(
  176. enabled: state.statusAcceptMeeting != Status.loading,
  177. value: 'confirm',
  178. child: Row(
  179. children: const [
  180. Icon(
  181. Icons.check_circle,
  182. color: Colors.green,
  183. size: 17,
  184. ),
  185. SizedBox(width: 8),
  186. Text(
  187. 'تایید جلسه',
  188. style: TextStyle(fontSize: 12),
  189. ),
  190. ],
  191. ),
  192. ),
  193. PopupMenuItem(
  194. enabled: state.statusCancelMeeting != Status.loading,
  195. value: 'cancel',
  196. child: Row(
  197. children: const [
  198. Icon(
  199. Icons.cancel,
  200. color: Colors.green,
  201. size: 17,
  202. ),
  203. SizedBox(width: 8),
  204. Text(
  205. 'لغو قرار',
  206. style: TextStyle(fontSize: 12),
  207. ),
  208. ],
  209. ),
  210. ),
  211. PopupMenuItem(
  212. value: 'report',
  213. child: Row(
  214. children: const [
  215. Icon(
  216. Icons.receipt_long,
  217. color: Colors.green,
  218. size: 17,
  219. ),
  220. SizedBox(width: 8),
  221. Text(
  222. 'صورت جلسه',
  223. style: TextStyle(fontSize: 12),
  224. ),
  225. ],
  226. ),
  227. ),
  228. ]),
  229. );
  230. },
  231. itemCount: state.meetingsModel!.data!.length,
  232. );
  233. case Status.loading:
  234. return SliverFillRemaining(child: const LoadingWidget());
  235. case Status.error:
  236. return SliverFillRemaining(
  237. child: CustomErrorWidget(
  238. onPressed: () async {
  239. await state.getMeetings(refresh: true);
  240. },
  241. ),
  242. );
  243. case Status.empty:
  244. return SliverFillRemaining(child: EmptyStateWidget());
  245. default:
  246. return Container();
  247. }
  248. }
  249. void cancelMeeting(
  250. MeetingsState state, BuildContext context, int cardId) async {
  251. final status = await state.cancelMeeting(id: cardId);
  252. if (status == Status.ready) {
  253. Tools.showCustomSnackBar(
  254. text: 'جلسه لغو شد!',
  255. isError: false,
  256. context,
  257. );
  258. } else {
  259. Tools.showCustomSnackBar(
  260. text: 'مشکلی رخ داده است. دوباره تلاش کنید!',
  261. isError: true,
  262. context,
  263. );
  264. }
  265. }
  266. void acceptMeeting(
  267. MeetingsState state, BuildContext context, int cardId) async {
  268. final status = await state.acceptMeeting(id: cardId);
  269. if (status == Status.ready) {
  270. Tools.showCustomSnackBar(
  271. text: 'جلسه تایید شد!',
  272. isError: false,
  273. context,
  274. );
  275. } else {
  276. Tools.showCustomSnackBar(
  277. text: 'مشکلی رخ داده است. دوباره تلاش کنید!',
  278. isError: true,
  279. context,
  280. );
  281. }
  282. }
  283. }