Add data to Shop page

This commit is contained in:
2021-10-31 19:38:08 +01:00
parent 2c0adcc4e2
commit 99fe09c4fd
9 changed files with 241 additions and 128 deletions

View File

@@ -0,0 +1,116 @@
<script lang="ts">
import { capitalizeFirstLetter } from '$utils/functions'
// Components
import Button from '$components/atoms/Button.svelte'
import Image from '$components/atoms/Image.svelte'
import Carousel from '$components/organisms/Carousel.svelte'
export let product: any
/**
* Preview photos specs
*/
let lastPreviewPhoto: any = undefined
$: if (product.photos_preview.length) {
lastPreviewPhoto = product.photos_preview[product.photos_preview.length - 1].directus_files_id
}
const photosPreview = [
{
sizes: {
small: { width: 275 },
medium: { width: 500 },
large: { width: 800 },
},
ratio: 0.75,
},
{
sizes: {
small: { width: 200 },
medium: { width: 300 },
large: { width: 400 },
},
ratio: 0.8,
},
{
sizes: {
small: { width: 200 },
medium: { width: 300 },
large: { width: 400 },
},
ratio: 1.28,
},
{
sizes: {
small: { width: 450 },
medium: { width: 700 },
large: { width: 1000 },
},
ratio: 0.68,
},
]
</script>
<section class="poster-layout grid">
<h2 class="title-huge">
{product.location.name}
</h2>
<aside class="poster-layout__buy">
<div class="poster-layout__info">
<dl>
<dt>{capitalizeFirstLetter(product.type)}</dt>
<dd>{product.name} 30€</dd>
</dl>
<Button
text="Add to cart"
color="pink"
/>
</div>
<Carousel
class="shadow-box-dark"
slides={product.photos_product.map(({ directus_files_id }) => ({
id: directus_files_id.id,
alt: directus_files_id.title,
}))}
/>
</aside>
{#if product.photos_preview.length}
<div class="poster-layout__images grid container">
{#each product.photos_preview.slice(0, product.photos_preview.length - 1) as { directus_files_id}, index}
<Image
class="image image--{index + 1} photo shadow-box-light"
id={directus_files_id.id}
sizeKey="photo-list"
sizes={photosPreview[index].sizes}
ratio={photosPreview[index].ratio}
alt={directus_files_id.title}
/>
{/each}
</div>
{/if}
<div class="poster-layout__about grid">
<div class="text container">
{#if product.description}
<p>{product.description}</p>
{/if}
{#if product.details}
<p class="details">{product.details}</p>
{/if}
</div>
</div>
{#if lastPreviewPhoto}
<Image
class="image image--4 photo shadow-box-light"
id={lastPreviewPhoto.id}
sizeKey="photo-grid"
sizes={photosPreview[photosPreview.length - 1].sizes}
ratio={photosPreview[photosPreview.length - 1].ratio}
alt={lastPreviewPhoto.title}
/>
{/if}
</section>

View File

@@ -10,7 +10,7 @@
<Button <Button
size="xsmall" size="xsmall"
url="/shop/poster-{slug}" url="/shop/poster-{slug}"
text="View poster" text="View"
/> />
<Button <Button
type="button" type="button"

View File

@@ -1,49 +0,0 @@
<script lang="ts">
import Button from '$components/atoms/Button.svelte'
import Image from '$components/atoms/Image.svelte'
</script>
<div class="poster-product grid">
<h2 class="title-huge">Melbourne</h2>
<div class="poster-product__buy">
<div class="info">
<dl>
<dt>Poster</dt>
<dd>Houses Of Melbourne 30€</dd>
</dl>
<Button
text="Add to cart"
color="pink"
/>
</div>
<img src="/images/poster-display.jpg" alt="">
</div>
<div class="poster-product__images grid container">
<picture class="image image--first photo shadow-box-light">
<img src="https://picsum.photos/656/493" width={656} height={493} alt="blob">
</picture>
<picture class="image image--second photo shadow-box-light">
<img src="https://picsum.photos/324/259" width={324} height={259} alt="blob">
</picture>
<picture class="image image--third photo shadow-box-light">
<img src="https://picsum.photos/324/416" width={324} height={416} alt="blob">
</picture>
</div>
<div class="poster-product__about grid">
<div class="text container">
<p>This poster will bring you to straight to Melbourne, Australia with its unique Victorian architectural style, wrought iron and colorful fronts.</p>
<p class="details">
Format: 40cm x 60cm (16” x 24”)<br>Printed on Recycled offset paper, 150gm/m2.<br>Frame not included.
</p>
</div>
</div>
<div class="poster-product__image grid container">
<picture class="image image--fourth photo shadow-box-light">
<img src="https://picsum.photos/854/588" width={854} height={588} alt="blob">
</picture>
</div>
</div>

View File

@@ -3,16 +3,18 @@
import Metas from '$components/Metas.svelte' import Metas from '$components/Metas.svelte'
import SiteTitle from '$components/atoms/SiteTitle.svelte' import SiteTitle from '$components/atoms/SiteTitle.svelte'
import Image from '$components/atoms/Image.svelte' import Image from '$components/atoms/Image.svelte'
import PosterProduct from '$components/organisms/PosterProduct.svelte' import PosterLayout from '$components/layouts/PosterLayout.svelte'
import Poster from '$components/molecules/Poster.svelte' import Poster from '$components/molecules/Poster.svelte'
import EmailForm from '$components/molecules/EmailForm.svelte' import EmailForm from '$components/molecules/EmailForm.svelte'
export let shop: any export let shop: any
export let locations: any export let locations: any
export let posters: any
export let product: any
</script> </script>
<Metas <Metas
title="Houses Of" title="Shop Houses Of"
description="" description=""
image="" image=""
/> />
@@ -34,7 +36,7 @@
<nav> <nav>
<ul> <ul>
{#each locations as { name, slug }} {#each locations as { name, slug }}
<li> <li class:is-active={slug === product.location.slug}>
<a href="/shop/poster-{slug}">{name}</a> <a href="/shop/poster-{slug}">{name}</a>
</li> </li>
{/each} {/each}
@@ -59,22 +61,17 @@
</section> </section>
<section class="shop-page__about grid"> <section class="shop-page__about grid">
<p class="description text-normal"> <p class="description text-normal">{shop.about}</p>
Welcome to our shop!<br />We wanted to create a physical expression to share theses unique places and let the architecture transport you while inside of your own home.
</p>
</section> </section>
<PosterProduct /> <PosterLayout {product} />
<section class="shop-page__posters grid"> <section class="shop-page__posters grid">
<h3>View all of our available posters</h3> <h3>View all of our available posters</h3>
<div class="set"> <div class="set">
<Poster slug="melbourne" /> {#each posters as { location }}
<Poster slug="melbourne" /> <Poster slug={location.slug} />
<Poster slug="melbourne" /> {/each}
<Poster slug="melbourne" />
<Poster slug="melbourne" />
<Poster slug="melbourne" />
</div> </div>
<div class="subscribe"> <div class="subscribe">
<p>Subscribe to be notified when new posters become available</p> <p>Subscribe to be notified when new posters become available</p>
@@ -88,11 +85,13 @@
<script context="module" lang="ts"> <script context="module" lang="ts">
import { fetchAPI } from '$utils/api' import { fetchAPI } from '$utils/api'
import { getRandomElement } from '$utils/functions'
export async function load ({ page, fetch, session, stuff }) { export async function load ({ page, fetch, session, stuff }) {
const res = await fetchAPI(` const res = await fetchAPI(`
query { query {
shop { shop {
about
page_heroimage { id } page_heroimage { id }
} }
@@ -103,15 +102,53 @@
name name
slug slug
} }
posters: product {
name
type
description
details
location {
name
slug
}
photos_product {
directus_files_id {
id
title
}
}
photos_preview {
directus_files_id {
id
title
}
}
}
} }
`) `)
const { data } = res const { data } = res
/**
* Define product
*/
let product: any
if (!page.params.type && !page.params.name) {
// Get a random product
product = data.posters[getRandomElement(data.posters)]
} else {
// Get the current product from slug
product = data.posters.find(({ location }: any) => location.slug === page.params.name)
}
return { return {
props: { props: {
shop: data.shop, shop: data.shop,
locations: data.location, locations: data.location,
posters: data.posters,
product,
} }
} }
} }

View File

@@ -1,4 +1,4 @@
.poster-product { .poster-layout {
background-color: $color-cream; background-color: $color-cream;
@include bp (sm) { @include bp (sm) {
@@ -19,8 +19,11 @@
} }
} }
// Poster Product
/*
** Product Layout
*/
// Poster Display // Poster Display
&__buy { &__buy {
grid-column: 1 / span var(--columns); grid-column: 1 / span var(--columns);
@@ -28,18 +31,18 @@
@include bp (sm) { @include bp (sm) {
grid-column: 2 / span 10; grid-column: 2 / span 10;
margin: 0; margin: 0 0 104px;
} }
}
// Product Info // Product Info
.info { &__info {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
margin-bottom: 32px; margin-bottom: 32px;
@include bp (sm) { @include bp (sm) {
margin-bottom: 72px; margin-bottom: 56px;
}
} }
// Title // Title
@@ -61,42 +64,42 @@
max-width: none; max-width: none;
} }
} }
// Image
img {
display: block;
width: 100%;
height: auto;
border-radius: 6px;
}
} }
// Images set // Images set
&__images { &__images {
@include bp (sm) { @include bp (sm) {
--columns: 10; --columns: 10;
position: relative; position: relative;
z-index: 2; z-index: 2;
grid-column: 14 / span var(--columns); grid-column: 14 / span var(--columns);
} }
}
.image {
position: relative;
border-radius: 6px;
.image { img {
border-radius: 6px; position: absolute;
top: 0;
img { left: 0;
display: block; display: block;
width: 100%; width: 100%;
height: auto; height: 100%;
} object-fit: cover;
} }
// Image 1 &:after {
.image--first { content: "";
display: block;
width: 100%;
padding-bottom: 75%;
}
&--1 {
grid-column: 1 / span 7; grid-column: 1 / span 7;
} }
// Image 2 &--2 {
.image--second {
grid-column: 2 / span 5; grid-column: 2 / span 5;
margin: 32px 0; margin: 32px 0;
@@ -104,8 +107,7 @@
margin: 48px 0; margin: 48px 0;
} }
} }
// Image 3 &--3 {
.image--third {
grid-column: 4 / span 5; grid-column: 4 / span 5;
z-index: 10; z-index: 10;
margin-bottom: -64px; margin-bottom: -64px;
@@ -114,6 +116,19 @@
grid-column: 5 / span 5; grid-column: 5 / span 5;
margin-bottom: 0; margin-bottom: 0;
} }
&:after {
padding-bottom: 128%;
}
}
&--4 {
grid-column: 1 / span 8;
margin-bottom: 56px;
@include bp (sm) {
grid-column: 8 / span 13;
margin-bottom: 120px;
}
} }
} }
@@ -126,6 +141,7 @@
font-weight: 300; font-weight: 300;
color: $color-primary-tertiary20; color: $color-primary-tertiary20;
line-height: 1.4; line-height: 1.4;
white-space: pre-line;
@include bp (sm) { @include bp (sm) {
padding: 148px 0 260px; padding: 148px 0 260px;
@@ -135,6 +151,7 @@
.text { .text {
grid-column: 1 / span 8; grid-column: 1 / span 8;
font-size: rem(28px); font-size: rem(28px);
font-weight: 200;
@include bp (sm) { @include bp (sm) {
grid-column: 4 / span 12; grid-column: 4 / span 12;
@@ -147,6 +164,7 @@
font-size: rem(16px); font-size: rem(16px);
margin-top: 32px; margin-top: 32px;
line-height: 1.5; line-height: 1.5;
font-weight: 300;
@include bp (sm) { @include bp (sm) {
margin-top: 56px; margin-top: 56px;
@@ -154,32 +172,4 @@
} }
} }
} }
// Single Image
&__image {
margin-bottom: 56px;
@include bp (sm) {
margin-bottom: 120px;
}
.image {
border-radius: 6px;
img {
display: block;
width: 100%;
height: auto;
}
}
// Image 4
.image--fourth {
grid-column: 1 / span 8;
@include bp (sm) {
grid-column: 8 / span 13;
}
}
}
} }

