fix: 4 bugs - checkout virtual, login redirect, licensing, categories

1. Virtual-only checkout:
   - Added 'virtual' and 'downloadable' to CartController response
   - Checkout can now detect virtual-only carts

2. Login redirect:
   - Added useEffect to redirect logged-in users to /my-account

3. License generation:
   - Fixed meta key mismatch (_woonoow_licensing_enabled -> _licensing_enabled)

4. Product categories:
   - Added queryClient.invalidateQueries after creating new category
   - List now refreshes immediately
This commit is contained in:
Dwindi Ramadhana
2026-01-07 21:08:01 +07:00
parent 984f4e2db4
commit f334e018fa
4 changed files with 18 additions and 6 deletions

View File

@@ -1,4 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { __ } from '@/lib/i18n'; import { __ } from '@/lib/i18n';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox'; import { Checkbox } from '@/components/ui/checkbox';
@@ -26,6 +27,7 @@ export function OrganizationTab({
selectedTags, selectedTags,
setSelectedTags, setSelectedTags,
}: OrganizationTabProps) { }: OrganizationTabProps) {
const queryClient = useQueryClient();
const [newCategoryName, setNewCategoryName] = useState(''); const [newCategoryName, setNewCategoryName] = useState('');
const [newTagName, setNewTagName] = useState(''); const [newTagName, setNewTagName] = useState('');
const [creatingCategory, setCreatingCategory] = useState(false); const [creatingCategory, setCreatingCategory] = useState(false);
@@ -46,7 +48,8 @@ export function OrganizationTab({
if (response.id) { if (response.id) {
setSelectedCategories([...selectedCategories, response.id]); setSelectedCategories([...selectedCategories, response.id]);
} }
// Note: Parent component should refetch categories // Invalidate categories query to refresh the list
queryClient.invalidateQueries({ queryKey: ['product-categories'] });
} catch (error: any) { } catch (error: any) {
toast.error(error.message || __('Failed to create category')); toast.error(error.message || __('Failed to create category'));
} finally { } finally {
@@ -183,11 +186,10 @@ export function OrganizationTab({
setSelectedTags([...selectedTags, tag.id]); setSelectedTags([...selectedTags, tag.id]);
} }
}} }}
className={`px-3 py-1 rounded-full text-sm border transition-colors ${ className={`px-3 py-1 rounded-full text-sm border transition-colors ${selectedTags.includes(tag.id)
selectedTags.includes(tag.id)
? 'bg-primary text-primary-foreground border-primary' ? 'bg-primary text-primary-foreground border-primary'
: 'bg-background border-border hover:bg-accent' : 'bg-background border-border hover:bg-accent'
}`} }`}
> >
{tag.name} {tag.name}
</button> </button>

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { useNavigate, useSearchParams, Link } from 'react-router-dom'; import { useNavigate, useSearchParams, Link } from 'react-router-dom';
import { toast } from 'sonner'; import { toast } from 'sonner';
import Container from '@/components/Layout/Container'; import Container from '@/components/Layout/Container';
@@ -12,6 +12,14 @@ export default function Login() {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const redirectTo = searchParams.get('redirect') || '/my-account'; const redirectTo = searchParams.get('redirect') || '/my-account';
// Redirect logged-in users to account page
useEffect(() => {
const user = (window as any).woonoowCustomer?.user;
if (user?.isLoggedIn) {
navigate(redirectTo, { replace: true });
}
}, [navigate, redirectTo]);
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);

View File

@@ -365,6 +365,8 @@ class CartController extends WP_REST_Controller {
'total' => $cart_item['line_total'], 'total' => $cart_item['line_total'],
'image' => wp_get_attachment_image_url($product->get_image_id(), 'thumbnail'), 'image' => wp_get_attachment_image_url($product->get_image_id(), 'thumbnail'),
'permalink' => $product->get_permalink(), 'permalink' => $product->get_permalink(),
'virtual' => $product->is_virtual(),
'downloadable' => $product->is_downloadable(),
]; ];
} }

View File

@@ -96,7 +96,7 @@ class LicenseManager {
if (!$product) continue; if (!$product) continue;
// Check if product has licensing enabled // Check if product has licensing enabled
$licensing_enabled = get_post_meta($product_id, '_woonoow_licensing_enabled', true); $licensing_enabled = get_post_meta($product_id, '_licensing_enabled', true);
if ($licensing_enabled !== 'yes') continue; if ($licensing_enabled !== 'yes') continue;
// Check if license already exists for this order item // Check if license already exists for this order item