fix: OrderForm variable product issues - empty colors, desktop dialog, duplicate handling

**Issues Fixed:**

1. **Empty Color Values**
   - Problem: Variation attributes showed 'Color:' with no value
   - Cause: Backend returned empty strings for some attributes
   - Fix: Filter empty values with .filter(([_, value]) => value)
   - Result: Only non-empty attributes displayed

2. **Desktop Should Use Dialog**
   - Problem: Both desktop and mobile used Drawer (bottom sheet)
   - Expected: Desktop = Dialog (modal), Mobile = Drawer
   - Fix: Added useMediaQuery hook, conditional rendering
   - Pattern: Same as Settings pages (Payments, Shipping, etc.)

3. **Duplicate Product+Variation Handling**
   - Problem: Same product+variation created new row each time
   - Expected: Should increment quantity of existing row
   - Fix: Check for existing item before adding
   - Logic: findIndex by product_id + variation_id, then increment qty

**Changes to OrderForm.tsx:**
- Added Dialog and useMediaQuery imports
- Added isDesktop detection
- Split variation selector into Desktop (Dialog) and Mobile (Drawer)
- Fixed variationLabel to filter empty values
- Added duplicate check logic before adding to cart
- If exists: increment qty, else: add new item

**Changes to PROJECT_SOP.md:**
- Added Responsive Modal Pattern section
- Documented Dialog/Drawer pattern with code example
- Added rule 3: Same product+variation = increment qty
- Added rule 6: Filter empty attribute values
- Added rule 7: Responsive modals (Dialog/Drawer)

**Result:**
 Color values display correctly (empty values filtered)
 Desktop uses Dialog (centered modal)
 Mobile uses Drawer (bottom sheet)
 Duplicate product+variation increments quantity
 UX matches Tokopedia/Shopee pattern
 Follows Settings page modal pattern
This commit is contained in:
dwindown
2025-11-20 10:44:48 +07:00
parent dfbd992a22
commit be69b40237
4 changed files with 176 additions and 24 deletions

View File

@@ -267,7 +267,7 @@ export default function Orders() {
</div>
<div className="flex gap-2 items-center">
<Filter className="w-4 h-4 opacity-60" />
<Filter className="min-w-4 w-4 h-4 opacity-60" />
<Select
value={status ?? 'all'}
onValueChange={(v) => {
@@ -308,7 +308,7 @@ export default function Orders() {
{activeFiltersCount > 0 && (
<button
className="text-sm text-muted-foreground hover:text-foreground underline"
className="text-sm text-muted-foreground hover:text-foreground underline text-nowrap"
onClick={handleResetFilters}
>
{__('Clear filters')}