order success

This commit is contained in:
Phuoc Nguyen
2025-11-24 17:28:17 +07:00
parent 1851d60038
commit c3b5653420
9 changed files with 55 additions and 34 deletions

View File

@@ -56,10 +56,11 @@ class CheckoutPage extends HookConsumerWidget {
// Payment method (will be set to first payment term name from API)
final paymentMethod = useState<String>('');
// Price negotiation
final needsNegotiation = useState<bool>(false);
// Price negotiation (ignore_pricing_rule in API)
final ignorePricingRule = useState<bool>(false);
final needsContract = useState(false);
// Contract request (contract_request in API)
final contractRequest = useState<bool>(false);
// Watch API provider for payment terms
final paymentTermsListAsync = ref.watch(paymentTermsListProvider);
@@ -145,8 +146,8 @@ class CheckoutPage extends HookConsumerWidget {
const SizedBox(height: AppSpacing.md),
// Payment Method Section (hidden if negotiation is checked)
if (!needsNegotiation.value)
// Payment Method Section (hidden if price negotiation is checked)
if (!ignorePricingRule.value)
paymentTermsListAsync.when(
data: (paymentTerms) {
// Set default payment method to first term if not set
@@ -220,7 +221,7 @@ class CheckoutPage extends HookConsumerWidget {
),
),
if (!needsNegotiation.value)
if (!ignorePricingRule.value)
const SizedBox(height: AppSpacing.md),
// Discount Code Section
@@ -240,7 +241,7 @@ class CheckoutPage extends HookConsumerWidget {
const SizedBox(height: AppSpacing.md),
// Price Negotiation Section
PriceNegotiationSection(needsNegotiation: needsNegotiation),
PriceNegotiationSection(ignorePricingRule: ignorePricingRule),
const SizedBox(height: AppSpacing.md),
@@ -256,9 +257,9 @@ class CheckoutPage extends HookConsumerWidget {
child: Row(
children: [
Checkbox(
value: needsContract.value,
value: contractRequest.value,
onChanged: (value) {
needsContract.value = value ?? false;
contractRequest.value = value ?? false;
},
activeColor: AppColors.warning,
),
@@ -308,7 +309,8 @@ class CheckoutPage extends HookConsumerWidget {
// Place Order Button
CheckoutSubmitButton(
formKey: formKey,
needsNegotiation: needsNegotiation.value,
ignorePricingRule: ignorePricingRule.value,
contractRequest: contractRequest.value,
needsInvoice: needsInvoice.value,
selectedAddress: selectedAddress.value,
paymentMethod: paymentMethod.value,

View File

@@ -20,7 +20,8 @@ class CheckoutSubmitButton extends HookConsumerWidget {
const CheckoutSubmitButton({
super.key,
required this.formKey,
required this.needsNegotiation,
required this.ignorePricingRule,
required this.contractRequest,
required this.needsInvoice,
required this.selectedAddress,
required this.paymentMethod,
@@ -30,7 +31,8 @@ class CheckoutSubmitButton extends HookConsumerWidget {
});
final GlobalKey<FormState> formKey;
final bool needsNegotiation;
final bool ignorePricingRule;
final bool contractRequest;
final bool needsInvoice;
final Address? selectedAddress;
final String paymentMethod;
@@ -62,7 +64,7 @@ class CheckoutSubmitButton extends HookConsumerWidget {
}
},
style: ElevatedButton.styleFrom(
backgroundColor: needsNegotiation
backgroundColor: ignorePricingRule
? AppColors.warning
: AppColors.primaryBlue,
foregroundColor: Colors.white,
@@ -73,7 +75,7 @@ class CheckoutSubmitButton extends HookConsumerWidget {
),
),
child: Text(
needsNegotiation ? 'Gửi yêu cầu đàm phán' : 'Đặt hàng',
ignorePricingRule ? 'Gửi yêu cầu đàm phán' : 'Đặt hàng',
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
@@ -122,7 +124,8 @@ class CheckoutSubmitButton extends HookConsumerWidget {
deliveryAddress: deliveryAddressData,
paymentMethod: paymentMethod,
needsInvoice: needsInvoice,
needsNegotiation: needsNegotiation,
ignorePricingRule: ignorePricingRule,
contractRequest: contractRequest,
notes: notes,
).future);
@@ -131,7 +134,7 @@ class CheckoutSubmitButton extends HookConsumerWidget {
result['orderId'] as String? ??
'DH${DateTime.now().millisecondsSinceEpoch.toString().substring(7)}';
if (needsNegotiation) {
if (ignorePricingRule) {
// Navigate to order success page with negotiation flag
if (context.mounted) {
Navigator.of(context).pop();

View File

@@ -13,8 +13,8 @@ import 'package:worker/core/theme/colors.dart';
/// Allows user to request price negotiation instead of direct order.
class PriceNegotiationSection extends HookWidget {
const PriceNegotiationSection({super.key, required this.needsNegotiation});
final ValueNotifier<bool> needsNegotiation;
const PriceNegotiationSection({super.key, required this.ignorePricingRule});
final ValueNotifier<bool> ignorePricingRule;
@override
Widget build(BuildContext context) {
@@ -29,9 +29,9 @@ class PriceNegotiationSection extends HookWidget {
child: Row(
children: [
Checkbox(
value: needsNegotiation.value,
value: ignorePricingRule.value,
onChanged: (value) {
needsNegotiation.value = value ?? false;
ignorePricingRule.value = value ?? false;
},
activeColor: AppColors.warning,
),

View File

@@ -92,6 +92,8 @@ class OrderRemoteDataSource {
/// "customer_address": "...",
/// "description": "...",
/// "payment_terms": "...",
/// "ignore_pricing_rule": true,
/// "contract_request": true,
/// "items": [{"item_id": "...", "qty_entered": 0, "primary_qty": 0, "price_entered": 0}]
/// }
/// Returns: { "message": { "name": "SAL-ORD-2025-00001", ... } }
@@ -100,7 +102,8 @@ class OrderRemoteDataSource {
required Map<String, dynamic> deliveryAddress,
required String paymentMethod,
bool needsInvoice = false,
bool needsNegotiation = false,
bool ignorePricingRule = false,
bool contractRequest = false,
String? notes,
}) async {
try {
@@ -126,6 +129,8 @@ class OrderRemoteDataSource {
'customer_address': deliveryAddress['name'] ?? '',
'description': notes ?? 'Order from mobile app',
'payment_terms': paymentMethod,
'ignore_pricing_rule': ignorePricingRule,
'contract_request': contractRequest,
'items': formattedItems,
};

View File

@@ -98,7 +98,8 @@ class OrderRepositoryImpl implements OrderRepository {
required Map<String, dynamic> deliveryAddress,
required String paymentMethod,
bool needsInvoice = false,
bool needsNegotiation = false,
bool ignorePricingRule = false,
bool contractRequest = false,
String? notes,
}) async {
try {
@@ -107,7 +108,8 @@ class OrderRepositoryImpl implements OrderRepository {
deliveryAddress: deliveryAddress,
paymentMethod: paymentMethod,
needsInvoice: needsInvoice,
needsNegotiation: needsNegotiation,
ignorePricingRule: ignorePricingRule,
contractRequest: contractRequest,
notes: notes,
);
} catch (e) {

View File

@@ -31,7 +31,8 @@ abstract class OrderRepository {
required Map<String, dynamic> deliveryAddress,
required String paymentMethod,
bool needsInvoice = false,
bool needsNegotiation = false,
bool ignorePricingRule = false,
bool contractRequest = false,
String? notes,
});

View File

@@ -183,7 +183,7 @@ class OrderSuccessPage extends StatelessWidget {
// Navigate to order details page
context.pushReplacementNamed(
RouteNames.orderDetail,
pathParameters: {'orderId': orderNumber},
pathParameters: {'id': orderNumber},
);
},
icon: const FaIcon(FontAwesomeIcons.eye, size: 18),

View File

@@ -31,7 +31,8 @@ Future<Map<String, dynamic>> createOrder(
required Map<String, dynamic> deliveryAddress,
required String paymentMethod,
bool needsInvoice = false,
bool needsNegotiation = false,
bool ignorePricingRule = false,
bool contractRequest = false,
String? notes,
}) async {
final repository = await ref.watch(orderRepositoryProvider.future);
@@ -40,7 +41,8 @@ Future<Map<String, dynamic>> createOrder(
deliveryAddress: deliveryAddress,
paymentMethod: paymentMethod,
needsInvoice: needsInvoice,
needsNegotiation: needsNegotiation,
ignorePricingRule: ignorePricingRule,
contractRequest: contractRequest,
notes: notes,
);
}

View File

@@ -83,7 +83,8 @@ final class CreateOrderProvider
Map<String, dynamic> deliveryAddress,
String paymentMethod,
bool needsInvoice,
bool needsNegotiation,
bool ignorePricingRule,
bool contractRequest,
String? notes,
})
super.argument,
@@ -120,7 +121,8 @@ final class CreateOrderProvider
Map<String, dynamic> deliveryAddress,
String paymentMethod,
bool needsInvoice,
bool needsNegotiation,
bool ignorePricingRule,
bool contractRequest,
String? notes,
});
return createOrder(
@@ -129,7 +131,8 @@ final class CreateOrderProvider
deliveryAddress: argument.deliveryAddress,
paymentMethod: argument.paymentMethod,
needsInvoice: argument.needsInvoice,
needsNegotiation: argument.needsNegotiation,
ignorePricingRule: argument.ignorePricingRule,
contractRequest: argument.contractRequest,
notes: argument.notes,
);
}
@@ -145,7 +148,7 @@ final class CreateOrderProvider
}
}
String _$createOrderHash() => r'2d13526815e19a2bbef2f2974dad991d8ffcb594';
String _$createOrderHash() => r'622a1d98d53a6696a302cde85842d449a8164fe7';
/// Create Order Provider
///
@@ -160,7 +163,8 @@ final class CreateOrderFamily extends $Family
Map<String, dynamic> deliveryAddress,
String paymentMethod,
bool needsInvoice,
bool needsNegotiation,
bool ignorePricingRule,
bool contractRequest,
String? notes,
})
> {
@@ -182,7 +186,8 @@ final class CreateOrderFamily extends $Family
required Map<String, dynamic> deliveryAddress,
required String paymentMethod,
bool needsInvoice = false,
bool needsNegotiation = false,
bool ignorePricingRule = false,
bool contractRequest = false,
String? notes,
}) => CreateOrderProvider._(
argument: (
@@ -190,7 +195,8 @@ final class CreateOrderFamily extends $Family
deliveryAddress: deliveryAddress,
paymentMethod: paymentMethod,
needsInvoice: needsInvoice,
needsNegotiation: needsNegotiation,
ignorePricingRule: ignorePricingRule,
contractRequest: contractRequest,
notes: notes,
),
from: this,