sidecart, toasts for add to cart
This commit is contained in:
parent
befb0c7fdb
commit
68eee09cf3
12 changed files with 295 additions and 108 deletions
5
bun.lock
5
bun.lock
|
@ -5,6 +5,7 @@
|
|||
"name": "medusa-sv",
|
||||
"dependencies": {
|
||||
"daisyui": "^5.0.43",
|
||||
"svelte-french-toast": "^1.2.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^6.0.0",
|
||||
|
@ -294,6 +295,10 @@
|
|||
|
||||
"svelte-check": ["svelte-check@4.2.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "chokidar": "^4.0.1", "fdir": "^6.2.0", "picocolors": "^1.0.0", "sade": "^1.7.4" }, "peerDependencies": { "svelte": "^4.0.0 || ^5.0.0-next.0", "typescript": ">=5.0.0" }, "bin": { "svelte-check": "bin/svelte-check" } }, "sha512-e49SU1RStvQhoipkQ/aonDhHnG3qxHSBtNfBRb9pxVXoa+N7qybAo32KgA9wEb2PCYFNaDg7bZCdhLD1vHpdYA=="],
|
||||
|
||||
"svelte-french-toast": ["svelte-french-toast@1.2.0", "", { "dependencies": { "svelte-writable-derived": "^3.1.0" }, "peerDependencies": { "svelte": "^3.57.0 || ^4.0.0" } }, "sha512-5PW+6RFX3xQPbR44CngYAP1Sd9oCq9P2FOox4FZffzJuZI2mHOB7q5gJBVnOiLF5y3moVGZ7u2bYt7+yPAgcEQ=="],
|
||||
|
||||
"svelte-writable-derived": ["svelte-writable-derived@3.1.1", "", { "peerDependencies": { "svelte": "^3.2.1 || ^4.0.0-next.1 || ^5.0.0-next.94" } }, "sha512-w4LR6/bYZEuCs7SGr+M54oipk/UQKtiMadyOhW0PTwAtJ/Ai12QS77sLngEcfBx2q4H8ZBQucc9ktSA5sUGZWw=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.8", "", {}, "sha512-kjeW8gjdxasbmFKpVGrGd5T4i40mV5J2Rasw48QARfYeQ8YS9x02ON9SFWax3Qf616rt4Cp3nVNIj6Hd1mP3og=="],
|
||||
|
||||
"tapable": ["tapable@2.2.2", "", {}, "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg=="],
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
"vite": "^6.2.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"daisyui": "^5.0.43"
|
||||
"daisyui": "^5.0.43",
|
||||
"svelte-french-toast": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
</script>
|
||||
|
||||
<header class="absolute left-0 right-0 mx-auto w-[calc(100%-1rem)] md:w-[80%] md:left-1/2 md:-translate-x-1/2 z-50 h-auto mt-2 rounded-lg">
|
||||
<nav class="navbar bg-transparent px-4 md:px-8 lg:px-12 h-full relative">
|
||||
<div class="navbar bg-transparent px-4 md:px-8 lg:px-12 h-full relative">
|
||||
<!-- Logo -->
|
||||
<div class="flex-1 relative">
|
||||
<a href="/" class="text-2xl font-display text-white hover:opacity-80 transition-opacity">
|
||||
<div class="flex-1">
|
||||
<a href="/" class="inline-block text-2xl font-display text-white hover:opacity-80 transition-opacity">
|
||||
<img src="/logo.png" alt="Standard Marine GCC" class="h-16 w-auto filter brightness-0 invert" />
|
||||
</a>
|
||||
</div>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<!-- Navigation -->
|
||||
<div class="flex-none">
|
||||
<ul class="menu menu-horizontal px-1 text-white font-body text-lg">
|
||||
<li>
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/products"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
|
@ -23,7 +23,7 @@
|
|||
Products
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/services"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
|
@ -32,7 +32,7 @@
|
|||
Services
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/contact"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
|
@ -43,7 +43,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<!-- Glass effect background -->
|
||||
<div class="absolute rounded-lg inset-0 bg-black/30 backdrop-blur-sm -z-10"></div>
|
||||
|
|
143
src/lib/components/HeaderCommerce.svelte
Normal file
143
src/lib/components/HeaderCommerce.svelte
Normal file
|
@ -0,0 +1,143 @@
|
|||
<script>
|
||||
import { page } from '$app/stores';
|
||||
import { cart } from '$lib/stores/cart';
|
||||
import { fly } from 'svelte/transition';
|
||||
|
||||
let isMobileMenuOpen = false;
|
||||
|
||||
function toggleMobileMenu() {
|
||||
isMobileMenuOpen = !isMobileMenuOpen;
|
||||
}
|
||||
</script>
|
||||
|
||||
<header class="absolute left-0 right-0 top-0 mx-auto w-[calc(100%-1rem)] md:w-[80%] md:left-1/2 md:-translate-x-1/2 z-50 h-auto mt-2 rounded-lg">
|
||||
<div class="navbar bg-transparent px-4 md:px-8 lg:px-12 h-full relative">
|
||||
<!-- Logo -->
|
||||
<div class="flex-1">
|
||||
<a href="/" class="inline-block text-2xl font-display text-white hover:opacity-80 transition-opacity">
|
||||
<img src="/logo.png" alt="Standard Marine GCC" class="h-16 w-auto filter brightness-0 invert" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu Button -->
|
||||
<button
|
||||
class="btn btn-ghost btn-circle text-white md:hidden mr-2"
|
||||
on:click={toggleMobileMenu}
|
||||
aria-label="Menu"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Cart Icon (Always Visible) -->
|
||||
<button
|
||||
class="btn btn-ghost btn-circle text-white"
|
||||
on:click={() => cart.toggleCart()}
|
||||
aria-label="Shopping cart"
|
||||
>
|
||||
<div class="indicator">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
{#if $cart.length > 0}
|
||||
<span class="badge badge-sm indicator-item">
|
||||
{$cart.reduce((sum, item) => sum + item.quantity, 0)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Desktop Navigation -->
|
||||
<div class="hidden md:flex">
|
||||
<ul class="menu menu-horizontal px-1 text-white font-body text-lg items-center">
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/products"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
class:active={$page.url.pathname === '/products'}
|
||||
>
|
||||
Products
|
||||
</a>
|
||||
</li>
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/services"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
class:active={$page.url.pathname === '/services'}
|
||||
>
|
||||
Services
|
||||
</a>
|
||||
</li>
|
||||
<li class="relative">
|
||||
<a
|
||||
href="/contact"
|
||||
class="hover:bg-white/10 transition-colors"
|
||||
class:active={$page.url.pathname === '/contact'}
|
||||
>
|
||||
Contact Us
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
{#if isMobileMenuOpen}
|
||||
<div
|
||||
class="absolute top-full left-0 right-0 mt-2 bg-base-100 rounded-lg shadow-lg overflow-hidden"
|
||||
transition:fly={{ y: -10, duration: 200 }}
|
||||
>
|
||||
<ul class="menu menu-lg p-4 font-body">
|
||||
<li>
|
||||
<a
|
||||
href="/products"
|
||||
class="hover:bg-base-200 transition-colors"
|
||||
class:active={$page.url.pathname === '/products'}
|
||||
on:click={toggleMobileMenu}
|
||||
>
|
||||
Products
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="/services"
|
||||
class="hover:bg-base-200 transition-colors"
|
||||
class:active={$page.url.pathname === '/services'}
|
||||
on:click={toggleMobileMenu}
|
||||
>
|
||||
Services
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="/contact"
|
||||
class="hover:bg-base-200 transition-colors"
|
||||
class:active={$page.url.pathname === '/contact'}
|
||||
on:click={toggleMobileMenu}
|
||||
>
|
||||
Contact Us
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Glass effect background -->
|
||||
<div class="absolute rounded-lg inset-0 bg-black/30 backdrop-blur-sm -z-10"></div>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
.active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Glass effect on scroll */
|
||||
:global(.scrolled) header {
|
||||
background-color: rgb(var(--color-base-100) / 0.9);
|
||||
backdrop-filter: blur(8px);
|
||||
border-bottom: 1px solid rgb(var(--color-base-200) / 0.5);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
</style>
|
|
@ -2,6 +2,7 @@
|
|||
import { cart } from '$lib/stores/cart';
|
||||
import type { CartItem } from '$lib/stores/cart';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
|
||||
let isOpen: boolean;
|
||||
cart.subscribeToOpen(value => isOpen = value);
|
||||
|
@ -17,91 +18,124 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="fixed bottom-4 right-4 md:right-8 z-50">
|
||||
<button
|
||||
class="btn btn-primary btn-circle shadow-lg"
|
||||
{#if isOpen}
|
||||
<!-- Backdrop -->
|
||||
<div
|
||||
class="fixed inset-0 bg-black/50 z-40"
|
||||
on:click={() => cart.toggleCart()}
|
||||
aria-label="Shopping cart"
|
||||
>
|
||||
<div class="indicator">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
{#if $cart.length > 0}
|
||||
<span class="badge badge-secondary badge-sm indicator-item">
|
||||
{$cart.reduce((sum, item) => sum + item.quantity, 0)}
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
transition:fly={{ duration: 200, opacity: 0 }}
|
||||
></div>
|
||||
|
||||
{#if isOpen}
|
||||
<div
|
||||
class="absolute bottom-full right-0 mb-2 w-80 bg-base-100 shadow-xl rounded-box p-4 z-50 max-w-[calc(100vw-2rem)]"
|
||||
transition:fly={{ y: 10, duration: 200 }}
|
||||
>
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="font-bold text-lg">Your Cart</h3>
|
||||
<button class="btn btn-sm btn-ghost" on:click={() => cart.toggleCart()}>×</button>
|
||||
</div>
|
||||
|
||||
<!-- Side Cart -->
|
||||
<div
|
||||
class="fixed top-0 right-0 h-full w-full max-w-md bg-base-100 shadow-xl z-50 flex flex-col"
|
||||
transition:fly={{ x: 400, duration: 300, easing: quintOut }}
|
||||
>
|
||||
<div class="flex justify-between items-center p-4 border-b">
|
||||
<h3 class="font-bold text-lg">Your Cart</h3>
|
||||
<button
|
||||
class="btn btn-ghost btn-sm"
|
||||
on:click={() => cart.toggleCart()}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-y-auto p-4">
|
||||
{#if $cart.length === 0}
|
||||
<p class="text-center py-4">Your cart is empty</p>
|
||||
<div class="h-full flex flex-col items-center justify-center text-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 text-base-300 mb-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" />
|
||||
</svg>
|
||||
<p class="text-lg mb-2">Your cart is empty</p>
|
||||
<p class="text-base-content/70 mb-4">Add some items to get started</p>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
on:click={() => cart.toggleCart()}
|
||||
>
|
||||
Continue Shopping
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="space-y-4 max-h-[60vh] overflow-y-auto">
|
||||
<div class="space-y-4">
|
||||
{#each $cart as item, i}
|
||||
<div class="flex flex-col gap-2 pb-3 mb-3 border-b border-base-200">
|
||||
<div class="flex justify-between items-start">
|
||||
<div>
|
||||
<h3 class="font-bold">{item.product.title}</h3>
|
||||
<p class="text-sm">{item.variant.title}</p>
|
||||
</div>
|
||||
<button class="btn btn-ghost btn-sm" on:click={() => cart.removeItem(i)}>×</button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<div class="join">
|
||||
<div class="flex gap-4 pb-4 border-b">
|
||||
{#if item.product.thumbnail}
|
||||
<img
|
||||
src={item.product.thumbnail}
|
||||
alt={item.product.title}
|
||||
class="w-20 h-20 object-cover rounded-lg bg-base-200"
|
||||
/>
|
||||
{/if}
|
||||
<div class="flex-1">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<h3 class="font-medium">{item.product.title}</h3>
|
||||
<p class="text-sm text-base-content/70">{item.variant.title}</p>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-sm join-item"
|
||||
on:click={() => cart.updateQuantity(i, item.quantity - 1)}
|
||||
>-</button>
|
||||
<input
|
||||
type="text"
|
||||
class="input number input-bordered input-sm w-16 join-item text-center"
|
||||
value={item.quantity}
|
||||
on:change={(e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const value = parseInt(target.value) || 1;
|
||||
if (value >= 1) {
|
||||
cart.updateQuantity(i, value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
class="btn btn-sm join-item"
|
||||
on:click={() => cart.updateQuantity(i, item.quantity + 1)}
|
||||
>+</button>
|
||||
class="btn btn-ghost btn-sm"
|
||||
on:click={() => cart.removeItem(i)}
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-end mt-2">
|
||||
<div class="join">
|
||||
<button
|
||||
class="btn btn-sm join-item"
|
||||
on:click={() => cart.updateQuantity(i, item.quantity - 1)}
|
||||
>-</button>
|
||||
<input
|
||||
type="text"
|
||||
class="input input-bordered input-sm w-14 join-item text-center"
|
||||
value={item.quantity}
|
||||
on:change={(e) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
const value = parseInt(target.value) || 1;
|
||||
if (value >= 1) {
|
||||
cart.updateQuantity(i, value);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
class="btn btn-sm join-item"
|
||||
on:click={() => cart.updateQuantity(i, item.quantity + 1)}
|
||||
>+</button>
|
||||
</div>
|
||||
<p class="font-medium">{calculateItemTotal(item)} €</p>
|
||||
</div>
|
||||
<p class="font-bold">{calculateItemTotal(item)} €</p>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
|
||||
<div class="flex justify-between font-bold pt-2">
|
||||
<span>Total:</span>
|
||||
<span>{calculateTotal($cart)} €</span>
|
||||
</div>
|
||||
|
||||
<div class="pt-4">
|
||||
<a href="/checkout" class="btn btn-primary w-full">
|
||||
Proceed to Checkout
|
||||
</a>
|
||||
<button class="btn btn-ghost btn-sm w-full mt-2" on:click={() => cart.toggleCart()}>
|
||||
Continue Shopping
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if $cart.length > 0}
|
||||
<div class="border-t p-4 space-y-4">
|
||||
<div class="flex justify-between items-center">
|
||||
<span class="text-lg font-bold">Total:</span>
|
||||
<span class="text-lg font-bold">{calculateTotal($cart)} €</span>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<a href="/checkout" class="btn btn-primary w-full">
|
||||
Proceed to Checkout
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-ghost btn-sm w-full"
|
||||
on:click={() => cart.toggleCart()}
|
||||
>
|
||||
Continue Shopping
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
|
@ -1,5 +1,6 @@
|
|||
import { writable } from 'svelte/store';
|
||||
import type { MedusaProduct, MedusaVariant } from '$lib/types/medusa';
|
||||
import toast from 'svelte-french-toast';
|
||||
|
||||
export interface CartItem {
|
||||
product: MedusaProduct;
|
||||
|
@ -10,7 +11,6 @@ export interface CartItem {
|
|||
function createCartStore() {
|
||||
const { subscribe, set, update } = writable<CartItem[]>([]);
|
||||
const isOpenStore = writable<boolean>(false);
|
||||
let autoCloseTimeout: number | undefined;
|
||||
|
||||
// Load initial state from localStorage
|
||||
if (typeof window !== 'undefined') {
|
||||
|
@ -20,15 +20,21 @@ function createCartStore() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function showAddToCartToast(product: MedusaProduct, variant: MedusaVariant) {
|
||||
toast(`${product.title} ${variant.title} added to cart`, {
|
||||
icon: '🛍️',
|
||||
duration: 2000,
|
||||
position: 'bottom-center',
|
||||
style: 'background-color: #000; color: #fff;',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
subscribeToOpen: isOpenStore.subscribe,
|
||||
toggleCart: () => {
|
||||
// Clear any existing auto-close timeout
|
||||
if (autoCloseTimeout) {
|
||||
clearTimeout(autoCloseTimeout);
|
||||
autoCloseTimeout = undefined;
|
||||
}
|
||||
isOpenStore.update(state => !state);
|
||||
},
|
||||
addToCart: (product: MedusaProduct, variant: MedusaVariant) => {
|
||||
|
@ -46,20 +52,9 @@ function createCartStore() {
|
|||
localStorage.setItem('cart', JSON.stringify(newItems));
|
||||
return newItems;
|
||||
});
|
||||
|
||||
// Clear any existing timeout
|
||||
if (autoCloseTimeout) {
|
||||
clearTimeout(autoCloseTimeout);
|
||||
}
|
||||
|
||||
// Open cart
|
||||
isOpenStore.set(true);
|
||||
|
||||
// Auto close after 2 seconds
|
||||
autoCloseTimeout = window.setTimeout(() => {
|
||||
isOpenStore.set(false);
|
||||
autoCloseTimeout = undefined;
|
||||
}, 800);
|
||||
|
||||
// Show toast notification instead of opening cart
|
||||
showAddToCartToast(product, variant);
|
||||
},
|
||||
updateQuantity: (index: number, quantity: number) => {
|
||||
update(items => {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import Header from '$lib/components/Header.svelte';
|
||||
import Footer from '$lib/components/Footer.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { Toaster } from 'svelte-french-toast';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
@ -19,6 +20,8 @@
|
|||
<Footer />
|
||||
</div>
|
||||
|
||||
<Toaster />
|
||||
|
||||
<style>
|
||||
:global(h1, h2, h3, h4, h5, h6) {
|
||||
font-family: 'Playfair Display', serif;
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
import Hero from '$lib/components/Hero.svelte'
|
||||
import Content from '$lib/components/Content.svelte'
|
||||
import Contact from '$lib/components/Contact.svelte'
|
||||
import Header from '$lib/components/Header.svelte'
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Header />
|
||||
<Hero />
|
||||
<Content />
|
||||
<Contact />
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<script lang="ts">
|
||||
import Checkout from '$lib/components/checkout.svelte';
|
||||
|
||||
import HeaderCommerce from '$lib/components/HeaderCommerce.svelte';
|
||||
</script>
|
||||
|
||||
<HeaderCommerce />
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<Checkout />
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
<script lang="ts">
|
||||
import MiniCart from '$lib/components/mini-cart.svelte';
|
||||
import HeaderCommerce from '$lib/components/HeaderCommerce.svelte';
|
||||
</script>
|
||||
|
||||
<div class="min-h-screen bg-base-100">
|
||||
<slot />
|
||||
|
||||
<!-- Mini Cart - only shows on products pages -->
|
||||
<HeaderCommerce />
|
||||
<div class="pt-16">
|
||||
<slot />
|
||||
</div>
|
||||
<MiniCart />
|
||||
</div>
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import Products from '$lib/components/products.svelte';
|
||||
import type { MedusaProduct } from '$lib/types/medusa';
|
||||
import Header from '$lib/components/HeaderCommerce.svelte';
|
||||
|
||||
export let data: { products: MedusaProduct[] }
|
||||
</script>
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
export let data: MedusaResponse;
|
||||
</script>
|
||||
|
||||
<div class="container mx-auto px-4 py-8">
|
||||
<div class="container mx-auto px-4 sm:px-10">
|
||||
<SingleProduct product={data.product} />
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue