Files
housesof/src/routes/[country]/[location]/index.svelte

258 lines
8.6 KiB
Svelte

<script lang="ts">
import { page } from '$app/stores'
import dayjs from 'dayjs'
import advancedFormat from 'dayjs/plugin/advancedFormat'
import relativeTime from 'dayjs/plugin/relativeTime'
import { getAssetUrl } from '$utils/helpers'
// Components
import Button from '$components/atoms/Button.svelte'
import IconEarth from '$components/atoms/IconEarth.svelte'
import Image from '$components/atoms/Image.svelte'
export let data: any
export let photos: any[]
export let lastUpdated: string
export let totalPhotos: number
dayjs.extend(advancedFormat)
dayjs.extend(relativeTime)
const { params } = $page
let descriptionEl: HTMLElement
let currentPage: number = 1
let ended: boolean
let currentPhotosAmount: number
$: currentPhotosAmount = photos.length
$: ended = currentPhotosAmount === totalPhotos
/**
* Load photos
*/
// Load more photos from CTA
const loadMorePhotos = async () => {
// Append more photos from API
const newPhotos: any = await loadPhotos(currentPage + 1)
if (newPhotos) {
photos = [...photos, ...newPhotos]
// Define actions if the number of new photos is the expected ones
if (newPhotos.length === Number(import.meta.env.VITE_LIST_INCREMENT)) {
// Increment the current page
currentPage++
}
// Increment the currently visible amount of photos
currentPhotosAmount += newPhotos.length
}
}
// [function] Load photos helper
const loadPhotos = async (page?: number) => {
const res = fetchAPI(`
query {
photos: photo (
filter: {
location: { slug: { _eq: "${params.location}" }},
status: { _eq: "published" },
},
sort: "-date_created",
limit: ${import.meta.env.VITE_LIST_INCREMENT},
page: ${page},
) {
title
slug
image {
id
title
}
date_taken
date_created
}
}
`)
const { data: { photos }} = await res
if (photos) {
// Return new photos
return photos
} else {
throw new Error('Error while loading new photos')
}
}
</script>
<main class="location-page">
<section class="location-page__intro grid"
style="
--illus-desktop: url({getAssetUrl(data.illustration_desktop.id, 1600, 1466, 90)});
--illus-desktop-2x: url({getAssetUrl(data.illustration_desktop_2x.id, 3200, 2932, 90)});
--illus-mobile: url({getAssetUrl(data.illustration_mobile.id, 1125, 2317, 90)});
"
>
<h1 class="title">
<span class="housesof">
<strong>Houses</strong>
<span>of</span>
</span>
<strong class="city">
{data.name}
</strong>
</h1>
<div class="location-page__description grid" bind:this={descriptionEl}>
<div class="wrap">
<div class="text-medium">
Houses of {data.name} {data.description}
</div>
<div class="info">
<p class="text-label">
Photos by
{#each data.credits as { credit_id: { name, website }}}
{#if website}
<a href={website} target="_blank" rel="noopener external">
{name}
</a>
{:else}
<span>{name}</span>
{/if}
{/each}
</p>
&middot;
<p class="text-label" title={dayjs(photos[0].date_created).format('DD/MM/YYYY, hh:mm')}>
Updated <time datetime={dayjs(photos[0].date_created).format('YYYY-MM-DD')}>
{dayjs().to(dayjs(photos[0].date_created))}
</time>
</p>
</div>
<div class="ctas">
<Button url="/locations" text="Change location" class="shadow-small">
<IconEarth />
</Button>
<Button url="/shop" text="Buy the poster" class="button--pink shadow-small">
<!-- <IconEarth /> -->
</Button>
</div>
</div>
</div>
<div class="location-page__illustration" />
</section>
<section class="location-page__houses grid">
{#each photos as { title, image: { id, title: alt }, slug, date_taken }}
<div class="house grid">
<div class="house__info">
<a href="/{params.country}/{params.location}/{slug}">
<h2 class="title-image">
{title}
</h2>
<time class="text-date" datetime={dayjs(date_taken).format('YYYY-MM-DD')}>
{dayjs(date_taken).format('MMMM, Do YYYY')}
</time>
</a>
</div>
<a class="house__photo" href="/{params.country}/{params.location}/{slug}">
<Image
id={id}
alt="{alt}"
width={1280}
height={853}
class="shadow-photo"
/>
<span class="house__index title-index">22</span>
</a>
</div>
{/each}
</section>
<section class="location-page__next">
<div class="pagination" role="button" on:click={!ended && loadMorePhotos} disabled={ended ? ended : undefined}>
<div class="pagination__progress">
<span class="current">{currentPhotosAmount}</span>
<span>/</span>
<span class="total">{totalPhotos}</span>
</div>
{#if !ended}
<p class="pagination__more">See more photos</p>
{:else}
<p>You've seen it all!</p>
{/if}
</div>
</section>
</main>
<script context="module" lang="ts">
import { fetchAPI } from '$utils/api'
export async function load ({ page, session, fetch, context }) {
const { location } = page.params
const res = await fetchAPI(`
query {
location (
filter: {
slug: { _eq: "${location}" },
status: { _eq: "published" },
},
limit: ${import.meta.env.VITE_LIST_AMOUNT},
) {
name
slug
description
date_updated
illustration_desktop { id }
illustration_desktop_2x { id }
illustration_mobile { id }
credits {
credit_id {
name
website
}
}
}
photos: photo (
filter: {
location: { slug: { _eq: "${location}" }}
},
sort: "-date_created",
limit: ${import.meta.env.VITE_LIST_AMOUNT},
page: 1,
) {
title
slug
image {
id
title
}
date_taken
date_created
}
total_published: photo (
filter: {
status: { _eq: "published" },
location: { slug: { _eq: "${location}" }}
}
) {
id
}
}
`)
const { data } = res
return {
props: {
data: data.location[0],
photos: data.photos,
totalPhotos: data.total_published.length,
lastUpdated: data.photos[0].date_created,
}
}
}
</script>