266 lines
7.7 KiB
Svelte
266 lines
7.7 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 PosterLayout from '$components/layouts/PosterLayout.svelte'
|
||
import SiteTitle from '$components/atoms/SiteTitle.svelte'
|
||
import Image from '$components/atoms/Image.svelte'
|
||
import ButtonCart from '$components/atoms/ButtonCart.svelte'
|
||
import Poster from '$components/molecules/Poster.svelte'
|
||
import NotificationCart from '$components/molecules/NotificationCart.svelte'
|
||
import EmailForm from '$components/molecules/EmailForm.svelte'
|
||
import ShopLocationSwitcher from '$components/molecules/ShopLocationSwitcher.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 shopProduct: any
|
||
export let shopProducts: any
|
||
|
||
let introEl: HTMLElement
|
||
let navObserver: IntersectionObserver
|
||
let scrolledPastIntro = false
|
||
|
||
|
||
// Locations with an existing poster product
|
||
$shopLocations = locations.filter(({ slug }: any) => {
|
||
if (posters.find((poster: any) => poster.location.slug === slug)) {
|
||
return true
|
||
}
|
||
})
|
||
|
||
|
||
onMount(async () => {
|
||
// Reveal the nav past the Intro
|
||
navObserver = new IntersectionObserver(entries => {
|
||
entries.forEach(entry => {
|
||
scrolledPastIntro = !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}>
|
||
<div class="top container">
|
||
<a href="/" class="back">
|
||
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||
<path d="M4 1 1 4l3 3" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/>
|
||
</svg>
|
||
<span>Back to site</span>
|
||
</a>
|
||
|
||
<span class="shop-title">Shop</span>
|
||
</div>
|
||
|
||
<SiteTitle
|
||
variant="inline"
|
||
/>
|
||
|
||
<nav class="shop-page__nav">
|
||
<div class="container">
|
||
<p class="text-label">Shop your city</p>
|
||
<nav>
|
||
<ul>
|
||
{#each $shopLocations as { name, slug }}
|
||
<li class:is-active={slug === product.location.slug}>
|
||
<a href="/shop/poster-{slug}" sveltekit:noscroll sveltekit:prefetch>
|
||
{name}
|
||
</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</nav>
|
||
|
||
<ButtonCart />
|
||
</div>
|
||
</nav>
|
||
|
||
<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"
|
||
class:is-visible={scrolledPastIntro}
|
||
class:is-overlaid={$cartOpen}
|
||
>
|
||
<ShopLocationSwitcher />
|
||
<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">
|
||
<div class="description grid text-normal">
|
||
<div class="description__inner">
|
||
{@html shop.about}
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<PosterLayout
|
||
product={product}
|
||
shopProduct={shopProduct}
|
||
/>
|
||
|
||
{#if posters}
|
||
<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}
|
||
product={shopProducts.find(item => item.slug.includes(location.slug))}
|
||
/>
|
||
{/each}
|
||
</div>
|
||
<div class="subscribe">
|
||
<p>Subscribe to be notified when new posters become available</p>
|
||
<EmailForm />
|
||
</div>
|
||
</section>
|
||
{/if}
|
||
</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 }) {
|
||
// 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 products data from Swell
|
||
*/
|
||
let shopProducts: any
|
||
let shopProduct: any
|
||
|
||
const shopProductRes = await fetch('/api/swell', {
|
||
method: 'POST',
|
||
body: JSON.stringify({
|
||
action: 'getProducts',
|
||
category: 'posters',
|
||
})
|
||
})
|
||
if (shopProductRes.ok) {
|
||
// Set all products
|
||
const { results } = await shopProductRes.json()
|
||
if (results) {
|
||
shopProducts = results
|
||
}
|
||
|
||
// Define current product
|
||
const product = results.find((result: any) => result.slug.includes(page.params.name))
|
||
if (product) {
|
||
shopProduct = product
|
||
}
|
||
}
|
||
|
||
|
||
return {
|
||
props: {
|
||
shop: data.shop,
|
||
locations: data.location,
|
||
posters: data.posters,
|
||
product: productAPI,
|
||
shopProducts,
|
||
shopProduct,
|
||
}
|
||
}
|
||
}
|
||
</script>
|