From a52f5fc70730a5f6dd034b285a1b63234f725c4e Mon Sep 17 00:00:00 2001 From: Dwindi Ramadhana Date: Wed, 7 Jan 2026 23:34:48 +0700 Subject: [PATCH] fix(admin): set explicit width for product search dropdown in order form Prevents the search dropdown from shrinking or overflowing unpredictably in the flex container. Also ensures better alignment. --- .../src/routes/Orders/partials/OrderForm.tsx | 131 +++++++++--------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/admin-spa/src/routes/Orders/partials/OrderForm.tsx b/admin-spa/src/routes/Orders/partials/OrderForm.tsx index cdeb2ae..08952f0 100644 --- a/admin-spa/src/routes/Orders/partials/OrderForm.tsx +++ b/admin-spa/src/routes/Orders/partials/OrderForm.tsx @@ -44,9 +44,9 @@ import { SearchableSelect } from '@/components/ui/searchable-select'; export type CountryOption = { code: string; name: string }; export type StatesMap = Record>; // { US: { CA: 'California' } } export type PaymentChannel = { id: string; title: string; meta?: any }; -export type PaymentMethod = { - id: string; - title: string; +export type PaymentMethod = { + id: string; + title: string; enabled?: boolean; channels?: PaymentChannel[]; // If present, show channels instead of gateway }; @@ -113,7 +113,7 @@ type Props = { hideSubmitButton?: boolean; }; -const STATUS_LIST = ['pending','processing','on-hold','completed','cancelled','refunded','failed']; +const STATUS_LIST = ['pending', 'processing', 'on-hold', 'completed', 'cancelled', 'refunded', 'failed']; // --- Component -------------------------------------------------------- export default function OrderForm({ @@ -167,11 +167,11 @@ export default function OrderForm({ const only = countries[0]?.code || ''; if (shipDiff) { if (only && shippingData.country !== only) { - setShippingData({...shippingData, country: only}); + setShippingData({ ...shippingData, country: only }); } } else { // keep shipping synced to billing when not different - setShippingData({...shippingData, country: bCountry}); + setShippingData({ ...shippingData, country: bCountry }); } } }, [oneCountryOnly, countries, shipDiff, bCountry, shippingData.country]); @@ -233,12 +233,12 @@ export default function OrderForm({ // Debounce city input to avoid hitting backend on every keypress const [debouncedCity, setDebouncedCity] = React.useState(effectiveShippingAddress.city); - + React.useEffect(() => { const timer = setTimeout(() => { setDebouncedCity(effectiveShippingAddress.city); }, 500); // Wait 500ms after user stops typing - + return () => clearTimeout(timer); }, [effectiveShippingAddress.city]); @@ -295,10 +295,10 @@ export default function OrderForm({ const products: ProductSearchItem[] = Array.isArray(raw) ? raw : Array.isArray(raw?.data) - ? raw.data - : Array.isArray(raw?.rows) - ? raw.rows - : []; + ? raw.data + : Array.isArray(raw?.rows) + ? raw.rows + : []; const customersRaw = customersQ.data as any; const customers: any[] = Array.isArray(customersRaw) ? customersRaw : []; @@ -311,7 +311,7 @@ export default function OrderForm({ () => items.reduce((sum, it) => sum + (Number(it.qty) || 0) * (Number(it.price) || 0), 0), [items] ); - + // Calculate shipping cost // In edit mode: use existing order shipping total (fixed unless address changes) // In create mode: calculate from selected shipping method @@ -325,34 +325,34 @@ export default function OrderForm({ const method = shippings.find(s => s.id === shippingMethod); return method ? Number(method.cost) || 0 : 0; }, [mode, initial?.totals?.shipping, shippingMethod, shippings]); - + // Calculate discount from validated coupons const couponDiscount = React.useMemo(() => { return validatedCoupons.reduce((sum, c) => sum + (c.discount_amount || 0), 0); }, [validatedCoupons]); - + // Calculate order total (items + shipping - coupons) const orderTotal = React.useMemo(() => { return Math.max(0, itemsTotal + shippingCost - couponDiscount); }, [itemsTotal, shippingCost, couponDiscount]); - + // Validate coupon const validateCoupon = async (code: string) => { if (!code.trim()) return; - + // Check if already added if (validatedCoupons.some(c => c.code.toLowerCase() === code.toLowerCase())) { toast.error(__('Coupon already added')); return; } - + setCouponValidating(true); try { const response = await api.post('/coupons/validate', { code: code.trim(), subtotal: itemsTotal, }); - + if (response.valid) { setValidatedCoupons([...validatedCoupons, response]); setCouponInput(''); @@ -366,7 +366,7 @@ export default function OrderForm({ setCouponValidating(false); } }; - + const removeCoupon = (code: string) => { setValidatedCoupons(validatedCoupons.filter(c => c.code !== code)); }; @@ -408,7 +408,7 @@ export default function OrderForm({ // Keep shipping country synced to billing when unchecked React.useEffect(() => { - if (!shipDiff) setShippingData({...shippingData, country: bCountry}); + if (!shipDiff) setShippingData({ ...shippingData, country: bCountry }); }, [shipDiff, bCountry]); // Clamp states when country changes @@ -417,7 +417,7 @@ export default function OrderForm({ }, [bCountry]); React.useEffect(() => { if (shippingData.state && !states[shippingData.country]?.[shippingData.state]) { - setShippingData({...shippingData, state: ''}); + setShippingData({ ...shippingData, state: '' }); } }, [shippingData.country]); @@ -426,7 +426,7 @@ export default function OrderForm({ async function handleSubmit(e: React.FormEvent) { e.preventDefault(); - + // For virtual-only products, don't send address fields const billingData: any = { first_name: bFirst, @@ -434,7 +434,7 @@ export default function OrderForm({ email: bEmail, phone: bPhone, }; - + // Only add address fields for physical products if (hasPhysicalProduct) { billingData.address_1 = bAddr1; @@ -443,7 +443,7 @@ export default function OrderForm({ billingData.postcode = bPost; billingData.country = bCountry; } - + const payload: OrderPayload = { status, billing: billingData, @@ -502,7 +502,7 @@ export default function OrderForm({ onChange={(val: string) => { const p = products.find((prod: ProductSearchItem) => String(prod.id) === val); if (!p) return; - + // If variable product, show variation selector if (p.type === 'variable' && p.variations && p.variations.length > 0) { setSelectedProduct(p); @@ -510,7 +510,7 @@ export default function OrderForm({ setShowVariationDrawer(true); return; } - + // Simple product - add directly (but allow duplicates for different quantities) setItems(prev => [ ...prev, @@ -530,6 +530,7 @@ export default function OrderForm({ onSearch={setSearchQ} disabled={!itemsEditable} showCheckIndicator={false} + className="w-[200px] md:w-[300px]" /> ) : ( @@ -733,7 +734,7 @@ export default function OrderForm({ .map(([key, value]) => `${key}: ${value || ''}`) .filter(([_, value]) => value) // Remove empty values .join(', '); - + return (