diff --git a/bun.lock b/bun.lock index 7fe1621..ea094bb 100644 --- a/bun.lock +++ b/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=="], diff --git a/package.json b/package.json index bae0279..00a8654 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "vite": "^6.2.6" }, "dependencies": { - "daisyui": "^5.0.43" + "daisyui": "^5.0.43", + "svelte-french-toast": "^1.2.0" } } diff --git a/src/lib/components/Header.svelte b/src/lib/components/Header.svelte index b7c483b..eba18ba 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -3,10 +3,10 @@
- +
diff --git a/src/lib/components/HeaderCommerce.svelte b/src/lib/components/HeaderCommerce.svelte new file mode 100644 index 0000000..7dd1826 --- /dev/null +++ b/src/lib/components/HeaderCommerce.svelte @@ -0,0 +1,143 @@ + + +
+ + + + {#if isMobileMenuOpen} + + {/if} + + +
+
+ + \ No newline at end of file diff --git a/src/lib/components/mini-cart.svelte b/src/lib/components/mini-cart.svelte index 0d723ab..eff8837 100644 --- a/src/lib/components/mini-cart.svelte +++ b/src/lib/components/mini-cart.svelte @@ -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 @@ } -
- + transition:fly={{ duration: 200, opacity: 0 }} + >
- {#if isOpen} -
-
-

Your Cart

- -
- + +
+
+

Your Cart

+ +
+ +
{#if $cart.length === 0} -

Your cart is empty

+
+ + + +

Your cart is empty

+

Add some items to get started

+ +
{:else} -
+
{#each $cart as item, i} -
-
-
-

{item.product.title}

-

{item.variant.title}

-
- -
- -
-
+
+ {#if item.product.thumbnail} + {item.product.title} + {/if} +
+
+
+

{item.product.title}

+

{item.variant.title}

+
- { - const target = e.target as HTMLInputElement; - const value = parseInt(target.value) || 1; - if (value >= 1) { - cart.updateQuantity(i, value); - } - }} - /> - + class="btn btn-ghost btn-sm" + on:click={() => cart.removeItem(i)} + > + + + + +
+ +
+
+ + { + const target = e.target as HTMLInputElement; + const value = parseInt(target.value) || 1; + if (value >= 1) { + cart.updateQuantity(i, value); + } + }} + /> + +
+

{calculateItemTotal(item)} €

-

{calculateItemTotal(item)} €

{/each} - -
- Total: - {calculateTotal($cart)} € -
- -
- - Proceed to Checkout - - -
{/if}
- {/if} -
\ No newline at end of file + + {#if $cart.length > 0} +
+
+ Total: + {calculateTotal($cart)} € +
+ +
+ + Proceed to Checkout + + +
+
+ {/if} +
+{/if} \ No newline at end of file diff --git a/src/lib/stores/cart.ts b/src/lib/stores/cart.ts index 6af66d0..d77eb68 100644 --- a/src/lib/stores/cart.ts +++ b/src/lib/stores/cart.ts @@ -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([]); const isOpenStore = writable(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 => { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index bb09c30..20de0c8 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -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'; @@ -19,6 +20,8 @@
+ +