✨ Add data to Shop page
This commit is contained in:
116
src/components/layouts/PosterLayout.svelte
Normal file
116
src/components/layouts/PosterLayout.svelte
Normal 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>
|
||||
@@ -10,7 +10,7 @@
|
||||
<Button
|
||||
size="xsmall"
|
||||
url="/shop/poster-{slug}"
|
||||
text="View poster"
|
||||
text="View"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -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>
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 32px;
|
||||
// Product Info
|
||||
&__info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 32px;
|
||||
|
||||
@include bp (sm) {
|
||||
margin-bottom: 72px;
|
||||
}
|
||||
@include bp (sm) {
|
||||
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;
|
||||
|
||||
.image {
|
||||
border-radius: 6px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user