feat: Go-to-Account button + wishlist merge on login
1. ThankYou page - Go to Account button: - Added for logged-in users (next to Continue Shopping) - Shows in both receipt and basic templates - Uses outline variant with User icon 2. Wishlist merge on login: - Reads guest wishlist from localStorage (woonoow_guest_wishlist) - POSTs each product to /account/wishlist API - Handles duplicates gracefully (skips on error) - Clears localStorage after successful merge
This commit is contained in:
@@ -54,6 +54,39 @@ export default function Login() {
|
||||
};
|
||||
}
|
||||
|
||||
// Merge guest wishlist to account
|
||||
const GUEST_WISHLIST_KEY = 'woonoow_guest_wishlist';
|
||||
try {
|
||||
const stored = localStorage.getItem(GUEST_WISHLIST_KEY);
|
||||
if (stored) {
|
||||
const guestProductIds = JSON.parse(stored) as number[];
|
||||
if (guestProductIds.length > 0) {
|
||||
// Merge each product to account wishlist
|
||||
const newNonce = data.nonce;
|
||||
for (const productId of guestProductIds) {
|
||||
try {
|
||||
await fetch(`${apiRoot}/account/wishlist`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-WP-Nonce': newNonce,
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ product_id: productId }),
|
||||
});
|
||||
} catch (e) {
|
||||
// Skip if product already in wishlist or other error
|
||||
console.debug('Wishlist merge skipped for product:', productId);
|
||||
}
|
||||
}
|
||||
// Clear guest wishlist after merge
|
||||
localStorage.removeItem(GUEST_WISHLIST_KEY);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to merge guest wishlist:', e);
|
||||
}
|
||||
|
||||
toast.success('Login successful!');
|
||||
|
||||
// Set the target URL with hash route, then force reload
|
||||
|
||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||
import { useParams, Link, useSearchParams } from 'react-router-dom';
|
||||
import { useThankYouSettings } from '@/hooks/useAppearanceSettings';
|
||||
import Container from '@/components/Layout/Container';
|
||||
import { CheckCircle, ShoppingBag, Package, Truck } from 'lucide-react';
|
||||
import { CheckCircle, ShoppingBag, Package, Truck, User } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { formatPrice } from '@/lib/currency';
|
||||
import { apiClient } from '@/lib/api/client';
|
||||
@@ -16,6 +16,7 @@ export default function ThankYou() {
|
||||
const [relatedProducts, setRelatedProducts] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const isLoggedIn = (window as any).woonoowCustomer?.user?.isLoggedIn;
|
||||
|
||||
useEffect(() => {
|
||||
const fetchOrderData = async () => {
|
||||
@@ -186,14 +187,24 @@ export default function ThankYou() {
|
||||
: 'Thank you for your business!'}
|
||||
</p>
|
||||
|
||||
{elements.continue_shopping_button && (
|
||||
<Link to="/shop">
|
||||
<Button size="lg" className="gap-2">
|
||||
<ShoppingBag className="w-5 h-5" />
|
||||
Continue Shopping
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
<div className="flex flex-col sm:flex-row gap-3 justify-center">
|
||||
{elements.continue_shopping_button && (
|
||||
<Link to="/shop">
|
||||
<Button size="lg" className="gap-2">
|
||||
<ShoppingBag className="w-5 h-5" />
|
||||
Continue Shopping
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
{isLoggedIn && (
|
||||
<Link to="/my-account">
|
||||
<Button size="lg" variant="outline" className="gap-2">
|
||||
<User className="w-5 h-5" />
|
||||
Go to Account
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -430,17 +441,25 @@ export default function ThankYou() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Continue Shopping Button */}
|
||||
{elements.continue_shopping_button && (
|
||||
<div className="text-center">
|
||||
{/* Action Buttons */}
|
||||
<div className="text-center flex flex-col sm:flex-row gap-3 justify-center">
|
||||
{elements.continue_shopping_button && (
|
||||
<Link to="/shop">
|
||||
<Button size="lg" className="gap-2">
|
||||
<ShoppingBag className="w-5 h-5" />
|
||||
Continue Shopping
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
)}
|
||||
{isLoggedIn && (
|
||||
<Link to="/my-account">
|
||||
<Button size="lg" variant="outline" className="gap-2">
|
||||
<User className="w-5 h-5" />
|
||||
Go to Account
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Related Products */}
|
||||
{elements.related_products && relatedProducts.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user