feat: Add product images support with WP Media Library integration
- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
This commit is contained in:
228
HASHROUTER_FIXES.md
Normal file
228
HASHROUTER_FIXES.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# HashRouter Fixes Complete
|
||||
|
||||
**Date:** Nov 26, 2025 2:59 PM GMT+7
|
||||
|
||||
---
|
||||
|
||||
## ✅ Issues Fixed
|
||||
|
||||
### 1. View Cart Button in Toast - HashRouter Compatible
|
||||
|
||||
**Problem:** Toast "View Cart" button was using `window.location.href` which doesn't work with HashRouter.
|
||||
|
||||
**Files Fixed:**
|
||||
- `customer-spa/src/pages/Shop/index.tsx`
|
||||
- `customer-spa/src/pages/Product/index.tsx`
|
||||
|
||||
**Changes:**
|
||||
```typescript
|
||||
// Before (Shop page)
|
||||
onClick: () => window.location.href = '/cart'
|
||||
|
||||
// After
|
||||
onClick: () => navigate('/cart')
|
||||
```
|
||||
|
||||
**Added:** `useNavigate` import from `react-router-dom`
|
||||
|
||||
---
|
||||
|
||||
### 2. Header Links - HashRouter Compatible
|
||||
|
||||
**Problem:** All header links were using `<a href>` which causes full page reload instead of client-side navigation.
|
||||
|
||||
**File Fixed:**
|
||||
- `customer-spa/src/layouts/BaseLayout.tsx`
|
||||
|
||||
**Changes:**
|
||||
|
||||
**All Layouts Fixed:**
|
||||
- Classic Layout
|
||||
- Modern Layout
|
||||
- Boutique Layout
|
||||
- Launch Layout
|
||||
|
||||
**Before:**
|
||||
```tsx
|
||||
<a href="/cart">Cart</a>
|
||||
<a href="/my-account">Account</a>
|
||||
<a href="/shop">Shop</a>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```tsx
|
||||
<Link to="/cart">Cart</Link>
|
||||
<Link to="/my-account">Account</Link>
|
||||
<Link to="/shop">Shop</Link>
|
||||
```
|
||||
|
||||
**Added:** `import { Link } from 'react-router-dom'`
|
||||
|
||||
---
|
||||
|
||||
### 3. Store Logo → Store Title
|
||||
|
||||
**Problem:** Header showed "Store Logo" placeholder text instead of actual site title.
|
||||
|
||||
**File Fixed:**
|
||||
- `customer-spa/src/layouts/BaseLayout.tsx`
|
||||
|
||||
**Changes:**
|
||||
|
||||
**Before:**
|
||||
```tsx
|
||||
<a href="/">Store Logo</a>
|
||||
```
|
||||
|
||||
**After:**
|
||||
```tsx
|
||||
<Link to="/shop">
|
||||
{(window as any).woonoowCustomer?.siteTitle || 'Store Title'}
|
||||
</Link>
|
||||
```
|
||||
|
||||
**Behavior:**
|
||||
- Shows actual site title from `window.woonoowCustomer.siteTitle`
|
||||
- Falls back to "Store Title" if not set
|
||||
- Consistent with Admin SPA behavior
|
||||
|
||||
---
|
||||
|
||||
### 4. Clear Cart Dialog - Modern UI
|
||||
|
||||
**Problem:** Cart page was using raw browser `confirm()` alert for Clear Cart confirmation.
|
||||
|
||||
**Files:**
|
||||
- Created: `customer-spa/src/components/ui/dialog.tsx`
|
||||
- Updated: `customer-spa/src/pages/Cart/index.tsx`
|
||||
|
||||
**Changes:**
|
||||
|
||||
**Dialog Component:**
|
||||
- Copied from Admin SPA
|
||||
- Uses Radix UI Dialog primitive
|
||||
- Modern, accessible UI
|
||||
- Consistent with Admin SPA
|
||||
|
||||
**Cart Page:**
|
||||
```typescript
|
||||
// Before
|
||||
const handleClearCart = () => {
|
||||
if (window.confirm('Are you sure?')) {
|
||||
clearCart();
|
||||
}
|
||||
};
|
||||
|
||||
// After
|
||||
const [showClearDialog, setShowClearDialog] = useState(false);
|
||||
|
||||
const handleClearCart = () => {
|
||||
clearCart();
|
||||
setShowClearDialog(false);
|
||||
toast.success('Cart cleared');
|
||||
};
|
||||
|
||||
// Dialog UI
|
||||
<Dialog open={showClearDialog} onOpenChange={setShowClearDialog}>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Clear Cart?</DialogTitle>
|
||||
<DialogDescription>
|
||||
Are you sure you want to remove all items from your cart?
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter>
|
||||
<Button variant="outline" onClick={() => setShowClearDialog(false)}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button variant="destructive" onClick={handleClearCart}>
|
||||
Clear Cart
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Summary
|
||||
|
||||
| Issue | Status | Files Modified |
|
||||
|-------|--------|----------------|
|
||||
| **View Cart Toast** | ✅ Fixed | Shop.tsx, Product.tsx |
|
||||
| **Header Links** | ✅ Fixed | BaseLayout.tsx (all layouts) |
|
||||
| **Store Title** | ✅ Fixed | BaseLayout.tsx (all layouts) |
|
||||
| **Clear Cart Dialog** | ✅ Fixed | dialog.tsx (new), Cart.tsx |
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Test View Cart Button
|
||||
1. Add product to cart from shop page
|
||||
2. Click "View Cart" in toast
|
||||
3. Should navigate to `/shop#/cart` (no page reload)
|
||||
|
||||
### Test Header Links
|
||||
1. Click "Cart" in header
|
||||
2. Should navigate to `/shop#/cart` (no page reload)
|
||||
3. Click "Shop" in header
|
||||
4. Should navigate to `/shop#/` (no page reload)
|
||||
5. Click "Account" in header
|
||||
6. Should navigate to `/shop#/my-account` (no page reload)
|
||||
|
||||
### Test Store Title
|
||||
1. Check header shows site title (not "Store Logo")
|
||||
2. If no title set, shows "Store Title"
|
||||
3. Title is clickable and navigates to shop
|
||||
|
||||
### Test Clear Cart Dialog
|
||||
1. Add items to cart
|
||||
2. Click "Clear Cart" button
|
||||
3. Should show dialog (not browser alert)
|
||||
4. Click "Cancel" - dialog closes, cart unchanged
|
||||
5. Click "Clear Cart" - dialog closes, cart cleared, toast shows
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Benefits
|
||||
|
||||
### HashRouter Navigation
|
||||
- ✅ No page reloads
|
||||
- ✅ Faster navigation
|
||||
- ✅ Better UX
|
||||
- ✅ Preserves SPA state
|
||||
- ✅ Works with direct URLs
|
||||
|
||||
### Modern Dialog
|
||||
- ✅ Better UX than browser alert
|
||||
- ✅ Accessible (keyboard navigation)
|
||||
- ✅ Consistent with Admin SPA
|
||||
- ✅ Customizable styling
|
||||
- ✅ Animation support
|
||||
|
||||
### Store Title
|
||||
- ✅ Shows actual site name
|
||||
- ✅ Professional appearance
|
||||
- ✅ Consistent with Admin SPA
|
||||
- ✅ Configurable
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
1. **All header links now use HashRouter** - Consistent navigation throughout
|
||||
2. **Dialog component available** - Can be reused for other confirmations
|
||||
3. **Store title dynamic** - Reads from `window.woonoowCustomer.siteTitle`
|
||||
4. **No breaking changes** - All existing functionality preserved
|
||||
|
||||
---
|
||||
|
||||
## 🔜 Next Steps
|
||||
|
||||
Continue with:
|
||||
1. Debug cart page access issue
|
||||
2. Add product variations support
|
||||
3. Build checkout page
|
||||
|
||||
**All HashRouter-related issues are now resolved!** ✅
|
||||
Reference in New Issue
Block a user