Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,191 changes: 2,191 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
"format": "prettier --write ."
},
"devDependencies": {
"@sveltejs/adapter-vercel": "^5.6.1",
"@sveltejs/kit": "2.17.1",
"@sveltejs/vite-plugin-svelte": "5.0.3",
"@tailwindcss/postcss": "^4.0.0",
Expand All @@ -24,5 +23,8 @@
"tailwindcss": "^4.0.0",
"vite": "^6.1.0"
},
"packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a"
"packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a",
"dependencies": {
"@sveltejs/adapter-auto": "^7.0.1"
}
}
13 changes: 7 additions & 6 deletions src/components/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
import Icons from '$components/Icons.svelte';
import { cartQuantity } from '../store';
import SearchBar from '$components/SearchBar.svelte';

let currentRoute = $derived($page.url.pathname);
let currentRoute = $derived(page.url.pathname);

let showMenu = $state(false);

/**
* @type {{ openCart: () => void }}
*/
let {openCart} = $props();
let { openCart } = $props();

let tabs = [
{ name: 'All', path: '/search' },
Expand All @@ -20,9 +20,8 @@
];
function onOpenCart() {
showMenu = false;
openCart()
openCart();
}

</script>

<nav class="flex items-center border-b border-zinc-700 p-4 lg:px-6">
Expand Down Expand Up @@ -93,7 +92,9 @@
<div class="flex w-full items-center justify-between">
<button
aria-label="Close menu"
onclick={closeCart}
onclick={() => {
showMenu = false;
}}
class="cursor-pointer"
>
<Icons strokeColor="#fff" type="close" />
Expand Down
12 changes: 6 additions & 6 deletions src/components/SearchBar.svelte
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
import { goto } from '$app/navigation';
import Icons from './Icons.svelte';

let value = $page.url.searchParams.get('q') || '';
let value = $state(page.url.searchParams.get('q') || '');

async function submit(e) {
e.preventDefault();
let query = new URLSearchParams();
async function submit(event) {
event.preventDefault();
const query = new URLSearchParams();
if (value) {
query.set('q', value);
}
await goto(`/search${query.toString() ? `?${query}` : ''}`, { keepFocus: true });
}
</script>

<form on:submit={submit} class="relative flex w-full items-center">
<form onsubmit={submit} class="relative flex w-full items-center">
<div class="absolute top-0 right-0 mr-2">
<Icons strokeColor="#fff" type="search" />
</div>
Expand Down
6 changes: 5 additions & 1 deletion src/components/ShoppingCart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
onClose();
}

function onOverlayClick(event) {
if (event.target === event.currentTarget) closeCart();
}

