// ignore_for_file: public_member_api_docs, sort_constructors_first import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:qadirneyriz/config/config.dart'; import 'package:qadirneyriz/screens/private_meeting/dilog_privateMeetings_filters.dart'; import 'package:qadirneyriz/screens/private_meeting/state.dart'; import 'package:qadirneyriz/setting/setting.dart'; import 'package:qadirneyriz/utils/enums/status.dart'; import 'package:qadirneyriz/utils/tools/tools.dart'; import 'package:qadirneyriz/widgets/custom_appbar.dart'; import 'package:qadirneyriz/widgets/custom_button.dart'; import 'package:qadirneyriz/widgets/empty_widget.dart'; import 'package:qadirneyriz/widgets/error_widget.dart'; import 'package:qadirneyriz/widgets/icon_button.dart'; import 'package:qadirneyriz/widgets/loading_widget.dart'; import 'package:qadirneyriz/widgets/today_widget.dart'; class PrivateMeetingsScreen extends StatefulWidget { const PrivateMeetingsScreen({super.key}); @override State createState() => _PrivateMeetingsScreenState(); } class _PrivateMeetingsScreenState extends State { late ScrollController _scrollController; late PrivateMeetingsState privateMeetingsState; @override void initState() { super.initState(); _scrollController = ScrollController(); _scrollController.addListener(_scrollListener); privateMeetingsState = Provider.of(context, listen: false); Future.delayed(Duration.zero, () async { privateMeetingsState.clearFilters(); await privateMeetingsState.getPrivateMeetings(); }); privateMeetingsState.setAllFiltersForThen(); } // ذخیره فیلترهای اولیه برای مقایسه در آیند _scrollListener() async { if (_scrollController.offset >= _scrollController.position.maxScrollExtent && !_scrollController.position.outOfRange) { if (!privateMeetingsState.pageEndedPrivateMeetings) { await privateMeetingsState.nextPagePrivateMeetings( toDate: privateMeetingsState.toDate, fromDate: privateMeetingsState.fromDate, location: privateMeetingsState.selectedLocationId, subject: privateMeetingsState.selectedSubjectId, meetingManager: privateMeetingsState.selectedManagersId, meetingStatus: privateMeetingsState.selectedStatusId); } } } @override Widget build(BuildContext context) { DateTime now = DateTime.now(); String dateMiladi = setting.userLocalDb.getUser().language == 'fa' ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)) : DateFormat('yyyy-MM-dd').format(now); String dateJalali = Tools.convertToPersianDigits( '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}'); return Consumer( builder: (context, value, child) { return RefreshIndicator( onRefresh: () async { await privateMeetingsState.getPrivateMeetings(); }, child: CustomScrollView( controller: _scrollController, physics: AlwaysScrollableScrollPhysics(), slivers: [ const CustomAppbar(), SliverToBoxAdapter( child: TodayWidget( formattedDate: setting.userLocalDb.getUser().language == 'en' ? dateMiladi : dateJalali), ), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 15), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( style: const TextStyle(fontSize: 14), AppLocalizations.of(context)!.privatemeeting, ), IconButtonCustom( iconColor: value.hasActiveFilters() ? Colors.white : config.ui.secendGreen, backColor: value.hasActiveFilters() ? config.ui.secendGreen : Colors.white, icon: FontAwesomeIcons.sliders, onTap: () { showModalBottomSheet( isScrollControlled: true, useSafeArea: true, context: context, builder: (context) { return DiologPrivateMeetingsFilters(); }, ); }, ) ], ), ), ), privateMeetingsList(value), (value.privatePaginationMeetings == Status.ready || value.privatePaginationMeetings == Status.empty) ? const SliverToBoxAdapter() : const SliverToBoxAdapter( child: Center( child: LoadingWidget( size: 10, ), ), ) ], ), ); }, ); } Widget privateMeetingsList(PrivateMeetingsState state) { switch (state.privateStatusMeetings) { case Status.ready: return SliverList.builder( itemBuilder: (context, index) { final userRole = setting.userLocalDb.getUser().role; final items = state.privateMeetingsModel!.data![index]; return PrivateMeetingWidget( status: items.accepted ?? 0, date: items.dateJalali ?? '', time: items.azHour ?? '', subject: items.subject != null ? items.subject!.subject ?? '' : '', location: items.location != null ? items.location!.address ?? '' : '', onAcceptButton: state.statusAcceptMeeting[items.id] != Status.loading ? () { acceptPrivateMeeting(state, context, items.id ?? -1); } : null, onCancelButton: state.statusCancelMeeting[items.id] != Status.loading ? () { cancelPrivateMeeting(state, context, items.id ?? -1); } : null, onSelectedMoreButton: (value) async { switch (value) { case 'edit': await context.pushNamed('privatemeetingedit', pathParameters: {'id': items.id.toString()}); state.getPrivateMeetings(); case 'report': await context.pushNamed( 'privatemeetinsammary', extra: items, // `items` should be a Datum instance ); case 'cancel': cancelPrivateMeeting(state, context, items.id ?? -1); case 'delete': deletePrivateMeeting(state, context, items.id ?? -1); default: } }, itemBuilderMoreButton: (context) => [ if (userRole == 0 || userRole == 2) PopupMenuItem( value: 'edit', child: Row( children: [ Icon( Icons.edit, color: Colors.green, size: 17, ), SizedBox(width: 8), Text( AppLocalizations.of(context)!.editprivatemeeting, style: TextStyle(fontSize: 12), ), ], ), ), PopupMenuItem( value: 'report', child: Row( children: [ Icon( Icons.receipt_long, color: Colors.green, size: 17, ), SizedBox(width: 8), Text( AppLocalizations.of(context)!.meetingsummary, style: TextStyle(fontSize: 12), ), ], ), ), PopupMenuItem( enabled: state.statusCancelMeeting != Status.loading, value: 'cancel', child: Row( children: [ Icon( Icons.cancel, color: Colors.green, size: 17, ), SizedBox(width: 8), Text( AppLocalizations.of(context)!.cancelmeeting, style: TextStyle(fontSize: 12), ), ], ), ), if (userRole == 0 || userRole == 2) PopupMenuItem( value: 'delete', child: Row( children: [ Icon( Icons.delete, color: Colors.green, size: 17, ), SizedBox(width: 8), Text( AppLocalizations.of(context)!.deleteprivatemeeting, style: TextStyle(fontSize: 12), ), ], ), ), ], ); }, itemCount: state.privateMeetingsModel!.data!.length, ); case Status.loading: return SliverFillRemaining(child: const LoadingWidget()); case Status.error: return SliverFillRemaining( child: CustomErrorWidget( onPressed: () async { await state.getPrivateMeetings(refresh: true); }, ), ); case Status.empty: return SliverFillRemaining(child: EmptyStateWidget()); default: return Container(); } } void cancelPrivateMeeting( PrivateMeetingsState state, BuildContext context, int cardId) async { final status = await state.cancelMeeting(id: cardId); if (status == Status.ready) { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.privatemeetingcanceld, isError: false, context, ); await privateMeetingsState.getPrivateMeetings(); } else { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.error, isError: true, context, ); } } void deletePrivateMeeting( PrivateMeetingsState state, BuildContext context, int cardId) async { final status = await state.deleteMeeting(id: cardId); if (status == Status.ready) { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.privatemeetingdeleted, isError: false, context, ); await privateMeetingsState.getPrivateMeetings(); } else { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.error, isError: true, context, ); } } void acceptPrivateMeeting( PrivateMeetingsState state, BuildContext context, int cardId) async { final status = await state.acceptMeeting(id: cardId); if (status == Status.ready) { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.privatemeetingaccept, isError: false, context, ); await privateMeetingsState.getPrivateMeetings(); } else { Tools.showCustomSnackBar( text: AppLocalizations.of(context)!.error, isError: true, context, ); } } } class PrivateMeetingWidget extends StatelessWidget { final String date; final String time; final String subject; final String location; final int status; final bool hasMoreButton; final void Function()? onAcceptButton; final void Function()? onCancelButton; final void Function(String)? onSelectedMoreButton; final List> Function(BuildContext)? itemBuilderMoreButton; const PrivateMeetingWidget( {Key? key, required this.date, required this.time, required this.subject, required this.location, required this.status, this.hasMoreButton = true, this.onAcceptButton, this.onCancelButton, this.onSelectedMoreButton, this.itemBuilderMoreButton, th}) : super(key: key); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), child: Container( child: Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( this.date, style: TextStyle(fontSize: 12), ), ), Divider(), SizedBox( height: 5, ), Container( decoration: BoxDecoration( boxShadow: [ BoxShadow( color: config.ui.mainGray.withOpacity(.1), spreadRadius: .1, offset: const Offset(0, 2), blurRadius: 6) ], color: const Color(0xffF4F9F6), borderRadius: BorderRadius.circular(10)), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), child: Column( children: [ Row( children: [ Text(this.time), SizedBox( width: 15, ), Container( width: 3, height: 45, decoration: BoxDecoration( color: Colors.green, ), ), SizedBox( width: 5, ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( this.subject, ), SizedBox( height: 5, ), Text( this.location, style: TextStyle( fontSize: 12, color: Color(0xff9AA8C7)), ), ], ), ), if (hasMoreButton) _moreButton(context) ], ), if (this.status == 0) Padding( padding: const EdgeInsets.only(top: 15), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ CustomButton( hieght: 30, text: AppLocalizations.of(context)!.accept, borderRadius: 5, color: Color(0xff00A848), fontSize: 12, onPressed: this.onAcceptButton, ), SizedBox( width: 7, ), CustomButton( hieght: 30, text: AppLocalizations.of(context)!.cancel, color: Colors.red, textColor: Colors.white, fontSize: 12, borderRadius: 5, onPressed: this.onCancelButton, ), SizedBox( width: 90, ), ], ), ), if (this.status == 1 || this.status == 2) Padding( padding: const EdgeInsets.only(top: 10), child: Row( children: [ SizedBox( width: 60, ), PrivateMeetingLabel( status: this.status, ), ], ), ) ], ), ), ) ], ), ), ); } Widget _moreButton(BuildContext context) { return PopupMenuButton( color: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(10.0), ), ), onSelected: onSelectedMoreButton, itemBuilder: itemBuilderMoreButton!, icon: const Icon(Icons.more_horiz), ); } } class PrivateMeetingLabel extends StatelessWidget { final int status; const PrivateMeetingLabel({ Key? key, required this.status, }) : super(key: key); @override Widget build(BuildContext context) { return Container( width: 82, child: Center( child: Padding( padding: const EdgeInsets.symmetric(vertical: 5), child: Text( this.status == 1 ? AppLocalizations.of(context)!.accepted : AppLocalizations.of(context)!.canceled, style: TextStyle(fontSize: 12, color: Colors.white), ), ), ), decoration: BoxDecoration( color: this.status == 1 ? Colors.green : Colors.red, borderRadius: BorderRadius.circular(4)), ); } }