🚧 Migrate to new SvelteKit routing system
A bit annoying but for the best I guess?
This commit is contained in:
14
src/app.d.ts
vendored
14
src/app.d.ts
vendored
@@ -1,13 +1,15 @@
|
||||
/// <reference types="@sveltejs/kit" />
|
||||
|
||||
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
// and what to do when importing types
|
||||
declare namespace App {
|
||||
// interface Locals {}
|
||||
interface Locals {
|
||||
userid: string;
|
||||
}
|
||||
|
||||
// interface Platform {}
|
||||
// interface PrivateEnv {}
|
||||
// interface PublicEnv {}
|
||||
// interface Session {}
|
||||
// interface Stuff {}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +42,7 @@ declare interface PhotoGridAbout {
|
||||
/**
|
||||
* Notifcation
|
||||
*/
|
||||
declare interface Notification {
|
||||
declare interface ShopNotification {
|
||||
title: string
|
||||
name: string
|
||||
image: string
|
||||
|
||||
@@ -27,30 +27,27 @@
|
||||
})
|
||||
if (existantCart.ok) {
|
||||
const cart = await existantCart.json()
|
||||
// console.log('Fetched existant cart:', $cartId, $cartData)
|
||||
|
||||
// Cart is active / has not been ordered
|
||||
if (cart.active || !cart.order_id) {
|
||||
// Keep current cart
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
return
|
||||
}
|
||||
|
||||
// Cart is inactive / has been ordered
|
||||
else {
|
||||
// Fetch a new cart
|
||||
const newCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'createCart'
|
||||
})
|
||||
const newCart = await fetch('/api/swell', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
action: 'createCart'
|
||||
})
|
||||
if (newCart.ok) {
|
||||
const cart = await newCart.json()
|
||||
// Save new cart
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
}
|
||||
})
|
||||
if (newCart.ok) {
|
||||
const cart = await newCart.json()
|
||||
// Save new cart
|
||||
$cartId = cart.id
|
||||
$cartData = cart
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
// Components
|
||||
import { page } from '$app/stores'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
import BoxCTA from '$components/atoms/BoxCTA.svelte'
|
||||
@@ -16,9 +16,6 @@
|
||||
import ShopModule from '$components/organisms/ShopModule.svelte'
|
||||
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
|
||||
|
||||
export let status: number
|
||||
export let message: string = undefined
|
||||
|
||||
const { locations }: any = getContext('global')
|
||||
const errors = {
|
||||
404: {
|
||||
@@ -30,17 +27,17 @@
|
||||
message: 'Server error…',
|
||||
},
|
||||
}
|
||||
const defaultMessage = 'But you are welcome to explore our locations or discover our shop.'
|
||||
const defaultMessage = 'You are welcome to explore our locations or discover our shop.'
|
||||
</script>
|
||||
|
||||
<Metas
|
||||
title="{errors[status].title} – Houses Of"
|
||||
title="{errors[$page.status].title} – Houses Of"
|
||||
/>
|
||||
|
||||
<PageTransition name="page-error">
|
||||
<div class="page-error__top">
|
||||
<Heading
|
||||
text="{message ?? errors[status].message} <br>{defaultMessage}"
|
||||
text="{$page.error.message ?? errors[$page.status].message} <br>{defaultMessage}"
|
||||
/>
|
||||
|
||||
<ListCTAs>
|
||||
@@ -82,18 +79,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PageTransition>
|
||||
|
||||
|
||||
<script context="module" lang="ts">
|
||||
import type { LoadEvent, LoadOutput } from '@sveltejs/kit'
|
||||
|
||||
export async function load ({ status, error: { message } }: LoadEvent): Promise<LoadOutput> {
|
||||
return {
|
||||
props: {
|
||||
status,
|
||||
message,
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</PageTransition>
|
||||
104
src/routes/+layout.server.ts
Normal file
104
src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
locations: location (filter: { status: { _eq: "published" }}) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
coordinates
|
||||
country {
|
||||
name
|
||||
slug
|
||||
flag { id }
|
||||
continent { slug }
|
||||
}
|
||||
date_updated
|
||||
photos (
|
||||
sort: "-date_created",
|
||||
limit: ${import.meta.env.VITE_PREVIEW_COUNT}
|
||||
) {
|
||||
image {
|
||||
id
|
||||
title
|
||||
}
|
||||
date_created
|
||||
}
|
||||
has_poster
|
||||
globe_close
|
||||
}
|
||||
|
||||
countries: country (filter: { status: { _eq: "published" }}) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
flag { id }
|
||||
locations { id slug }
|
||||
}
|
||||
|
||||
continents: continent (filter: { countries: { slug: { _neq: "_empty" }}}) {
|
||||
name
|
||||
slug
|
||||
rotation
|
||||
}
|
||||
|
||||
settings {
|
||||
seo_name
|
||||
seo_title
|
||||
seo_description
|
||||
description
|
||||
explore_list
|
||||
limit_new
|
||||
instagram
|
||||
footer_links
|
||||
switcher_links
|
||||
newsletter_subtitle
|
||||
newsletter_text
|
||||
}
|
||||
|
||||
shop {
|
||||
enabled
|
||||
module_title
|
||||
module_text
|
||||
module_images {
|
||||
directus_files_id {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Count
|
||||
countPhotos: photo_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
countLocations: location_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
countCountries: country_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
if (res) {
|
||||
const { data } = res
|
||||
|
||||
return {
|
||||
...data,
|
||||
count: {
|
||||
photos: data.countPhotos[0].count.id,
|
||||
locations: data.countLocations[0].count.id,
|
||||
countries: data.countCountries[0].count.id,
|
||||
},
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err || 'Failed to fetch data')
|
||||
}
|
||||
}
|
||||
90
src/routes/+layout.svelte
Normal file
90
src/routes/+layout.svelte
Normal file
@@ -0,0 +1,90 @@
|
||||
<script lang="ts">
|
||||
import '../style/global.scss'
|
||||
|
||||
import { browser } from '$app/env'
|
||||
import { navigating, page } from '$app/stores'
|
||||
import { beforeNavigate } from '$app/navigation'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { onMount, setContext } from 'svelte'
|
||||
import { pageLoading, previousPage } from '$utils/stores'
|
||||
import { DURATION } from '$utils/contants'
|
||||
import '$utils/polyfills'
|
||||
// Components
|
||||
import SVGSprite from '$components/SVGSprite.svelte'
|
||||
import SmoothScroll from '$components/SmoothScroll.svelte'
|
||||
import Analytics from '$components/Analytics.svelte'
|
||||
import Switcher from '$components/molecules/Switcher.svelte'
|
||||
import Footer from '$components/organisms/Footer.svelte'
|
||||
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
|
||||
// Fonts to preload
|
||||
const fonts = [
|
||||
'G-Light',
|
||||
'G-Regular',
|
||||
'G-Medium',
|
||||
'G-Semibold',
|
||||
'J-Extralight',
|
||||
'J-Light',
|
||||
]
|
||||
|
||||
// Set global data
|
||||
setContext('global', data)
|
||||
|
||||
|
||||
/**
|
||||
* On page change
|
||||
*/
|
||||
// Store previous page (for photo Viewer close button)
|
||||
beforeNavigate(({ from }) => {
|
||||
$previousPage = from.pathname
|
||||
})
|
||||
|
||||
// Define page loading from navigating store
|
||||
navigating.subscribe((store: any) => {
|
||||
if (store) {
|
||||
$pageLoading = true
|
||||
|
||||
// Turn page loading when changing page
|
||||
setTimeout(() => {
|
||||
$pageLoading = false
|
||||
}, DURATION.PAGE_IN * 1.25)
|
||||
}
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
// Avoid FOUC
|
||||
document.body.style.opacity = '1'
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#each fonts as font}
|
||||
<link rel="preload" href="/fonts/{font}.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
||||
|
||||
<Switcher isOver={!!$page.params.location && !!$page.params.photo} />
|
||||
|
||||
<slot />
|
||||
|
||||
{#if !$page.params.photo}
|
||||
<Footer />
|
||||
{/if}
|
||||
|
||||
{#if $pageLoading}
|
||||
<div class="page-loading" />
|
||||
{/if}
|
||||
|
||||
<SVGSprite />
|
||||
<SmoothScroll />
|
||||
|
||||
{#if browser}
|
||||
<Analytics
|
||||
appKey={import.meta.env.VITE_ANALYTICS_KEY}
|
||||
url={import.meta.env.VITE_ANALYTICS_URL}
|
||||
/>
|
||||
{/if}
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getRandomItems } from '$utils/functions'
|
||||
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
// Get total of published photos
|
||||
const totalRes = await fetchAPI(`
|
||||
@@ -47,15 +48,10 @@ export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
|
||||
if (photos) {
|
||||
return {
|
||||
body: {
|
||||
photos,
|
||||
}
|
||||
photos,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { page, navigating } from '$app/stores'
|
||||
import { navigating } from '$app/stores'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { timeline, stagger } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
@@ -26,7 +27,8 @@
|
||||
import ShopModule from '$components/organisms/ShopModule.svelte'
|
||||
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
|
||||
|
||||
export let photos: any
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const { settings, locations }: any = getContext('global')
|
||||
|
||||
@@ -109,7 +111,7 @@
|
||||
</section>
|
||||
|
||||
<section class="homepage__photos">
|
||||
<Collage {photos} />
|
||||
<Collage photos={data.photos} />
|
||||
</section>
|
||||
|
||||
<div class="homepage__ctas">
|
||||
@@ -118,7 +120,7 @@
|
||||
<ListCTAs>
|
||||
<li>
|
||||
<BoxCTA
|
||||
url="{$page.url.pathname}"
|
||||
url="#locations"
|
||||
icon="globe"
|
||||
label="Discover locations"
|
||||
alt="Globe"
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export const photoFields = `
|
||||
@@ -14,7 +15,7 @@ export const photoFields = `
|
||||
date_created
|
||||
`
|
||||
|
||||
export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
const { location: slug } = params
|
||||
|
||||
@@ -76,27 +77,20 @@ export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutp
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
const { data: { location: location, photos, total_published, product }} = res
|
||||
|
||||
if (!location.length || location.length && params.country !== location[0].country.slug) {
|
||||
return {
|
||||
status: 404,
|
||||
body: Error("This location is not available… yet!"),
|
||||
}
|
||||
throw error(404, "This location is not available… yet!")
|
||||
}
|
||||
|
||||
return {
|
||||
body: {
|
||||
location: location[0],
|
||||
photos,
|
||||
totalPhotos: photos.length ? total_published[0].count.location : 0,
|
||||
product: product[0],
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
location: location[0],
|
||||
photos,
|
||||
totalPhotos: photos.length ? total_published[0].count.location : 0,
|
||||
product: product[0],
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,15 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { page, navigating } from '$app/stores'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { onMount } from 'svelte'
|
||||
import { timeline } from 'motion'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { quartOut } from '$animations/easings'
|
||||
import { fetchAPI, getAssetUrlKey } from '$utils/api'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { photoFields } from '.'
|
||||
import { photoFields } from './+page.server'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
@@ -23,14 +24,14 @@
|
||||
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
|
||||
import ShopModule from '$components/organisms/ShopModule.svelte'
|
||||
|
||||
export let location: any
|
||||
export let photos: any[]
|
||||
export let totalPhotos: number
|
||||
export let product: any = undefined
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const { params } = $page
|
||||
let { photos }: { photos: any[] } = data
|
||||
const { location, totalPhotos, product = undefined }: { location: any, totalPhotos: number, product: any } = data
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
let introEl: HTMLElement
|
||||
let photosListEl: HTMLElement
|
||||
@@ -152,6 +153,7 @@
|
||||
y: ['110%', 0],
|
||||
}, {
|
||||
at: 0.2,
|
||||
delay: stagger(0.4)
|
||||
}],
|
||||
|
||||
// Illustration
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
// Get the first photo ID
|
||||
const firstPhoto = await fetchAPI(`
|
||||
@@ -75,10 +76,11 @@ export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutp
|
||||
`)
|
||||
|
||||
const { data } = res
|
||||
const currentIndex = data.photos.findIndex((photo: any) => photo.slug === params.photo)
|
||||
|
||||
return {
|
||||
body: {
|
||||
if (data) {
|
||||
const currentIndex = data.photos.findIndex((photo: any) => photo.slug === params.photo)
|
||||
|
||||
return {
|
||||
photos: data.photos,
|
||||
location: data.location[0],
|
||||
currentIndex,
|
||||
@@ -87,10 +89,7 @@ export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutp
|
||||
offset,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
<style lang="scss">
|
||||
@import "../../../style/pages/viewer";
|
||||
@import "../../../../style/pages/viewer";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/env'
|
||||
import { page, navigating } from '$app/stores'
|
||||
import { goto } from '$app/navigation'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { onMount, tick } from 'svelte'
|
||||
import { fade, scale } from 'svelte/transition'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
@@ -25,12 +26,11 @@
|
||||
import IconArrow from '$components/atoms/IconArrow.svelte'
|
||||
import ButtonCircle from '$components/atoms/ButtonCircle.svelte'
|
||||
|
||||
export let photos: any[]
|
||||
export let location: any
|
||||
export let currentIndex: number
|
||||
export let countPhotos: number
|
||||
export let limit: number
|
||||
export let offset: number
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
let { photos, currentIndex }: { photos: any[], currentIndex: number } = data
|
||||
const { location, countPhotos, limit, offset }: { location: any, countPhotos: number, limit: number, offset: number } = data
|
||||
|
||||
enum directions { PREV, NEXT }
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
<script lang="ts">
|
||||
import '../style/global.scss'
|
||||
|
||||
import { browser } from '$app/env'
|
||||
import { navigating, page } from '$app/stores'
|
||||
import { beforeNavigate } from '$app/navigation'
|
||||
import { onMount, setContext } from 'svelte'
|
||||
import { pageLoading, previousPage } from '$utils/stores'
|
||||
import { DURATION } from '$utils/contants'
|
||||
import '$utils/polyfills'
|
||||
// Components
|
||||
import SVGSprite from '$components/SVGSprite.svelte'
|
||||
import SmoothScroll from '$components/SmoothScroll.svelte'
|
||||
import Analytics from '$components/Analytics.svelte'
|
||||
import Switcher from '$components/molecules/Switcher.svelte'
|
||||
import Footer from '$components/organisms/Footer.svelte'
|
||||
|
||||
export let data: any
|
||||
export let count: any
|
||||
|
||||
// Fonts to preload
|
||||
const fonts = [
|
||||
'G-Light',
|
||||
'G-Regular',
|
||||
'G-Medium',
|
||||
'G-Semibold',
|
||||
'J-Extralight',
|
||||
'J-Light',
|
||||
]
|
||||
|
||||
// Set global data
|
||||
setContext('global', {
|
||||
...data,
|
||||
count,
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* On page change
|
||||
*/
|
||||
// Store previous page (for photo Viewer close button)
|
||||
beforeNavigate(({ from }) => {
|
||||
$previousPage = from.pathname
|
||||
})
|
||||
|
||||
// Define page loading from navigating store
|
||||
navigating.subscribe((store: any) => {
|
||||
if (store) {
|
||||
$pageLoading = true
|
||||
|
||||
// Turn page loading when changing page
|
||||
setTimeout(() => {
|
||||
$pageLoading = false
|
||||
}, DURATION.PAGE_IN * 1.25)
|
||||
}
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
// Avoid FOUC
|
||||
document.body.style.opacity = '1'
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
{#each fonts as font}
|
||||
<link rel="preload" href="/fonts/{font}.woff2" as="font" type="font/woff2" crossorigin="anonymous">
|
||||
{/each}
|
||||
</svelte:head>
|
||||
|
||||
|
||||
<Switcher isOver={!!$page.params.location && !!$page.params.photo} />
|
||||
|
||||
<slot />
|
||||
|
||||
{#if !$page.params.photo}
|
||||
<Footer />
|
||||
{/if}
|
||||
|
||||
{#if $pageLoading}
|
||||
<div class="page-loading" />
|
||||
{/if}
|
||||
|
||||
<SVGSprite />
|
||||
<SmoothScroll />
|
||||
|
||||
{#if browser}
|
||||
<Analytics
|
||||
appKey={import.meta.env.VITE_ANALYTICS_KEY}
|
||||
url={import.meta.env.VITE_ANALYTICS_URL}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
|
||||
<script context="module" lang="ts">
|
||||
import type { LoadEvent, LoadOutput } from '@sveltejs/kit'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export async function load ({}: LoadEvent): Promise<LoadOutput> {
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
locations: location (filter: { status: { _eq: "published" }}) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
coordinates
|
||||
country {
|
||||
name
|
||||
slug
|
||||
flag { id }
|
||||
continent { slug }
|
||||
}
|
||||
date_updated
|
||||
photos (
|
||||
sort: "-date_created",
|
||||
limit: ${import.meta.env.VITE_PREVIEW_COUNT}
|
||||
) {
|
||||
image {
|
||||
id
|
||||
title
|
||||
}
|
||||
date_created
|
||||
}
|
||||
has_poster
|
||||
globe_close
|
||||
}
|
||||
|
||||
countries: country (filter: { status: { _eq: "published" }}) {
|
||||
id
|
||||
name
|
||||
slug
|
||||
flag { id }
|
||||
locations { id slug }
|
||||
}
|
||||
|
||||
continents: continent (filter: { countries: { slug: { _neq: "_empty" }}}) {
|
||||
name
|
||||
slug
|
||||
rotation
|
||||
}
|
||||
|
||||
settings {
|
||||
seo_name
|
||||
seo_title
|
||||
seo_description
|
||||
description
|
||||
explore_list
|
||||
limit_new
|
||||
instagram
|
||||
footer_links
|
||||
switcher_links
|
||||
newsletter_subtitle
|
||||
newsletter_text
|
||||
}
|
||||
|
||||
shop {
|
||||
enabled
|
||||
module_title
|
||||
module_text
|
||||
module_images {
|
||||
directus_files_id {
|
||||
id
|
||||
title
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Count
|
||||
countPhotos: photo_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
countLocations: location_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
countCountries: country_aggregated (filter: { status: { _eq: "published" }}) {
|
||||
count { id }
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
if (res) {
|
||||
const { data } = res
|
||||
|
||||
return {
|
||||
props: {
|
||||
data,
|
||||
count: {
|
||||
photos: data.countPhotos[0].count.id,
|
||||
locations: data.countLocations[0].count.id,
|
||||
countries: data.countCountries[0].count.id,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 500,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getRandomItems } from '$utils/functions'
|
||||
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
// Get data and total of published photos
|
||||
const res = await fetchAPI(`
|
||||
@@ -76,18 +77,15 @@ export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
}
|
||||
`)
|
||||
|
||||
const { data: { photo: photos }} = photosRes
|
||||
if (photosRes) {
|
||||
const { data: { photo: photos }} = photosRes
|
||||
|
||||
return {
|
||||
body: {
|
||||
data: about,
|
||||
return {
|
||||
about,
|
||||
photos,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
<style lang="scss">
|
||||
@import "../style/pages/about";
|
||||
@import "../../style/pages/about";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount, afterUpdate } from 'svelte'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { map } from '$utils/functions'
|
||||
import { scroll, animate, inView, type ScrollOptions } from 'motion'
|
||||
// Components
|
||||
@@ -16,8 +17,8 @@
|
||||
import ShopModule from '$components/organisms/ShopModule.svelte'
|
||||
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
|
||||
|
||||
export let data: any
|
||||
export let photos: PhotoGridAbout[]
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
// console.log(data)
|
||||
|
||||
@@ -45,7 +46,7 @@
|
||||
* Steps scroll animation
|
||||
*/
|
||||
const cards = stepsEl.querySelectorAll('.step')
|
||||
const cardsAmount = data.process_steps.length
|
||||
const cardsAmount = data.about.process_steps.length
|
||||
|
||||
cards.forEach((card: HTMLElement, i: number) => {
|
||||
const index = i + 1
|
||||
@@ -86,13 +87,13 @@
|
||||
|
||||
<PageTransition name="about">
|
||||
<Heading
|
||||
text={data.description}
|
||||
text={data.about.description}
|
||||
/>
|
||||
|
||||
<section class="about__purpose" bind:this={purposeEl}>
|
||||
<div class="container-wide">
|
||||
<div class="text title-xl" role="heading">
|
||||
{@html data.purpose_text}
|
||||
{@html data.about.purpose_text}
|
||||
</div>
|
||||
|
||||
<div class="background" />
|
||||
@@ -102,21 +103,21 @@
|
||||
<section class="about__process">
|
||||
<div class="container grid">
|
||||
<div class="title">
|
||||
<h2 class="title-big">{data.process_title}</h2>
|
||||
<p class="text-normal">{data.process_subtitle}</p>
|
||||
<h2 class="title-big">{data.about.process_title}</h2>
|
||||
<p class="text-normal">{data.about.process_subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div class="steps" bind:this={stepsEl}
|
||||
style:--cards-amount={data.process_steps.length}
|
||||
style:--cards-amount={data.about.process_steps.length}
|
||||
>
|
||||
{#each data.process_steps as step, index}
|
||||
{#each data.about.process_steps as step, index}
|
||||
<ProcessStep {...step} index={index} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="intention">
|
||||
<p class="intention__content title-medium">
|
||||
{data.process_intention}
|
||||
{data.about.process_intention}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,7 +126,7 @@
|
||||
<section class="about__photos" bind:this={photosGridEl}>
|
||||
<div class="container-wide">
|
||||
<div class="photos-grid" style:--parallax-y="{parallaxPhotos}px">
|
||||
{#each photos as { image: { id }, title }, index}
|
||||
{#each data.photos as { image: { id }, title }, index}
|
||||
<AboutGridPhoto class="about-grid-photo"
|
||||
{id}
|
||||
alt={title}
|
||||
@@ -138,10 +139,10 @@
|
||||
|
||||
<div class="about__bottom container grid">
|
||||
<section class="about__interest grid">
|
||||
<h2 class="title-xl">{data.contact_title}</h2>
|
||||
<h2 class="title-xl">{data.about.contact_title}</h2>
|
||||
|
||||
<div class="blocks">
|
||||
{#each data.contact_blocks as { title, text, link, button }}
|
||||
{#each data.about.contact_blocks as { title, text, link, button }}
|
||||
<div class="block">
|
||||
<h3 class="text-label">{title}</h3>
|
||||
<p class="text-normal">{text}</p>
|
||||
@@ -1,44 +0,0 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
|
||||
|
||||
// Block GET requests
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
return {
|
||||
status: 403,
|
||||
body: 'nope!'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* POST request
|
||||
*/
|
||||
export async function POST ({ request }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
const body = await request.text()
|
||||
|
||||
if (body) {
|
||||
const req = await fetch(`https://emailoctopus.com/api/1.6/lists/${import.meta.env.VITE_NEWSLETTER_LIST_ID}/contacts`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
api_key: import.meta.env.VITE_NEWSLETTER_API_TOKEN,
|
||||
email_address: body,
|
||||
})
|
||||
})
|
||||
const res = await req.json()
|
||||
|
||||
if (res && res.email_address && res.status === 'PENDING') {
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
code: 'PENDING'
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
status: 403,
|
||||
body: res.error,
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/routes/api/newsletter/+server.ts
Normal file
29
src/routes/api/newsletter/+server.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { RequestHandler } from './$types'
|
||||
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
try {
|
||||
const body = await request.text()
|
||||
|
||||
if (body) {
|
||||
const req = await fetch(`https://emailoctopus.com/api/1.6/lists/${import.meta.env.VITE_NEWSLETTER_LIST_ID}/contacts`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
api_key: import.meta.env.VITE_NEWSLETTER_API_TOKEN,
|
||||
email_address: body,
|
||||
})
|
||||
})
|
||||
const res = await req.json()
|
||||
|
||||
if (res && res.email_address && res.status === 'PENDING') {
|
||||
return new Response(JSON.stringify({
|
||||
code: 'PENDING'
|
||||
}))
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(403, err)
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import {
|
||||
getProducts,
|
||||
getProduct,
|
||||
createCart,
|
||||
fetchCart,
|
||||
addToCart,
|
||||
updateCartItem,
|
||||
removeCartItem,
|
||||
} from '$utils/functions/swell'
|
||||
|
||||
|
||||
// Block GET requests
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
return {
|
||||
status: 403,
|
||||
body: 'nope!'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* POST request
|
||||
*/
|
||||
export async function POST ({ request }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { action, cartId, productId } = body
|
||||
let result = {}
|
||||
|
||||
if (body) {
|
||||
switch (action) {
|
||||
case 'getProducts': {
|
||||
result = await getProducts(body.category)
|
||||
break
|
||||
}
|
||||
case 'getProduct': {
|
||||
result = await getProduct(productId)
|
||||
break
|
||||
}
|
||||
case 'createCart': {
|
||||
result = await createCart()
|
||||
break
|
||||
}
|
||||
case 'fetchCart': {
|
||||
result = await fetchCart(cartId)
|
||||
break
|
||||
}
|
||||
case 'addToCart': {
|
||||
result = await addToCart(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'updateCartItem': {
|
||||
result = await updateCartItem(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'removeCartItem': {
|
||||
result = await removeCartItem(cartId, productId)
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
}
|
||||
return {
|
||||
status: 200,
|
||||
body: result,
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
status: error.status || 500,
|
||||
body: error.message || error.text || `Can't fetch query`
|
||||
}
|
||||
}
|
||||
}
|
||||
52
src/routes/api/swell/+server.ts
Normal file
52
src/routes/api/swell/+server.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { RequestHandler } from './$types'
|
||||
import * as swell from '$utils/functions/swell'
|
||||
|
||||
|
||||
export const POST: RequestHandler = async ({ request }) => {
|
||||
try {
|
||||
const body = await request.json()
|
||||
const { action, cartId, productId } = body
|
||||
let result = {}
|
||||
|
||||
if (body) {
|
||||
switch (action) {
|
||||
case 'getProducts': {
|
||||
result = await swell.getProducts(body.category)
|
||||
break
|
||||
}
|
||||
case 'getProduct': {
|
||||
result = await swell.getProduct(productId)
|
||||
break
|
||||
}
|
||||
case 'createCart': {
|
||||
result = await swell.createCart()
|
||||
break
|
||||
}
|
||||
case 'fetchCart': {
|
||||
result = await swell.fetchCart(cartId)
|
||||
break
|
||||
}
|
||||
case 'addToCart': {
|
||||
result = await swell.addToCart(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'updateCartItem': {
|
||||
result = await swell.updateCartItem(cartId, productId, body.quantity)
|
||||
break
|
||||
}
|
||||
case 'removeCartItem': {
|
||||
result = await swell.removeCartItem(cartId, productId)
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
...result
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err.message || `Can't fetch query`)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
@@ -32,14 +33,9 @@ export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
const { data } = res
|
||||
|
||||
return {
|
||||
body: {
|
||||
data
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
...data
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
<style lang="scss">
|
||||
@import "../style/pages/credits";
|
||||
@import "../../style/pages/credits";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { navigating } from '$app/stores'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { onMount } from 'svelte'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
@@ -15,7 +16,8 @@
|
||||
import Heading from '$components/molecules/Heading.svelte'
|
||||
import InteractiveGlobe2 from '$components/organisms/InteractiveGlobe2.svelte'
|
||||
|
||||
export let data: any
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
|
||||
onMount(() => {
|
||||
@@ -1,5 +1,5 @@
|
||||
<style lang="scss">
|
||||
@import "../style/pages/explore";
|
||||
@import "../../style/pages/explore";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
// Default filters values
|
||||
const defaultCountry = String(import.meta.env.VITE_FILTERS_DEFAULT_COUNTRY)
|
||||
const defaultSort = String(import.meta.env.VITE_FILTERS_DEFAULT_SORT)
|
||||
|
||||
export async function GET ({ url }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async ({ url }) => {
|
||||
try {
|
||||
// Query parameters
|
||||
const queryCountry = url.searchParams.get('country') || defaultCountry
|
||||
@@ -63,16 +64,11 @@ export async function GET ({ url }: RequestEvent): Promise<RequestHandlerOutput>
|
||||
const { data } = res
|
||||
|
||||
return {
|
||||
body: {
|
||||
photos: data.photos,
|
||||
filteredCountryExists: data.country.length > 0,
|
||||
totalPhotos: data.total_published[0].count.id,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
photos: data.photos,
|
||||
filteredCountryExists: data.country.length > 0,
|
||||
totalPhotos: data.total_published[0].count.id,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
<style lang="scss">
|
||||
@import "../style/pages/photos";
|
||||
@import "../../style/pages/photos";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { page, navigating } from '$app/stores'
|
||||
import { goto } from '$app/navigation'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { fly } from 'svelte/transition'
|
||||
import { quartOut as quartOutSvelte } from 'svelte/easing'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
@@ -29,14 +30,15 @@
|
||||
import ShopModule from '$components/organisms/ShopModule.svelte'
|
||||
import NewsletterModule from '$components/organisms/NewsletterModule.svelte'
|
||||
|
||||
export let photos: any[]
|
||||
export let totalPhotos: number
|
||||
export let filteredCountryExists: boolean
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
let { photos }: { photos: any[] } = data
|
||||
const { totalPhotos, filteredCountryExists }: { totalPhotos: number, filteredCountryExists: boolean } = data
|
||||
const { countries, locations }: any = getContext('global')
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
|
||||
const { countries, locations }: any = getContext('global')
|
||||
|
||||
let photosContentEl: HTMLElement
|
||||
let photosGridEl: HTMLElement
|
||||
let observerPhotos: IntersectionObserver
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { getContext } from 'svelte'
|
||||
import { page } from '$app/stores'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
import ShopHeader from '$components/organisms/ShopHeader.svelte'
|
||||
import PostersGrid from '$components/organisms/PostersGrid.svelte'
|
||||
|
||||
export let status: number
|
||||
|
||||
const { posters } = getContext('shop')
|
||||
const errors = {
|
||||
404: {
|
||||
@@ -21,7 +21,7 @@
|
||||
</script>
|
||||
|
||||
<Metas
|
||||
title="{errors[status].title} – Houses Of"
|
||||
title="{errors[$page.status].title} – Houses Of"
|
||||
/>
|
||||
|
||||
|
||||
@@ -32,23 +32,10 @@
|
||||
<div class="container grid">
|
||||
<div class="inner">
|
||||
<h2 class="title-big">Uh oh!</h2>
|
||||
<p class="text-medium">{errors[status].message}</p>
|
||||
<p class="text-medium">{errors[$page.status].message}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<PostersGrid {posters} />
|
||||
</PageTransition>
|
||||
|
||||
|
||||
<script context="module" lang="ts">
|
||||
import type { LoadEvent, LoadOutput } from '@sveltejs/kit'
|
||||
|
||||
export async function load ({ status }: LoadEvent): Promise<LoadOutput> {
|
||||
return {
|
||||
props: {
|
||||
status,
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</PageTransition>
|
||||
73
src/routes/shop/+layout.server.ts
Normal file
73
src/routes/shop/+layout.server.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getProducts } from '$utils/functions/swell'
|
||||
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
// Get content from API
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
shop {
|
||||
page_heroimage { id }
|
||||
}
|
||||
|
||||
location (
|
||||
filter: {
|
||||
has_poster: { _eq: true },
|
||||
status: { _eq: "published" },
|
||||
},
|
||||
sort: "name"
|
||||
) {
|
||||
name
|
||||
slug
|
||||
}
|
||||
|
||||
posters: product (
|
||||
filter: { status: { _eq: "published" }}
|
||||
) {
|
||||
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: { shop, location, posters }} = res
|
||||
|
||||
|
||||
/**
|
||||
* Get products data from Swell
|
||||
*/
|
||||
const shopProducts = await getProducts('posters')
|
||||
|
||||
if (shopProducts) {
|
||||
return {
|
||||
shop,
|
||||
locations: location,
|
||||
posters,
|
||||
shopProducts: shopProducts.results,
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
50
src/routes/shop/+layout.svelte
Normal file
50
src/routes/shop/+layout.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<style lang="scss">
|
||||
@import "../../style/pages/shop";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { setContext } from 'svelte'
|
||||
import { cartNotifications } from '$utils/stores/shop'
|
||||
// Components
|
||||
import Cart from '$components/organisms/Cart.svelte'
|
||||
import NotificationCart from '$components/molecules/NotificationCart.svelte'
|
||||
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const { shop, locations, posters, shopProducts } = data
|
||||
|
||||
let scrollY: number
|
||||
|
||||
// Locations with an existing poster product
|
||||
const shopLocations = locations.filter(({ slug }: any) => {
|
||||
if (posters.find((poster: any) => poster.location.slug === slug)) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
setContext('shop', {
|
||||
shop,
|
||||
posters,
|
||||
shopLocations,
|
||||
shopProducts,
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:window bind:scrollY />
|
||||
|
||||
|
||||
<Cart />
|
||||
|
||||
<div class="notifications" class:is-top={scrollY <= 100}>
|
||||
{#each $cartNotifications as { id, title, name, image } (id)}
|
||||
<NotificationCart
|
||||
title={title}
|
||||
name={name}
|
||||
image={image}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getRandomItem } from '$utils/functions'
|
||||
import { getProduct } from '$utils/functions/swell'
|
||||
import { getRandomItem } from '$utils/functions'
|
||||
|
||||
export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async ({}) => {
|
||||
try {
|
||||
// Get content from API
|
||||
const data = await fetchAPI(`
|
||||
@@ -44,17 +45,12 @@ export async function GET ({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
|
||||
if (shopProduct) {
|
||||
return {
|
||||
body: {
|
||||
product: randomPoster,
|
||||
shopProduct,
|
||||
}
|
||||
product: randomPoster,
|
||||
shopProduct,
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { getContext } from 'svelte'
|
||||
import { shopCurrentProductSlug } from '$utils/stores/shop'
|
||||
// Components
|
||||
@@ -8,9 +9,10 @@
|
||||
import ShopHeader from '$components/organisms/ShopHeader.svelte'
|
||||
import PosterLayout from '$components/layouts/PosterLayout.svelte'
|
||||
|
||||
export let product: any
|
||||
export let shopProduct: any
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const { product, shopProduct } = data
|
||||
const { posters } = getContext('shop')
|
||||
|
||||
// Update current random product slug
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { getProduct } from '$utils/functions/swell'
|
||||
|
||||
export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
// Get content from API
|
||||
const data = await fetchAPI(`
|
||||
@@ -41,17 +42,12 @@ export async function GET ({ params }: RequestEvent): Promise<RequestHandlerOutp
|
||||
|
||||
if (shopProduct) {
|
||||
return {
|
||||
body: {
|
||||
product: poster,
|
||||
shopProduct,
|
||||
}
|
||||
product: poster,
|
||||
shopProduct,
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(404, err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { getContext } from 'svelte'
|
||||
import { capitalizeFirstLetter } from '$utils/functions'
|
||||
// Components
|
||||
@@ -8,25 +9,25 @@
|
||||
import PostersGrid from '$components/organisms/PostersGrid.svelte'
|
||||
import PosterLayout from '$components/layouts/PosterLayout.svelte'
|
||||
|
||||
export let product: any
|
||||
export let shopProduct: any
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const { posters } = getContext('shop')
|
||||
</script>
|
||||
|
||||
<Metas
|
||||
title="{product.location.name} {capitalizeFirstLetter(product.type)} – Houses Of"
|
||||
title="{data.product.location.name} {capitalizeFirstLetter(data.product.type)} – Houses Of"
|
||||
description=""
|
||||
image=""
|
||||
/>
|
||||
|
||||
|
||||
<PageTransition name="shop-page">
|
||||
<ShopHeader {product} />
|
||||
<ShopHeader product={data.product} />
|
||||
|
||||
<PosterLayout
|
||||
product={product}
|
||||
shopProduct={shopProduct}
|
||||
product={data.product}
|
||||
shopProduct={data.shopProduct}
|
||||
/>
|
||||
|
||||
<PostersGrid {posters} />
|
||||
@@ -1,132 +0,0 @@
|
||||
<style lang="scss">
|
||||
@import "../../style/pages/shop";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { setContext } from 'svelte'
|
||||
import { cartNotifications } from '$utils/stores/shop'
|
||||
// Components
|
||||
import Cart from '$components/organisms/Cart.svelte'
|
||||
import NotificationCart from '$components/molecules/NotificationCart.svelte'
|
||||
|
||||
export let shop: any
|
||||
export let locations: any
|
||||
export let posters: any
|
||||
export let shopProducts: any
|
||||
|
||||
// Locations with an existing poster product
|
||||
const shopLocations = locations.filter(({ slug }: any) => {
|
||||
if (posters.find((poster: any) => poster.location.slug === slug)) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
setContext('shop', {
|
||||
shop,
|
||||
posters,
|
||||
shopLocations,
|
||||
shopProducts,
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<Cart />
|
||||
|
||||
<div class="notifications">
|
||||
{#each $cartNotifications as { id, title, name, image } (id)}
|
||||
<NotificationCart
|
||||
title={title}
|
||||
name={name}
|
||||
image={image}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
|
||||
|
||||
<script context="module" lang="ts">
|
||||
import type { LoadEvent, LoadOutput } from '@sveltejs/kit'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export async function load ({ fetch }: LoadEvent): Promise<LoadOutput> {
|
||||
// Get content from API
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
shop {
|
||||
page_heroimage { id }
|
||||
}
|
||||
|
||||
location (
|
||||
filter: {
|
||||
has_poster: { _eq: true },
|
||||
status: { _eq: "published" },
|
||||
},
|
||||
sort: "name"
|
||||
) {
|
||||
name
|
||||
slug
|
||||
}
|
||||
|
||||
posters: product (
|
||||
filter: { status: { _eq: "published" }}
|
||||
) {
|
||||
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: { shop, location, posters }} = res
|
||||
|
||||
|
||||
/**
|
||||
* Get products data from Swell
|
||||
*/
|
||||
let shopProducts: 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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
props: {
|
||||
shop,
|
||||
locations: location,
|
||||
posters,
|
||||
shopProducts,
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { RequestEvent, RequestHandlerOutput } from '@sveltejs/kit'
|
||||
import { error } from '@sveltejs/kit'
|
||||
import type { PageServerLoad } from './$types'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
|
||||
export async function GET({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
export const load: PageServerLoad = async () => {
|
||||
try {
|
||||
const res = await fetchAPI(`
|
||||
query {
|
||||
@@ -26,15 +27,10 @@ export async function GET({}: RequestEvent): Promise<RequestHandlerOutput> {
|
||||
const { data } = res
|
||||
|
||||
return {
|
||||
body: {
|
||||
data: data.settings,
|
||||
issues: data.newsletter,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
status: 404,
|
||||
body: error,
|
||||
...data.settings,
|
||||
issues: data.newsletter,
|
||||
}
|
||||
} catch (err) {
|
||||
throw error(500, err)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
<style lang="scss">
|
||||
@import "../style/pages/subscribe";
|
||||
@import "../../style/pages/subscribe";
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { navigating } from '$app/stores'
|
||||
import type { PageData, Errors } from './$types'
|
||||
import { onMount } from 'svelte'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
@@ -16,10 +17,10 @@
|
||||
import NewsletterIssue from '$components/molecules/NewsletterIssue.svelte'
|
||||
import InteractiveGlobe2 from '$components/organisms/InteractiveGlobe2.svelte'
|
||||
|
||||
export let data: any
|
||||
export let issues: any[]
|
||||
export let data: PageData
|
||||
export let errors: Errors
|
||||
|
||||
const latestIssue = issues[0]
|
||||
const latestIssue = data.issues[0]
|
||||
|
||||
|
||||
onMount(() => {
|
||||
@@ -80,10 +81,10 @@
|
||||
<NewsletterIssue size="large" date={latestIssue.date_sent} {...latestIssue} />
|
||||
</div>
|
||||
|
||||
{#if issues.length > 1}
|
||||
{#if data.issues.length > 1}
|
||||
<h2 class="title-small">Past Issues</h2>
|
||||
<ul>
|
||||
{#each issues.slice(1) as { issue, title, date_sent: date, link, thumbnail }}
|
||||
{#each data.issues.slice(1) as { issue, title, date_sent: date, link, thumbnail }}
|
||||
<li class="issue-container">
|
||||
<NewsletterIssue {issue} {title} {link} {thumbnail} {date} />
|
||||
</li>
|
||||
@@ -69,6 +69,10 @@
|
||||
right: 32px;
|
||||
}
|
||||
|
||||
&.is-top {
|
||||
top: 20px;
|
||||
}
|
||||
|
||||
& > :global(*) {
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 8px;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { cartNotifications } from '$utils/stores/shop'
|
||||
/**
|
||||
* Add a notification
|
||||
*/
|
||||
export const addNotification = (notification: Notification) => {
|
||||
export const addNotification = (notification: ShopNotification) => {
|
||||
const id = Math.floor(Math.random() * 10000)
|
||||
|
||||
// Add ID and default timeout
|
||||
|
||||
@@ -2,7 +2,6 @@ import { addNotification } from '$utils/functions/notifications'
|
||||
import { cartData } from '$utils/stores/shop'
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add a product to a cart
|
||||
*/
|
||||
@@ -17,6 +16,7 @@ export const addToCart = async (cartId: string, product: any, quantity: number =
|
||||
quantity,
|
||||
})
|
||||
})
|
||||
|
||||
if (updatedCart.ok) {
|
||||
const newCart = await updatedCart.json()
|
||||
cartData.set(newCart)
|
||||
|
||||
Reference in New Issue
Block a user