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
size="xsmall"
url="/shop/poster-{slug}"
text="View poster"
text="View"
/>
<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 SiteTitle from '$components/atoms/SiteTitle.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 EmailForm from '$components/molecules/EmailForm.svelte'
export let shop: any
export let locations: any
export let posters: any
export let product: any
</script>
<Metas
title="Houses Of"
title="Shop Houses Of"
description=""
image=""
/>
@@ -34,7 +36,7 @@
<nav>
<ul>
{#each locations as { name, slug }}
<li>
<li class:is-active={slug === product.location.slug}>
<a href="/shop/poster-{slug}">{name}</a>
</li>
{/each}
@@ -59,22 +61,17 @@
</section>
<section class="shop-page__about grid">
<p class="description text-normal">
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>
<p class="description text-normal">{shop.about}</p>
</section>
<PosterProduct />
<PosterLayout {product} />
<section class="shop-page__posters grid">
<h3>View all of our available posters</h3>
<div class="set">
<Poster slug="melbourne" />
<Poster slug="melbourne" />
<Poster slug="melbourne" />
<Poster slug="melbourne" />
<Poster slug="melbourne" />
<Poster slug="melbourne" />
{#each posters as { location }}
<Poster slug={location.slug} />
{/each}
</div>
<div class="subscribe">
<p>Subscribe to be notified when new posters become available</p>
@@ -88,11 +85,13 @@
<script context="module" lang="ts">
import { fetchAPI } from '$utils/api'
import { getRandomElement } from '$utils/functions'
export async function load ({ page, fetch, session, stuff }) {
const res = await fetchAPI(`
query {
shop {
about
page_heroimage { id }
}
@@ -103,15 +102,53 @@
name
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
/**
* 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 {
props: {
shop: data.shop,
locations: data.location,
posters: data.posters,
product,
}
}
}

View File

@@ -1,4 +1,4 @@
.poster-product {
.poster-layout {
background-color: $color-cream;
@include bp (sm) {
@@ -19,8 +19,11 @@
}
}
// Poster Product
/*
** Product Layout
*/
// Poster Display
&__buy {
grid-column: 1 / span var(--columns);
@@ -28,18 +31,18 @@
@include bp (sm) {
grid-column: 2 / span 10;
margin: 0;
margin: 0 0 104px;
}
}
// Product Info
.info {
&__info {
display: flex;
justify-content: space-between;
margin-bottom: 32px;
@include bp (sm) {
margin-bottom: 72px;
}
margin-bottom: 56px;
}
// Title
@@ -61,42 +64,42 @@
max-width: none;
}
}
// Image
img {
display: block;
width: 100%;
height: auto;
border-radius: 6px;
}
}
// Images set
&__images {
@include bp (sm) {
--columns: 10;
position: relative;
z-index: 2;
grid-column: 14 / span var(--columns);
}
}
.image {
position: relative;
border-radius: 6px;
img {
position: absolute;
top: 0;
left: 0;
display: block;
width: 100%;
height: auto;
}
height: 100%;
object-fit: cover;
}
// Image 1
.image--first {
&:after {
content: "";
display: block;
width: 100%;
padding-bottom: 75%;
}
&--1 {
grid-column: 1 / span 7;
}
// Image 2
.image--second {
&--2 {
grid-column: 2 / span 5;
margin: 32px 0;
@@ -104,8 +107,7 @@
margin: 48px 0;
}
}
// Image 3
.image--third {
&--3 {
grid-column: 4 / span 5;
z-index: 10;
margin-bottom: -64px;
@@ -114,6 +116,19 @@
grid-column: 5 / span 5;
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;
color: $color-primary-tertiary20;
line-height: 1.4;
white-space: pre-line;
@include bp (sm) {
padding: 148px 0 260px;
@@ -135,6 +151,7 @@
.text {
grid-column: 1 / span 8;
font-size: rem(28px);
font-weight: 200;
@include bp (sm) {
grid-column: 4 / span 12;
@@ -147,6 +164,7 @@
font-size: rem(16px);
margin-top: 32px;
line-height: 1.5;
font-weight: 300;
@include bp (sm) {
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;
color: $color-tertiary;
margin: 0 10px;
transition: color 0.3s;
&:hover {
color: $color-secondary;
@@ -141,6 +142,13 @@
margin: 0 12px;
}
}
// Active
.is-active {
a {
color: $color-secondary;
}
}
}
}
}
@@ -163,6 +171,7 @@
margin-left: 20px;
padding-right: 20px;
font-size: rem(18px);
white-space: pre-line;
@include bp (sm) {
grid-column: 3 / span 12;
@@ -272,7 +281,8 @@
// Subscribe
.subscribe {
grid-column: 1 / span var(--columns);
margin-top: 72px;
max-width: 380px;
margin: 72px auto 0;
text-align: center;
@include bp (sm) {
@@ -300,7 +310,6 @@
@include bp (sm) {
margin: 0;
min-width: 368px;
}
}

View File

@@ -59,9 +59,11 @@
@import "organisms/newsletter";
@import "organisms/carousel";
@import "organisms/shop";
@import "organisms/poster-product";
@import "organisms/footer";
// Layouts
@import "layouts/poster";
// Pages
@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
*/