create order
This commit is contained in:
280
lib/features/orders/presentation/pages/order_success_page.dart
Normal file
280
lib/features/orders/presentation/pages/order_success_page.dart
Normal file
@@ -0,0 +1,280 @@
|
||||
/// Order Success Page
|
||||
///
|
||||
/// Displays order confirmation after successful order placement.
|
||||
/// Features:
|
||||
/// - Success icon and message
|
||||
/// - Order information (order number, date, total, payment method, status)
|
||||
/// - Different message for negotiation requests
|
||||
/// - Navigation to order details or home
|
||||
library;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.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/router/app_router.dart';
|
||||
import 'package:worker/core/theme/colors.dart';
|
||||
|
||||
/// Order Success Page
|
||||
class OrderSuccessPage extends StatelessWidget {
|
||||
const OrderSuccessPage({
|
||||
super.key,
|
||||
required this.orderNumber,
|
||||
this.total,
|
||||
this.paymentMethod,
|
||||
this.isNegotiation = false,
|
||||
});
|
||||
|
||||
final String orderNumber;
|
||||
final double? total;
|
||||
final String? paymentMethod;
|
||||
final bool isNegotiation;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final now = DateTime.now();
|
||||
final dateFormat = DateFormat('dd/MM/yyyy HH:mm');
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
body: SafeArea(
|
||||
child: Center(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Success Icon
|
||||
Container(
|
||||
width: 80,
|
||||
height: 80,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.success.withValues(alpha: 0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
FontAwesomeIcons.check,
|
||||
color: AppColors.success,
|
||||
size: 40,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.lg),
|
||||
|
||||
// Success Title
|
||||
Text(
|
||||
isNegotiation
|
||||
? 'Gửi yêu cầu thành công!'
|
||||
: 'Tạo đơn hàng thành công!',
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF212121),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
|
||||
// Success Message
|
||||
Text(
|
||||
isNegotiation
|
||||
? 'Chúng tôi sẽ liên hệ với bạn để đàm phán giá trong vòng 24 giờ.'
|
||||
: 'Cảm ơn bạn đã đặt hàng. Chúng tôi sẽ liên hệ xác nhận trong vòng 24 giờ.',
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.grey500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// Order Info Card
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF4F6F8),
|
||||
borderRadius: BorderRadius.circular(AppRadius.card),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Order Number
|
||||
Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Mã đơn hàng',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.grey500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
orderNumber,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.primaryBlue,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
|
||||
// Order Date
|
||||
_buildInfoRow(
|
||||
'Ngày đặt',
|
||||
dateFormat.format(now),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
|
||||
// Total Amount
|
||||
if (total != null)
|
||||
_buildInfoRow(
|
||||
'Tổng tiền',
|
||||
_formatCurrency(total!),
|
||||
valueStyle: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Color(0xFF212121),
|
||||
),
|
||||
),
|
||||
|
||||
if (total != null) const SizedBox(height: AppSpacing.sm),
|
||||
|
||||
// Payment Method
|
||||
if (paymentMethod != null && !isNegotiation)
|
||||
_buildInfoRow(
|
||||
'Phương thức thanh toán',
|
||||
paymentMethod!,
|
||||
),
|
||||
|
||||
if (paymentMethod != null && !isNegotiation)
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
|
||||
// Status
|
||||
_buildInfoRow(
|
||||
'Trạng thái',
|
||||
isNegotiation ? 'Chờ đàm phán' : 'Chờ xác nhận',
|
||||
valueStyle: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: isNegotiation
|
||||
? AppColors.warning
|
||||
: AppColors.warning,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// View Order Details Button
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// Navigate to order details page
|
||||
context.pushReplacementNamed(
|
||||
RouteNames.orderDetail,
|
||||
pathParameters: {'orderId': orderNumber},
|
||||
);
|
||||
},
|
||||
icon: const FaIcon(FontAwesomeIcons.eye, size: 18),
|
||||
label: const Text(
|
||||
'Xem chi tiết đơn hàng',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryBlue,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.button),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
|
||||
// Back to Home Button
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () {
|
||||
// Navigate to home page
|
||||
context.goNamed(RouteNames.home);
|
||||
},
|
||||
icon: const FaIcon(FontAwesomeIcons.house, size: 18),
|
||||
label: const Text(
|
||||
'Quay về trang chủ',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColors.grey900,
|
||||
side: BorderSide(
|
||||
color: AppColors.grey100,
|
||||
width: 1.5,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppRadius.button),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Build info row
|
||||
Widget _buildInfoRow(
|
||||
String label,
|
||||
String value, {
|
||||
TextStyle? valueStyle,
|
||||
}) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.grey500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: valueStyle ??
|
||||
const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF212121),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Format currency
|
||||
String _formatCurrency(double amount) {
|
||||
return '${amount.toStringAsFixed(0).replaceAllMapped(RegExp(r'(\d)(?=(\d{3})+(?!\d))'), (Match m) => '${m[1]}.')}₫';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user