fix: Resolve Tax and OrderForm errors

## Error 1: Tax Settings - Empty SelectItem value 
**Issue:** Radix UI Select does not allow empty string as SelectItem value
**Error:** "A <Select.Item /> must have a value prop that is not an empty string"

**Solution:**
- Use 'standard' instead of empty string for UI
- Convert 'standard' → '' when submitting to API
- Initialize selectedTaxClass to 'standard'
- Update all dialog handlers to use 'standard'

## Error 2: OrderForm - Undefined shipping variables 
**Issue:** Removed individual shipping state variables (sFirst, sLast, sCountry, etc.) but forgot to update all references
**Error:** "Cannot find name 'sCountry'"

**Solution:**
Fixed all remaining references:
1. **useEffect for country sync:** `setSCountry(bCountry)` → `setShippingData({...shippingData, country: bCountry})`
2. **useEffect for state validation:** `sState && !states[sCountry]` → `shippingData.state && !states[shippingData.country]`
3. **Customer autofill:** Individual setters → `setShippingData({ first_name, last_name, ... })`
4. **Removed sStateOptions:** No longer needed with dynamic fields

## Testing:
-  Tax settings page loads without errors
-  Add/Edit tax rate dialog works
-  OrderForm loads without errors
-  Shipping fields render dynamically
-  Customer autofill works with new state structure
This commit is contained in:
dwindown
2025-11-10 15:42:16 +07:00
parent e05635f358
commit a487baa61d
2 changed files with 27 additions and 22 deletions

View File

