Files
housesof/src/routes/shop/__layout.svelte

266 lines
7.7 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>