Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6e5c1ed62 | |||
| 693b21ba5f | |||
| d237c1406a | |||
| 8fc1133da5 | |||
| c715903b30 | |||
| e56246cab4 | |||
| 4c7174208d |
@@ -33,7 +33,7 @@ export default function BlogPage() {
|
|||||||
<div id="nav" data-section="nav">
|
<div id="nav" data-section="nav">
|
||||||
<NavbarLayoutFloatingInline
|
<NavbarLayoutFloatingInline
|
||||||
navItems={[
|
navItems={[
|
||||||
{ name: "Home", id: "/" },
|
{ name: "Features", id: "#features" }, { name: "Products", id: "#products" }, { name: "Testimonials", id: "#testimonials" }, { name: "FAQ", id: "#faq" }, { name: "Contact", id: "#contact" }
|
||||||
]}
|
]}
|
||||||
brandName="Biorogo"
|
brandName="Biorogo"
|
||||||
button={{ text: "Shop Now", href: "/shop" }}
|
button={{ text: "Shop Now", href: "/shop" }}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export default function RootLayout({
|
|||||||
|
|
||||||
const buttonClasses = ['btn', 'button', 'cta', 'action-button'];
|
const buttonClasses = ['btn', 'button', 'cta', 'action-button'];
|
||||||
const hasButtonClass = buttonClasses.some(cls =>
|
const hasButtonClass = buttonClasses.some(cls =>
|
||||||
element.classList.contains(cls) || element.classList.contains(\`btn-\${cls}\`)
|
element.classList.contains(cls) || element.classList.contains(`btn-${cls}`)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (hasButtonClass && element.textContent && element.textContent.trim().length > 0) {
|
if (hasButtonClass && element.textContent && element.textContent.trim().length > 0) {
|
||||||
@@ -237,7 +237,8 @@ export default function RootLayout({
|
|||||||
try {
|
try {
|
||||||
const urlObj = new URL(url);
|
const urlObj = new URL(url);
|
||||||
return urlObj.pathname;
|
return urlObj.pathname;
|
||||||
} catch (e) {
|
}
|
||||||
|
catch (e) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -631,17 +632,17 @@ export default function RootLayout({
|
|||||||
const rect = element.getBoundingClientRect();
|
const rect = element.getBoundingClientRect();
|
||||||
const overlay = document.createElement('div');
|
const overlay = document.createElement('div');
|
||||||
overlay.className = 'webild-hover-overlay';
|
overlay.className = 'webild-hover-overlay';
|
||||||
overlay.style.cssText = \`
|
overlay.style.cssText = `
|
||||||
position: fixed !important;
|
position: fixed !important;
|
||||||
top: \${rect.top - 2}px !important;
|
top: ${rect.top - 2}px !important;
|
||||||
left: \${rect.left - 2}px !important;
|
left: ${rect.left - 2}px !important;
|
||||||
width: \${rect.width + 4}px !important;
|
width: ${rect.width + 4}px !important;
|
||||||
height: \${rect.height + 4}px !important;
|
height: ${rect.height + 4}px !important;
|
||||||
background-color: rgba(90, 113, 230, 0.15) !important;
|
background-color: rgba(90, 113, 230, 0.15) !important;
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
z-index: 999998 !important;
|
z-index: 999998 !important;
|
||||||
transition: all 0.15s ease !important;
|
transition: all 0.15s ease !important;
|
||||||
\`;
|
`;
|
||||||
document.body.appendChild(overlay);
|
document.body.appendChild(overlay);
|
||||||
return overlay;
|
return overlay;
|
||||||
};
|
};
|
||||||
@@ -704,11 +705,11 @@ export default function RootLayout({
|
|||||||
elementTypeLabel.classList.add('label-bottom');
|
elementTypeLabel.classList.add('label-bottom');
|
||||||
}
|
}
|
||||||
|
|
||||||
elementTypeLabel.style.cssText = \`
|
elementTypeLabel.style.cssText = `
|
||||||
left: \${labelLeft}px !important;
|
left: ${labelLeft}px !important;
|
||||||
top: \${labelTop}px !important;
|
top: ${labelTop}px !important;
|
||||||
transform: none !important;
|
transform: none !important;
|
||||||
\`;
|
`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeElementTypeLabel = () => {
|
const removeElementTypeLabel = () => {
|
||||||
@@ -962,7 +963,7 @@ export default function RootLayout({
|
|||||||
const getStorageKey = () => {
|
const getStorageKey = () => {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
const pathParts = url.pathname.split('/').filter(Boolean);
|
const pathParts = url.pathname.split('/').filter(Boolean);
|
||||||
return \`webild-changes-\${pathParts.join('-')}\`;
|
return `webild-changes-${pathParts.join('-')}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveChangeToStorage = (change) => {
|
const saveChangeToStorage = (change) => {
|
||||||
@@ -1187,7 +1188,7 @@ export default function RootLayout({
|
|||||||
|
|
||||||
if (isBackground) {
|
if (isBackground) {
|
||||||
oldValue = window.getComputedStyle(element).backgroundImage;
|
oldValue = window.getComputedStyle(element).backgroundImage;
|
||||||
element.style.backgroundImage = \`url('\${newSrc}')\`;
|
element.style.backgroundImage = `url('${newSrc}')`;
|
||||||
replaced = true;
|
replaced = true;
|
||||||
} else if (element.tagName.toLowerCase() === 'img') {
|
} else if (element.tagName.toLowerCase() === 'img') {
|
||||||
oldValue = element.src;
|
oldValue = element.src;
|
||||||
@@ -1197,7 +1198,7 @@ export default function RootLayout({
|
|||||||
const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none';
|
const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none';
|
||||||
if (hasBackgroundImage) {
|
if (hasBackgroundImage) {
|
||||||
oldValue = window.getComputedStyle(element).backgroundImage;
|
oldValue = window.getComputedStyle(element).backgroundImage;
|
||||||
element.style.backgroundImage = \`url('\${newSrc}')\`;
|
element.style.backgroundImage = `url('${newSrc}')`;
|
||||||
replaced = true;
|
replaced = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1372,7 +1373,9 @@ export default function RootLayout({
|
|||||||
' background-color: #4d96ff05 !important;' +
|
' background-color: #4d96ff05 !important;' +
|
||||||
'}' +
|
'}' +
|
||||||
'img.webild-hover,' +
|
'img.webild-hover,' +
|
||||||
'img.webild-selected {' +
|
'img.webild-selected,' +
|
||||||
|
'video.webild-hover,' +
|
||||||
|
'video.webild-selected {' +
|
||||||
' outline-offset: 2px !important;' +
|
' outline-offset: 2px !important;' +
|
||||||
'}' +
|
'}' +
|
||||||
'.webild-element-type-label {' +
|
'.webild-element-type-label {' +
|
||||||
@@ -1444,6 +1447,10 @@ export default function RootLayout({
|
|||||||
return 'Image';
|
return 'Image';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tagName === 'video') {
|
||||||
|
return 'Video';
|
||||||
|
}
|
||||||
|
|
||||||
const backgroundImage = computedStyle.backgroundImage;
|
const backgroundImage = computedStyle.backgroundImage;
|
||||||
if (backgroundImage && backgroundImage !== 'none') {
|
if (backgroundImage && backgroundImage !== 'none') {
|
||||||
const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/);
|
const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/);
|
||||||
@@ -1526,6 +1533,38 @@ export default function RootLayout({
|
|||||||
return url;
|
return url;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getMediaTypeFromUrl = (url) => {
|
||||||
|
const videoExts = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv', '.m4v', '.wmv'];
|
||||||
|
const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.ico', '.tiff', '.avif'];
|
||||||
|
try {
|
||||||
|
const pathname = new URL(url).pathname.toLowerCase();
|
||||||
|
if (videoExts.some(function(ext) { return pathname.endsWith(ext); })) return 'video';
|
||||||
|
if (imageExts.some(function(ext) { return pathname.endsWith(ext); })) return 'image';
|
||||||
|
} catch(e) {}
|
||||||
|
return 'unknown';
|
||||||
|
};
|
||||||
|
|
||||||
|
const swapMediaElement = (oldEl, newTag, newSrc) => {
|
||||||
|
const newEl = document.createElement(newTag);
|
||||||
|
Array.from(oldEl.attributes).forEach(function(attr) {
|
||||||
|
if (attr.name !== 'src' && attr.name !== 'alt' && attr.name !== 'srcset' && attr.name !== 'autoplay' && attr.name !== 'loop' && attr.name !== 'muted' && attr.name !== 'playsinline') {
|
||||||
|
try { newEl.setAttribute(attr.name, attr.value); } catch(e) {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newEl.style.cssText = oldEl.style.cssText;
|
||||||
|
if (newTag === 'video') {
|
||||||
|
newEl.setAttribute('autoplay', '');
|
||||||
|
newEl.setAttribute('loop', '');
|
||||||
|
newEl.setAttribute('muted', '');
|
||||||
|
newEl.setAttribute('playsinline', '');
|
||||||
|
}
|
||||||
|
newEl.src = newSrc;
|
||||||
|
if (oldEl.parentNode) {
|
||||||
|
oldEl.parentNode.replaceChild(newEl, oldEl);
|
||||||
|
}
|
||||||
|
return newEl;
|
||||||
|
};
|
||||||
|
|
||||||
const getElementInfo = (element, assignId = false) => {
|
const getElementInfo = (element, assignId = false) => {
|
||||||
const rect = element.getBoundingClientRect();
|
const rect = element.getBoundingClientRect();
|
||||||
const tagName = element.tagName.toLowerCase();
|
const tagName = element.tagName.toLowerCase();
|
||||||
@@ -1569,6 +1608,17 @@ export default function RootLayout({
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tagName === 'video') {
|
||||||
|
const rawSrc = element.src || element.currentSrc || (element.querySelector('source') && element.querySelector('source').src) || '';
|
||||||
|
const resolvedSrc = extractOriginalUrl(rawSrc);
|
||||||
|
info.imageData = {
|
||||||
|
src: resolvedSrc,
|
||||||
|
alt: element.getAttribute('aria-label') || undefined,
|
||||||
|
isBackground: false,
|
||||||
|
isVideo: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const computedStyle = window.getComputedStyle(element);
|
const computedStyle = window.getComputedStyle(element);
|
||||||
const backgroundImage = computedStyle.backgroundImage;
|
const backgroundImage = computedStyle.backgroundImage;
|
||||||
if (backgroundImage && backgroundImage !== 'none') {
|
if (backgroundImage && backgroundImage !== 'none') {
|
||||||
@@ -1616,7 +1666,8 @@ export default function RootLayout({
|
|||||||
const tagName = element.tagName?.toLowerCase();
|
const tagName = element.tagName?.toLowerCase();
|
||||||
if (invalidElements.includes(tagName)) return false;
|
if (invalidElements.includes(tagName)) return false;
|
||||||
const isImage = tagName === 'img';
|
const isImage = tagName === 'img';
|
||||||
if (isImage) return true;
|
const isVideo = tagName === 'video';
|
||||||
|
if (isImage || isVideo) return true;
|
||||||
const hasInnerHTML = element.innerHTML && element.innerHTML.trim().length > 0;
|
const hasInnerHTML = element.innerHTML && element.innerHTML.trim().length > 0;
|
||||||
const hasTextContent = element.textContent && element.textContent.trim().length > 0;
|
const hasTextContent = element.textContent && element.textContent.trim().length > 0;
|
||||||
const hasChildren = element.children && element.children.length > 0;
|
const hasChildren = element.children && element.children.length > 0;
|
||||||
@@ -1656,7 +1707,7 @@ export default function RootLayout({
|
|||||||
node.nodeType === Node.TEXT_NODE && node.textContent && node.textContent.trim().length > 0
|
node.nodeType === Node.TEXT_NODE && node.textContent && node.textContent.trim().length > 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasImages = element.tagName === 'IMG' || computedStyle.backgroundImage !== 'none' || element.querySelector('img');
|
const hasImages = element.tagName === 'IMG' || element.tagName === 'VIDEO' || computedStyle.backgroundImage !== 'none' || element.querySelector('img') || element.querySelector('video');
|
||||||
const isInteractive = ['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName);
|
const isInteractive = ['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName);
|
||||||
const hasFewChildren = element.children.length <= 3;
|
const hasFewChildren = element.children.length <= 3;
|
||||||
const area = rect.width * rect.height;
|
const area = rect.width * rect.height;
|
||||||
@@ -2337,11 +2388,22 @@ export default function RootLayout({
|
|||||||
updateButtonText(element, change.oldValue);
|
updateButtonText(element, change.oldValue);
|
||||||
}
|
}
|
||||||
} else if (change.type === 'replaceImage') {
|
} else if (change.type === 'replaceImage') {
|
||||||
const isBackground = element.tagName.toLowerCase() !== 'img';
|
const revertTag = element.tagName.toLowerCase();
|
||||||
|
const isBackground = revertTag !== 'img' && revertTag !== 'video';
|
||||||
if (isBackground) {
|
if (isBackground) {
|
||||||
element.style.backgroundImage = change.oldValue ? 'url(' + change.oldValue + ')' : '';
|
element.style.backgroundImage = change.oldValue ? 'url(' + change.oldValue + ')' : '';
|
||||||
} else {
|
} else {
|
||||||
element.src = change.oldValue;
|
const oldMediaType = getMediaTypeFromUrl(change.oldValue);
|
||||||
|
if (revertTag === 'video' && oldMediaType === 'image') {
|
||||||
|
swapMediaElement(element, 'img', change.oldValue);
|
||||||
|
} else if (revertTag === 'img' && oldMediaType === 'video') {
|
||||||
|
swapMediaElement(element, 'video', change.oldValue);
|
||||||
|
} else if (revertTag === 'video') {
|
||||||
|
element.src = change.oldValue;
|
||||||
|
element.load();
|
||||||
|
} else {
|
||||||
|
element.src = change.oldValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -2441,7 +2503,7 @@ export default function RootLayout({
|
|||||||
if (!isActive) return;
|
if (!isActive) return;
|
||||||
|
|
||||||
if (e.data.type === 'webild-replace-image') {
|
if (e.data.type === 'webild-replace-image') {
|
||||||
const { selector, newSrc, isBackground } = e.data.data;
|
const { selector, newSrc, isBackground, allowMediaTypeSwap } = e.data.data;
|
||||||
let element = null;
|
let element = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -2472,7 +2534,32 @@ export default function RootLayout({
|
|||||||
replaced = true;
|
replaced = true;
|
||||||
} else if (element.tagName.toLowerCase() === 'img') {
|
} else if (element.tagName.toLowerCase() === 'img') {
|
||||||
oldValue = element.src;
|
oldValue = element.src;
|
||||||
element.src = newSrc;
|
const newMediaType = getMediaTypeFromUrl(newSrc);
|
||||||
|
if (newMediaType === 'video' && allowMediaTypeSwap) {
|
||||||
|
const swapped = swapMediaElement(element, 'video', newSrc);
|
||||||
|
if (selectedElement === element) selectedElement = swapped;
|
||||||
|
element = swapped;
|
||||||
|
} else {
|
||||||
|
element.src = newSrc;
|
||||||
|
}
|
||||||
|
replaced = true;
|
||||||
|
} else if (element.tagName.toLowerCase() === 'video') {
|
||||||
|
oldValue = element.src || element.currentSrc || '';
|
||||||
|
const newMediaType = getMediaTypeFromUrl(newSrc);
|
||||||
|
const sources = element.querySelectorAll('source');
|
||||||
|
if (newMediaType === 'image' && allowMediaTypeSwap) {
|
||||||
|
const swapped = swapMediaElement(element, 'img', newSrc);
|
||||||
|
if (selectedElement === element) selectedElement = swapped;
|
||||||
|
element = swapped;
|
||||||
|
} else {
|
||||||
|
if (sources.length > 0) {
|
||||||
|
sources.forEach(function(source) { source.src = newSrc; });
|
||||||
|
element.load();
|
||||||
|
} else {
|
||||||
|
element.src = newSrc;
|
||||||
|
element.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
replaced = true;
|
replaced = true;
|
||||||
} else {
|
} else {
|
||||||
const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none';
|
const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none';
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import ContactSplit from '@/components/sections/contact/ContactSplit';
|
|||||||
import FaqDouble from '@/components/sections/faq/FaqDouble';
|
import FaqDouble from '@/components/sections/faq/FaqDouble';
|
||||||
import FeatureCardSeven from '@/components/sections/feature/FeatureCardSeven';
|
import FeatureCardSeven from '@/components/sections/feature/FeatureCardSeven';
|
||||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
||||||
import HeroSplitKpi from '@/components/sections/hero/HeroSplitKpi';
|
import HeroOverlay from '@/components/sections/hero/HeroOverlay';
|
||||||
import ProductCardThree from '@/components/sections/product/ProductCardThree';
|
import ProductCardThree from '@/components/sections/product/ProductCardThree';
|
||||||
import TestimonialCardFive from '@/components/sections/testimonial/TestimonialCardFive';
|
import TestimonialCardFive from '@/components/sections/testimonial/TestimonialCardFive';
|
||||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||||
@@ -36,12 +36,9 @@ export default function LandingPage() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="hero" data-section="hero">
|
<div id="hero" data-section="hero">
|
||||||
<HeroSplitKpi
|
<HeroOverlay
|
||||||
title="Elevate Your Daily Rituals with Biorogo Cups"
|
title="Elevate Your Daily Rituals with Biorogo Cups"
|
||||||
description="Discover our curated collection of beautifully designed, sustainable, and handcrafted cups for every occasion. Experience the perfect blend of aesthetics and functionality."
|
description="Discover our curated collection of beautifully designed, sustainable, and handcrafted cups for every occasion. Experience the perfect blend of aesthetics and functionality."
|
||||||
background={{ variant: 'plain' }}
|
|
||||||
kpis={[{ value: "1000+", label: "Happy Customers" }, { value: "50+", label: "Unique Designs" }, { value: "Eco-Friendly", label: "Materials" }]}
|
|
||||||
enableKpiAnimation={true}
|
|
||||||
tag="Artistry in Every Sip"
|
tag="Artistry in Every Sip"
|
||||||
tagIcon={Sparkles}
|
tagIcon={Sparkles}
|
||||||
tagAnimation="slide-up"
|
tagAnimation="slide-up"
|
||||||
@@ -51,7 +48,9 @@ export default function LandingPage() {
|
|||||||
imageAlt="Collection of elegant Biorogo cups"
|
imageAlt="Collection of elegant Biorogo cups"
|
||||||
mediaAnimation="opacity"
|
mediaAnimation="opacity"
|
||||||
ariaLabel="Welcome to Biorogo Cups"
|
ariaLabel="Welcome to Biorogo Cups"
|
||||||
imagePosition="right"
|
textPosition="bottom-left"
|
||||||
|
showBlur={true}
|
||||||
|
showDimOverlay={false}
|
||||||
titleClassName="text-foreground text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold"
|
titleClassName="text-foreground text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold"
|
||||||
descriptionClassName="text-foreground/80 text-lg md:text-xl"
|
descriptionClassName="text-foreground/80 text-lg md:text-xl"
|
||||||
tagClassName="text-accent text-sm md:text-base"
|
tagClassName="text-accent text-sm md:text-base"
|
||||||
|
|||||||
@@ -3,277 +3,97 @@
|
|||||||
import { use, useCallback } from "react";
|
import { use, useCallback } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import ReactLenis from "lenis/react";
|
import ReactLenis from "lenis/react";
|
||||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
import { ThemeProvider } => {
|
||||||
import NavbarLayoutFloatingInline from "@/components/navbar/NavbarLayoutFloatingInline";
|
const navigationItems = [
|
||||||
import ProductDetailCard from "@/components/ecommerce/productDetail/ProductDetailCard";
|
{ name: "Features", id: "/#features" },
|
||||||
import ProductCart from "@/components/ecommerce/cart/ProductCart";
|
{ name: "Products", id: "/#products" },
|
||||||
import { useProductDetail } from "@/hooks/useProductDetail";
|
{ name: "Testimonials", id: "/#testimonials" },
|
||||||
import { useCart } from "@/hooks/useCart";
|
{ name: "FAQ", id: "/#faq" },
|
||||||
import { useCheckout } from "@/hooks/useCheckout";
|
{ name: "Contact", id: "/#contact" }
|
||||||
import FooterBaseCard from '@/components/sections/footer/FooterBaseCard';
|
];
|
||||||
|
|
||||||
interface ProductPageProps {
|
return (
|
||||||
params: Promise<{ id: string }>;
|
<ThemeProvider
|
||||||
}
|
defaultButtonVariant="slide-background"
|
||||||
|
defaultTextAnimation="background-highlight"
|
||||||
export default function ProductPage({ params }: ProductPageProps) {
|
borderRadius="rounded"
|
||||||
const { id } = use(params);
|
contentWidth="small"
|
||||||
const router = useRouter();
|
sizing="largeSmall"
|
||||||
|
background="none"
|
||||||
const {
|
cardStyle="inset"
|
||||||
product,
|
primaryButtonStyle="primary-glow"
|
||||||
isLoading,
|
secondaryButtonStyle="layered"
|
||||||
images,
|
headingFontWeight="extrabold"
|
||||||
meta,
|
>
|
||||||
variants,
|
<ReactLenis root>
|
||||||
quantityVariant,
|
<div id="navbar" data-section="navbar">
|
||||||
selectedQuantity,
|
<NavbarLayoutFloatingInline
|
||||||
createCartItem,
|
navItems={navigationItems}
|
||||||
} = useProductDetail(id);
|
brandName="Biorogo"
|
||||||
|
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
||||||
const {
|
className="py-4 px-6 md:px-8 lg:px-12"
|
||||||
items: cartItems,
|
navItemClassName="text-foreground hover:text-primary-cta"
|
||||||
isOpen: cartOpen,
|
buttonClassName=""
|
||||||
setIsOpen: setCartOpen,
|
buttonTextClassName=""
|
||||||
addItem,
|
/>
|
||||||
updateQuantity,
|
</div>
|
||||||
removeItem,
|
<div id="product-detail-card" data-section="product-detail-card">
|
||||||
total: cartTotal,
|
<ProductDetailCard
|
||||||
getCheckoutItems,
|
layout="page"
|
||||||
} = useCart();
|
name={product.name}
|
||||||
|
price={product.price}
|
||||||
const { buyNow, checkout, isLoading: isCheckoutLoading } = useCheckout();
|
salePrice={meta.salePrice}
|
||||||
|
rating={product.rating || 0}
|
||||||
const handleAddToCart = useCallback(() => {
|
description={product.description}
|
||||||
const item = createCartItem();
|
images={images}
|
||||||
if (item) {
|
variants={variants.length > 0 ? variants : undefined}
|
||||||
addItem(item);
|
quantity={quantityVariant}
|
||||||
}
|
ribbon={meta.ribbon}
|
||||||
}, [createCartItem, addItem]);
|
inventoryStatus={meta.inventoryStatus}
|
||||||
|
inventoryQuantity={meta.inventoryQuantity}
|
||||||
const handleBuyNow = useCallback(() => {
|
sku={meta.sku}
|
||||||
if (product) {
|
buttons={[
|
||||||
buyNow(product, selectedQuantity);
|
{ text: "Add To Cart", onClick: handleAddToCart },
|
||||||
}
|
{ text: "Buy Now", onClick: handleBuyNow },
|
||||||
}, [product, selectedQuantity, buyNow]);
|
]}
|
||||||
|
/>
|
||||||
const handleCheckout = useCallback(async () => {
|
</div>
|
||||||
if (cartItems.length === 0) return;
|
<div id="product-cart" data-section="product-cart">
|
||||||
|
<ProductCart
|
||||||
const currentUrl = new URL(window.location.href);
|
isOpen={cartOpen}
|
||||||
currentUrl.searchParams.set("success", "true");
|
onClose={() => setCartOpen(false)}
|
||||||
|
items={cartItems}
|
||||||
await checkout(getCheckoutItems(), { successUrl: currentUrl.toString() });
|
onQuantityChange={updateQuantity}
|
||||||
}, [cartItems, checkout, getCheckoutItems]);
|
onRemove={removeItem}
|
||||||
|
total={`$${cartTotal}`}
|
||||||
if (isLoading) {
|
buttons={[
|
||||||
return (
|
{
|
||||||
<ThemeProvider
|
text: isCheckoutLoading ? "Processing..." : "Check Out", onClick: handleCheckout,
|
||||||
defaultButtonVariant="slide-background"
|
},
|
||||||
defaultTextAnimation="background-highlight"
|
]}
|
||||||
borderRadius="rounded"
|
/>
|
||||||
contentWidth="small"
|
</div>
|
||||||
sizing="largeSmall"
|
<div id="footer" data-section="footer">
|
||||||
background="none"
|
<FooterBaseCard
|
||||||
cardStyle="inset"
|
logoText="Biorogo"
|
||||||
primaryButtonStyle="primary-glow"
|
columns={[
|
||||||
secondaryButtonStyle="layered"
|
{ title: "Shop", items: [{ label: "All Cups", href: "/#products" }, { label: "Ceramic", href: "/#products" }, { label: "Glassware", href: "/#products" }, { label: "Travel Mugs", href: "/#products" }] },
|
||||||
headingFontWeight="extrabold"
|
{ title: "Company", items: [{ label: "About Us", href: "/#features" }, { label: "Testimonials", href: "/#testimonials" }, { label: "FAQ", href: "/#faq" }] },
|
||||||
>
|
{ title: "Support", items: [{ label: "Contact Us", href: "/#contact" }, { label: "Shipping", href: "/shipping" }, { label: "Returns", href: "/returns" }, { label: "Sitemap", href: "/sitemap" }] }
|
||||||
<ReactLenis root>
|
]}
|
||||||
<div id="navbar" data-section="navbar">
|
copyrightText="© 2024 Biorogo. All rights reserved."
|
||||||
<NavbarLayoutFloatingInline
|
onPrivacyClick={() => console.log('Privacy policy clicked')}
|
||||||
navItems={[
|
ariaLabel="Site footer for Biorogo"
|
||||||
{ name: "Home", id: "/" },
|
className="py-16 md:py-20"
|
||||||
]}
|
cardClassName="bg-card rounded-t-3xl shadow-lg border-t border-l border-r border-accent/20"
|
||||||
brandName="Biorogo"
|
logoTextClassName="text-foreground text-3xl font-extrabold"
|
||||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
columnTitleClassName="text-foreground text-lg font-semibold"
|
||||||
className="py-4 px-6 md:px-8 lg:px-12"
|
columnItemClassName="text-foreground/80 hover:text-primary-cta"
|
||||||
navItemClassName="text-foreground hover:text-primary-cta"
|
copyrightTextClassName="text-foreground/60 text-sm"
|
||||||
buttonClassName=""
|
privacyButtonClassName="text-foreground/60 text-sm hover:text-primary-cta"
|
||||||
buttonTextClassName=""
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</ReactLenis>
|
||||||
<div id="loading-indicator" data-section="loading-indicator">
|
</ThemeProvider>
|
||||||
<main className="min-h-screen flex items-center justify-center pt-20">
|
);
|
||||||
<p className="text-foreground">Loading product...</p>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<div id="footer" data-section="footer">
|
|
||||||
<FooterBaseCard
|
|
||||||
logoText="Biorogo"
|
|
||||||
columns={[
|
|
||||||
{ title: "Shop", items: [{ label: "All Cups", href: "/#products" }, { label: "Ceramic", href: "/#products" }, { label: "Glassware", href: "/#products" }, { label: "Travel Mugs", href: "/#products" }] },
|
|
||||||
{ title: "Company", items: [{ label: "About Us", href: "/#features" }, { label: "Testimonials", href: "/#testimonials" }, { label: "FAQ", href: "/#faq" }] },
|
|
||||||
{ title: "Support", items: [{ label: "Contact Us", href: "/#contact" }, { label: "Shipping", href: "/shipping" }, { label: "Returns", href: "/returns" }, { label: "Sitemap", href: "/sitemap" }] }
|
|
||||||
]}
|
|
||||||
copyrightText="© 2024 Biorogo. All rights reserved."
|
|
||||||
onPrivacyClick={() => console.log('Privacy policy clicked')}
|
|
||||||
ariaLabel="Site footer for Biorogo"
|
|
||||||
className="py-16 md:py-20"
|
|
||||||
cardClassName="bg-card rounded-t-3xl shadow-lg border-t border-l border-r border-accent/20"
|
|
||||||
logoTextClassName="text-foreground text-3xl font-extrabold"
|
|
||||||
columnTitleClassName="text-foreground text-lg font-semibold"
|
|
||||||
columnItemClassName="text-foreground/80 hover:text-primary-cta"
|
|
||||||
copyrightTextClassName="text-foreground/60 text-sm"
|
|
||||||
privacyButtonClassName="text-foreground/60 text-sm hover:text-primary-cta"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ReactLenis>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!product) {
|
|
||||||
return (
|
|
||||||
<ThemeProvider
|
|
||||||
defaultButtonVariant="slide-background"
|
|
||||||
defaultTextAnimation="background-highlight"
|
|
||||||
borderRadius="rounded"
|
|
||||||
contentWidth="small"
|
|
||||||
sizing="largeSmall"
|
|
||||||
background="none"
|
|
||||||
cardStyle="inset"
|
|
||||||
primaryButtonStyle="primary-glow"
|
|
||||||
secondaryButtonStyle="layered"
|
|
||||||
headingFontWeight="extrabold"
|
|
||||||
>
|
|
||||||
<ReactLenis root>
|
|
||||||
<div id="navbar" data-section="navbar">
|
|
||||||
<NavbarLayoutFloatingInline
|
|
||||||
navItems={[
|
|
||||||
{ name: "Home", id: "/" },
|
|
||||||
]}
|
|
||||||
brandName="Biorogo"
|
|
||||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
|
||||||
className="py-4 px-6 md:px-8 lg:px-12"
|
|
||||||
navItemClassName="text-foreground hover:text-primary-cta"
|
|
||||||
buttonClassName=""
|
|
||||||
buttonTextClassName=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="product-not-found" data-section="product-not-found">
|
|
||||||
<main className="min-h-screen flex items-center justify-center pt-20">
|
|
||||||
<div className="text-center">
|
|
||||||
<p className="text-foreground mb-4">Product not found</p>
|
|
||||||
<button
|
|
||||||
onClick={() => router.push("/shop")}
|
|
||||||
className="primary-button px-6 py-2 rounded-theme"
|
|
||||||
>
|
|
||||||
Back to Shop
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
<div id="footer" data-section="footer">
|
|
||||||
<FooterBaseCard
|
|
||||||
logoText="Biorogo"
|
|
||||||
columns={[
|
|
||||||
{ title: "Shop", items: [{ label: "All Cups", href: "/#products" }, { label: "Ceramic", href: "/#products" }, { label: "Glassware", href: "/#products" }, { label: "Travel Mugs", href: "/#products" }] },
|
|
||||||
{ title: "Company", items: [{ label: "About Us", href: "/#features" }, { label: "Testimonials", href: "/#testimonials" }, { label: "FAQ", href: "/#faq" }] },
|
|
||||||
{ title: "Support", items: [{ label: "Contact Us", href: "/#contact" }, { label: "Shipping", href: "/shipping" }, { label: "Returns", href: "/returns" }, { label: "Sitemap", href: "/sitemap" }] }
|
|
||||||
]}
|
|
||||||
copyrightText="© 2024 Biorogo. All rights reserved."
|
|
||||||
onPrivacyClick={() => console.log('Privacy policy clicked')}
|
|
||||||
ariaLabel="Site footer for Biorogo"
|
|
||||||
className="py-16 md:py-20"
|
|
||||||
cardClassName="bg-card rounded-t-3xl shadow-lg border-t border-l border-r border-accent/20"
|
|
||||||
logoTextClassName="text-foreground text-3xl font-extrabold"
|
|
||||||
columnTitleClassName="text-foreground text-lg font-semibold"
|
|
||||||
columnItemClassName="text-foreground/80 hover:text-primary-cta"
|
|
||||||
copyrightTextClassName="text-foreground/60 text-sm"
|
|
||||||
privacyButtonClassName="text-foreground/60 text-sm hover:text-primary-cta"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ReactLenis>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ThemeProvider
|
|
||||||
defaultButtonVariant="slide-background"
|
|
||||||
defaultTextAnimation="background-highlight"
|
|
||||||
borderRadius="rounded"
|
|
||||||
contentWidth="small"
|
|
||||||
sizing="largeSmall"
|
|
||||||
background="none"
|
|
||||||
cardStyle="inset"
|
|
||||||
primaryButtonStyle="primary-glow"
|
|
||||||
secondaryButtonStyle="layered"
|
|
||||||
headingFontWeight="extrabold"
|
|
||||||
>
|
|
||||||
<ReactLenis root>
|
|
||||||
<div id="navbar" data-section="navbar">
|
|
||||||
<NavbarLayoutFloatingInline
|
|
||||||
navItems={[
|
|
||||||
{ name: "Home", id: "/" },
|
|
||||||
]}
|
|
||||||
brandName="Biorogo"
|
|
||||||
button={{ text: "Cart", onClick: () => setCartOpen(true) }}
|
|
||||||
className="py-4 px-6 md:px-8 lg:px-12"
|
|
||||||
navItemClassName="text-foreground hover:text-primary-cta"
|
|
||||||
buttonClassName=""
|
|
||||||
buttonTextClassName=""
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="product-detail-card" data-section="product-detail-card">
|
|
||||||
<ProductDetailCard
|
|
||||||
layout="page"
|
|
||||||
name={product.name}
|
|
||||||
price={product.price}
|
|
||||||
salePrice={meta.salePrice}
|
|
||||||
rating={product.rating || 0}
|
|
||||||
description={product.description}
|
|
||||||
images={images}
|
|
||||||
variants={variants.length > 0 ? variants : undefined}
|
|
||||||
quantity={quantityVariant}
|
|
||||||
ribbon={meta.ribbon}
|
|
||||||
inventoryStatus={meta.inventoryStatus}
|
|
||||||
inventoryQuantity={meta.inventoryQuantity}
|
|
||||||
sku={meta.sku}
|
|
||||||
buttons={[
|
|
||||||
{ text: "Add To Cart", onClick: handleAddToCart },
|
|
||||||
{ text: "Buy Now", onClick: handleBuyNow },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="product-cart" data-section="product-cart">
|
|
||||||
<ProductCart
|
|
||||||
isOpen={cartOpen}
|
|
||||||
onClose={() => setCartOpen(false)}
|
|
||||||
items={cartItems}
|
|
||||||
onQuantityChange={updateQuantity}
|
|
||||||
onRemove={removeItem}
|
|
||||||
total={`$${cartTotal}`}
|
|
||||||
buttons={[
|
|
||||||
{
|
|
||||||
text: isCheckoutLoading ? "Processing..." : "Check Out", onClick: handleCheckout,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div id="footer" data-section="footer">
|
|
||||||
<FooterBaseCard
|
|
||||||
logoText="Biorogo"
|
|
||||||
columns={[
|
|
||||||
{ title: "Shop", items: [{ label: "All Cups", href: "/#products" }, { label: "Ceramic", href: "/#products" }, { label: "Glassware", href: "/#products" }, { label: "Travel Mugs", href: "/#products" }] },
|
|
||||||
{ title: "Company", items: [{ label: "About Us", href: "/#features" }, { label: "Testimonials", href: "/#testimonials" }, { label: "FAQ", href: "/#faq" }] },
|
|
||||||
{ title: "Support", items: [{ label: "Contact Us", href: "/#contact" }, { label: "Shipping", href: "/shipping" }, { label: "Returns", href: "/returns" }, { label: "Sitemap", href: "/sitemap" }] }
|
|
||||||
]}
|
|
||||||
copyrightText="© 2024 Biorogo. All rights reserved."
|
|
||||||
onPrivacyClick={() => console.log('Privacy policy clicked')}
|
|
||||||
ariaLabel="Site footer for Biorogo"
|
|
||||||
className="py-16 md:py-20"
|
|
||||||
cardClassName="bg-card rounded-t-3xl shadow-lg border-t border-l border-r border-accent/20"
|
|
||||||
logoTextClassName="text-foreground text-3xl font-extrabold"
|
|
||||||
columnTitleClassName="text-foreground text-lg font-semibold"
|
|
||||||
columnItemClassName="text-foreground/80 hover:text-primary-cta"
|
|
||||||
copyrightTextClassName="text-foreground/60 text-sm"
|
|
||||||
privacyButtonClassName="text-foreground/60 text-sm hover:text-primary-cta"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</ReactLenis>
|
|
||||||
</ThemeProvider>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function ShopPage() {
|
|||||||
<div id="navbar" data-section="navbar">
|
<div id="navbar" data-section="navbar">
|
||||||
<NavbarLayoutFloatingInline
|
<NavbarLayoutFloatingInline
|
||||||
navItems={[
|
navItems={[
|
||||||
{ name: "Home", id: "/" },
|
{ name: "Features", id: "/#features" }, { name: "Products", id: "/#products" }, { name: "Testimonials", id: "/#testimonials" }, { name: "FAQ", id: "/#faq" }, { name: "Contact", id: "/#contact" }
|
||||||
]}
|
]}
|
||||||
brandName="Biorogo"
|
brandName="Biorogo"
|
||||||
button={{ text: "Cart", onClick: () => {} }}
|
button={{ text: "Cart", onClick: () => {} }}
|
||||||
@@ -91,7 +91,7 @@ export default function ShopPage() {
|
|||||||
<div id="navbar" data-section="navbar">
|
<div id="navbar" data-section="navbar">
|
||||||
<NavbarLayoutFloatingInline
|
<NavbarLayoutFloatingInline
|
||||||
navItems={[
|
navItems={[
|
||||||
{ name: "Home", id: "/" },
|
{ name: "Features", id: "/#features" }, { name: "Products", id: "/#products" }, { name: "Testimonials", id: "/#testimonials" }, { name: "FAQ", id: "/#faq" }, { name: "Contact", id: "/#contact" }
|
||||||
]}
|
]}
|
||||||
brandName="Biorogo"
|
brandName="Biorogo"
|
||||||
button={{ text: "Cart", onClick: () => {} }}
|
button={{ text: "Cart", onClick: () => {} }}
|
||||||
|
|||||||
Reference in New Issue
Block a user