feat: add SEOHead to all SPA pages for dynamic page titles

Added SEOHead component to:
- ThankYou page (both template styles)
- Login page
- Account/Dashboard
- Account/Orders
- Account/Downloads
- Account/Addresses
- Account/Wishlist
- Account/Licenses
- Account/AccountDetails
- Public Wishlist page

Also created usePageTitle hook as alternative for non-Helmet usage.
This commit is contained in:
Dwindi Ramadhana
2026-01-07 22:51:47 +07:00
parent d7b132d9d9
commit a4a055a98e
10 changed files with 147 additions and 126 deletions

View File

@@ -1,6 +1,7 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { api } from '@/lib/api/client'; import { api } from '@/lib/api/client';
import SEOHead from '@/components/SEOHead';
interface AvatarSettings { interface AvatarSettings {
allow_custom_avatar: boolean; allow_custom_avatar: boolean;
@@ -198,6 +199,7 @@ export default function AccountDetails() {
return ( return (
<div> <div>
<SEOHead title="Account Details" description="Edit your account information" />
<h1 className="text-2xl font-bold mb-6">Account Details</h1> <h1 className="text-2xl font-bold mb-6">Account Details</h1>
{/* Avatar Section */} {/* Avatar Section */}

View File

@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import { MapPin, Plus, Edit, Trash2, Star } from 'lucide-react'; import { MapPin, Plus, Edit, Trash2, Star } from 'lucide-react';
import { api } from '@/lib/api/client'; import { api } from '@/lib/api/client';
import { toast } from 'sonner'; import { toast } from 'sonner';
import SEOHead from '@/components/SEOHead';
interface Address { interface Address {
id: number; id: number;
@@ -50,10 +51,10 @@ export default function Addresses() {
const loadAddresses = async () => { const loadAddresses = async () => {
try { try {
const response: any = await api.get('/account/addresses'); const response: any = await api.get('/account/addresses');
// Handle different response structures // Handle different response structures
let data: Address[] = []; let data: Address[] = [];
if (Array.isArray(response)) { if (Array.isArray(response)) {
data = response; data = response;
} else if (response && typeof response === 'object') { } else if (response && typeof response === 'object') {
@@ -121,7 +122,7 @@ export default function Addresses() {
const handleDelete = async (id: number) => { const handleDelete = async (id: number) => {
if (!confirm('Are you sure you want to delete this address?')) return; if (!confirm('Are you sure you want to delete this address?')) return;
try { try {
await api.delete(`/account/addresses/${id}`); await api.delete(`/account/addresses/${id}`);
toast.success('Address deleted successfully'); toast.success('Address deleted successfully');
@@ -153,9 +154,10 @@ export default function Addresses() {
return ( return (
<div> <div>
<SEOHead title="Addresses" description="Manage your shipping and billing addresses" />
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-6">
<h1 className="text-2xl font-bold">Addresses</h1> <h1 className="text-2xl font-bold">Addresses</h1>
<button <button
onClick={handleAdd} onClick={handleAdd}
className="font-[inherit] inline-flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors" className="font-[inherit] inline-flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors"
> >
@@ -163,12 +165,12 @@ export default function Addresses() {
Add Address Add Address
</button> </button>
</div> </div>
{addresses.length === 0 ? ( {addresses.length === 0 ? (
<div className="text-center py-12 border rounded-lg"> <div className="text-center py-12 border rounded-lg">
<MapPin className="w-12 h-12 text-gray-300 mx-auto mb-2" /> <MapPin className="w-12 h-12 text-gray-300 mx-auto mb-2" />
<p className="text-gray-600 mb-4">No addresses saved yet</p> <p className="text-gray-600 mb-4">No addresses saved yet</p>
<button <button
onClick={handleAdd} onClick={handleAdd}
className="font-[inherit] inline-flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors" className="font-[inherit] inline-flex items-center gap-2 px-4 py-2 bg-primary text-white rounded-lg hover:bg-primary/90 transition-colors"
> >
@@ -185,14 +187,14 @@ export default function Addresses() {
<Star className="w-5 h-5 text-yellow-500 fill-yellow-500" /> <Star className="w-5 h-5 text-yellow-500 fill-yellow-500" />
</div> </div>
)} )}
<div className="mb-4"> <div className="mb-4">
<h3 className="font-semibold text-lg">{address.label}</h3> <h3 className="font-semibold text-lg">{address.label}</h3>
<span className="text-xs text-gray-500 uppercase"> <span className="text-xs text-gray-500 uppercase">
{address.type === 'both' ? 'Billing & Shipping' : address.type} {address.type === 'both' ? 'Billing & Shipping' : address.type}
</span> </span>
</div> </div>
<div className="text-sm text-gray-700 space-y-1 mb-4"> <div className="text-sm text-gray-700 space-y-1 mb-4">
<p className="font-medium">{address.first_name} {address.last_name}</p> <p className="font-medium">{address.first_name} {address.last_name}</p>
{address.company && <p>{address.company}</p>} {address.company && <p>{address.company}</p>}
@@ -203,7 +205,7 @@ export default function Addresses() {
{address.phone && <p className="pt-2">Phone: {address.phone}</p>} {address.phone && <p className="pt-2">Phone: {address.phone}</p>}
{address.email && <p>Email: {address.email}</p>} {address.email && <p>Email: {address.email}</p>}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<button <button
onClick={() => handleEdit(address)} onClick={() => handleEdit(address)}
@@ -242,7 +244,7 @@ export default function Addresses() {
<h2 className="text-xl font-bold mb-4"> <h2 className="text-xl font-bold mb-4">
{editingAddress ? 'Edit Address' : 'Add New Address'} {editingAddress ? 'Edit Address' : 'Add New Address'}
</h2> </h2>
<div className="space-y-4"> <div className="space-y-4">
<div> <div>
<label className="block text-sm font-medium mb-1">Label *</label> <label className="block text-sm font-medium mb-1">Label *</label>
@@ -254,7 +256,7 @@ export default function Addresses() {
className="w-full px-3 py-2 border rounded-lg" className="w-full px-3 py-2 border rounded-lg"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium mb-1">Address Type *</label> <label className="block text-sm font-medium mb-1">Address Type *</label>
<select <select
@@ -267,7 +269,7 @@ export default function Addresses() {
<option value="shipping">Shipping Only</option> <option value="shipping">Shipping Only</option>
</select> </select>
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium mb-1">First Name *</label> <label className="block text-sm font-medium mb-1">First Name *</label>
@@ -288,7 +290,7 @@ export default function Addresses() {
/> />
</div> </div>
</div> </div>
<div> <div>
<label className="block text-sm font-medium mb-1">Company</label> <label className="block text-sm font-medium mb-1">Company</label>
<input <input
@@ -298,7 +300,7 @@ export default function Addresses() {
className="w-full px-3 py-2 border rounded-lg" className="w-full px-3 py-2 border rounded-lg"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium mb-1">Address Line 1 *</label> <label className="block text-sm font-medium mb-1">Address Line 1 *</label>
<input <input
@@ -308,7 +310,7 @@ export default function Addresses() {
className="w-full px-3 py-2 border rounded-lg" className="w-full px-3 py-2 border rounded-lg"
/> />
</div> </div>
<div> <div>
<label className="block text-sm font-medium mb-1">Address Line 2</label> <label className="block text-sm font-medium mb-1">Address Line 2</label>
<input <input
@@ -318,7 +320,7 @@ export default function Addresses() {
className="w-full px-3 py-2 border rounded-lg" className="w-full px-3 py-2 border rounded-lg"
/> />
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium mb-1">City *</label> <label className="block text-sm font-medium mb-1">City *</label>
@@ -339,7 +341,7 @@ export default function Addresses() {
/> />
</div> </div>
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium mb-1">Postcode *</label> <label className="block text-sm font-medium mb-1">Postcode *</label>
@@ -360,7 +362,7 @@ export default function Addresses() {
/> />
</div> </div>
</div> </div>
<div className="grid grid-cols-2 gap-4"> <div className="grid grid-cols-2 gap-4">
<div> <div>
<label className="block text-sm font-medium mb-1">Email</label> <label className="block text-sm font-medium mb-1">Email</label>
@@ -381,7 +383,7 @@ export default function Addresses() {
/> />
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<input <input
type="checkbox" type="checkbox"
@@ -393,7 +395,7 @@ export default function Addresses() {
<label htmlFor="is_default" className="text-sm">Set as default address</label> <label htmlFor="is_default" className="text-sm">Set as default address</label>
</div> </div>
</div> </div>
<div className="flex gap-3 mt-6"> <div className="flex gap-3 mt-6">
<button <button
onClick={handleSave} onClick={handleSave}

View File

@@ -1,16 +1,18 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { ShoppingBag, Package, MapPin, User } from 'lucide-react'; import { ShoppingBag, Package, MapPin, User } from 'lucide-react';
import SEOHead from '@/components/SEOHead';
export default function Dashboard() { export default function Dashboard() {
const user = (window as any).woonoowCustomer?.user; const user = (window as any).woonoowCustomer?.user;
return ( return (
<div> <div>
<SEOHead title="My Account" description="Manage your account" />
<h1 className="text-2xl font-bold mb-6"> <h1 className="text-2xl font-bold mb-6">
Hello {user?.display_name || 'there'}! Hello {user?.display_name || 'there'}!
</h1> </h1>
<p className="text-gray-600 mb-8"> <p className="text-gray-600 mb-8">
From your account dashboard you can view your recent orders, manage your shipping and billing addresses, and edit your password and account details. From your account dashboard you can view your recent orders, manage your shipping and billing addresses, and edit your password and account details.
</p> </p>

View File

@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button';
import { api } from '@/lib/api/client'; import { api } from '@/lib/api/client';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { formatPrice } from '@/lib/currency'; import { formatPrice } from '@/lib/currency';
import SEOHead from '@/components/SEOHead';
interface DownloadItem { interface DownloadItem {
download_id: string; download_id: string;
@@ -97,6 +98,7 @@ export default function Downloads() {
return ( return (
<div> <div>
<SEOHead title="Downloads" description="Your purchased downloads" />
<h1 className="text-2xl font-bold mb-6">Downloads</h1> <h1 className="text-2xl font-bold mb-6">Downloads</h1>
<div className="space-y-4"> <div className="space-y-4">

View File

@@ -15,6 +15,7 @@ import {
} from '@/components/ui/alert-dialog'; } from '@/components/ui/alert-dialog';
import { Key, Copy, Check, ChevronDown, ChevronUp, Monitor, Globe, Power } from 'lucide-react'; import { Key, Copy, Check, ChevronDown, ChevronUp, Monitor, Globe, Power } from 'lucide-react';
import { toast } from 'sonner'; import { toast } from 'sonner';
import SEOHead from '@/components/SEOHead';
interface Activation { interface Activation {
id: number; id: number;
@@ -94,6 +95,7 @@ export default function Licenses() {
return ( return (
<div className="space-y-6"> <div className="space-y-6">
<SEOHead title="Licenses" description="Manage your software licenses" />
<div> <div>
<h1 className="text-2xl font-bold flex items-center gap-2"> <h1 className="text-2xl font-bold flex items-center gap-2">
<Key className="h-6 w-6" /> <Key className="h-6 w-6" />

View File

@@ -3,6 +3,7 @@ import { Link } from 'react-router-dom';
import { Package, Eye } from 'lucide-react'; import { Package, Eye } from 'lucide-react';
import { api } from '@/lib/api/client'; import { api } from '@/lib/api/client';
import { toast } from 'sonner'; import { toast } from 'sonner';
import SEOHead from '@/components/SEOHead';
interface Order { interface Order {
id: number; id: number;
@@ -69,7 +70,7 @@ export default function Orders() {
return ( return (
<div> <div>
<h1 className="text-2xl font-bold mb-6">Orders</h1> <h1 className="text-2xl font-bold mb-6">Orders</h1>
<div className="text-center py-12"> <div className="text-center py-12">
<Package className="w-16 h-16 text-gray-300 mx-auto mb-4" /> <Package className="w-16 h-16 text-gray-300 mx-auto mb-4" />
<p className="text-gray-600 mb-4">No orders yet</p> <p className="text-gray-600 mb-4">No orders yet</p>
@@ -86,8 +87,9 @@ export default function Orders() {
return ( return (
<div> <div>
<SEOHead title="Orders" description="View your order history" />
<h1 className="text-2xl font-bold mb-6">Orders</h1> <h1 className="text-2xl font-bold mb-6">Orders</h1>
<div className="space-y-4"> <div className="space-y-4">
{orders.map((order) => ( {orders.map((order) => (
<div key={order.id} className="border rounded-lg p-4 hover:border-primary transition-colors"> <div key={order.id} className="border rounded-lg p-4 hover:border-primary transition-colors">
@@ -100,7 +102,7 @@ export default function Orders() {
{order.status.replace('-', ' ').toUpperCase()} {order.status.replace('-', ' ').toUpperCase()}
</span> </span>
</div> </div>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<div className="text-sm text-gray-600"> <div className="text-sm text-gray-600">
{order.items_count} {order.items_count === 1 ? 'item' : 'items'} {order.items_count} {order.items_count === 1 ? 'item' : 'items'}

View File

@@ -8,6 +8,7 @@ import { formatPrice } from '@/lib/currency';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { useModules } from '@/hooks/useModules'; import { useModules } from '@/hooks/useModules';
import { useModuleSettings } from '@/hooks/useModuleSettings'; import { useModuleSettings } from '@/hooks/useModuleSettings';
import SEOHead from '@/components/SEOHead';
interface WishlistItem { interface WishlistItem {
product_id: number; product_id: number;
@@ -126,119 +127,120 @@ export default function Wishlist() {
return ( return (
<div> <div>
<SEOHead title="Wishlist" description="Your saved products" />
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-6">
<div> <div>
<h1 className="text-2xl font-bold">My Wishlist</h1> <h1 className="text-2xl font-bold">My Wishlist</h1>
<p className="text-gray-600 text-sm mt-1"> <p className="text-gray-600 text-sm mt-1">
{items.length} {items.length === 1 ? 'item' : 'items'} {items.length} {items.length === 1 ? 'item' : 'items'}
</p> </p>
</div>
{items.length > 0 && (
<Button
variant="outline"
size="sm"
onClick={handleClearAll}
className="text-red-600 hover:text-red-700 hover:border-red-600"
>
<Trash2 className="w-4 h-4 mr-2" />
Clear All
</Button>
)}
</div> </div>
{items.length > 0 && (
<Button
variant="outline"
size="sm"
onClick={handleClearAll}
className="text-red-600 hover:text-red-700 hover:border-red-600"
>
<Trash2 className="w-4 h-4 mr-2" />
Clear All
</Button>
)}
</div>
{/* Empty State */} {/* Empty State */}
{items.length === 0 ? ( {items.length === 0 ? (
<div className="text-center py-16 bg-white border rounded-lg"> <div className="text-center py-16 bg-white border rounded-lg">
<Heart className="w-16 h-16 mx-auto text-gray-300 mb-4" /> <Heart className="w-16 h-16 mx-auto text-gray-300 mb-4" />
<h2 className="text-xl font-semibold mb-2">Your wishlist is empty</h2> <h2 className="text-xl font-semibold mb-2">Your wishlist is empty</h2>
<p className="text-gray-600 mb-6"> <p className="text-gray-600 mb-6">
Save your favorite products to buy them later Save your favorite products to buy them later
</p> </p>
<Button onClick={() => navigate('/shop')}> <Button onClick={() => navigate('/shop')}>
Browse Products Browse Products
</Button> </Button>
</div> </div>
) : ( ) : (
/* Wishlist Grid */ /* Wishlist Grid */
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{items.map((item) => ( {items.map((item) => (
<div <div
key={item.product_id} key={item.product_id}
className="bg-white border rounded-lg overflow-hidden hover:shadow-lg transition-shadow group" className="bg-white border rounded-lg overflow-hidden hover:shadow-lg transition-shadow group"
> >
{/* Image */} {/* Image */}
<div className="relative aspect-square bg-gray-100"> <div className="relative aspect-square bg-gray-100">
<button <button
onClick={() => handleRemove(item.product_id)} onClick={() => handleRemove(item.product_id)}
className="absolute top-3 right-3 z-10 p-2 bg-white rounded-full shadow-md hover:bg-red-50 transition-colors" className="absolute top-3 right-3 z-10 p-2 bg-white rounded-full shadow-md hover:bg-red-50 transition-colors"
title="Remove from wishlist" title="Remove from wishlist"
> >
<X className="w-4 h-4 text-red-600" /> <X className="w-4 h-4 text-red-600" />
</button> </button>
<img <img
src={item.image || '/placeholder.png'} src={item.image || '/placeholder.png'}
alt={item.name} alt={item.name}
className="w-full h-full object-cover cursor-pointer" className="w-full h-full object-cover cursor-pointer"
onClick={() => navigate(`/product/${item.slug}`)} onClick={() => navigate(`/product/${item.slug}`)}
/> />
{item.on_sale && ( {item.on_sale && (
<div className="absolute top-3 left-3 bg-red-600 text-white text-xs font-bold px-2 py-1 rounded"> <div className="absolute top-3 left-3 bg-red-600 text-white text-xs font-bold px-2 py-1 rounded">
SALE SALE
</div> </div>
)}
</div>
{/* Content */}
<div className="p-4">
<h3
className="font-medium text-gray-900 mb-2 line-clamp-2 cursor-pointer hover:text-primary transition-colors"
onClick={() => navigate(`/product/${item.slug}`)}
>
{item.name}
</h3>
{/* Price */}
<div className="flex items-center gap-2 mb-4">
{item.on_sale && item.regular_price ? (
<>
<span className="text-lg font-bold text-primary">
{formatPrice(item.sale_price || item.price)}
</span>
<span className="text-sm text-gray-500 line-through">
{formatPrice(item.regular_price)}
</span>
</>
) : (
<span className="text-lg font-bold text-gray-900">
{formatPrice(item.price)}
</span>
)} )}
</div> </div>
{/* Content */} {/* Actions */}
<div className="p-4"> {(wishlistSettings.show_add_to_cart_button ?? true) && (
<h3 <Button
className="font-medium text-gray-900 mb-2 line-clamp-2 cursor-pointer hover:text-primary transition-colors" onClick={() => handleAddToCart(item)}
onClick={() => navigate(`/product/${item.slug}`)} disabled={item.stock_status === 'outofstock'}
className="w-full"
size="sm"
> >
{item.name} <ShoppingCart className="w-4 h-4 mr-2" />
</h3> {item.stock_status === 'outofstock'
? 'Out of Stock'
{/* Price */} : item.type === 'variable'
<div className="flex items-center gap-2 mb-4">
{item.on_sale && item.regular_price ? (
<>
<span className="text-lg font-bold text-primary">
{formatPrice(item.sale_price || item.price)}
</span>
<span className="text-sm text-gray-500 line-through">
{formatPrice(item.regular_price)}
</span>
</>
) : (
<span className="text-lg font-bold text-gray-900">
{formatPrice(item.price)}
</span>
)}
</div>
{/* Actions */}
{(wishlistSettings.show_add_to_cart_button ?? true) && (
<Button
onClick={() => handleAddToCart(item)}
disabled={item.stock_status === 'outofstock'}
className="w-full"
size="sm"
>
<ShoppingCart className="w-4 h-4 mr-2" />
{item.stock_status === 'outofstock'
? 'Out of Stock'
: item.type === 'variable'
? 'Select Options' ? 'Select Options'
: 'Add to Cart'} : 'Add to Cart'}
</Button> </Button>
)} )}
</div>
</div> </div>
))} </div>
</div> ))}
)} </div>
)}
</div> </div>
); );
} }

View File

@@ -2,6 +2,7 @@ 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';
import SEOHead from '@/components/SEOHead';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label'; import { Label } from '@/components/ui/label';
@@ -115,6 +116,7 @@ export default function Login() {
return ( return (
<Container> <Container>
<SEOHead title="Login" description="Sign in to your account" />
<div className="min-h-[60vh] flex items-center justify-center py-12"> <div className="min-h-[60vh] flex items-center justify-center py-12">
<div className="w-full max-w-md"> <div className="w-full max-w-md">
{/* Back link */} {/* Back link */}

View File

@@ -2,6 +2,7 @@ import React, { useEffect, useState } from 'react';
import { useParams, Link, useSearchParams } from 'react-router-dom'; import { useParams, Link, useSearchParams } from 'react-router-dom';
import { useThankYouSettings } from '@/hooks/useAppearanceSettings'; import { useThankYouSettings } from '@/hooks/useAppearanceSettings';
import Container from '@/components/Layout/Container'; import Container from '@/components/Layout/Container';
import SEOHead from '@/components/SEOHead';
import { CheckCircle, ShoppingBag, Package, Truck, User, LogIn } from 'lucide-react'; import { CheckCircle, ShoppingBag, Package, Truck, User, LogIn } from 'lucide-react';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { formatPrice } from '@/lib/currency'; import { formatPrice } from '@/lib/currency';
@@ -74,6 +75,7 @@ export default function ThankYou() {
if (template === 'receipt') { if (template === 'receipt') {
return ( return (
<div style={{ backgroundColor }}> <div style={{ backgroundColor }}>
<SEOHead title="Order Confirmed" description={`Order #${order?.number || orderId} confirmed`} />
<Container> <Container>
<div className="py-12 max-w-2xl mx-auto"> <div className="py-12 max-w-2xl mx-auto">
{/* Receipt Container */} {/* Receipt Container */}
@@ -351,6 +353,7 @@ export default function ThankYou() {
// Render basic style template (default) // Render basic style template (default)
return ( return (
<div style={{ backgroundColor }}> <div style={{ backgroundColor }}>
<SEOHead title="Order Confirmed" description={`Order #${order?.number || orderId} confirmed`} />
<Container> <Container>
<div className="py-12 max-w-3xl mx-auto"> <div className="py-12 max-w-3xl mx-auto">
{/* Success Header */} {/* Success Header */}

View File

@@ -7,6 +7,7 @@ import { Button } from '@/components/ui/button';
import { toast } from 'sonner'; import { toast } from 'sonner';
import { apiClient } from '@/lib/api/client'; import { apiClient } from '@/lib/api/client';
import { formatPrice } from '@/lib/currency'; import { formatPrice } from '@/lib/currency';
import SEOHead from '@/components/SEOHead';
interface ProductData { interface ProductData {
id: number; id: number;
@@ -106,6 +107,7 @@ export default function Wishlist() {
return ( return (
<div className="container mx-auto px-4 py-8"> <div className="container mx-auto px-4 py-8">
<SEOHead title="Wishlist" description="Your saved products" />
<div className="max-w-4xl mx-auto"> <div className="max-w-4xl mx-auto">
<div className="flex items-center justify-between mb-6"> <div className="flex items-center justify-between mb-6">
<h1 className="text-3xl font-bold">My Wishlist</h1> <h1 className="text-3xl font-bold">My Wishlist</h1>