// ignore_for_file: avoid_print, use_build_context_synchronously, unused_local_variable, deprecated_member_use import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; import 'package:hoshan/core/gen/assets.gen.dart'; import 'package:hoshan/core/routes/route_generator.dart'; import 'package:hoshan/data/model/empty_states_enum.dart'; import 'package:hoshan/data/repository/auth_repository.dart'; import 'package:hoshan/ui/theme/colors.dart'; import 'package:hoshan/ui/theme/cubit/theme_mode_cubit.dart'; import 'package:hoshan/ui/theme/responsive.dart'; import 'package:hoshan/ui/theme/text.dart'; import 'package:hoshan/ui/widgets/components/button/circle_icon_btn.dart'; import 'package:hoshan/ui/widgets/components/snackbar/snackbar_manager.dart'; import 'package:hoshan/ui/widgets/sections/empty/empty_states.dart'; import 'package:hoshan/ui/widgets/sections/header/primary_appbar.dart'; class AddFamily extends StatefulWidget { const AddFamily({super.key}); @override State createState() => _AddFamilyState(); } class _AddFamilyState extends State { @override void initState() { super.initState(); _fetchFamilyMembers(); } bool _showInviteForm = false; int? _selectedAgeIndex; final TextEditingController _phoneController = TextEditingController(); final List> _invitedMembers = []; static const int _maxMembers = 5; @override void dispose() { _phoneController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final isDark = theme.brightness == Brightness.dark; final backgroundColor = colorScheme.background; final surfaceColor = colorScheme.surface; final onSurface = colorScheme.onSurface; final borderColor = const Color.fromARGB(255, 207, 206, 205); final accent = colorScheme.primary; final success = colorScheme.secondary; final int invitedMembersCount = _invitedMembers.length; return Scaffold( appBar: PrimaryAppbar( context, onBack: () => context.pop(), actions: [ Center( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: GestureDetector( onTap: () => context.go(Routes.myAccount), child: Row( mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ CircleIconBtn( size: Responsive(context).isMobile() ? 32 : 46, iconPadding: Responsive(context).isMobile() ? null : const EdgeInsets.all(8), icon: Assets.icon.outline.coin, color: context.read().isDark() ? AppColors.black[900] : AppColors.secondryColor[50], iconColor: Theme.of(context).colorScheme.secondary, ) .animate( autoPlay: true, onPlay: (controller) => controller.repeat(reverse: true), ) .moveY( begin: 0, end: -15, duration: 800.ms, curve: Curves.easeInBack, delay: 30.seconds, ), ], ), ), ), ), ], ), body: Directionality( textDirection: TextDirection.rtl, child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTopInfoCard( context, title: 'امکانات نامحدود', icon: 'assets/icon/outline/ion_infinite.svg', ), const SizedBox(width: 8), _buildTopInfoCard( context, title: '5 عضو خانواده', icon: 'assets/icon/outline/carbon_pedestrian-family.svg', ), const SizedBox(width: 8), _buildTopInfoCard( context, title: 'سکه باسا', icon: 'assets/icon/outline/streamline_coins-stack.svg', ), ], ), const SizedBox(height: 24), Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isDark ? surfaceColor : const Color.fromARGB(255, 233, 232, 231), borderRadius: BorderRadius.circular(16), ), child: Text( 'در صورت اتمام شارژ، می‌توانید با پرداخت هزینه مجددا سکه دریافت کنید یا تا تمدید بعدی اعتبار باساکارت منتظر بمانید.', style: AppTextStyles.body5.copyWith(color: onSurface), textAlign: TextAlign.justify, ), ), const SizedBox(height: 24), Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: surfaceColor, border: Border.all(color: borderColor), borderRadius: BorderRadius.circular(16), ), child: Column( children: [ Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( 'مدیریت خانواده', style: AppTextStyles.body3.copyWith( color: accent, fontWeight: FontWeight.bold, ), ), RichText( text: TextSpan( style: AppTextStyles.body3 .copyWith(fontFamily: 'Dana'), children: [ TextSpan( text: '$invitedMembersCount', style: TextStyle( color: accent, fontWeight: FontWeight.bold, fontSize: 25, ), ), TextSpan( text: '/$_maxMembers', style: TextStyle( color: Color.fromARGB(255, 173, 173, 173), ), ), ], ), ), ], ), const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'دعوت و مدیریت اعضای خانواده', style: AppTextStyles.body6.copyWith( color: Color.fromARGB(255, 173, 173, 173), fontWeight: FontWeight.bold), ), Text( 'اعضای خانواده', style: AppTextStyles.body6.copyWith( color: Color.fromARGB(255, 173, 173, 173), fontWeight: FontWeight.bold), ), ], ), ], ), const SizedBox(height: 20), ClipRRect( borderRadius: BorderRadius.circular(4), child: Directionality( textDirection: TextDirection.ltr, child: TweenAnimationBuilder( duration: const Duration(milliseconds: 1250), curve: Curves.easeOutQuart, tween: Tween( begin: 0, end: invitedMembersCount / _maxMembers, ), builder: (context, value, _) { return LinearProgressIndicator( value: value, minHeight: 6, backgroundColor: onSurface.withOpacity(0.1), valueColor: AlwaysStoppedAnimation( Color.fromARGB(255, 34, 197, 94)), ); }, ), ), ), const SizedBox(height: 20), Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Align( alignment: Alignment.centerRight, child: Text( '${_maxMembers - invitedMembersCount} جایگاه خالی', style: AppTextStyles.body5.copyWith( color: accent, fontWeight: FontWeight.normal, ), ), ), if (invitedMembersCount < _maxMembers) ...[ const SizedBox(height: 12), ElevatedButton( onPressed: () { setState(() { _showInviteForm = !_showInviteForm; }); }, style: ElevatedButton.styleFrom( backgroundColor: isDark ? success.withOpacity(0.15) : const Color.fromARGB(255, 187, 247, 208), foregroundColor: onSurface, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8), elevation: 0, ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( _showInviteForm ? CupertinoIcons.minus : CupertinoIcons.add, size: 18, ), const SizedBox(width: 4), Text( _showInviteForm ? 'بستن فرم' : 'افزودن عضو جدید', style: AppTextStyles.body5.copyWith( color: onSurface, fontWeight: FontWeight.bold), ), ], ), ), ], AnimatedSize( duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: _showInviteForm ? Padding( padding: const EdgeInsets.only(top: 24), child: _buildInviteCard( invitedMembersCount + 1), ) : const SizedBox.shrink(), ), ], ), ], ), ), if (_invitedMembers.isEmpty) EmptyStates.getEmptyState( status: EmptyStatesEnum.familyMembers, title: 'هنوز عضوی اضافه نشده است.', ) else _buildInvitedMembersList(), ], ), ), ), ), ); } Widget _buildInvitedMembersList() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(bottom: 12, top: 20), child: Text( 'افراد دعوت شده', style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface, ), ), ), SizedBox(height: 10), ListView.separated( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _invitedMembers.length, separatorBuilder: (context, index) => const SizedBox(height: 12), itemBuilder: (context, index) { final member = _invitedMembers[index]; return _buildInvitedMemberCard(member, index); }, ), ], ); } Widget _buildInvitedMemberCard(Map member, int index) { final colorScheme = Theme.of(context).colorScheme; final onSurface = colorScheme.onSurface; final surface = colorScheme.surface; final outline = colorScheme.outlineVariant; final warning = colorScheme.error; final isDark = Theme.of(context).brightness == Brightness.dark; return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: isDark ? Color.fromARGB(255, 80, 80, 80) : Color.fromARGB(255, 252, 252, 252), borderRadius: BorderRadius.circular(20), border: Border.all(color: Color.fromARGB(255, 207, 206, 205)), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.03), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( children: [ Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( color: AppColors.primaryColor[50], shape: BoxShape.circle, ), child: Icon( CupertinoIcons.person_solid, color: AppColors.primaryColor[500], size: 28, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( member['phone'] ?? '', style: AppTextStyles.body4.copyWith( fontWeight: FontWeight.normal, fontFamily: 'Dana', color: onSurface, ), ), const SizedBox(height: 4), Text( member['time'], style: AppTextStyles.body6.copyWith( color: onSurface.withOpacity(0.6), fontSize: 11, ), ), ], ), ), ], ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ // InkWell( // onTap: () { // _showEditDialog(index); // }, // child: // // Row( // // children: [ // // Text( // // 'ویرایش', // // style: AppTextStyles.body6.copyWith( // // color: AppColors.primaryColor[500], // // ), // // ), // // const SizedBox(width: 4), // // SvgPicture.asset( // // 'assets/icon/outline/edit.svg', // // ), // // ], // // ), // ), const SizedBox(width: 16), InkWell( onTap: () { _showDeleteDialog(index); }, child: SvgPicture.asset( 'assets/icon/outline/trash.svg', color: warning, height: 25, ), ), const SizedBox(width: 16), // Container( // padding: // const EdgeInsets.symmetric(horizontal: 15, vertical: 9), // decoration: BoxDecoration( // color: Color.fromARGB(255, 224, 236, 255), // borderRadius: BorderRadius.circular(6), // ), // child: Text( // 'در انتظار تایید', // style: AppTextStyles.body6.copyWith( // color: colorScheme.primary, // fontWeight: FontWeight.bold, // fontSize: 10, // ), // ), // ), ], ), ], ), ); } void _showEditDialog(int index) { final member = _invitedMembers[index]; final TextEditingController editPhoneController = TextEditingController(text: member['phone']); int? editAgeIndex = member['ageIndex']; showDialog( context: context, builder: (context) { return StatefulBuilder( builder: (context, setDialogState) { return Dialog( backgroundColor: Colors.transparent, insetPadding: const EdgeInsets.symmetric(horizontal: 16), child: Container( decoration: BoxDecoration( color: const Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), border: Border.all(color: AppColors.gray[300]), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric( vertical: 12, horizontal: 16), decoration: const BoxDecoration( color: Color.fromARGB(255, 224, 236, 255), borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), child: Directionality( textDirection: TextDirection.rtl, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'ویرایش عضو ${_getOrdinal(index + 1)}', textAlign: TextAlign.right, style: AppTextStyles.body4.copyWith( color: Colors.black, fontWeight: FontWeight.bold, ), ), InkWell( onTap: () => Navigator.pop(context), child: const Icon(CupertinoIcons.clear, size: 20), ) ], ), ), ), Container( height: 2, color: const Color.fromARGB(255, 30, 29, 27), ), Padding( padding: const EdgeInsets.all(16), child: Directionality( textDirection: TextDirection.rtl, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'شماره همراه', style: AppTextStyles.body5.copyWith( color: AppColors.primaryColor[500], fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), TextFormField( controller: editPhoneController, keyboardType: TextInputType.phone, textDirection: TextDirection.ltr, decoration: InputDecoration( suffixIcon: Icon( CupertinoIcons.phone, color: Theme.of(context).colorScheme.primary, ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide(color: AppColors.gray[300]), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide(color: AppColors.gray[300]), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide( color: AppColors.primaryColor[500]), ), ), ), const SizedBox(height: 20), Text( 'رده سنی', style: AppTextStyles.body5.copyWith( color: AppColors.primaryColor[500], fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildDialogAgeOption( title: 'زیر ۱۸ سال', index: 0, groupValue: editAgeIndex, onChanged: (val) => setDialogState( () => editAgeIndex = val), ), ), const SizedBox(width: 8), Expanded( child: _buildDialogAgeOption( title: '۱۸ تا ۳۰ سال', index: 1, groupValue: editAgeIndex, onChanged: (val) => setDialogState( () => editAgeIndex = val), ), ), const SizedBox(width: 8), Expanded( child: _buildDialogAgeOption( title: 'بالای ۳۰ سال', index: 2, groupValue: editAgeIndex, onChanged: (val) => setDialogState( () => editAgeIndex = val), ), ), ], ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () { if (editPhoneController.text.isNotEmpty) { setState(() { _invitedMembers[index] = { 'phone': editPhoneController.text, 'ageIndex': editAgeIndex, 'time': member['time'], }; }); Navigator.pop(context); SnackBarManager(context).show( message: 'اطلاعات با موفقیت ویرایش شد', status: SnackBarStatus.success, isTop: true, ); } }, style: ElevatedButton.styleFrom( backgroundColor: const Color.fromARGB(255, 34, 82, 160), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), padding: const EdgeInsets.symmetric(vertical: 12), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'ثبت تغییرات', style: AppTextStyles.body4.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), SvgPicture.asset( 'assets/icon/outline/edit.svg', color: Colors.white) ], ), ), ), ], ), ), ), ], ), ), ); }, ); }, ); } void _showDeleteDialog(int index) { final member = _invitedMembers[index]; showDialog( context: context, builder: (context) { return Dialog( backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), child: Padding( padding: const EdgeInsets.all(16.0), child: Directionality( textDirection: TextDirection.rtl, child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.end, children: [ InkWell( onTap: () => Navigator.pop(context), child: SvgPicture.asset( 'assets/icon/outline/close-circle.svg')), ], ), SvgPicture.asset( 'assets/icon/outline/trashPopup.svg', width: 55, height: 55, ), const SizedBox(height: 16), Text( 'کاربر حذف شود؟', style: AppTextStyles.body3.copyWith( fontWeight: FontWeight.bold, color: Colors.black, ), ), const SizedBox(height: 8), Text( 'شماره همراه: ${member['phone']}', style: AppTextStyles.body5.copyWith( color: AppColors.black[700], fontFamily: 'Dana', ), ), const SizedBox(height: 24), Row( children: [ Expanded( child: ElevatedButton( onPressed: () => Navigator.pop(context), style: ElevatedButton.styleFrom( backgroundColor: Color.fromARGB(255, 190, 18, 60), foregroundColor: Colors.white, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(100), ), padding: const EdgeInsets.symmetric(vertical: 12), ), child: const Text( 'خیر', style: TextStyle( fontFamily: 'Dana', ), ), ), ), const SizedBox(width: 12), Expanded( child: ElevatedButton( onPressed: () async { final dynamic rawId = member['id']; print( 'Debug - Delete: rawId = $rawId (${rawId.runtimeType})'); print('Debug - Delete: member = $member'); String? id; if (rawId is String) { id = rawId; } else if (rawId is int) { id = rawId.toString(); } if (id == null || id.isEmpty) { Navigator.pop(context); SnackBarManager(context).show( message: 'شناسه کاربر نامعتبر است: rawId=$rawId (type: ${rawId.runtimeType})', status: SnackBarStatus.error, isTop: true, ); return; } print('Debug - Delete: parsed id = $id'); try { print('Debug - Deleting user with id: $id'); final isDeleted = await AuthRepository.deleteSubUser(id); if (!mounted) return; if (isDeleted) { setState(() { _invitedMembers.removeAt(index); }); Navigator.pop(context); SnackBarManager(context).show( message: 'کاربر با موفقیت حذف شد', status: SnackBarStatus.success, isTop: true, ); } else { Navigator.pop(context); SnackBarManager(context).show( message: 'خطا در حذف کاربر', status: SnackBarStatus.error, isTop: true, ); } } catch (e) { print('Debug - Delete error: $e'); if (!mounted) return; Navigator.pop(context); SnackBarManager(context).show( message: 'خطا در حذف کاربر: $e', status: SnackBarStatus.error, isTop: true, ); } }, style: ElevatedButton.styleFrom( backgroundColor: Colors.grey[200], foregroundColor: Colors.black, elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(100), side: const BorderSide( color: Color.fromARGB(255, 190, 18, 60), ), ), padding: const EdgeInsets.symmetric(vertical: 12), ), child: const Text( 'بله', style: TextStyle( fontFamily: 'Dana', ), ), ), ), ], ) ], ), ), ), ); }, ); } Widget _buildDialogAgeOption({ required String title, required int index, required int? groupValue, required ValueChanged onChanged, }) { final colorScheme = Theme.of(context).colorScheme; final isSelected = groupValue == index; return InkWell( onTap: () => onChanged(index), borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: isSelected ? colorScheme.primaryContainer.withOpacity(0.35) : colorScheme.surfaceVariant, borderRadius: BorderRadius.circular(30), ), child: Text( title, textAlign: TextAlign.center, style: AppTextStyles.body6.copyWith( color: isSelected ? colorScheme.onPrimaryContainer : colorScheme.onSurface.withOpacity(0.7), fontWeight: FontWeight.bold, fontSize: 11, ), ), ), ); } String _getOrdinal(int number) { switch (number) { case 1: return 'اول'; case 2: return 'دوم'; case 3: return 'سوم'; case 4: return 'چهارم'; case 5: return 'پنجم'; default: return '$numberام'; } } Widget _buildInviteCard(int memberNumber) { final colorScheme = Theme.of(context).colorScheme; return Container( decoration: BoxDecoration( color: Color.fromARGB(255, 246, 246, 246), borderRadius: BorderRadius.circular(16), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.05), blurRadius: 10, offset: const Offset(0, 4), ) ], ), child: Column( children: [ Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16), decoration: BoxDecoration( color: Color.fromARGB(255, 224, 236, 255), borderRadius: const BorderRadius.vertical(top: Radius.circular(16)), ), child: Text( 'دعوت از عضو ${_getOrdinal(memberNumber)}', textAlign: TextAlign.right, style: AppTextStyles.body4.copyWith( color: Colors.black, fontWeight: FontWeight.bold, ), ), ), Container( height: 2, color: colorScheme.outline, ), Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'شماره همراه', style: AppTextStyles.body5.copyWith( color: colorScheme.primary, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), TextFormField( controller: _phoneController, keyboardType: TextInputType.phone, textDirection: TextDirection.ltr, decoration: InputDecoration( suffixIcon: Icon( CupertinoIcons.phone, color: Theme.of(context).colorScheme.primary, ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 12), border: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide(color: Color.fromARGB(255, 161, 160, 160)), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide(color: colorScheme.outlineVariant), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(16), borderSide: BorderSide(color: colorScheme.primary), ), ), ), const SizedBox(height: 20), Text( 'رده سنی', style: AppTextStyles.body5.copyWith( color: colorScheme.primary, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 12), Row( children: [ Expanded( child: _buildAgeOption( title: 'زیر ۱۸ سال', index: 0, ), ), const SizedBox(width: 8), Expanded( child: _buildAgeOption( title: '۱۸ تا ۳۰ سال', index: 1, ), ), const SizedBox(width: 8), Expanded( child: _buildAgeOption( title: 'بالای ۳۰ سال', index: 2, ), ), ], ), const SizedBox(height: 24), SizedBox( width: double.infinity, child: ElevatedButton( onPressed: () async { final phone = _phoneController.text; if (phone.isEmpty) { SnackBarManager(context).show( message: 'لطفا شماره همراه را وارد کنید', status: SnackBarStatus.error, isTop: true, ); return; } if (_selectedAgeIndex == null) { SnackBarManager(context).show( message: 'لطفا رده سنی را انتخاب کنید', status: SnackBarStatus.error, isTop: true, ); return; } int level; switch (_selectedAgeIndex) { case 0: level = 3; break; case 1: level = 2; break; case 2: level = 1; break; default: level = 3; } try { final isSuccess = await AuthRepository.addSubUser(phone, level); if (isSuccess) { if (!context.mounted) return; SnackBarManager(context).show( message: 'دعوتنامه برای $phone با موفقیت ارسال شد', status: SnackBarStatus.success, isTop: true, ); setState(() { _showInviteForm = false; _phoneController.clear(); _selectedAgeIndex = null; }); await _fetchFamilyMembers(); } } catch (e) { if (!context.mounted) return; SnackBarManager(context).show( message: 'خطا در ارسال دعوتنامه. لطفا مجدد تلاش کنید.', status: SnackBarStatus.error, isTop: true, ); } }, style: ElevatedButton.styleFrom( backgroundColor: colorScheme.primary, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20), ), padding: const EdgeInsets.symmetric(vertical: 12), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( 'ارسال دعوتنامه', style: AppTextStyles.body4.copyWith( color: Colors.white, fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), SvgPicture.asset('assets/icon/outline/send.svg') ], ), ), ), ], ), ), ], ), ); } Widget _buildAgeOption({required String title, required int index}) { final colorScheme = Theme.of(context).colorScheme; final isSelected = _selectedAgeIndex == index; return InkWell( onTap: () { setState(() { _selectedAgeIndex = index; }); }, borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: isSelected ? Color.fromARGB(255, 224, 236, 255) : Color.fromARGB(255, 233, 232, 231), borderRadius: BorderRadius.circular(30), ), child: Text( title, textAlign: TextAlign.center, style: AppTextStyles.body6.copyWith( color: isSelected ? Colors.black : colorScheme.onSurface.withOpacity(0.7), fontWeight: FontWeight.bold, fontSize: 11, ), ), ), ); } Widget _buildTopInfoCard(BuildContext context, {required String title, required String icon}) { final colorScheme = Theme.of(context).colorScheme; return Column( children: [ Container( height: 64, width: 64, padding: const EdgeInsets.all(5), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), color: Color.fromARGB(255, 248, 231, 241), ), child: Center( child: SvgPicture.asset( icon, width: 32, height: 32, ), ), ), const SizedBox(height: 8), Text( title, style: AppTextStyles.body6.copyWith( fontSize: 11, fontWeight: FontWeight.bold, color: colorScheme.onSurface, ), textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ); } Future _fetchFamilyMembers() async { try { final subUsers = await AuthRepository.getSubUsers(); setState(() { _invitedMembers.clear(); for (var user in subUsers) { print('Debug - User data: $user'); print('Debug - User ID: ${user['id']} (${user['id'].runtimeType})'); _invitedMembers.add({ 'id': user['id'], 'phone': user['mobile_number'], 'ageIndex': _getAgeIndexFromLevel(user['level']), 'time': _formatDate(user['created_at']), }); } }); print('Debug - Total members loaded: ${_invitedMembers.length}'); } catch (e) { print('Debug - Error fetching family members: $e'); if (mounted) { SnackBarManager(context).show( message: 'خطا در دریافت اطلاعات خانواده: $e', status: SnackBarStatus.error, ); } } } int _getAgeIndexFromLevel(int level) { switch (level) { case 3: return 0; case 2: return 1; case 1: return 2; default: return 1; } } String _formatDate(String? isoDate) { if (isoDate == null) return ''; try { DateTime date = DateTime.parse(isoDate); DateTime now = DateTime.now(); Duration difference = now.difference(date); if (difference.inSeconds < 60) { return 'دعوت شده در ${difference.inSeconds} ثانیه قبل'; } else if (difference.inMinutes < 60) { return 'دعوت شده در ${difference.inMinutes} دقیقه قبل'; } else if (difference.inHours < 24) { return 'دعوت شده در ${difference.inHours} ساعت قبل'; } else if (difference.inDays < 30) { return 'دعوت شده در ${difference.inDays} روز قبل'; } else if (difference.inDays < 365) { int months = (difference.inDays / 30).floor(); return 'دعوت شده در $months ماه قبل'; } else { int years = (difference.inDays / 365).floor(); return 'دعوت شده در $years سال قبل'; } } catch (e) { return isoDate; } } }