Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

382 righe
14 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:intl/intl.dart';
  7. import 'package:provider/provider.dart';
  8. import 'package:qadirneyriz/config/config.dart';
  9. import 'package:qadirneyriz/screens/meeting/diolog_meetings_filters.dart';
  10. import 'package:qadirneyriz/screens/meeting/state.dart';
  11. import 'package:qadirneyriz/setting/setting.dart';
  12. import 'package:qadirneyriz/utils/enums/status.dart';
  13. import 'package:qadirneyriz/utils/tools/tools.dart';
  14. import 'package:qadirneyriz/widgets/card_meeting.dart';
  15. import 'package:qadirneyriz/widgets/custom_appbar.dart';
  16. import 'package:qadirneyriz/widgets/empty_widget.dart';
  17. import 'package:qadirneyriz/widgets/error_widget.dart';
  18. import 'package:qadirneyriz/widgets/icon_button.dart';
  19. import 'package:qadirneyriz/widgets/loading_widget.dart';
  20. import 'package:qadirneyriz/widgets/today_widget.dart';
  21. class MeetingsScreen extends StatefulWidget {
  22. const MeetingsScreen({super.key});
  23. @override
  24. State<MeetingsScreen> createState() => _MeetingsScreenState();
  25. }
  26. class _MeetingsScreenState extends State<MeetingsScreen> {
  27. late ScrollController _scrollController;
  28. late MeetingsState meetingsState;
  29. @override
  30. void initState() {
  31. _scrollController = ScrollController();
  32. _scrollController.addListener(_scrollListener);
  33. meetingsState = Provider.of<MeetingsState>(context, listen: false);
  34. Future.delayed(Duration.zero, () async {
  35. await meetingsState.getMeetings();
  36. meetingsState.clearFilters();
  37. });
  38. super.initState();
  39. }
  40. @override
  41. void dispose() {
  42. _scrollController.dispose();
  43. super.dispose();
  44. }
  45. _scrollListener() async {
  46. if (_scrollController.offset >=
  47. _scrollController.position.maxScrollExtent &&
  48. !_scrollController.position.outOfRange) {
  49. if (!meetingsState.pageEndedMeetings) {
  50. await meetingsState.nextPageMeetings(
  51. toDate: meetingsState.toDate,
  52. fromDate: meetingsState.fromDate,
  53. location: meetingsState.selectedLocationId,
  54. subject: meetingsState.selectedSubjectId,
  55. meetingManager: meetingsState.selectedManagersId,
  56. meetingStatus: meetingsState.selectedStatusId);
  57. }
  58. }
  59. }
  60. @override
  61. Widget build(BuildContext context) {
  62. DateTime now = DateTime.now();
  63. String dateMiladi = setting.userLocalDb.getUser().language == 'fa'
  64. ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now))
  65. : DateFormat('yyyy-MM-dd').format(now);
  66. String dateJalali = Tools.convertToPersianDigits(
  67. '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}');
  68. // فرمت کردن تاریخ
  69. return Consumer<MeetingsState>(
  70. builder: (context, value, child) {
  71. return RefreshIndicator(
  72. onRefresh: () async {
  73. await meetingsState.getMeetings();
  74. },
  75. child: CustomScrollView(
  76. physics: AlwaysScrollableScrollPhysics(),
  77. controller: _scrollController,
  78. slivers: <Widget>[
  79. const CustomAppbar(),
  80. SliverToBoxAdapter(
  81. child: TodayWidget(
  82. formattedDate:
  83. setting.userLocalDb.getUser().language == 'en'
  84. ? dateMiladi
  85. : dateJalali),
  86. ),
  87. SliverToBoxAdapter(
  88. child: Padding(
  89. padding:
  90. const EdgeInsets.symmetric(vertical: 30, horizontal: 15),
  91. child: Row(
  92. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  93. crossAxisAlignment: CrossAxisAlignment.center,
  94. children: [
  95. Text(
  96. style: const TextStyle(fontSize: 14),
  97. AppLocalizations.of(context)!.meetings,
  98. ),
  99. IconButtonCustom(
  100. iconColor: value.hasActiveFilters()
  101. ? Colors.white
  102. : config.ui.secendGreen,
  103. backColor: value.hasActiveFilters()
  104. ? config.ui.secendGreen
  105. : Colors.white,
  106. icon: FontAwesomeIcons.sliders,
  107. onTap: () {
  108. showModalBottomSheet(
  109. isScrollControlled: true,
  110. useSafeArea: true,
  111. context: context,
  112. builder: (context) {
  113. return DiologMeetingsFilters();
  114. },
  115. );
  116. },
  117. )
  118. ],
  119. ),
  120. ),
  121. ),
  122. meetingsList(value),
  123. (value.paginationMeetings == Status.ready ||
  124. value.paginationMeetings == Status.empty)
  125. ? const SliverToBoxAdapter()
  126. : const SliverToBoxAdapter(
  127. child: Center(
  128. child: LoadingWidget(
  129. size: 10,
  130. ),
  131. ),
  132. )
  133. ],
  134. ),
  135. );
  136. },
  137. );
  138. }
  139. Widget meetingsList(MeetingsState state) {
  140. switch (state.statusMeetings) {
  141. case Status.ready:
  142. return SliverList.builder(
  143. itemBuilder: (context, index) {
  144. final userRole = setting.userLocalDb.getUser().role;
  145. final items = state.meetingsModel!.data![index];
  146. return Padding(
  147. padding: const EdgeInsets.all(8.0),
  148. child: CustomCardMeeting(
  149. status: items.accepted ?? 0,
  150. titel:
  151. items.subject != null ? items.subject!.subject ?? '' : '',
  152. fromTime: items.azHour ?? '',
  153. toTime: items.taHour ?? "",
  154. location: items.location != null
  155. ? items.location!.address ?? ''
  156. : '',
  157. date: items.dateJalali ?? '',
  158. cardId: items.id ?? 0,
  159. onSelectedMoreButton: (value) async {
  160. switch (value) {
  161. case 'edit':
  162. await context.pushNamed('meetingedit',
  163. pathParameters: {'id': items.id.toString()});
  164. meetingsState.getMeetings();
  165. case 'confirm':
  166. acceptMeeting(state, context, items.id ?? -1);
  167. case 'cancel':
  168. cancelMeeting(state, context, items.id ?? -1);
  169. case 'delete':
  170. deleteMeeting(state, context, items.id ?? -1);
  171. case 'report':
  172. if (userRole == 1 && items.description != null) {
  173. await context.pushNamed(
  174. 'meetinsammary',
  175. extra: items, // `items` should be a Datum instance
  176. );
  177. await meetingsState.getMeetings();
  178. } else if (userRole == 1 && items.description == null) {
  179. Tools.showCustomSnackBar(
  180. text:
  181. AppLocalizations.of(context)!.thereisnosummary,
  182. isError: true,
  183. context,
  184. );
  185. } else {
  186. await context.pushNamed(
  187. 'meetinsammary',
  188. extra: items, // `items` should be a Datum instance
  189. );
  190. await meetingsState.getMeetings();
  191. }
  192. default:
  193. }
  194. },
  195. itemBuilderMoreButton: (context) => [
  196. if (userRole == 0 || userRole == 2)
  197. PopupMenuItem(
  198. value: 'edit',
  199. child: Row(
  200. children: [
  201. Icon(
  202. Icons.edit,
  203. color: Colors.green,
  204. size: 17,
  205. ),
  206. SizedBox(width: 8),
  207. Text(
  208. AppLocalizations.of(context)!.editmeeting,
  209. style: TextStyle(fontSize: 12),
  210. ),
  211. ],
  212. ),
  213. ),
  214. if ((userRole == 0 || userRole == 2) &&
  215. items.accepted == 0)
  216. PopupMenuItem(
  217. enabled:
  218. state.statusAcceptMeeting != Status.loading,
  219. value: 'confirm',
  220. child: Row(
  221. children: [
  222. Icon(
  223. Icons.check_circle,
  224. color: Colors.green,
  225. size: 17,
  226. ),
  227. SizedBox(width: 8),
  228. Text(
  229. AppLocalizations.of(context)!.acceptmeeting,
  230. style: TextStyle(fontSize: 12),
  231. ),
  232. ],
  233. ),
  234. ),
  235. if (userRole == 0 || userRole == 2)
  236. PopupMenuItem(
  237. enabled:
  238. state.statusCancelMeeting != Status.loading,
  239. value: 'cancel',
  240. child: Row(
  241. children: [
  242. Icon(
  243. Icons.cancel,
  244. color: Colors.green,
  245. size: 17,
  246. ),
  247. SizedBox(width: 8),
  248. Text(
  249. AppLocalizations.of(context)!.cancelmeeting,
  250. style: TextStyle(fontSize: 12),
  251. ),
  252. ],
  253. ),
  254. ),
  255. PopupMenuItem(
  256. value: 'report',
  257. child: Row(
  258. children: [
  259. Icon(
  260. Icons.receipt_long,
  261. color: Colors.green,
  262. size: 17,
  263. ),
  264. SizedBox(width: 8),
  265. Text(
  266. AppLocalizations.of(context)!.meetingsummary,
  267. style: TextStyle(fontSize: 12),
  268. ),
  269. ],
  270. ),
  271. ),
  272. if (userRole == 0 || userRole == 2)
  273. PopupMenuItem(
  274. enabled:
  275. state.statusCancelMeeting != Status.loading,
  276. value: 'delete',
  277. child: Row(
  278. children: [
  279. Icon(
  280. Icons.delete,
  281. color: Colors.green,
  282. size: 17,
  283. ),
  284. SizedBox(width: 8),
  285. Text(
  286. AppLocalizations.of(context)!.deletemeeting,
  287. style: TextStyle(fontSize: 12),
  288. ),
  289. ],
  290. ),
  291. ),
  292. ]),
  293. );
  294. },
  295. itemCount: state.meetingsModel!.data!.length,
  296. );
  297. case Status.loading:
  298. return SliverFillRemaining(child: const LoadingWidget());
  299. case Status.error:
  300. return SliverFillRemaining(
  301. child: CustomErrorWidget(
  302. onPressed: () async {
  303. await state.getMeetings(refresh: true);
  304. },
  305. ),
  306. );
  307. case Status.empty:
  308. return SliverFillRemaining(child: EmptyStateWidget());
  309. default:
  310. return Container();
  311. }
  312. }
  313. void cancelMeeting(
  314. MeetingsState state, BuildContext context, int cardId) async {
  315. final status = await state.cancelMeeting(id: cardId);
  316. if (status == Status.ready) {
  317. Tools.showCustomSnackBar(
  318. text: AppLocalizations.of(context)!.meetingcanceled,
  319. isError: false,
  320. context,
  321. );
  322. await meetingsState.getMeetings();
  323. } else {
  324. Tools.showCustomSnackBar(
  325. text: AppLocalizations.of(context)!.error,
  326. isError: true,
  327. context,
  328. );
  329. }
  330. }
  331. void deleteMeeting(
  332. MeetingsState state, BuildContext context, int cardId) async {
  333. final status = await state.deleteMeeting(id: cardId);
  334. if (status == Status.ready) {
  335. Tools.showCustomSnackBar(
  336. text: AppLocalizations.of(context)!.meetingdeleted,
  337. isError: false,
  338. context,
  339. );
  340. await meetingsState.getMeetings();
  341. } else {
  342. Tools.showCustomSnackBar(
  343. text: AppLocalizations.of(context)!.error,
  344. isError: true,
  345. context,
  346. );
  347. }
  348. }
  349. void acceptMeeting(
  350. MeetingsState state, BuildContext context, int cardId) async {
  351. final status = await state.acceptMeeting(id: cardId);
  352. if (status == Status.ready) {
  353. Tools.showCustomSnackBar(
  354. text: AppLocalizations.of(context)!.meetingaccepted,
  355. isError: false,
  356. context,
  357. );
  358. await meetingsState.getMeetings();
  359. } else {
  360. Tools.showCustomSnackBar(
  361. text: AppLocalizations.of(context)!.error,
  362. isError: true,
  363. context,
  364. );
  365. }
  366. }
  367. }