fix(orders): Fix shipping rate recalculation and auto-selection
## Issues Fixed: ### 1. Shipping rates not recalculating when address changes ✅ **Problem:** - Change province → Rates stay the same - Query was cached incorrectly **Root Cause:** Query key only tracked country, state, postcode: ```ts queryKey: [..., shippingData.country, shippingData.state, shippingData.postcode] ``` But Rajaongkir and other plugins also need: - City (different rates per city) - Address (for some plugins) **Solution:** ```ts queryKey: [ ..., shippingData.country, shippingData.state, shippingData.city, // Added shippingData.postcode, shippingData.address_1 // Added ], staleTime: 0, // Always refetch when key changes ``` ### 2. First rate auto-selected but dropdown shows placeholder ✅ **Problem:** - Rates calculated → First rate used in total - But dropdown shows "Select shipping" - Confusing UX **Solution:** Added useEffect to auto-select first rate: ```ts useEffect(() => { if (shippingRates?.methods?.length > 0) { const firstRateId = shippingRates.methods[0].id; const currentExists = shippingRates.methods.some(m => m.id === shippingMethod); // Auto-select if no selection or current not in new rates if (!shippingMethod || !currentExists) { setShippingMethod(firstRateId); } } }, [shippingRates?.methods]); ``` ## Benefits: - ✅ Change province → Rates recalculate immediately - ✅ First rate auto-selected in dropdown - ✅ Selection cleared if no rates available - ✅ Selection preserved if still valid after recalculation ## Testing: 1. Select Jakarta → Shows JNE rates 2. Change to Bali → Rates recalculate, first auto-selected 3. Change to remote area → Different rates, first auto-selected 4. Dropdown always shows current selection
This commit is contained in:
@@ -187,7 +187,7 @@ export default function OrderForm({
|
||||
|
||||
// Calculate shipping rates dynamically
|
||||
const { data: shippingRates, isLoading: shippingLoading } = useQuery({
|
||||
queryKey: ['shipping-rates', items.map(i => ({ product_id: i.product_id, qty: i.qty })), shippingData.country, shippingData.postcode, shippingData.state],
|
||||
queryKey: ['shipping-rates', items.map(i => ({ product_id: i.product_id, qty: i.qty })), shippingData.country, shippingData.state, shippingData.city, shippingData.postcode, shippingData.address_1],
|
||||
queryFn: async () => {
|
||||
if (!shippingData.country) return null;
|
||||
return api.post('/shipping/calculate', {
|
||||
@@ -196,11 +196,12 @@ export default function OrderForm({
|
||||
});
|
||||
},
|
||||
enabled: !!shippingData.country && items.length > 0,
|
||||
staleTime: 0, // Always refetch when query key changes
|
||||
});
|
||||
|
||||
// Calculate order preview with taxes
|
||||
const { data: orderPreview, isLoading: previewLoading } = useQuery({
|
||||
queryKey: ['order-preview', items.map(i => ({ product_id: i.product_id, qty: i.qty })), bCountry, bState, bPost, bCity, shippingData, shippingMethod, validatedCoupons.map(c => c.code)],
|
||||
queryKey: ['order-preview', items.map(i => ({ product_id: i.product_id, qty: i.qty })), bCountry, bState, bPost, bCity, shippingData.country, shippingData.state, shippingData.city, shippingData.postcode, shippingMethod, validatedCoupons.map(c => c.code)],
|
||||
queryFn: async () => {
|
||||
if (items.length === 0) return null;
|
||||
return api.post('/orders/preview', {
|
||||
@@ -212,6 +213,7 @@ export default function OrderForm({
|
||||
});
|
||||
},
|
||||
enabled: items.length > 0 && !!bCountry,
|
||||
staleTime: 0, // Always refetch when query key changes
|
||||
});
|
||||
|
||||
// --- Product search for Add Item ---
|
||||
@@ -301,6 +303,21 @@ export default function OrderForm({
|
||||
setValidatedCoupons(validatedCoupons.filter(c => c.code !== code));
|
||||
};
|
||||
|
||||
// Auto-select first shipping rate when rates change
|
||||
React.useEffect(() => {
|
||||
if (shippingRates?.methods && shippingRates.methods.length > 0) {
|
||||
const firstRateId = shippingRates.methods[0].id;
|
||||
// Only auto-select if no method selected or current method not in new rates
|
||||
const currentMethodExists = shippingRates.methods.some((m: any) => m.id === shippingMethod);
|
||||
if (!shippingMethod || !currentMethodExists) {
|
||||
setShippingMethod(firstRateId);
|
||||
}
|
||||
} else if (shippingRates?.methods && shippingRates.methods.length === 0) {
|
||||
// Clear selection if no rates available
|
||||
setShippingMethod('');
|
||||
}
|
||||
}, [shippingRates?.methods]);
|
||||
|
||||
// Check if cart has physical products
|
||||
const hasPhysicalProduct = React.useMemo(
|
||||
() => items.some(item => {
|
||||
|
||||
Reference in New Issue
Block a user