fix: dbDelta separate tables, add SEOHead for page titles

1. License table creation:
   - dbDelta requires separate calls per CREATE TABLE
   - Split into sql_licenses and sql_activations
   - Added 'PRIMARY KEY  (id)' with two spaces (dbDelta requirement)

2. Page titles:
   - Added SEOHead to Cart page (title: Shopping Cart)
   - Added SEOHead to Checkout page (title: Checkout)
   - Shop already had SEOHead

3. usePageTitle hook created (alternative to SEOHead for non-Helmet usage)
This commit is contained in:
Dwindi Ramadhana
2026-01-07 22:40:45 +07:00
parent 3a08e80c1f
commit d7b132d9d9
4 changed files with 38 additions and 7 deletions

View File

@@ -0,0 +1,22 @@
import { useEffect } from 'react';
/**
* Hook to set the document title dynamically
* @param title - The page title to set
* @param suffix - Optional suffix (default: store name from settings)
*/
export function usePageTitle(title: string, suffix?: string) {
useEffect(() => {
const storeName = (window as any).woonoowCustomer?.storeName || 'Store';
const finalSuffix = suffix ?? storeName;
document.title = title ? `${title} | ${finalSuffix}` : finalSuffix;
// Cleanup: restore original title when component unmounts
return () => {
// Don't restore - let the next page set its own title
};
}, [title, suffix]);
}
export default usePageTitle;

View File

@@ -13,6 +13,7 @@ import {
DialogTitle, DialogTitle,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import Container from '@/components/Layout/Container'; import Container from '@/components/Layout/Container';
import SEOHead from '@/components/SEOHead';
import { formatPrice } from '@/lib/currency'; import { formatPrice } from '@/lib/currency';
import { Trash2, Plus, Minus, ShoppingBag, ArrowLeft, Loader2, X, Tag } from 'lucide-react'; import { Trash2, Plus, Minus, ShoppingBag, ArrowLeft, Loader2, X, Tag } from 'lucide-react';
import { toast } from 'sonner'; import { toast } from 'sonner';
@@ -155,6 +156,7 @@ export default function Cart() {
return ( return (
<Container> <Container>
<SEOHead title="Shopping Cart" description="Review your shopping cart" />
<div className={`py-8 ${layout.style === 'boxed' ? 'max-w-5xl mx-auto' : ''}`}> <div className={`py-8 ${layout.style === 'boxed' ? 'max-w-5xl mx-auto' : ''}`}>
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-8"> <div className="flex items-center justify-between mb-8">

View File

@@ -4,6 +4,7 @@ import { useCartStore } from '@/lib/cart/store';
import { useCheckoutSettings } from '@/hooks/useAppearanceSettings'; import { useCheckoutSettings } from '@/hooks/useAppearanceSettings';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import Container from '@/components/Layout/Container'; import Container from '@/components/Layout/Container';
import SEOHead from '@/components/SEOHead';
import { formatPrice } from '@/lib/currency'; import { formatPrice } from '@/lib/currency';
import { ArrowLeft, ShoppingBag, MapPin, Check, Edit2, Loader2, X, Tag } from 'lucide-react'; import { ArrowLeft, ShoppingBag, MapPin, Check, Edit2, Loader2, X, Tag } from 'lucide-react';
import { toast } from 'sonner'; import { toast } from 'sonner';
@@ -339,6 +340,7 @@ export default function Checkout() {
return ( return (
<Container> <Container>
<SEOHead title="Checkout" description="Complete your purchase" />
<div className="py-8"> <div className="py-8">
{/* Header */} {/* Header */}
<div className="mb-8"> <div className="mb-8">

View File

@@ -42,7 +42,10 @@ class LicenseManager {
$licenses_table = $wpdb->prefix . self::$table_name; $licenses_table = $wpdb->prefix . self::$table_name;
$activations_table = $wpdb->prefix . self::$activations_table; $activations_table = $wpdb->prefix . self::$activations_table;
$sql = "CREATE TABLE IF NOT EXISTS $licenses_table ( require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
// Create licenses table - dbDelta requires each CREATE TABLE to be called separately
$sql_licenses = "CREATE TABLE $licenses_table (
id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
license_key varchar(255) NOT NULL, license_key varchar(255) NOT NULL,
product_id bigint(20) UNSIGNED NOT NULL, product_id bigint(20) UNSIGNED NOT NULL,
@@ -55,15 +58,18 @@ class LicenseManager {
expires_at datetime DEFAULT NULL, expires_at datetime DEFAULT NULL,
created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id), PRIMARY KEY (id),
UNIQUE KEY license_key (license_key), UNIQUE KEY license_key (license_key),
KEY product_id (product_id), KEY product_id (product_id),
KEY order_id (order_id), KEY order_id (order_id),
KEY user_id (user_id), KEY user_id (user_id),
KEY status (status) KEY status (status)
) $charset_collate; ) $charset_collate;";
CREATE TABLE IF NOT EXISTS $activations_table ( dbDelta($sql_licenses);
// Create activations table
$sql_activations = "CREATE TABLE $activations_table (
id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
license_id bigint(20) UNSIGNED NOT NULL, license_id bigint(20) UNSIGNED NOT NULL,
domain varchar(255) DEFAULT NULL, domain varchar(255) DEFAULT NULL,
@@ -73,13 +79,12 @@ class LicenseManager {
status varchar(20) NOT NULL DEFAULT 'active', status varchar(20) NOT NULL DEFAULT 'active',
activated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, activated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
deactivated_at datetime DEFAULT NULL, deactivated_at datetime DEFAULT NULL,
PRIMARY KEY (id), PRIMARY KEY (id),
KEY license_id (license_id), KEY license_id (license_id),
KEY status (status) KEY status (status)
) $charset_collate;"; ) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql_activations);
dbDelta($sql);
} }
/** /**