fix(orders): Prevent premature shipping rate fetching
## Issues Fixed: ### 1. Shipping rates fetched on page load ✅ **Problem:** - Open New Order form → Shipping already calculated - Using cached/legacy values - Should wait for address to be filled **Solution:** Added address completeness check: ```ts const isShippingAddressComplete = useMemo(() => { if (!shippingData.country) return false; if (!shippingData.city) return false; // If country has states, require state const countryStates = states[shippingData.country]; if (countryStates && Object.keys(countryStates).length > 0) { if (!shippingData.state) return false; } return true; }, [shippingData.country, shippingData.state, shippingData.city]); ``` Query only enabled when address is complete: ```ts enabled: isShippingAddressComplete && items.length > 0 ``` ### 2. Unnecessary refetches ✅ **Problem:** - Every keystroke triggered refetch - staleTime: 0 meant always refetch **Solution:** ```ts staleTime: 5 * 60 * 1000 // Cache for 5 minutes ``` Query key still includes all address fields, so: - Change country → Refetch (key changed) - Change state → Refetch (key changed) - Change city → Refetch (key changed) - Change postcode → Refetch (key changed) - Same values → Use cache (key unchanged) ### 3. Order preview fetching too early ✅ **Problem:** - Preview calculated before shipping method selected - Incomplete data **Solution:** ```ts enabled: items.length > 0 && !!bCountry && !!shippingMethod ``` ## New Behavior: ### On Page Load: - ❌ No shipping fetch - ❌ No preview fetch - ✅ Clean state ### User Fills Address: 1. Enter country → Not enough 2. Enter state → Not enough 3. Enter city → ✅ **Fetch shipping rates** 4. Rates appear → First auto-selected 5. ✅ **Fetch order preview** (has method now) ### User Changes Address: 1. Change Jakarta → Bandung 2. Query key changes (city changed) 3. ✅ **Refetch shipping rates** 4. New rates appear → First auto-selected 5. ✅ **Refetch order preview** ### User Types in Same Field: 1. Type "Jak..." → "Jakarta" 2. Query key same (city still "Jakarta") 3. ❌ No refetch (use cache) 4. Efficient! ## Benefits: - ✅ No premature fetching - ✅ No unnecessary API calls - ✅ Smart caching (5 min) - ✅ Only refetch when address actually changes - ✅ Better UX and performance
This commit is contained in:
@@ -185,25 +185,36 @@ export default function OrderForm({
|
||||
enabled: items.length > 0,
|
||||
});
|
||||
|
||||
// Check if shipping address is complete enough to calculate rates
|
||||
const isShippingAddressComplete = React.useMemo(() => {
|
||||
// Need at minimum: country, state (if applicable), city
|
||||
if (!shippingData.country) return false;
|
||||
if (!shippingData.city) return false;
|
||||
// If country has states, require state
|
||||
const countryStates = states[shippingData.country];
|
||||
if (countryStates && Object.keys(countryStates).length > 0 && !shippingData.state) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, [shippingData.country, shippingData.state, shippingData.city, states]);
|
||||
|
||||
// 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.state, shippingData.city, shippingData.postcode, shippingData.address_1],
|
||||
queryFn: async () => {
|
||||
if (!shippingData.country) return null;
|
||||
return api.post('/shipping/calculate', {
|
||||
items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
|
||||
shipping: shippingData,
|
||||
});
|
||||
},
|
||||
enabled: !!shippingData.country && items.length > 0,
|
||||
staleTime: 0, // Always refetch when query key changes
|
||||
enabled: isShippingAddressComplete && items.length > 0,
|
||||
staleTime: 5 * 60 * 1000, // Cache for 5 minutes - only refetch if 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.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', {
|
||||
items: items.map(i => ({ product_id: i.product_id, qty: i.qty })),
|
||||
billing: { country: bCountry, state: bState, postcode: bPost, city: bCity },
|
||||
@@ -212,8 +223,8 @@ export default function OrderForm({
|
||||
coupons: validatedCoupons.map(c => c.code),
|
||||
});
|
||||
},
|
||||
enabled: items.length > 0 && !!bCountry,
|
||||
staleTime: 0, // Always refetch when query key changes
|
||||
enabled: items.length > 0 && !!bCountry && !!shippingMethod,
|
||||
staleTime: 5 * 60 * 1000, // Cache for 5 minutes - only refetch if query key changes
|
||||
});
|
||||
|
||||
// --- Product search for Add Item ---
|
||||
|
||||
Reference in New Issue
Block a user