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:
@@ -412,6 +412,40 @@ All CRUD list pages MUST follow these consistent UI patterns:
|
||||
|
||||
When adding products to orders, variable products MUST follow the Tokopedia/Shopee pattern:
|
||||
|
||||
**Responsive Modal Pattern:**
|
||||
- **Desktop:** Use `Dialog` component (centered modal)
|
||||
- **Mobile:** Use `Drawer` component (bottom sheet)
|
||||
- **Detection:** Use `useMediaQuery("(min-width: 768px)")`
|
||||
|
||||
**Implementation:**
|
||||
```tsx
|
||||
const isDesktop = useMediaQuery("(min-width: 768px)");
|
||||
|
||||
{/* Desktop: Dialog */}
|
||||
{selectedProduct && isDesktop && (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<DialogHeader>
|
||||
<DialogTitle>{product.name}</DialogTitle>
|
||||
</DialogHeader>
|
||||
{/* Variation list */}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)}
|
||||
|
||||
{/* Mobile: Drawer */}
|
||||
{selectedProduct && !isDesktop && (
|
||||
<Drawer open={open} onOpenChange={setOpen}>
|
||||
<DrawerContent>
|
||||
<DrawerHeader>
|
||||
<DrawerTitle>{product.name}</DrawerTitle>
|
||||
</DrawerHeader>
|
||||
{/* Variation list */}
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
)}
|
||||
```
|
||||
|
||||
**Desktop Pattern:**
|
||||
```
|
||||
[Search Product...]
|
||||
@@ -438,7 +472,6 @@ When adding products to orders, variable products MUST follow the Tokopedia/Shop
|
||||
|
||||
✓ Anker Earbuds
|
||||
Black Rp296,000 [-] 1 [+] [🗑️]
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
1. ✅ Each variation is a **separate line item**
|
||||
@@ -447,6 +480,8 @@ When adding products to orders, variable products MUST follow the Tokopedia/Shop
|
||||
4. ✅ Mobile: Click variation to open drawer for selection
|
||||
5. ❌ Don't auto-select first variation
|
||||
6. ❌ Don't hide variation selector
|
||||
7. ✅ **Duplicate Handling**: Same product + same variation = increment quantity (NOT new row)
|
||||
8. ✅ **Empty Attribute Values**: Filter empty attribute values - Use `.filter()` to remove empty strings
|
||||
|
||||
**Implementation:**
|
||||
- Product search shows variable products
|
||||
|
||||
Reference in New Issue
Block a user