[wip] Rework Shop

- Change strategy for content fetching
- Add a route per page instead of using __layout for all
- Change the behaviors of the posters section (add a carousel on small screens)
- Change Poster buttons styling and make interactions only for desktop
This commit is contained in:
2021-12-14 23:23:12 +01:00
parent 140e8f1fa2
commit 82f5dd4727
17 changed files with 808 additions and 364 deletions

View File

@@ -9,7 +9,7 @@
onMount(async () => {
// Disable when changing filters on /photos and shop?
if (!$page.query.get('country') && !$page.path.includes('/shop/poster')) {
if (!$page.query.get('country') && !$page.path.includes('/shop')) {
await tick()
setTimeout(() => {
// Scroll back to top between page transitions

View File

@@ -3,8 +3,10 @@
import { addToCart } from '$utils/functions/shop'
import { capitalizeFirstLetter } from '$utils/functions'
// Components
import SplitText from '$components/SplitText.svelte'
import Button from '$components/atoms/Button.svelte'
import Image from '$components/atoms/Image.svelte'
import ScrollingTitle from '$components/atoms/ScrollingTitle.svelte'
import Carousel from '$components/organisms/Carousel.svelte'
export let product: any
@@ -60,9 +62,11 @@
</script>
<section class="poster-layout grid" id="poster">
<h2 class="title-huge">
{product.location.name}
</h2>
<div class="poster-layout__title">
<ScrollingTitle tag="h2" label={product.location.name}>
<SplitText mode="chars" text={product.location.name} />
</ScrollingTitle>
</div>
<aside class="poster-layout__buy">
<div class="poster-layout__info">

View File

@@ -33,11 +33,11 @@
text="View"
/>
<Button
type="button"
text="Add to cart"
color="pinklight"
tag="button"
size="xsmall"
on:click={() => addToCart($cartId, product)}
text="Add to cart"
color="pink"
/>
</div>
</div>

View File

@@ -1,10 +1,12 @@
<script lang="ts">
import { page } from '$app/stores'
import { goto } from '$app/navigation'
import { shopLocations } from '$utils/stores/shop'
import { getContext } from 'svelte'
export let isOver: boolean = false
const { shopLocations } = getContext('shop')
const classes = [
'shop-locationswitcher',
isOver && 'is-over',
@@ -26,7 +28,7 @@
<use xlink:href="#icon-map-pin" />
</svg>
<select on:change={quickLocationChange}>
{#each $shopLocations as { name, slug }}
{#each shopLocations as { name, slug }}
<option value={slug} selected={slug === $page.params.name}>{name}</option>
{/each}
</select>

View File

@@ -0,0 +1,115 @@
<script lang="ts">
import { getContext, onMount } from 'svelte'
import EmblaCarousel, { EmblaCarouselType } from 'embla-carousel'
// Components
import Poster from '$components/molecules/Poster.svelte'
import EmailForm from '$components/molecules/EmailForm.svelte'
import { debounce } from '$utils/functions'
export let posters: any = []
let innerWidth: number
let carouselEl: HTMLElement
let carousel: EmblaCarouselType
let currentSlide = 0
let carouselDots = []
const { shopProducts } = getContext('shop')
/** Navigate to specific slide */
const goToSlide = (index: number = 0) => {
carousel.scrollTo(index)
}
/** Init Carousel */
const initCarousel = () => {
if (innerWidth < 992) {
if (!carousel) {
carousel = EmblaCarousel(carouselEl, {
slidesToScroll: innerWidth < 550 ? 1 : 2,
})
// On init
carousel.on('init', () => {
// Define amounts of dots
carouselDots = carousel.scrollSnapList()
})
// On slide change
carousel.on('select', () => {
// Define current slide
currentSlide = carousel.selectedScrollSnap()
})
// On resize
carousel.on('resize', () => {
// Redefine options
carousel.reInit({
slidesToScroll: innerWidth < 550 ? 1 : 2
})
// Define amounts of dots
carouselDots = carousel.scrollSnapList()
// Define current slide
currentSlide = carousel.selectedScrollSnap()
})
}
} else {
if (carousel) {
carousel.destroy()
carousel = undefined
}
}
}
/** Destroy carousel for larger screens */
const handleResize = debounce(initCarousel, 200)
onMount(() => {
initCarousel()
// Destroy
return () => {
if (carousel) {
carousel.destroy()
}
}
})
</script>
<svelte:window
bind:innerWidth
on:resize={handleResize}
/>
{#if posters}
<section class="shop-page__posters grid">
<h3>View all of our available posters</h3>
<div class="set" bind:this={carouselEl}>
<div class="set__content">
{#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>
{#if carousel}
<ul class="set__dots">
{#each carouselDots as _, index}
<li class:is-active={index === currentSlide}>
<button on:click={() => goToSlide(index)} aria-label="Go to slide #{index + 1}" />
</li>
{/each}
</ul>
{/if}
</div>
<div class="subscribe">
<label class="subscribe__text" for="SUB_EMAIL">Subscribe to be notified when new posters become available</label>
<EmailForm />
</div>
</section>
{/if}