function handleKeyDown(event) {
if (event.key === 'Escape') {
closeCart();
Expand All @@ -60,7 +64,7 @@

<div
class="absolute inset-0 z-50 flex max-h-screen w-full justify-end overflow-hidden bg-black/50"
onclick={closeCart}
onclick={onOverlayClick}
onkeydown={handleKeyDown}
role="dialog"
aria-label="Shopping Cart"
Expand Down
95 changes: 39 additions & 56 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import Footer from '$components/Footer.svelte';
import ShoppingCart from '$components/ShoppingCart.svelte';
import { getCartItems } from '../store';
import { onMount } from 'svelte';
import { createCart } from '$utils/shopify';
/** @type {{children?: import('svelte').Snippet}} */
let { children } = $props();
Expand All @@ -16,27 +15,33 @@
let showCart = $state(false);
let loading = $state(false);

onMount(async () => {
if (typeof window !== 'undefined') {
$effect(() => {
if (typeof window === 'undefined') return;

void (async () => {
cartId = JSON.parse(localStorage.getItem('cartId'));
cartCreatedAt = JSON.parse(localStorage.getItem('cartCreatedAt'));
checkoutUrl = JSON.parse(localStorage.getItem('cartUrl'));

let currentDate = Date.now();
let difference = currentDate - cartCreatedAt;
let totalDays = Math.ceil(difference / (1000 * 3600 * 24));
let cartIdExpired = totalDays > 6;
const currentDate = Date.now();
const difference = currentDate - cartCreatedAt;
const totalDays = Math.ceil(difference / (1000 * 3600 * 24));
const cartIdExpired = totalDays > 6;

if (cartId === 'undefined' || cartId === 'null' || cartIdExpired) {
await callCreateCart();
}
await loadCart();
document.addEventListener('keydown', (e) => {
let keyCode = e.keyCode;
if (keyCode === 27) {
showCart = false;
}
});
}
})();

const onKeyDown = (event) => {
if (event.key === 'Escape') showCart = false;
};
document.addEventListener('keydown', onKeyDown);

return () => {
document.removeEventListener('keydown', onKeyDown);
};
});

async function callCreateCart() {
Expand Down Expand Up @@ -70,57 +75,35 @@
loading = false;
}

async function addToCart(event) {
await fetch('/cart.json', {
method: 'PATCH',
body: JSON.stringify({ cartId: cartId, variantId: event.detail.body })
});
// Wait for the API to finish before updating cart items
await loadCart();
loading = false;
}
async function addToCart(variantId) {
await fetch('/cart.json', {
method: 'PATCH',
body: JSON.stringify({ cartId, variantId })
});
await loadCart();
loading = false;
}

async function removeProduct(event) {
if (typeof window !== 'undefined') {
cartId = JSON.parse(localStorage.getItem('cartId'));
}
await fetch('/cart.json', {
method: 'PUT',
body: JSON.stringify({
cartId,
lineId: event.detail.body.lineId,
quantity: event.detail.body.quantity,
variantId: event.detail.body.variantId
})
});
await loadCart();
loading = false;
async function removeProduct(variantId, quantity, lineId) {
if (typeof window !== 'undefined') {
cartId = JSON.parse(localStorage.getItem('cartId'));
}
await fetch('/cart.json', {
method: 'PUT',
body: JSON.stringify({ cartId, lineId, quantity, variantId })
});
await loadCart();
loading = false;
}
</script>

<main class={`${showCart ? 'h-screen' : 'min-h-screen'} text-white overflow-hidden`}>
{#if showCart}
<ShoppingCart
items={cartItems}
onClose={hideCart}
onRemoveProduct={(variantId, quantity, lineId) =>
removeProduct({
detail: {
body: {
variantId,
quantity,
lineId
}
}
})
}
onAddProduct={(variantId) =>
addToCart({
detail: {
body: variantId
}
})
}
onRemoveProduct={removeProduct}
onAddProduct={addToCart}
onCheckout={getCheckoutUrl}
bind:loading
/>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/product/+error.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';
</script>

<h1>{$page.status} : {$page.error.message}</h1>
<h1>{page.status} : {page.error?.message}</h1>
8 changes: 4 additions & 4 deletions src/routes/search/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
import { page } from '$app/stores';
import { page } from '$app/state';

/** @type {import('svelte').Snippet} */
const { children } = $props();
Expand All @@ -15,7 +15,7 @@
data-testid="category-link"
class="whitespace-nowrap hover:underline focus:underline"
href="/search"
aria-current={$page.url.pathname === '/search' ? 'page' : undefined}
aria-current={page.url.pathname === '/search' ? 'page' : undefined}
>All</a
>
</li>
Expand All @@ -25,7 +25,7 @@
data-testid="category-link"
class="whitespace-nowrap hover:underline focus:underline"
href="/search/featured"
aria-current={$page.url.pathname === '/search/featured' ? 'page' : undefined}
aria-current={page.url.pathname === '/search/featured' ? 'page' : undefined}
>Featured</a
>
</li>
Expand All @@ -35,7 +35,7 @@
data-testid="category-link"
class="whitespace-nowrap hover:underline focus:underline"
href="/search/clothes"
aria-current={$page.url.pathname === '/search/clothes' ? 'page' : undefined}
aria-current={page.url.pathname === '/search/clothes' ? 'page' : undefined}
>Apparel</a
>
</li>
Expand Down
4 changes: 2 additions & 2 deletions src/routes/search/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script>
import GridTile from '$components/GridTile.svelte';
import { page } from '$app/stores';
import { page } from '$app/state';


/** @type {{data: import('./$types').PageData}} */
let { data } = $props();
let search = $derived($page.url.searchParams.get('q'));
let search = $derived(page.url.searchParams.get('q'));

let displayedProducts = $derived(search
? data.body.allProducts.edges.filter((item) => {
Expand Down
4 changes: 2 additions & 2 deletions src/routes/search/[collection]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script>
import GridTile from '$components/GridTile.svelte';
import { page } from '$app/stores';
import { page } from '$app/state';

/** @type {{data: import('./$types').PageData}} */
let { data } = $props();
let collection = $derived.by(() => {
for (const d of data.body.collections) {
if (d.node.handle === $page?.params?.collection) {
if (d.node.handle === page?.params?.collection) {
return d.node;
}
}
Expand Down
6 changes: 3 additions & 3 deletions svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import adapter from '@sveltejs/adapter-vercel';
// svelte.config.js
import adapter from '@sveltejs/adapter-auto';

/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
alias: {
$components: 'src/components',
$utils: 'src/utils'
}
},
},
};

export default config;