/// Addresses Page /// /// Displays list of saved addresses with management options. /// Features: /// - List of saved addresses /// - Default address indicator /// - Edit/delete actions /// - Set as default functionality /// - Add new address library; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:worker/core/constants/ui_constants.dart'; import 'package:worker/core/router/app_router.dart'; import 'package:worker/core/theme/colors.dart'; import 'package:worker/features/account/domain/entities/address.dart'; import 'package:worker/features/account/presentation/providers/address_provider.dart'; import 'package:worker/features/account/presentation/widgets/address_card.dart'; /// Addresses Page /// /// Page for managing saved delivery addresses. class AddressesPage extends ConsumerWidget { const AddressesPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { // Watch addresses from API final addressesAsync = ref.watch(addressesProvider); return Scaffold( backgroundColor: const Color(0xFFF4F6F8), appBar: AppBar( backgroundColor: AppColors.white, elevation: AppBarSpecs.elevation, leading: IconButton( icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20), onPressed: () => context.pop(), ), title: const Text( 'Địa chỉ của bạn', style: TextStyle(color: Colors.black), ), foregroundColor: AppColors.grey900, centerTitle: false, actions: [ IconButton( icon: const FaIcon(FontAwesomeIcons.circleInfo, color: Colors.black, size: 20), onPressed: () { _showInfoDialog(context); }, ), const SizedBox(width: AppSpacing.sm), ], ), body: addressesAsync.when( data: (addresses) => Column( children: [ // Address List Expanded( child: RefreshIndicator( onRefresh: () async { await ref.read(addressesProvider.notifier).refresh(); }, child: addresses.isEmpty ? _buildEmptyState(context) : ListView.separated( padding: const EdgeInsets.all(AppSpacing.md), itemCount: addresses.length, separatorBuilder: (context, index) => const SizedBox(height: AppSpacing.md), itemBuilder: (context, index) { final address = addresses[index]; return AddressCard( name: address.addressTitle, phone: address.phone, address: address.fullAddress, isDefault: address.isDefault, onEdit: () { context.push( RouteNames.addressForm, extra: address, ); }, onDelete: () { _showDeleteConfirmation(context, ref, address); }, onSetDefault: () { _setDefaultAddress(context, ref, address); }, ); }, ), ), ), // Add New Address Button Padding( padding: const EdgeInsets.all(AppSpacing.md), child: SizedBox( width: double.infinity, child: ElevatedButton.icon( onPressed: () { context.push(RouteNames.addressForm); }, icon: const FaIcon(FontAwesomeIcons.plus, size: 18), label: const Text( 'Thêm địa chỉ mới', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), style: ElevatedButton.styleFrom( backgroundColor: AppColors.primaryBlue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(vertical: 14), elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.button), ), ), ), ), ), ], ), loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const FaIcon( FontAwesomeIcons.triangleExclamation, size: 64, color: AppColors.danger, ), const SizedBox(height: 16), const Text( 'Không thể tải danh sách địa chỉ', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.grey900, ), ), const SizedBox(height: 8), Text( error.toString(), style: const TextStyle(fontSize: 14, color: AppColors.grey500), textAlign: TextAlign.center, ), const SizedBox(height: 24), ElevatedButton.icon( onPressed: () { ref.read(addressesProvider.notifier).refresh(); }, icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 18), label: const Text('Thử lại'), style: ElevatedButton.styleFrom( backgroundColor: AppColors.primaryBlue, foregroundColor: Colors.white, ), ), ], ), ), ), ); } /// Build empty state Widget _buildEmptyState(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ FaIcon( FontAwesomeIcons.locationDot, size: 64, color: AppColors.grey500.withValues(alpha: 0.4), ), const SizedBox(height: 16), const Text( 'Chưa có địa chỉ nào', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: AppColors.grey900, ), ), const SizedBox(height: 8), Text( 'Thêm địa chỉ để nhận hàng nhanh hơn', style: TextStyle( fontSize: 14, color: AppColors.grey500.withValues(alpha: 0.8), ), ), const SizedBox(height: 24), ElevatedButton.icon( onPressed: () { context.push(RouteNames.addressForm); }, icon: const FaIcon(FontAwesomeIcons.plus, size: 18), label: const Text( 'Thêm địa chỉ mới', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), ), style: ElevatedButton.styleFrom( backgroundColor: AppColors.primaryBlue, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), elevation: 0, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(AppRadius.button), ), ), ), ], ), ); } /// Set address as default void _setDefaultAddress(BuildContext context, WidgetRef ref, Address address) { ref.read(addressesProvider.notifier).setDefaultAddress(address.name); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const FaIcon( FontAwesomeIcons.circleCheck, color: Colors.white, size: 18, ), const SizedBox(width: 12), const Text('Đã đặt làm địa chỉ mặc định'), ], ), backgroundColor: const Color(0xFF10B981), duration: const Duration(seconds: 2), ), ); } /// Show info dialog void _showInfoDialog(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text( 'Hướng dẫn sử dụng', style: TextStyle(fontWeight: FontWeight.bold), ), content: const SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text('Quản lý địa chỉ giao hàng của bạn:'), SizedBox(height: 12), Text('• Thêm địa chỉ mới để dễ dàng đặt hàng'), Text('• Đặt địa chỉ mặc định cho đơn hàng'), Text('• Chỉnh sửa hoặc xóa địa chỉ bất kỳ'), Text('• Lưu nhiều địa chỉ cho các mục đích khác nhau'), ], ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Đóng'), ), ], ), ); } /// Show delete confirmation dialog void _showDeleteConfirmation( BuildContext context, WidgetRef ref, Address address, ) { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Xóa địa chỉ'), content: const Text('Bạn có chắc chắn muốn xóa địa chỉ này?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Hủy'), ), TextButton( onPressed: () { Navigator.pop(context); _deleteAddress(context, ref, address); }, style: TextButton.styleFrom(foregroundColor: AppColors.danger), child: const Text('Xóa'), ), ], ), ); } /// Delete address void _deleteAddress( BuildContext context, WidgetRef ref, Address address, ) async { try { await ref.read(addressesProvider.notifier).deleteAddress(address.name); if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const FaIcon( FontAwesomeIcons.circleCheck, color: Colors.white, size: 18, ), const SizedBox(width: 12), const Text('Đã xóa địa chỉ'), ], ), backgroundColor: const Color(0xFF10B981), duration: const Duration(seconds: 2), ), ); } } catch (e) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ const FaIcon( FontAwesomeIcons.circleExclamation, color: Colors.white, size: 18, ), const SizedBox(width: 12), Text('Lỗi: ${e.toString()}'), ], ), backgroundColor: AppColors.danger, duration: const Duration(seconds: 3), ), ); } } } }