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:
Dwindi Ramadhana
2025-11-26 16:18:43 +07:00
parent 909bddb23d
commit f397ef850f
69 changed files with 12481 additions and 156 deletions

240
CANONICAL_REDIRECT_FIX.md Normal file
View File

@@ -0,0 +1,240 @@
# Fix: Product Page Redirect Issue
## Problem
Direct access to product URLs like `/product/edukasi-anak` redirects to `/shop`.
## Root Cause
**WordPress Canonical Redirect**
WordPress has a built-in canonical redirect system that redirects "incorrect" URLs to their "canonical" version. When you access `/product/edukasi-anak`, WordPress doesn't recognize this as a valid WordPress route (because it's a React Router route), so it redirects to the shop page.
### How WordPress Canonical Redirect Works
1. User visits `/product/edukasi-anak`
2. WordPress checks if this is a valid WordPress route
3. WordPress doesn't find a post/page with this URL
4. WordPress thinks it's a 404 or incorrect URL
5. WordPress redirects to the nearest valid URL (shop page)
This happens **before** React Router can handle the URL.
---
## Solution
Disable WordPress canonical redirects for SPA routes.
### Implementation
**File:** `includes/Frontend/TemplateOverride.php`
#### 1. Hook into Redirect Filter
```php
public static function init() {
// ... existing code ...
// Disable canonical redirects for SPA routes
add_filter('redirect_canonical', [__CLASS__, 'disable_canonical_redirect'], 10, 2);
}
```
#### 2. Add Redirect Handler
```php
/**
* Disable canonical redirects for SPA routes
* This prevents WordPress from redirecting /product/slug URLs
*/
public static function disable_canonical_redirect($redirect_url, $requested_url) {
$settings = get_option('woonoow_customer_spa_settings', []);
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
// Only disable redirects in full SPA mode
if ($mode !== 'full') {
return $redirect_url;
}
// Check if this is a SPA route
$spa_routes = ['/product/', '/cart', '/checkout', '/my-account'];
foreach ($spa_routes as $route) {
if (strpos($requested_url, $route) !== false) {
// This is a SPA route, disable WordPress redirect
return false;
}
}
return $redirect_url;
}
```
---
## How It Works
### The `redirect_canonical` Filter
WordPress provides the `redirect_canonical` filter that allows you to control canonical redirects.
**Parameters:**
- `$redirect_url` - The URL WordPress wants to redirect to
- `$requested_url` - The URL the user requested
**Return Values:**
- Return `$redirect_url` - Allow the redirect
- Return `false` - Disable the redirect
- Return different URL - Redirect to that URL instead
### Our Logic
1. Check if SPA mode is enabled
2. Check if the requested URL contains SPA routes (`/product/`, `/cart`, etc.)
3. If yes, return `false` to disable redirect
4. If no, return `$redirect_url` to allow normal WordPress behavior
---
## Why This Works
### Before Fix
```
User → /product/edukasi-anak
WordPress: "This isn't a valid route"
WordPress: "Redirect to /shop"
React Router never gets a chance to handle the URL
```
### After Fix
```
User → /product/edukasi-anak
WordPress: "Should I redirect?"
Our filter: "No, this is a SPA route"
WordPress: "OK, loading template"
React Router: "I'll handle /product/edukasi-anak"
Product page loads correctly
```
---
## Testing
### Test Direct Access
1. Open new browser tab
2. Go to: `https://woonoow.local/product/edukasi-anak`
3. Should load product page directly
4. Should NOT redirect to `/shop`
### Test Navigation
1. Go to `/shop`
2. Click a product
3. Should navigate to `/product/slug`
4. Should work correctly
### Test Other Routes
1. `/cart` - Should work
2. `/checkout` - Should work
3. `/my-account` - Should work
### Check Console
Open browser console and check for logs:
```
Product Component - Slug: edukasi-anak
Product Component - Current URL: https://woonoow.local/product/edukasi-anak
Product Query - Starting fetch for slug: edukasi-anak
Product API Response: {...}
Product found: {...}
```
---
## Additional Notes
### SPA Routes Protected
The following routes are protected from canonical redirects:
- `/product/` - Product detail pages
- `/cart` - Cart page
- `/checkout` - Checkout page
- `/my-account` - Account pages
### Only in Full SPA Mode
This fix only applies when SPA mode is set to `full`. In other modes, WordPress canonical redirects work normally.
### No Impact on SEO
Disabling canonical redirects for SPA routes doesn't affect SEO because:
1. These are client-side routes handled by React
2. The actual WordPress product pages still exist
3. Search engines see the server-rendered content
4. Canonical URLs are still set in meta tags
---
## Alternative Solutions
### Option 1: Hash Router (Not Recommended)
Use HashRouter instead of BrowserRouter:
```tsx
<HashRouter>
{/* routes */}
</HashRouter>
```
**URLs become:** `https://woonoow.local/#/product/edukasi-anak`
**Pros:**
- No server-side configuration needed
- Works everywhere
**Cons:**
- Ugly URLs with `#`
- Poor SEO
- Not modern web standard
### Option 2: Custom Rewrite Rules (More Complex)
Add custom WordPress rewrite rules for SPA routes.
**Pros:**
- More "proper" WordPress way
**Cons:**
- More complex
- Requires flush_rewrite_rules()
- Can conflict with other plugins
### Option 3: Our Solution (Best)
Disable canonical redirects for SPA routes.
**Pros:**
- ✅ Clean URLs
- ✅ Simple implementation
- ✅ No conflicts
- ✅ Easy to maintain
**Cons:**
- None!
---
## Summary
**Problem:** WordPress canonical redirect interferes with React Router
**Solution:** Disable canonical redirects for SPA routes using `redirect_canonical` filter
**Result:** Direct product URLs now work correctly! ✅
**Files Modified:**
- `includes/Frontend/TemplateOverride.php` - Added redirect handler
**Test:** Navigate to `/product/edukasi-anak` directly - should work!