fix order, update qr
This commit is contained in:
@@ -11,6 +11,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:worker/core/constants/ui_constants.dart';
|
||||
import 'package:worker/core/enums/status_color.dart';
|
||||
import 'package:worker/core/router/app_router.dart';
|
||||
import 'package:worker/core/theme/colors.dart';
|
||||
import 'package:worker/core/utils/extensions.dart';
|
||||
import 'package:worker/features/account/domain/entities/address.dart';
|
||||
@@ -38,8 +39,8 @@ class OrderDetailPage extends ConsumerWidget {
|
||||
onPopInvoked: (didPop) {
|
||||
if (didPop) {
|
||||
// Dispose providers when leaving the page
|
||||
ref.invalidate(updateOrderAddressProvider);
|
||||
ref.invalidate(cancelOrderProvider);
|
||||
ref..invalidate(updateOrderAddressProvider)
|
||||
..invalidate(cancelOrderProvider);
|
||||
}
|
||||
},
|
||||
child: Scaffold(
|
||||
@@ -1411,11 +1412,9 @@ class OrderDetailPage extends ConsumerWidget {
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
// TODO: Navigate to payment page
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Chức năng thanh toán đang phát triển'),
|
||||
),
|
||||
// Navigate to payment QR page
|
||||
context.push(
|
||||
'${RouteNames.paymentQr}?orderId=${orderDetail.order.name}',
|
||||
);
|
||||
},
|
||||
icon: const FaIcon(FontAwesomeIcons.creditCard, size: 18),
|
||||
|
||||
@@ -37,8 +37,8 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.removeListener(_onSearchChanged);
|
||||
_searchController.dispose();
|
||||
_searchController..removeListener(_onSearchChanged)
|
||||
..dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -50,8 +50,9 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final filteredOrdersAsync = ref.watch(filteredOrdersProvider);
|
||||
final ordersAsync = ref.watch(ordersProvider);
|
||||
final selectedStatus = ref.watch(selectedOrderStatusProvider);
|
||||
final searchQuery = ref.watch(orderSearchQueryProvider);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFF4F6F8),
|
||||
@@ -102,22 +103,49 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
|
||||
// Orders List
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 24),
|
||||
sliver: filteredOrdersAsync.when(
|
||||
sliver: ordersAsync.when(
|
||||
data: (orders) {
|
||||
if (orders.isEmpty) {
|
||||
return _buildEmptyState();
|
||||
// Filter by status
|
||||
var filtered = orders;
|
||||
if (selectedStatus != null) {
|
||||
filtered = filtered
|
||||
.where((order) => order.status == selectedStatus)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Filter by search query
|
||||
if (searchQuery.isNotEmpty) {
|
||||
filtered = filtered
|
||||
.where((order) => order.name
|
||||
.toLowerCase()
|
||||
.contains(searchQuery.toLowerCase()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
// Sort by transaction date (newest first)
|
||||
filtered.sort((a, b) {
|
||||
try {
|
||||
final aDate = DateTime.parse(a.transactionDate);
|
||||
final bDate = DateTime.parse(b.transactionDate);
|
||||
return bDate.compareTo(aDate);
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
if (filtered.isEmpty) {
|
||||
return _buildEmptyState();
|
||||
}
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate((context, index) {
|
||||
final order = orders[index];
|
||||
final order = filtered[index];
|
||||
return OrderCard(
|
||||
order: order,
|
||||
onTap: () {
|
||||
context.push('/orders/${order.name}');
|
||||
},
|
||||
);
|
||||
}, childCount: orders.length),
|
||||
}, childCount: filtered.length),
|
||||
);
|
||||
},
|
||||
loading: () => _buildLoadingState(),
|
||||
@@ -149,10 +177,13 @@ class _OrdersPageState extends ConsumerState<OrdersPage> {
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Mã đơn hàng',
|
||||
hintStyle: const TextStyle(color: AppColors.grey500, fontSize: 14),
|
||||
prefixIcon: const FaIcon(
|
||||
FontAwesomeIcons.magnifyingGlass,
|
||||
color: AppColors.grey500,
|
||||
size: 18,
|
||||
prefixIcon: const Padding(
|
||||
padding: EdgeInsets.all(14),
|
||||
child: FaIcon(
|
||||
FontAwesomeIcons.magnifyingGlass,
|
||||
color: AppColors.grey500,
|
||||
size: 18,
|
||||
),
|
||||
),
|
||||
suffixIcon: _searchController.text.isNotEmpty
|
||||
? IconButton(
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
///
|
||||
/// QR code payment screen with bank transfer information.
|
||||
/// Features:
|
||||
/// - Payment amount display with minimum payment warning
|
||||
/// - QR code for quick payment
|
||||
/// - Bank transfer information with copy buttons
|
||||
/// - Payment confirmation and proof upload buttons
|
||||
@@ -31,12 +30,10 @@ import 'package:worker/features/orders/presentation/providers/order_repository_p
|
||||
/// Displays QR code and bank transfer information for payment.
|
||||
class PaymentQrPage extends HookConsumerWidget {
|
||||
final String orderId;
|
||||
final double amount;
|
||||
|
||||
const PaymentQrPage({
|
||||
super.key,
|
||||
required this.orderId,
|
||||
required this.amount,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -126,14 +123,8 @@ class PaymentQrPage extends HookConsumerWidget {
|
||||
children: [
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
|
||||
// Payment Amount Card
|
||||
_buildAmountCard(amount),
|
||||
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
|
||||
// QR Code Card
|
||||
_buildQrCodeCard(
|
||||
amount,
|
||||
orderId,
|
||||
qrCodeData.value?['qr_code'] as String?,
|
||||
isLoadingQr.value,
|
||||
@@ -187,70 +178,8 @@ class PaymentQrPage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Build payment amount card
|
||||
Widget _buildAmountCard(double amount) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: AppSpacing.md),
|
||||
padding: const EdgeInsets.all(AppSpacing.md),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(AppRadius.card),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
_formatCurrency(amount),
|
||||
style: const TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColors.primaryBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Số tiền cần thanh toán',
|
||||
style: TextStyle(fontSize: 14, color: AppColors.grey500),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFFF8E1),
|
||||
borderRadius: BorderRadius.circular(AppRadius.card),
|
||||
border: Border.all(color: const Color(0xFFFFD54F)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const FaIcon(FontAwesomeIcons.circleInfo, color: AppColors.warning, size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Thanh toán không dưới 20%',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.orange[900],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Build QR code card
|
||||
Widget _buildQrCodeCard(
|
||||
double amount,
|
||||
String orderId,
|
||||
String? qrCodeData,
|
||||
bool isLoading,
|
||||
@@ -956,7 +885,6 @@ class PaymentQrPage extends HookConsumerWidget {
|
||||
RouteNames.orderSuccess,
|
||||
queryParameters: {
|
||||
'orderNumber': orderId,
|
||||
'total': amount.toString(),
|
||||
'isNegotiation': 'false',
|
||||
},
|
||||
);
|
||||
@@ -985,9 +913,4 @@ class PaymentQrPage extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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