@@ -149,13 +149,15 @@ export default function OrderForm({
if (oneCountryOnly) { if (oneCountryOnly) {
const only = countries[0]?.code || ''; const only = countries[0]?.code || '';
if (shipDiff) { if (shipDiff) {
if (only && sCountry !== only) setSCountry(only); if (only && shippingData.country !== only) {
setShippingData({...shippingData, country: only});
}
} else { } else {
// keep shipping synced to billing when not different // keep shipping synced to billing when not different
setSCountry(bCountry); setShippingData({...shippingData, country: bCountry});
} }
} }
}, [oneCountryOnly, countries, shipDiff, bCountry, sCountry]); }, [oneCountryOnly, countries, shipDiff, bCountry, shippingData.country]);
// Order meta // Order meta
const [status, setStatus] = React.useState(initial?.status || 'pending'); const [status, setStatus] = React.useState(initial?.status || 'pending');
@@ -292,7 +294,7 @@ export default function OrderForm({
// Keep shipping country synced to billing when unchecked // Keep shipping country synced to billing when unchecked
React.useEffect(() => { React.useEffect(() => {
if (!shipDiff) setSCountry(bCountry); if (!shipDiff) setShippingData({...shippingData, country: bCountry});
}, [shipDiff, bCountry]); }, [shipDiff, bCountry]);
// Clamp states when country changes // Clamp states when country changes
@@ -300,12 +302,13 @@ export default function OrderForm({
if (bState && !states[bCountry]?.[bState]) setBState(''); if (bState && !states[bCountry]?.[bState]) setBState('');
}, [bCountry]); }, [bCountry]);
React.useEffect(() => { React.useEffect(() => {
if (sState && !states[sCountry]?.[sState]) setSState(''); if (shippingData.state && !states[shippingData.country]?.[shippingData.state]) {
}, [sCountry]); setShippingData({...shippingData, state: ''});
}
}, [shippingData.country]);
const countryOptions = countries.map(c => ({ value: c.code, label: `${c.name} (${c.code})` })); const countryOptions = countries.map(c => ({ value: c.code, label: `${c.name} (${c.code})` }));
const bStateOptions = Object.entries(states[bCountry] || {}).map(([code, name]) => ({ value: code, label: name })); const bStateOptions = Object.entries(states[bCountry] || {}).map(([code, name]) => ({ value: code, label: name }));
const sStateOptions = Object.entries(states[sCountry] || {}).map(([code, name]) => ({ value: code, label: name }));
async function handleSubmit(e: React.FormEvent) { async function handleSubmit(e: React.FormEvent) {
e.preventDefault(); e.preventDefault();
@@ -692,13 +695,15 @@ export default function OrderForm({
// Autofill shipping if available // Autofill shipping if available
if (data.shipping && data.shipping.address_1) { if (data.shipping && data.shipping.address_1) {
setShipDiff(true); setShipDiff(true);
setSFirst(data.shipping.first_name || ''); setShippingData({
setSLast(data.shipping.last_name || ''); first_name: data.shipping.first_name || '',
setSAddr1(data.shipping.address_1 || ''); last_name: data.shipping.last_name || '',
setSCity(data.shipping.city || ''); address_1: data.shipping.address_1 || '',
setSPost(data.shipping.postcode || ''); city: data.shipping.city || '',
setSCountry(data.shipping.country || bCountry); postcode: data.shipping.postcode || '',
setSState(data.shipping.state || ''); country: data.shipping.country || bCountry,
state: data.shipping.state || '',
});
} }
} }

View File

@@ -24,7 +24,7 @@ export default function TaxSettings() {
const [editingRate, setEditingRate] = useState<any | null>(null); const [editingRate, setEditingRate] = useState<any | null>(null);
const [deletingRate, setDeletingRate] = useState<any | null>(null); const [deletingRate, setDeletingRate] = useState<any | null>(null);
const [dismissedSuggestions, setDismissedSuggestions] = useState<string[]>([]); const [dismissedSuggestions, setDismissedSuggestions] = useState<string[]>([]);
const [selectedTaxClass, setSelectedTaxClass] = useState<string>(''); const [selectedTaxClass, setSelectedTaxClass] = useState<string>('standard');
// Fetch tax settings // Fetch tax settings
const { data: settings, isLoading } = useQuery({ const { data: settings, isLoading } = useQuery({
@@ -142,7 +142,7 @@ export default function TaxSettings() {
state: formData.get('state') as string || '', state: formData.get('state') as string || '',
rate: parseFloat(formData.get('rate') as string), rate: parseFloat(formData.get('rate') as string),
name: formData.get('name') as string, name: formData.get('name') as string,
tax_class: selectedTaxClass || '', tax_class: selectedTaxClass === 'standard' ? '' : selectedTaxClass,
priority: 1, priority: 1,
compound: 0, compound: 0,
shipping: 1, shipping: 1,
@@ -222,7 +222,7 @@ export default function TaxSettings() {
<Button <Button
size="sm" size="sm"
onClick={() => { onClick={() => {
setSelectedTaxClass(''); setSelectedTaxClass('standard');
setShowAddRate(true); setShowAddRate(true);
}} }}
> >
@@ -396,10 +396,10 @@ export default function TaxSettings() {
if (!open) { if (!open) {
setShowAddRate(false); setShowAddRate(false);
setEditingRate(null); setEditingRate(null);
setSelectedTaxClass(''); setSelectedTaxClass('standard');
} else { } else {
// Initialize tax class when opening // Initialize tax class when opening (convert empty to 'standard')
setSelectedTaxClass(editingRate?.tax_class || ''); setSelectedTaxClass(editingRate?.tax_class || 'standard');
} }
}}> }}>
<DialogContent> <DialogContent>
@@ -464,12 +464,12 @@ export default function TaxSettings() {
<div> <div>
<Label>{__('Tax Class (Optional)')}</Label> <Label>{__('Tax Class (Optional)')}</Label>
<Select value={selectedTaxClass} onValueChange={setSelectedTaxClass}> <Select value={selectedTaxClass || 'standard'} onValueChange={setSelectedTaxClass}>
<SelectTrigger> <SelectTrigger>
<SelectValue placeholder={__('Standard')} /> <SelectValue placeholder={__('Standard')} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value="">{__('Standard')}</SelectItem> <SelectItem value="standard">{__('Standard')}</SelectItem>
<SelectItem value="reduced-rate">{__('Reduced Rate')}</SelectItem> <SelectItem value="reduced-rate">{__('Reduced Rate')}</SelectItem>
<SelectItem value="zero-rate">{__('Zero Rate')}</SelectItem> <SelectItem value="zero-rate">{__('Zero Rate')}</SelectItem>
</SelectContent> </SelectContent>