fix: resolve email shortcode rendering and TypeScript errors
- Fix EmailRenderer.php: add missing \ namespace prefix on instanceof
checks for WC_Order, WC_Product, WC_Customer in get_variables()
(root cause of unrendered {order_number} etc. in all order emails)
- Fix ProductCard.tsx: remove deprecated isClassic/isModern/isBoutique
branches, consolidate into single settings-driven render path
- Fix AccountLayout.tsx: add missing return statement
- Remove orphaned Layout.tsx (imported nothing, referenced missing Header)
This commit is contained in:
@@ -1,19 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import Header from './Header';
|
|
||||||
import Footer from './Footer';
|
|
||||||
|
|
||||||
interface LayoutProps {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Layout({ children }: LayoutProps) {
|
|
||||||
return (
|
|
||||||
<div className="flex min-h-screen flex-col">
|
|
||||||
<Header />
|
|
||||||
<main className="flex-1">
|
|
||||||
{children}
|
|
||||||
</main>
|
|
||||||
<Footer />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -80,15 +80,14 @@ export function ProductCard({ product, onAddToCart }: ProductCardProps) {
|
|||||||
// Determine button variant and position based on settings
|
// Determine button variant and position based on settings
|
||||||
const buttonVariant = addToCart.style === 'outline' ? 'outline' : addToCart.style === 'text' ? 'ghost' : 'default';
|
const buttonVariant = addToCart.style === 'outline' ? 'outline' : addToCart.style === 'text' ? 'ghost' : 'default';
|
||||||
const showButtonOnHover = addToCart.position === 'overlay';
|
const showButtonOnHover = addToCart.position === 'overlay';
|
||||||
const buttonPosition = addToCart.position; // 'below', 'overlay', 'bottom'
|
|
||||||
const isTextOnly = addToCart.style === 'text';
|
const isTextOnly = addToCart.style === 'text';
|
||||||
|
|
||||||
// Card style variations - adapt to column count
|
// Card style variations - adapt to column count
|
||||||
const cardStyle = layout.card_style || 'card';
|
|
||||||
const gridCols = parseInt(layout.grid_columns) || 3;
|
const gridCols = parseInt(layout.grid_columns) || 3;
|
||||||
|
|
||||||
// More columns = cleaner styling
|
// More columns = cleaner styling
|
||||||
const getCardClasses = () => {
|
const getCardClasses = () => {
|
||||||
|
const cardStyle = layout.card_style || 'card';
|
||||||
if (cardStyle === 'minimal') {
|
if (cardStyle === 'minimal') {
|
||||||
return gridCols >= 4
|
return gridCols >= 4
|
||||||
? 'overflow-hidden hover:opacity-90 transition-opacity'
|
? 'overflow-hidden hover:opacity-90 transition-opacity'
|
||||||
@@ -114,330 +113,37 @@ export function ProductCard({ product, onAddToCart }: ProductCardProps) {
|
|||||||
'right': 'text-right',
|
'right': 'text-right',
|
||||||
}[layout.card_text_align || 'left'] || 'text-left';
|
}[layout.card_text_align || 'left'] || 'text-left';
|
||||||
|
|
||||||
// Classic Layout - Traditional card with border
|
// Unified card render — adapts via card_style (card / minimal / overlay) + shop settings
|
||||||
if (isClassic) {
|
|
||||||
return (
|
|
||||||
<Link to={`/product/${product.slug}`} className="group h-full">
|
|
||||||
<div className={`${cardClasses} h-full flex flex-col`}>
|
|
||||||
{/* Image */}
|
|
||||||
<div className={`relative w-full overflow-hidden bg-gray-100 ${aspectRatioClass}`}>
|
|
||||||
{product.image ? (
|
|
||||||
<img
|
|
||||||
src={product.image}
|
|
||||||
alt={product.name}
|
|
||||||
className="absolute inset-0 w-full !h-full object-cover object-center group-hover:scale-105 transition-transform duration-300"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="absolute inset-0 flex items-center justify-center text-gray-400">
|
|
||||||
No Image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Sale Badge */}
|
|
||||||
{elements.sale_badges && product.on_sale && discount && (
|
|
||||||
<div
|
|
||||||
className="absolute top-2 right-2 text-white text-xs font-bold px-2 py-1 rounded"
|
|
||||||
style={{ backgroundColor: saleBadge.color }}
|
|
||||||
>
|
|
||||||
{discount}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Wishlist Button */}
|
|
||||||
{showWishlist && (
|
|
||||||
<div className="absolute top-2 left-2 z-10">
|
|
||||||
<button
|
|
||||||
onClick={handleWishlistClick}
|
|
||||||
className={`font-[inherit] p-2 rounded-full shadow-md hover:bg-gray-50 flex items-center justify-center transition-all ${inWishlist ? 'bg-red-50' : 'bg-white'
|
|
||||||
}`}
|
|
||||||
title={inWishlist ? 'Remove from wishlist' : 'Add to wishlist'}
|
|
||||||
>
|
|
||||||
<Heart className={`w-4 h-4 block transition-all ${inWishlist ? 'fill-red-500 text-red-500' : ''
|
|
||||||
}`} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Hover/Overlay Button */}
|
|
||||||
{showButtonOnHover && (
|
|
||||||
<div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-10 transition-all duration-300 flex items-center justify-center">
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant={buttonVariant}
|
|
||||||
className="opacity-0 group-hover:opacity-100 transition-opacity"
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
|
||||||
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className={`p-4 flex-1 flex flex-col ${textAlignClass}`}>
|
|
||||||
<h3 className="text-sm font-medium text-gray-900 mb-2 line-clamp-2 leading-snug group-hover:text-primary transition-colors">
|
|
||||||
{product.name}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Price */}
|
|
||||||
<div className={`flex items-center gap-2 mb-3 ${(layout.card_text_align || 'left') === 'center' ? 'justify-center' : (layout.card_text_align || 'left') === 'right' ? 'justify-end' : ''}`}>
|
|
||||||
{product.on_sale && product.regular_price ? (
|
|
||||||
<>
|
|
||||||
<span className="text-base font-bold" style={{ color: 'var(--color-primary)' }}>
|
|
||||||
{formatPrice(product.sale_price || product.price)}
|
|
||||||
</span>
|
|
||||||
<span className="text-xs text-gray-500 line-through">
|
|
||||||
{formatPrice(product.regular_price)}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<span className="text-base font-bold text-gray-900">
|
|
||||||
{formatPrice(product.price)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Add to Cart Button - Below Image */}
|
|
||||||
{!showButtonOnHover && (
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant={buttonVariant}
|
|
||||||
className={`w-full mt-auto ${isTextOnly ? 'border-0 shadow-none hover:bg-transparent hover:underline' : ''}`}
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
|
||||||
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modern Layout - Minimalist, clean
|
|
||||||
if (isModern) {
|
|
||||||
return (
|
|
||||||
<Link to={`/product/${product.slug}`} className="group">
|
|
||||||
<div className="overflow-hidden">
|
|
||||||
{/* Image */}
|
|
||||||
<div className={`relative w-full mb-4 overflow-hidden bg-gray-50 ${aspectRatioClass}`} style={{ fontSize: 0 }}>
|
|
||||||
{product.image ? (
|
|
||||||
<img
|
|
||||||
src={product.image}
|
|
||||||
alt={product.name}
|
|
||||||
className="block w-full !h-full object-cover object-center group-hover:scale-105 transition-transform duration-500"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="w-full !h-full flex items-center justify-center text-gray-300" style={{ fontSize: '1rem' }}>
|
|
||||||
No Image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Sale Badge */}
|
|
||||||
{elements.sale_badges && product.on_sale && discount && (
|
|
||||||
<div
|
|
||||||
className="absolute top-4 left-4 text-white text-xs font-medium px-3 py-1"
|
|
||||||
style={{ backgroundColor: saleBadge.color }}
|
|
||||||
>
|
|
||||||
{discount}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Wishlist Button */}
|
|
||||||
{showWishlist && (
|
|
||||||
<div className="absolute top-4 right-4 z-10">
|
|
||||||
<button
|
|
||||||
onClick={handleWishlistClick}
|
|
||||||
className={`font-[inherit] p-2 rounded-full shadow-md hover:bg-gray-50 flex items-center justify-center transition-all ${inWishlist ? 'bg-red-50' : 'bg-white'
|
|
||||||
}`}
|
|
||||||
title={inWishlist ? 'Remove from wishlist' : 'Add to wishlist'}
|
|
||||||
>
|
|
||||||
<Heart className={`w-4 h-4 block transition-all ${inWishlist ? 'fill-red-500 text-red-500' : ''
|
|
||||||
}`} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Hover Overlay - Only show if position is hover/overlay */}
|
|
||||||
{showButtonOnHover && (
|
|
||||||
<div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-10 transition-all duration-300 flex items-center justify-center">
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant={buttonVariant}
|
|
||||||
className="opacity-0 group-hover:opacity-100 transition-opacity"
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
|
||||||
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="text-center">
|
|
||||||
<h3 className="text-sm font-medium text-gray-900 mb-2 leading-snug group-hover:text-primary transition-colors">
|
|
||||||
{product.name}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Price */}
|
|
||||||
<div className="flex items-center justify-center gap-2 mb-3">
|
|
||||||
{product.on_sale && product.regular_price ? (
|
|
||||||
<>
|
|
||||||
<span className="text-base font-bold" style={{ color: 'var(--color-primary)' }}>
|
|
||||||
{formatPrice(product.sale_price || product.price)}
|
|
||||||
</span>
|
|
||||||
<span className="text-xs text-gray-400 line-through">
|
|
||||||
{formatPrice(product.regular_price)}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<span className="text-base font-bold text-gray-900">
|
|
||||||
{formatPrice(product.price)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Add to Cart Button - Below or Bottom */}
|
|
||||||
{!showButtonOnHover && (
|
|
||||||
<div className="flex flex-col mt-auto">
|
|
||||||
{buttonPosition === 'below' && (
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant={buttonVariant}
|
|
||||||
className="w-full"
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
|
||||||
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{buttonPosition === 'bottom' && (
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant={buttonVariant}
|
|
||||||
className="w-full"
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
|
||||||
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boutique Layout - Luxury, elegant
|
|
||||||
if (isBoutique) {
|
|
||||||
return (
|
|
||||||
<Link to={`/product/${product.slug}`} className="group">
|
|
||||||
<div className="overflow-hidden">
|
|
||||||
{/* Image */}
|
|
||||||
<div className={`relative w-full mb-6 overflow-hidden bg-gray-50 ${aspectRatioClass}`} style={{ fontSize: 0 }}>
|
|
||||||
{product.image ? (
|
|
||||||
<img
|
|
||||||
src={product.image}
|
|
||||||
alt={product.name}
|
|
||||||
className="block w-full !h-full object-cover object-center group-hover:scale-110 transition-transform duration-700"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="w-full !h-full flex items-center justify-center text-gray-300 font-serif" style={{ fontSize: '1rem' }}>
|
|
||||||
No Image
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Sale Badge */}
|
|
||||||
{elements.sale_badges && product.on_sale && discount && (
|
|
||||||
<div
|
|
||||||
className="absolute top-6 right-6 text-white text-xs font-medium px-4 py-2 tracking-wider"
|
|
||||||
style={{ backgroundColor: saleBadge.color }}
|
|
||||||
>
|
|
||||||
{discount}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Wishlist Button */}
|
|
||||||
{showWishlist && (
|
|
||||||
<div className="absolute top-6 left-6 z-10">
|
|
||||||
<button
|
|
||||||
onClick={handleWishlistClick}
|
|
||||||
className={`font-[inherit] p-2 rounded-full shadow-md hover:bg-gray-50 flex items-center justify-center transition-all ${inWishlist ? 'bg-red-50' : 'bg-white'
|
|
||||||
}`}
|
|
||||||
title={inWishlist ? 'Remove from wishlist' : 'Add to wishlist'}
|
|
||||||
>
|
|
||||||
<Heart className={`w-4 h-4 block transition-all ${inWishlist ? 'fill-red-500 text-red-500' : ''
|
|
||||||
}`} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content */}
|
|
||||||
<div className="text-center font-serif">
|
|
||||||
<h3 className="text-sm font-medium text-gray-900 mb-3 tracking-wide leading-snug group-hover:text-primary transition-colors">
|
|
||||||
{product.name}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{/* Price */}
|
|
||||||
<div className="flex items-center justify-center gap-3 mb-4">
|
|
||||||
{product.on_sale && product.regular_price ? (
|
|
||||||
<>
|
|
||||||
<span className="text-lg font-semibold" style={{ color: 'var(--color-primary)' }}>
|
|
||||||
{formatPrice(product.sale_price || product.price)}
|
|
||||||
</span>
|
|
||||||
<span className="text-sm text-gray-400 line-through">
|
|
||||||
{formatPrice(product.regular_price)}
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<span className="text-lg font-semibold text-gray-900">
|
|
||||||
{formatPrice(product.price)}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Add to Cart Button */}
|
|
||||||
<Button
|
|
||||||
onClick={handleAddToCart}
|
|
||||||
variant="outline"
|
|
||||||
className="w-full font-serif tracking-wider"
|
|
||||||
disabled={product.stock_status === 'outofstock'}
|
|
||||||
>
|
|
||||||
{product.stock_status === 'outofstock' ? 'OUT OF STOCK' : isVariable ? 'SELECT OPTIONS' : 'ADD TO CART'}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Launch Layout - Funnel optimized (shouldn't show product grid, but just in case)
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/product/${product.slug}`} className="group">
|
<Link to={`/product/${product.slug}`} className="group h-full">
|
||||||
<div className="border rounded-lg overflow-hidden hover:shadow-md transition-shadow bg-white">
|
<div className={`${cardClasses} h-full flex flex-col`}>
|
||||||
<div className="relative w-full h-64 overflow-hidden bg-gray-100" style={{ fontSize: 0 }}>
|
{/* Image */}
|
||||||
|
<div className={`relative w-full overflow-hidden bg-gray-100 ${aspectRatioClass}`}>
|
||||||
{product.image ? (
|
{product.image ? (
|
||||||
<img
|
<img
|
||||||
src={product.image}
|
src={product.image}
|
||||||
alt={product.name}
|
alt={product.name}
|
||||||
className="block w-full !h-full object-cover object-center"
|
className="absolute inset-0 w-full !h-full object-cover object-center group-hover:scale-105 transition-transform duration-300"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="w-full !h-full flex items-center justify-center text-gray-400" style={{ fontSize: '1rem' }}>
|
<div className="absolute inset-0 flex items-center justify-center text-gray-400">
|
||||||
No Image
|
No Image
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Sale Badge */}
|
||||||
|
{elements.sale_badges && product.on_sale && discount && (
|
||||||
|
<div
|
||||||
|
className="absolute top-2 right-2 text-white text-xs font-bold px-2 py-1 rounded"
|
||||||
|
style={{ backgroundColor: saleBadge.color }}
|
||||||
|
>
|
||||||
|
{discount}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Wishlist Button */}
|
{/* Wishlist Button */}
|
||||||
{showWishlist && (
|
{showWishlist && (
|
||||||
<div className="absolute top-3 right-3 z-10">
|
<div className="absolute top-2 left-2 z-10">
|
||||||
<button
|
<button
|
||||||
onClick={handleWishlistClick}
|
onClick={handleWishlistClick}
|
||||||
className={`font-[inherit] p-2 rounded-full shadow-md hover:bg-gray-50 flex items-center justify-center transition-all ${inWishlist ? 'bg-red-50' : 'bg-white'
|
className={`font-[inherit] p-2 rounded-full shadow-md hover:bg-gray-50 flex items-center justify-center transition-all ${inWishlist ? 'bg-red-50' : 'bg-white'
|
||||||
@@ -449,16 +155,59 @@ export function ProductCard({ product, onAddToCart }: ProductCardProps) {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Hover/Overlay Button */}
|
||||||
|
{showButtonOnHover && (
|
||||||
|
<div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-10 transition-all duration-300 flex items-center justify-center">
|
||||||
|
<Button
|
||||||
|
onClick={handleAddToCart}
|
||||||
|
variant={buttonVariant}
|
||||||
|
className="opacity-0 group-hover:opacity-100 transition-opacity"
|
||||||
|
disabled={product.stock_status === 'outofstock'}
|
||||||
|
>
|
||||||
|
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
||||||
|
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="p-4 text-center">
|
{/* Content */}
|
||||||
<h3 className="text-sm font-medium text-gray-900 mb-2 leading-snug">{product.name}</h3>
|
<div className={`p-4 flex-1 flex flex-col ${textAlignClass}`}>
|
||||||
<div className="text-lg font-bold mb-3" style={{ color: 'var(--color-primary)' }}>
|
<h3 className="text-sm font-medium text-gray-900 mb-2 line-clamp-2 leading-snug group-hover:text-primary transition-colors">
|
||||||
{formatPrice(product.price)}
|
{product.name}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
{/* Price */}
|
||||||
|
<div className={`flex items-center gap-2 mb-3 ${(layout.card_text_align || 'left') === 'center' ? 'justify-center' : (layout.card_text_align || 'left') === 'right' ? 'justify-end' : ''}`}>
|
||||||
|
{product.on_sale && product.regular_price ? (
|
||||||
|
<>
|
||||||
|
<span className="text-base font-bold" style={{ color: 'var(--color-primary)' }}>
|
||||||
|
{formatPrice(product.sale_price || product.price)}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-gray-500 line-through">
|
||||||
|
{formatPrice(product.regular_price)}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<span className="text-base font-bold text-gray-900">
|
||||||
|
{formatPrice(product.price)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={handleAddToCart} className="w-full" size="lg">
|
|
||||||
{isVariable ? 'Select Options' : 'Buy Now'}
|
{/* Add to Cart Button */}
|
||||||
</Button>
|
{!showButtonOnHover && (
|
||||||
|
<Button
|
||||||
|
onClick={handleAddToCart}
|
||||||
|
variant={buttonVariant}
|
||||||
|
className={`w-full mt-auto ${isTextOnly ? 'border-0 shadow-none hover:bg-transparent hover:underline' : ''}`}
|
||||||
|
disabled={product.stock_status === 'outofstock'}
|
||||||
|
>
|
||||||
|
{!isTextOnly && addToCart.show_icon && <ShoppingCart className="w-4 h-4 mr-2" />}
|
||||||
|
{product.stock_status === 'outofstock' ? 'Out of Stock' : isVariable ? 'Select Options' : 'Add to Cart'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ export function AccountLayout({ children }: AccountLayoutProps) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Responsive layout: Tabs on mobile, Sidebar on desktop
|
// Responsive layout: Tabs on mobile, Sidebar on desktop
|
||||||
<div className="py-8">
|
return (
|
||||||
|
<div className="py-8">
|
||||||
{/* Mobile: Tab Navigation */}
|
{/* Mobile: Tab Navigation */}
|
||||||
{renderTabNav()}
|
{renderTabNav()}
|
||||||
|
|
||||||
@@ -216,6 +217,7 @@ export function AccountLayout({ children }: AccountLayoutProps) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ class EmailRenderer
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Order variables
|
// Order variables
|
||||||
if ($data instanceof WC_Order) {
|
if ($data instanceof \WC_Order) {
|
||||||
// Calculate estimated delivery (3-5 business days from now)
|
// Calculate estimated delivery (3-5 business days from now)
|
||||||
$estimated_delivery = date('F j', strtotime('+3 days')) . '-' . date('j', strtotime('+5 days'));
|
$estimated_delivery = date('F j', strtotime('+3 days')) . '-' . date('j', strtotime('+5 days'));
|
||||||
|
|
||||||
@@ -289,7 +289,7 @@ class EmailRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Product variables
|
// Product variables
|
||||||
if ($data instanceof WC_Product) {
|
if ($data instanceof \WC_Product) {
|
||||||
$variables = array_merge($variables, [
|
$variables = array_merge($variables, [
|
||||||
'product_id' => $data->get_id(),
|
'product_id' => $data->get_id(),
|
||||||
'product_name' => $data->get_name(),
|
'product_name' => $data->get_name(),
|
||||||
@@ -302,7 +302,7 @@ class EmailRenderer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Customer variables
|
// Customer variables
|
||||||
if ($data instanceof WC_Customer) {
|
if ($data instanceof \WC_Customer) {
|
||||||
// Get temp password from user meta (stored during auto-registration)
|
// Get temp password from user meta (stored during auto-registration)
|
||||||
$user_temp_password = get_user_meta($data->get_id(), '_woonoow_temp_password', true);
|
$user_temp_password = get_user_meta($data->get_id(), '_woonoow_temp_password', true);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user