Files
worker/lib/features/account/presentation/pages/addresses_page.dart
2025-11-17 11:03:51 +07:00

284 lines
9.0 KiB
Dart

/// 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:flutter_hooks/flutter_hooks.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/theme/colors.dart';
import 'package:worker/features/account/presentation/widgets/address_card.dart';
/// Addresses Page
///
/// Page for managing saved delivery addresses.
class AddressesPage extends HookConsumerWidget {
const AddressesPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Mock addresses data
final addresses = useState<List<Map<String, dynamic>>>([
{
'id': '1',
'name': 'Hoàng Minh Hiệp',
'phone': '0347302911',
'address':
'123 Đường Võ Văn Ngân, Phường Linh Chiểu, Thành phố Thủ Đức, TP.HCM',
'isDefault': true,
},
{
'id': '2',
'name': 'Hoàng Minh Hiệp',
'phone': '0347302911',
'address': '456 Đường Nguyễn Thị Minh Khai, Quận 3, TP.HCM',
'isDefault': false,
},
{
'id': '3',
'name': 'Công ty TNHH ABC',
'phone': '0283445566',
'address': '789 Đường Lê Văn Sỹ, Quận Phú Nhuận, TP.HCM',
'isDefault': false,
},
]);
return Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
leading: IconButton(
icon: const FaIcon(FontAwesomeIcons.arrowLeft, color: Colors.black, size: 20),
onPressed: () => context.pop(),
),
title: const Text(
'Địa chỉ đã lưu',
style: TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
centerTitle: false,
actions: [
IconButton(
icon: const FaIcon(FontAwesomeIcons.plus, color: Colors.black, size: 20),
onPressed: () {
_showAddAddress(context);
},
),
const SizedBox(width: AppSpacing.sm),
],
),
body: Column(
children: [
// Address List
Expanded(
child: addresses.value.isEmpty
? _buildEmptyState(context)
: ListView.separated(
padding: const EdgeInsets.all(AppSpacing.md),
itemCount: addresses.value.length,
separatorBuilder: (context, index) =>
const SizedBox(height: AppSpacing.md),
itemBuilder: (context, index) {
final address = addresses.value[index];
return AddressCard(
name: address['name'] as String,
phone: address['phone'] as String,
address: address['address'] as String,
isDefault: address['isDefault'] as bool,
onEdit: () {
_showEditAddress(context, address);
},
onDelete: () {
_showDeleteConfirmation(context, addresses, index);
},
onSetDefault: () {
_setDefaultAddress(addresses, index);
},
);
},
),
),
// Add New Address Button
Padding(
padding: const EdgeInsets.all(AppSpacing.md),
child: SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () {
_showAddAddress(context);
},
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),
),
),
),
),
),
],
),
);
}
/// 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.5),
),
const SizedBox(height: 16),
const Text(
'Chưa có địa chỉ nào',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: AppColors.grey500,
),
),
const SizedBox(height: 8),
const Text(
'Thêm địa chỉ để nhận hàng nhanh hơn',
style: TextStyle(fontSize: 14, color: AppColors.grey500),
),
const SizedBox(height: 24),
ElevatedButton.icon(
onPressed: () {
_showAddAddress(context);
},
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(
ValueNotifier<List<Map<String, dynamic>>> addresses,
int index,
) {
final updatedAddresses = addresses.value.map((address) {
return {...address, 'isDefault': false};
}).toList();
updatedAddresses[index]['isDefault'] = true;
addresses.value = updatedAddresses;
}
/// Show add address dialog (TODO: implement form page)
void _showAddAddress(BuildContext context) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Chức năng thêm địa chỉ mới sẽ được phát triển'),
duration: Duration(seconds: 2),
),
);
}
/// Show edit address dialog (TODO: implement form page)
void _showEditAddress(BuildContext context, Map<String, dynamic> address) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Chỉnh sửa địa chỉ: ${address['name']}'),
duration: const Duration(seconds: 2),
),
);
}
/// Show delete confirmation dialog
void _showDeleteConfirmation(
BuildContext context,
ValueNotifier<List<Map<String, dynamic>>> addresses,
int index,
) {
showDialog<void>(
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, addresses, index);
},
style: TextButton.styleFrom(foregroundColor: AppColors.danger),
child: const Text('Xóa'),
),
],
),
);
}
/// Delete address
void _deleteAddress(
BuildContext context,
ValueNotifier<List<Map<String, dynamic>>> addresses,
int index,
) {
final deletedAddress = addresses.value[index];
final updatedAddresses = List<Map<String, dynamic>>.from(addresses.value);
updatedAddresses.removeAt(index);
// If deleted address was default and there are other addresses,
// set the first one as default
if (deletedAddress['isDefault'] == true && updatedAddresses.isNotEmpty) {
updatedAddresses[0]['isDefault'] = true;
}
addresses.value = updatedAddresses;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Đã xóa địa chỉ'),
duration: Duration(seconds: 2),
),
);
}
}