update order detail

This commit is contained in:
Phuoc Nguyen
2025-11-24 17:00:11 +07:00
parent 75d6507719
commit 1851d60038
9 changed files with 1238 additions and 455 deletions

View File

@@ -3,14 +3,17 @@
/// Displays detailed order information including status timeline, delivery info, and products.
library;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:worker/core/constants/ui_constants.dart';
import 'package:worker/core/database/models/enums.dart';
import 'package:worker/core/enums/status_color.dart';
import 'package:worker/core/theme/colors.dart';
import 'package:worker/features/orders/domain/entities/order_detail.dart';
import 'package:worker/features/orders/presentation/providers/orders_provider.dart';
/// Order Detail Page
///
@@ -27,9 +30,7 @@ class OrderDetailPage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
// TODO: Replace with actual order data from provider
// For now using mock data based on HTML reference
final mockOrder = _getMockOrder();
final orderDetailAsync = ref.watch(orderDetailProvider(orderId));
return Scaffold(
backgroundColor: const Color(0xFFF4F6F8),
@@ -69,136 +70,98 @@ class OrderDetailPage extends ConsumerWidget {
foregroundColor: AppColors.grey900,
centerTitle: false,
),
body: Stack(
children: [
SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 100),
child: Column(
children: [
// Status Timeline Card
_buildStatusTimelineCard(
mockOrder['orderNumber']! as String,
mockOrder['status']! as OrderStatus,
mockOrder['statusHistory']! as List<Map<String, dynamic>>,
body: orderDetailAsync.when(
data: (orderDetail) {
return Stack(
children: [
SingleChildScrollView(
padding: const EdgeInsets.only(bottom: 100),
child: Column(
children: [
// Status Timeline Card
_buildStatusTimelineCard(orderDetail),
// Delivery/Address Information Card
_buildAddressInfoCard(orderDetail),
// Customer Information Card
_buildCustomerInfoCard(orderDetail),
// Products List Card
_buildProductsListCard(orderDetail),
// Order Summary Card
_buildOrderSummaryCard(orderDetail),
],
),
// Delivery Information Card
_buildDeliveryInfoCard(
mockOrder['deliveryMethod']! as String,
mockOrder['warehouseDate']! as DateTime,
mockOrder['deliveryDate']! as DateTime,
mockOrder['deliveryAddress']! as String,
mockOrder['receiverName']! as String,
mockOrder['receiverPhone']! as String,
),
// Customer Information Card
_buildCustomerInfoCard(
mockOrder['customerName']! as String,
mockOrder['customerPhone']! as String,
mockOrder['customerEmail']! as String,
mockOrder['customerType']! as String,
),
// Products List Card
_buildProductsListCard(),
// Order Summary Card
_buildOrderSummaryCard(
mockOrder['subtotal']! as double,
mockOrder['shippingFee']! as double,
mockOrder['discount']! as double,
mockOrder['total']! as double,
mockOrder['paymentMethod']! as String,
mockOrder['notes'] as String?,
),
],
),
),
// Fixed Action Buttons
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
decoration: BoxDecoration(
color: AppColors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 15,
offset: const Offset(0, -4),
),
],
),
padding: const EdgeInsets.all(16),
child: Row(
spacing: 12,
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: () {
// TODO: Implement contact customer
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Gọi điện cho khách hàng...'),
),
);
},
icon: const FaIcon(FontAwesomeIcons.phone, size: 18),
label: const Text('Liên hệ khách hàng'),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
side: const BorderSide(
color: AppColors.grey100,
width: 2,
),
foregroundColor: AppColors.grey900,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
Expanded(
child: ElevatedButton.icon(
onPressed: () {
// TODO: Implement update status
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Cập nhật trạng thái...'),
),
);
},
icon: const FaIcon(FontAwesomeIcons.penToSquare, size: 18),
label: const Text('Cập nhật trạng thái'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
backgroundColor: AppColors.primaryBlue,
foregroundColor: Colors.white,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
],
// Fixed Action Buttons
Positioned(
bottom: 0,
left: 0,
right: 0,
child: _buildActionButtons(context, orderDetail),
),
),
],
);
},
loading: () => const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const FaIcon(
FontAwesomeIcons.circleExclamation,
size: 64,
color: AppColors.danger,
),
const SizedBox(height: 16),
const Text(
'Không thể tải thông tin đơn hàng',
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.invalidate(orderDetailProvider(orderId));
},
icon: const FaIcon(FontAwesomeIcons.arrowsRotate, size: 16),
label: const Text('Thử lại'),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryBlue,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
),
),
),
],
),
],
),
),
);
}
/// Build Status Timeline Card
Widget _buildStatusTimelineCard(
String orderNumber,
OrderStatus currentStatus,
List<Map<String, dynamic>> statusHistory,
) {
Widget _buildStatusTimelineCard(OrderDetail orderDetail) {
final order = orderDetail.order;
final timeline = orderDetail.timeline;
return Card(
margin: const EdgeInsets.all(16),
elevation: 1,
@@ -209,33 +172,30 @@ class OrderDetailPage extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Order Number and Status Badge
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'#$orderNumber',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: AppColors.primaryBlue,
),
),
_buildStatusBadge(currentStatus),
],
Text(
'#${order.name}',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
color: AppColors.primaryBlue,
),
),
const SizedBox(height: 12,),
_buildStatusBadge(order.status, order.statusColor),
const SizedBox(height: 24),
// Status Timeline
...statusHistory.asMap().entries.map((entry) {
...timeline.asMap().entries.map((entry) {
final index = entry.key;
final item = entry.value;
final isLast = index == statusHistory.length - 1;
final isLast = index == timeline.length - 1;
return _buildTimelineItem(
title: item['title']! as String,
date: item['date'] as String?,
status: item['status']! as String,
title: item.label,
date: item.value,
status: item.status,
isLast: isLast,
);
}),
@@ -249,28 +209,28 @@ class OrderDetailPage extends ConsumerWidget {
Widget _buildTimelineItem({
required String title,
String? date,
required String status, // 'completed', 'active', 'pending'
required String status, // 'Success', 'Warning', 'Secondary', etc.
required bool isLast,
}) {
final statusColor = StatusColor.fromString(status) ?? StatusColor.secondary;
Color iconColor;
Color iconBgColor;
IconData iconData;
switch (status) {
case 'completed':
iconColor = Colors.white;
iconBgColor = AppColors.success;
iconData = FontAwesomeIcons.check;
break;
case 'active':
iconColor = Colors.white;
iconBgColor = AppColors.warning;
iconData = FontAwesomeIcons.gear;
break;
default: // pending
iconColor = AppColors.grey500;
iconBgColor = AppColors.grey100;
iconData = _getIconForTitle(title);
if (statusColor == StatusColor.success) {
iconColor = Colors.white;
iconBgColor = statusColor.color;
iconData = FontAwesomeIcons.check;
} else if (statusColor == StatusColor.warning) {
iconColor = Colors.white;
iconBgColor = statusColor.color;
iconData = FontAwesomeIcons.gear;
} else {
// Secondary or other
iconColor = AppColors.grey500;
iconBgColor = AppColors.grey100;
iconData = _getIconForTitle(title);
}
return Row(
@@ -286,7 +246,7 @@ class OrderDetailPage extends ConsumerWidget {
color: iconBgColor,
shape: BoxShape.circle,
),
child: FaIcon(iconData, size: 10, color: iconColor),
child: Center(child: FaIcon(iconData, size: 10, color: iconColor)),
),
if (!isLast)
Container(
@@ -342,85 +302,34 @@ class OrderDetailPage extends ConsumerWidget {
}
/// Build Status Badge
Widget _buildStatusBadge(OrderStatus status) {
Widget _buildStatusBadge(String status, String statusColorName) {
final statusColor = StatusColor.fromString(statusColorName) ?? StatusColor.secondary;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: _getStatusColor(status).withValues(alpha: 0.1),
color: statusColor.light,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: _getStatusColor(status).withValues(alpha: 0.3),
color: statusColor.border,
width: 1,
),
),
child: Text(
_getStatusText(status),
status,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: _getStatusColor(status),
color: statusColor.color,
),
),
);
}
/// Get status color
Color _getStatusColor(OrderStatus status) {
switch (status) {
case OrderStatus.draft:
return AppColors.grey500;
case OrderStatus.pending:
return AppColors.info;
case OrderStatus.confirmed:
return AppColors.info;
case OrderStatus.processing:
return AppColors.warning;
case OrderStatus.shipped:
return AppColors.primaryBlue;
case OrderStatus.delivered:
return AppColors.success;
case OrderStatus.completed:
return AppColors.success;
case OrderStatus.cancelled:
return AppColors.danger;
case OrderStatus.refunded:
return const Color(0xFFF97316);
}
}
/// Get status text
String _getStatusText(OrderStatus status) {
switch (status) {
case OrderStatus.draft:
return 'Nháp';
case OrderStatus.pending:
return 'Chờ xác nhận';
case OrderStatus.confirmed:
return 'Đã xác nhận';
case OrderStatus.processing:
return 'Đang xử lý';
case OrderStatus.shipped:
return 'Đang vận chuyển';
case OrderStatus.delivered:
return 'Đã giao hàng';
case OrderStatus.completed:
return 'Hoàn thành';
case OrderStatus.cancelled:
return 'Đã hủy';
case OrderStatus.refunded:
return 'Đã hoàn tiền';
}
}
/// Build Delivery Info Card
Widget _buildDeliveryInfoCard(
String deliveryMethod,
DateTime warehouseDate,
DateTime deliveryDate,
String deliveryAddress,
String receiverName,
String receiverPhone,
) {
/// Build Address Info Card
Widget _buildAddressInfoCard(OrderDetail orderDetail) {
final order = orderDetail.order;
final shippingAddress = orderDetail.shippingAddress;
final dateFormatter = DateFormat('dd/MM/yyyy');
return Card(
@@ -453,72 +362,11 @@ class OrderDetailPage extends ConsumerWidget {
const SizedBox(height: 16),
// Delivery Method
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.grey50,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: AppColors.primaryBlue,
borderRadius: BorderRadius.circular(8),
),
child: const FaIcon(
FontAwesomeIcons.truck,
color: Colors.white,
size: 18,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
deliveryMethod,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
),
),
const SizedBox(height: 2),
const Text(
'Giao trong 3-5 ngày làm việc',
style: TextStyle(
fontSize: 12,
color: AppColors.grey500,
),
),
],
),
),
],
),
),
const SizedBox(height: 16),
// Delivery Details
// Delivery Date
_buildInfoRow(
icon: FontAwesomeIcons.calendar,
label: 'Ngày xuất kho',
value: dateFormatter.format(warehouseDate),
valueColor: AppColors.success,
),
const SizedBox(height: 12),
_buildInfoRow(
icon: FontAwesomeIcons.clock,
label: 'Thời gian giao hàng',
value: '${dateFormatter.format(deliveryDate)}, 8:00 - 17:00',
label: 'Ngày giao hàng',
value: dateFormatter.format(DateTime.parse(order.deliveryDate)),
),
const SizedBox(height: 12),
@@ -526,7 +374,8 @@ class OrderDetailPage extends ConsumerWidget {
_buildInfoRow(
icon: FontAwesomeIcons.locationDot,
label: 'Địa chỉ giao hàng',
value: deliveryAddress,
value:
'${shippingAddress.addressLine1}\n${shippingAddress.wardName}, ${shippingAddress.cityName}',
),
const SizedBox(height: 12),
@@ -534,7 +383,7 @@ class OrderDetailPage extends ConsumerWidget {
_buildInfoRow(
icon: FontAwesomeIcons.user,
label: 'Người nhận',
value: '$receiverName - $receiverPhone',
value: '${shippingAddress.addressTitle} - ${shippingAddress.phone}',
),
],
),
@@ -590,12 +439,9 @@ class OrderDetailPage extends ConsumerWidget {
}
/// Build Customer Info Card
Widget _buildCustomerInfoCard(
String customerName,
String customerPhone,
String customerEmail,
String customerType,
) {
Widget _buildCustomerInfoCard(OrderDetail orderDetail) {
final order = orderDetail.order;
final billingAddress = orderDetail.billingAddress;
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
elevation: 1,
@@ -626,46 +472,19 @@ class OrderDetailPage extends ConsumerWidget {
const SizedBox(height: 16),
_buildCustomerRow('Tên khách hàng:', customerName),
_buildCustomerRow('Tên khách hàng:', order.customer),
const SizedBox(height: 12),
_buildCustomerRow('Số điện thoại:', customerPhone),
_buildCustomerRow('Số điện thoại:', billingAddress.phone),
const SizedBox(height: 12),
_buildCustomerRow('Email:', customerEmail),
_buildCustomerRow('Email:', billingAddress.email),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'Loại khách hàng:',
style: TextStyle(fontSize: 14, color: AppColors.grey500),
),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 4,
),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFFFFD700), Color(0xFFFFA500)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(12),
),
child: Text(
customerType,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
],
),
if (billingAddress.taxCode.isNotEmpty) ...[
_buildCustomerRow('Mã số thuế:', billingAddress.taxCode),
const SizedBox(height: 12),
],
],
),
),
@@ -694,25 +513,13 @@ class OrderDetailPage extends ConsumerWidget {
}
/// Build Products List Card
Widget _buildProductsListCard() {
final products = [
{
'name': 'Gạch Eurotile MỘC LAM E03',
'size': '60x60cm',
'sku': 'ET-ML-E03-60x60',
'quantity': '30 m²',
'unitPrice': '285.000đ/m²',
'totalPrice': '8.550.000đ',
},
{
'name': 'Gạch Eurotile STONE GREY S02',
'size': '80x80cm',
'sku': 'ET-SG-S02-80x80',
'quantity': '20 m²',
'unitPrice': '217.500đ/m²',
'totalPrice': '4.350.000đ',
},
];
Widget _buildProductsListCard(OrderDetail orderDetail) {
final items = orderDetail.items;
final currencyFormatter = NumberFormat.currency(
locale: 'vi_VN',
symbol: 'đ',
decimalDigits: 0,
);
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
@@ -744,8 +551,8 @@ class OrderDetailPage extends ConsumerWidget {
const SizedBox(height: 16),
...products.map(
(product) => Container(
...items.map(
(item) => Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
@@ -756,19 +563,48 @@ class OrderDetailPage extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Product Image
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: AppColors.grey50,
if (item.thumbnail != null)
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: CachedNetworkImage(
imageUrl: item.thumbnail!,
width: 60,
height: 60,
fit: BoxFit.cover,
placeholder: (context, url) => Container(
width: 60,
height: 60,
color: AppColors.grey50,
child: const Center(
child: CircularProgressIndicator(strokeWidth: 2),
),
),
errorWidget: (context, url, error) => Container(
width: 60,
height: 60,
color: AppColors.grey50,
child: const FaIcon(
FontAwesomeIcons.image,
color: AppColors.grey500,
size: 28,
),
),
),
)
else
Container(
width: 60,
height: 60,
decoration: BoxDecoration(
color: AppColors.grey50,
borderRadius: BorderRadius.circular(6),
),
child: const FaIcon(
FontAwesomeIcons.image,
color: AppColors.grey500,
size: 28,
),
),
child: const FaIcon(
FontAwesomeIcons.image,
color: AppColors.grey500,
size: 28,
),
),
const SizedBox(width: 12),
@@ -778,7 +614,7 @@ class OrderDetailPage extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
product['name']!,
item.itemName,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
@@ -787,14 +623,7 @@ class OrderDetailPage extends ConsumerWidget {
),
const SizedBox(height: 4),
Text(
'Kích thước: ${product['size']}',
style: const TextStyle(
fontSize: 12,
color: AppColors.grey500,
),
),
Text(
'SKU: ${product['sku']}',
'Mã: ${item.itemCode}',
style: const TextStyle(
fontSize: 12,
color: AppColors.grey500,
@@ -815,7 +644,7 @@ class OrderDetailPage extends ConsumerWidget {
),
),
Text(
product['quantity']!,
'${item.qtyOfSm}',
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
@@ -828,14 +657,14 @@ class OrderDetailPage extends ConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
product['unitPrice']!,
'${currencyFormatter.format(item.price)}/m²',
style: const TextStyle(
fontSize: 12,
color: AppColors.grey500,
),
),
Text(
product['totalPrice']!,
currencyFormatter.format(item.totalAmount),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
@@ -860,14 +689,9 @@ class OrderDetailPage extends ConsumerWidget {
}
/// Build Order Summary Card
Widget _buildOrderSummaryCard(
double subtotal,
double shippingFee,
double discount,
double total,
String paymentMethod,
String? notes,
) {
Widget _buildOrderSummaryCard(OrderDetail orderDetail) {
final order = orderDetail.order;
final paymentTerms = orderDetail.paymentTerms;
final currencyFormatter = NumberFormat.currency(
locale: 'vi_VN',
symbol: 'đ',
@@ -904,35 +728,29 @@ class OrderDetailPage extends ConsumerWidget {
const SizedBox(height: 16),
_buildSummaryRow('Tạm tính:', currencyFormatter.format(subtotal)),
_buildSummaryRow('Tổng tiền hàng:', currencyFormatter.format(order.total)),
const SizedBox(height: 8),
_buildSummaryRow(
'Phí vận chuyển:',
shippingFee == 0
? 'Miễn phí'
: currencyFormatter.format(shippingFee),
valueColor: shippingFee == 0 ? AppColors.success : null,
),
const SizedBox(height: 8),
_buildSummaryRow(
'Giảm giá VIP:',
'-${currencyFormatter.format(discount)}',
valueColor: AppColors.success,
),
if (order.totalRemaining > 0) ...[
_buildSummaryRow(
'Còn lại:',
currencyFormatter.format(order.totalRemaining),
valueColor: AppColors.warning,
),
const SizedBox(height: 8),
],
const Divider(height: 24),
_buildSummaryRow(
'Tổng cộng:',
currencyFormatter.format(total),
currencyFormatter.format(order.grandTotal),
isTotal: true,
),
const Divider(height: 24),
// Payment Method
// Payment Terms
Row(
children: [
const FaIcon(
@@ -942,22 +760,31 @@ class OrderDetailPage extends ConsumerWidget {
),
const SizedBox(width: 6),
const Text(
'Phương thức thanh toán:',
'Điều khoản thanh toán:',
style: TextStyle(fontSize: 14, color: AppColors.grey500),
),
],
),
const SizedBox(height: 4),
Text(
paymentMethod,
paymentTerms.name,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
fontWeight: FontWeight.w600,
color: AppColors.grey900,
),
),
const SizedBox(height: 4),
Text(
paymentTerms.description,
style: const TextStyle(
fontSize: 12,
color: AppColors.grey500,
height: 1.4,
),
),
if (notes != null) ...[
if (order.description.isNotEmpty) ...[
const Divider(height: 24),
// Order Notes
@@ -973,7 +800,7 @@ class OrderDetailPage extends ConsumerWidget {
),
const SizedBox(height: 4),
Text(
notes,
order.description,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
@@ -1019,56 +846,73 @@ class OrderDetailPage extends ConsumerWidget {
);
}
/// Get mock order data for development
Map<String, dynamic> _getMockOrder() {
return {
'orderNumber': 'DH001234',
'status': OrderStatus.processing,
'statusHistory': [
{
'title': 'Đơn hàng được tạo',
'date': '03/08/2023 - 09:30',
'status': 'completed',
},
{
'title': 'Đã xác nhận đơn hàng',
'date': '03/08/2023 - 10:15',
'status': 'completed',
},
{
'title': 'Đang chuẩn bị hàng',
'date': 'Đang thực hiện',
'status': 'active',
},
{
'title': 'Vận chuyển',
'date': 'Dự kiến: 05/08/2023',
'status': 'pending',
},
{
'title': 'Giao hàng thành công',
'date': 'Dự kiến: 07/08/2023',
'status': 'pending',
},
],
'deliveryMethod': 'Giao hàng tiêu chuẩn',
'warehouseDate': DateTime(2023, 8, 5),
'deliveryDate': DateTime(2023, 8, 7),
'deliveryAddress':
'123 Đường Lê Văn Lương, Phường Tân Hưng,\nQuận 7, TP. Hồ Chí Minh',
'receiverName': 'Nguyễn Văn A',
'receiverPhone': '0901234567',
'customerName': 'Nguyễn Văn A',
'customerPhone': '0901234567',
'customerEmail': 'nguyenvana@email.com',
'customerType': 'Khách VIP',
'subtotal': 12900000.0,
'shippingFee': 0.0,
'discount': 129000.0,
'total': 12771000.0,
'paymentMethod': 'Chuyển khoản ngân hàng',
'notes':
'Giao hàng trong giờ hành chính. Vui lòng gọi trước 30 phút khi đến giao hàng.',
};
/// Build Action Buttons
Widget _buildActionButtons(BuildContext context, OrderDetail orderDetail) {
final shippingAddress = orderDetail.shippingAddress;
return Container(
decoration: BoxDecoration(
color: AppColors.white,
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.1),
blurRadius: 15,
offset: const Offset(0, -4),
),
],
),
padding: const EdgeInsets.all(16),
child: Row(
spacing: 12,
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Gọi ${shippingAddress.phone}...'),
),
);
},
icon: const FaIcon(FontAwesomeIcons.phone, size: 18),
label: const Text('Liên hệ'),
style: OutlinedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
side: const BorderSide(
color: AppColors.grey100,
width: 2,
),
foregroundColor: AppColors.grey900,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
Expanded(
child: ElevatedButton.icon(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Chức năng đang phát triển...'),
),
);
},
icon: const FaIcon(FontAwesomeIcons.penToSquare, size: 18),
label: const Text('Cập nhật'),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
backgroundColor: AppColors.primaryBlue,
foregroundColor: Colors.white,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
],
),
);
}
}