237 lines
6.8 KiB
Svelte
237 lines
6.8 KiB
Svelte
<script lang="ts">
|
||
import { onMount } from 'svelte'
|
||
import { shopLocations, cartOpen, cartNotifications } from '$utils/stores/shop'
|
||
// Components
|
||
import Metas from '$components/Metas.svelte'
|
||
import SiteTitle from '$components/atoms/SiteTitle.svelte'
|
||
import Image from '$components/atoms/Image.svelte'
|
||
import ButtonCart from '$components/atoms/ButtonCart.svelte'
|
||
import PosterLayout from '$components/layouts/PosterLayout.svelte'
|
||
import Poster from '$components/molecules/Poster.svelte'
|
||
import NotificationCart from '$components/molecules/NotificationCart.svelte'
|
||
import EmailForm from '$components/molecules/EmailForm.svelte'
|
||
import Cart from '$components/organisms/Cart.svelte'
|
||
|
||
export let shop: any
|
||
export let locations: any
|
||
export let posters: any
|
||
export let product: any
|
||
export let productShop: any
|
||
|
||
let navEl: HTMLElement, introEl: HTMLElement
|
||
let navObserver: IntersectionObserver
|
||
|
||
|
||
onMount(async () => {
|
||
// Reveal the nav past the Intro
|
||
navObserver = new IntersectionObserver(entries => {
|
||
entries.forEach(entry => {
|
||
navEl.classList.toggle('is-visible', !entry.isIntersecting)
|
||
})
|
||
}, {
|
||
threshold: 0,
|
||
rootMargin: '0px 0px 0px'
|
||
})
|
||
navObserver.observe(introEl)
|
||
|
||
|
||
// Destroy
|
||
return () => {
|
||
navObserver && navObserver.unobserve(introEl)
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<Metas
|
||
title="Shop – Houses Of"
|
||
description=""
|
||
image=""
|
||
/>
|
||
|
||
<main class="shop-page">
|
||
<Cart />
|
||
|
||
<section class="shop-page__intro" bind:this={introEl}>
|
||
<a href="/" class="back">
|
||
Back to Houses Of
|
||
</a>
|
||
<span class="shop-title">Shop</span>
|
||
|
||
<SiteTitle
|
||
variant="inline"
|
||
/>
|
||
|
||
<header class="shop-page__header">
|
||
<div class="container">
|
||
<p class="text-label">Shop your city</p>
|
||
<nav>
|
||
<ul>
|
||
{#each locations as { name, slug }}
|
||
{#if posters.find(poster => poster.location.slug === slug )}
|
||
<li class:is-active={slug === product.location.slug}>
|
||
<a href="/shop/poster-{slug}">{name}</a>
|
||
</li>
|
||
{/if}
|
||
{/each}
|
||
</ul>
|
||
</nav>
|
||
|
||
<ButtonCart />
|
||
</div>
|
||
</header>
|
||
|
||
<Image
|
||
id={shop.page_heroimage.id}
|
||
alt="photo"
|
||
sizeKey="hero"
|
||
sizes={{
|
||
large: { width: 1800, height: 1200 },
|
||
medium: { width: 1200, height: 800 },
|
||
small: { width: 700, height: 700 },
|
||
}}
|
||
/>
|
||
</section>
|
||
|
||
<nav class="shop-location" bind:this={navEl}>
|
||
<dl class="shop-location__left">
|
||
<dt class="text-label">shop your city</dt>
|
||
<dd>
|
||
<img src="/images/icons/pin.svg" alt="">
|
||
<select name="" id="">
|
||
<option value="melbourne">Melbourne</option>
|
||
</select>
|
||
</dd>
|
||
</dl>
|
||
|
||
<ButtonCart />
|
||
|
||
<div class="shop-location__notifications">
|
||
{#each $cartNotifications as { id, title, name, image } (id)}
|
||
<NotificationCart
|
||
title={title}
|
||
name={name}
|
||
image={image}
|
||
/>
|
||
{/each}
|
||
</div>
|
||
</nav>
|
||
|
||
<section class="shop-page__about grid">
|
||
<p class="description text-normal">{shop.about}</p>
|
||
</section>
|
||
|
||
<PosterLayout
|
||
product={product}
|
||
productShop={productShop}
|
||
/>
|
||
|
||
<section class="shop-page__posters grid">
|
||
<h3>View all of our available posters</h3>
|
||
<div class="set">
|
||
{#each posters as { location, photos_product }}
|
||
<Poster
|
||
location={location}
|
||
image={photos_product.length && photos_product[1].directus_files_id}
|
||
/>
|
||
{/each}
|
||
</div>
|
||
<div class="subscribe">
|
||
<p>Subscribe to be notified when new posters become available</p>
|
||
<EmailForm />
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<slot />
|
||
|
||
|
||
<script context="module" lang="ts">
|
||
import { fetchAPI } from '$utils/api'
|
||
import { getRandomElement } from '$utils/functions'
|
||
|
||
export async function load ({ page, fetch, session, stuff }) {
|
||
// Init Swell
|
||
// swell.init(import.meta.env.VITE_SWELL_STORE_ID, import.meta.env.VITE_SWELL_API_TOKEN)
|
||
|
||
// Get content from API
|
||
const res = await fetchAPI(`
|
||
query {
|
||
shop {
|
||
about
|
||
page_heroimage { id }
|
||
}
|
||
|
||
location (
|
||
filter: { has_poster: { _eq: true }},
|
||
sort: "name"
|
||
) {
|
||
name
|
||
slug
|
||
}
|
||
|
||
posters: product {
|
||
name
|
||
type
|
||
description
|
||
details
|
||
location {
|
||
name
|
||
slug
|
||
}
|
||
product_id
|
||
photos_product {
|
||
directus_files_id {
|
||
id
|
||
title
|
||
}
|
||
}
|
||
photos_preview {
|
||
directus_files_id {
|
||
id
|
||
title
|
||
}
|
||
}
|
||
}
|
||
}
|
||
`)
|
||
|
||
const { data } = res
|
||
|
||
/**
|
||
* Define product
|
||
*/
|
||
const productAPI = (!page.params.type && !page.params.name)
|
||
// Get a random product
|
||
? data.posters[getRandomElement(data.posters)]
|
||
// Get the current product from slug
|
||
: data.posters.find(({ location }: any) => location.slug === page.params.name)
|
||
|
||
/**
|
||
* Get product data from Swell
|
||
*/
|
||
let productShopRes: any
|
||
|
||
const productShop = await fetch('/api/swell', {
|
||
method: 'POST',
|
||
body: JSON.stringify({
|
||
action: 'getProduct',
|
||
productId: productAPI.product_id,
|
||
})
|
||
})
|
||
if (productShop) {
|
||
productShopRes = await productShop.json()
|
||
}
|
||
|
||
|
||
return {
|
||
props: {
|
||
shop: data.shop,
|
||
locations: data.location,
|
||
posters: data.posters,
|
||
product: productAPI,
|
||
productShop: productShopRes,
|
||
}
|
||
}
|
||
}
|
||
</script>
|