Files
housesof/src/routes/viewer/[country]/[place]/[photo].svelte

137 lines
4.9 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script context="module">
// Define either to preload data or use the store
let preloaded
currentPhotos.subscribe(store => preloaded = store ? store : undefined)
// Preload data
export async function preload (page, session) {
// Load the photos if not loaded
if (!preloaded) {
const fields = [
'id', 'name', 'slug', 'date', 'image.private_hash',
'location.id', 'location.name', 'location.slug',
'location.country.name', 'location.country.slug'
]
const req = await this.fetch(`${apiEndpoints.rest}/items/photos?fields=${fields.join()}&status=published&filter[location.slug][rlike]=%${page.params.place}%`, {
'Authorization': 'bearer ' + process.env.CONFIG.API_TOKEN
})
const photos = await req.json()
if (req.ok) {
return { photos: photos.data }
}
}
// Use the store otherwise
else return {
photos: preloaded
}
this.error(404, 'Not found')
}
</script>
<script>
import { onMount } from 'svelte'
import { stores } from '@sapper/app'
import {
apiEndpoints,
site,
locations,
currentLocation,
currentPhotos,
pageReady,
pageAnimation
} from 'utils/store'
import { getThumbnail } from 'utils/functions'
// Components
import IconGlobe from 'atoms/IconGlobe'
import IconCross from 'atoms/IconCross'
import Carousel from 'organisms/Carousel'
import Fullscreen from 'organisms/Fullscreen'
import Transition from 'utils/Transition'
import SocialMetas from 'utils/SocialMetas'
// Animations
import { animateIn } from 'animations/viewer'
// Props
export let photos
const { page } = stores()
pageAnimation.set(animateIn)
// Update store current location
currentLocation.set($locations.find(loc => loc.slug === $page.params.place))
currentPhotos.set(photos)
let windowWidth
let gotoLink
let pageTitle
let currentPhoto = photos.find(photo => photo.slug === $page.params.photo)
// Photo has changed (from Carousel)
const photoChanged = event => {
const currentPhoto = event.detail
const windowPathname = window.location.pathname
if (currentPhoto) {
const newUrl = windowPathname.substring(0, windowPathname.lastIndexOf('/') + 1) + currentPhoto.slug
// Go to page via a sapper-noscroll link to avoid scroll jump (hacky)
if (gotoLink && newUrl) {
gotoLink.href = newUrl
gotoLink.click()
}
}
}
/*
** Run code when mounted
*/
onMount(() => {
// Page is loaded
pageReady.set(true)
})
</script>
<svelte:head>
{#if $currentLocation}
<title>{$site.seo_name} {$site.seo_title_default} of {$currentLocation.name}, {$currentLocation.country.name}</title>
<meta name="description" content="{$site.seo_name} {$currentLocation.name} {$currentLocation.description}">
<SocialMetas
url="{process.env.CONFIG.PROD_URL}/viewer/{currentPhoto.location.country.slug}/{currentPhoto.location.slug}/{currentPhoto.slug}"
title="{$site.seo_name} - {$site.seo_title_default} of {$currentLocation.name}, {$currentLocation.country.name}"
description="{$site.seo_name} {$currentLocation.name} {$currentLocation.description}"
image={getThumbnail(currentPhoto.image.private_hash, 1200, 630)}
/>
{/if}
</svelte:head>
<svelte:window bind:innerWidth={windowWidth} />
<main class="housesof" class:is-transitioning={!$pageReady}>
<section class="viewer">
<div class="viewer__top">
<p class="tip">Tap for fullscreen</p>
<div class="viewer__buttons">
<a href="/choose" class="button-control button-control--dashed" aria-label="Change the location" rel="prefetch">
<IconGlobe color="#fff" width={windowWidth >= 768 ? 22 : 18} />
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<circle cx="50%" cy="50%" r="{windowWidth >= 768 ? 32 : 24}px"></circle>
</svg>
</a>
{#if $currentLocation}
<a href="/location/{$currentLocation.country.slug}/{$currentLocation.slug}" class="button-control button-control--lightpink dir-bottom" aria-label="Back to photos" rel="prefetch">
<IconCross color="#fff" width="18" class="icon" />
<IconCross color="#fff" width="18" class="icon" hidden="true" />
</a>
{/if}
</div>
<a href="/" bind:this={gotoLink} aria-hidden="true" hidden class="hidden" sapper-noscroll>&nbsp;</a>
</div>
<Carousel {photos} viewer={true}
on:photoChange={photoChanged}
/>
<Fullscreen />
</section>
</main>