View File

@@ -131,6 +131,7 @@
font-family: $font-serif; font-family: $font-serif;
color: $color-tertiary; color: $color-tertiary;
margin: 0 10px; margin: 0 10px;
transition: color 0.3s;
&:hover { &:hover {
color: $color-secondary; color: $color-secondary;
@@ -141,6 +142,13 @@
margin: 0 12px; margin: 0 12px;
} }
} }
// Active
.is-active {
a {
color: $color-secondary;
}
}
} }
} }
} }
@@ -163,6 +171,7 @@
margin-left: 20px; margin-left: 20px;
padding-right: 20px; padding-right: 20px;
font-size: rem(18px); font-size: rem(18px);
white-space: pre-line;
@include bp (sm) { @include bp (sm) {
grid-column: 3 / span 12; grid-column: 3 / span 12;
@@ -272,7 +281,8 @@
// Subscribe // Subscribe
.subscribe { .subscribe {
grid-column: 1 / span var(--columns); grid-column: 1 / span var(--columns);
margin-top: 72px; max-width: 380px;
margin: 72px auto 0;
text-align: center; text-align: center;
@include bp (sm) { @include bp (sm) {
@@ -300,7 +310,6 @@
@include bp (sm) { @include bp (sm) {
margin: 0; margin: 0;
min-width: 368px;
} }
} }

View File

@@ -59,9 +59,11 @@
@import "organisms/newsletter"; @import "organisms/newsletter";
@import "organisms/carousel"; @import "organisms/carousel";
@import "organisms/shop"; @import "organisms/shop";
@import "organisms/poster-product";
@import "organisms/footer"; @import "organisms/footer";
// Layouts
@import "layouts/poster";
// Pages // Pages
@import "pages/viewer-photo"; @import "pages/viewer-photo";

View File

@@ -48,6 +48,14 @@ export const debounce = (func: Function, timeout: number) => {
} }
/**
* Capitalize first letter
*/
export const capitalizeFirstLetter = (string: string) => {
return string[0].toUpperCase() + string.slice(1)
}
/** /**
* Linear Interpolation * Linear Interpolation
*/ */