🚧 Migrate to new SvelteKit routing system

A bit annoying but for the best I guess?
This commit is contained in:
2022-08-16 15:54:15 +02:00
parent cf2becc931
commit 5e5c08ddd1
40 changed files with 775 additions and 774 deletions

14
src/app.d.ts vendored
View File

@@ -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

View File

@@ -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
}
}
}

View File

@@ -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>

View 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
View 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}

View File

@@ -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)
}
}

View File

@@ -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"

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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 }

View File

@@ -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>

View File

@@ -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)
}
}

View File

@@ -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>

View File

@@ -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,
}
}
}

View 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)
}
}

View File

@@ -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`
}
}
}

View 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`)
}
}

View File

@@ -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)
}
}

View File

@@ -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(() => {

View File

@@ -1,5 +1,5 @@
<style lang="scss">
@import "../style/pages/explore";
@import "../../style/pages/explore";
</style>
<script lang="ts">

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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>

View 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)
}
}

View 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 />

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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} />

View File

@@ -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>

View File

@@ -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)
}
}

View File

@@ -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>

View File

@@ -69,6 +69,10 @@
right: 32px;
}
&.is-top {
top: 20px;
}
& > :global(*) {
&:not(:last-child) {
margin-bottom: 8px;

View File

@@ -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

View File

@@ -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)