209 lines
7.8 KiB
Svelte
209 lines
7.8 KiB
Svelte
<script context="module">
|
||
import { apiEndpoints } from 'utils/store'
|
||
|
||
// Preload data
|
||
export async function preload (page, session) {
|
||
// Load photos
|
||
const fields = [
|
||
'id', 'name', 'slug', 'date', 'image.private_hash',
|
||
'location.id', 'location.name', 'location.slug', 'location.region',
|
||
'location.country.name', 'location.country.slug',
|
||
'created_on', 'modified_on'
|
||
].join(',')
|
||
const sort = ['-created_on', 'name'].join(',')
|
||
const limit = -1
|
||
const req = await this.fetch(`${apiEndpoints.rest}/items/photos?fields=${fields}&status=published&filter[location.slug][rlike]=%${page.params.place}%&limit=${limit}&sort=${sort}`, {
|
||
'Authorization': 'bearer ' + process.env.CONFIG.API_TOKEN
|
||
})
|
||
const photos = await req.json()
|
||
if (req.ok) {
|
||
return { photos: photos.data }
|
||
}
|
||
this.error(404, 'Not found')
|
||
}
|
||
</script>
|
||
|
||
<script>
|
||
import { onMount } from 'svelte'
|
||
import { stores } from '@sapper/app'
|
||
import {
|
||
site,
|
||
locations,
|
||
currentLocation,
|
||
currentPhotos,
|
||
pageReady,
|
||
pageAnimation
|
||
} from 'utils/store'
|
||
import { formatDate, relativeTime, getThumbnail } from 'utils/functions'
|
||
// Components
|
||
import IconGlobe from 'atoms/IconGlobe'
|
||
import IconGlobeSmall from 'atoms/IconGlobeSmall'
|
||
import LinkChange from 'atoms/LinkChange'
|
||
import ToggleLayout from 'atoms/ToggleLayout'
|
||
import Photo from 'molecules/Photo'
|
||
import Switcher from 'molecules/Switcher'
|
||
import Pagination from 'organisms/Pagination'
|
||
import Footer from 'organisms/Footer'
|
||
import SocialMetas from 'utils/SocialMetas'
|
||
// Animations
|
||
import { animateIn } from 'animations/place'
|
||
|
||
// Props and variables
|
||
export let photos
|
||
const { page } = stores()
|
||
pageAnimation.set(animateIn)
|
||
let layoutSetting
|
||
let windowWidth
|
||
$: latestPhoto = photos[0]
|
||
|
||
// Update current location
|
||
const location = $locations.find(loc => loc.slug === $page.params.place)
|
||
const { description, country, illu_desktop, illu_desktop_2x, illu_mobile } = location
|
||
currentLocation.set(location)
|
||
currentPhotos.set(photos)
|
||
|
||
// Define dates
|
||
$: latestPhotoModified = latestPhoto ? latestPhoto.modified_on.replace(' ', 'T') : ''
|
||
$: dateUpdatedFull = latestPhoto ? formatDate(latestPhotoModified, 'FULL') : ''
|
||
$: dateUpdatedDatetime = latestPhoto ? formatDate(latestPhotoModified, 'DATETIME') : ''
|
||
$: dateUpdatedRelative = latestPhoto ? relativeTime(latestPhotoModified, 2592000000) : ''
|
||
|
||
|
||
/*
|
||
** Pagination
|
||
*/
|
||
let photosPerPage = $site.photos_per_page
|
||
let currentIndex = photosPerPage
|
||
|
||
// Hide photos by default
|
||
photos.forEach((photo, index) => photo.hidden = (index + 1 > photosPerPage) ? true : false)
|
||
let paginatedPhotos = photos.filter(photo => photo.hidden === false)
|
||
|
||
// Update pagination event from Pagination component
|
||
const updatePagination = event => paginatedPhotos = event.detail
|
||
|
||
|
||
/*
|
||
** Run code when mounted
|
||
*/
|
||
onMount(() => {
|
||
// Page is loaded
|
||
pageReady.set(true)
|
||
|
||
// Get layout setting from storage
|
||
layoutSetting = localStorage.getItem('photosLayout')
|
||
})
|
||
</script>
|
||
|
||
<svelte:head>
|
||
<title>{$site.seo_name} – {$site.seo_title_default} of {location.name}, {country.name}</title>
|
||
<meta name="description" content="{$site.seo_name} {location.name} {description}">
|
||
<SocialMetas
|
||
url="{process.env.CONFIG.PROD_URL}/location/{country.slug}/{location.slug}"
|
||
title="{$site.seo_name} – {$site.seo_title_default} of {location.name}, {country.name}"
|
||
description="{$site.seo_name} {location.name} {description}"
|
||
image={latestPhoto ? getThumbnail(latestPhoto.image.private_hash, 1200, 630) : null}
|
||
/>
|
||
</svelte:head>
|
||
|
||
<svelte:window bind:innerWidth={windowWidth} />
|
||
|
||
<main class="housesof" class:is-transitioning={!$pageReady}>
|
||
<section class="place">
|
||
<div class="place__title">
|
||
<h1 class="title-location title-location--big" aria-label="Houses of {location.name}" data-rellax-speed="-2.75" data-rellax-max-y="200">
|
||
<span class="place__title_top anim-mask">
|
||
<span class="place__title_houses">Houses</span>
|
||
<em class="place__title_of">of</em>
|
||
</span>
|
||
<span class="place__title_bottom anim-mask">
|
||
<span class="place__title_name">{location.name}</span>
|
||
</span>
|
||
</h1>
|
||
|
||
<div data-rellax-speed={windowWidth <= 768 ? -2.5 : -1.75} data-rellax-max-y="200">
|
||
<a href="/choose" class="button-control button-control--big button-control--dashed" aria-label="Change location">
|
||
<span class="center">
|
||
<IconGlobe width={windowWidth <= 768 ? 32 : 44} color="#fff" />
|
||
<span>Change</span>
|
||
</span>
|
||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
|
||
<circle cx="50%" cy="50%" r="43%" />
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="place__wrap wrap">
|
||
<div class="place__description">
|
||
<div class="wrapper">
|
||
<p>{$site.description}</p>
|
||
|
||
{#if description}
|
||
<p>
|
||
Houses Of
|
||
<LinkChange href="/choose" text={location.name}>
|
||
<IconGlobeSmall width="14" color="#999" />
|
||
</LinkChange>
|
||
{description}
|
||
</p>
|
||
{/if}
|
||
|
||
{#if photos.length}
|
||
<p class="updated style-caps">
|
||
<strong>Updated</strong>
|
||
<time datetime={dateUpdatedDatetime} title={dateUpdatedFull}>{dateUpdatedRelative}</time>
|
||
</p>
|
||
|
||
<ToggleLayout />
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{#if illu_desktop || illu_desktop_2x || illu_mobile}
|
||
<div class="place__illustration">
|
||
<div class="parallax" data-rellax-speed="-5" data-rellax-max-y="400">
|
||
<div class="place__illustration_img" style="{`--url-desktop: ${illu_desktop ? `url(${illu_desktop.full_url});` : undefined}`}
|
||
{`--url-desktop-2x: ${illu_desktop_2x ? `url(${illu_desktop_2x.full_url});` : undefined}`}
|
||
{`--url-mobile: ${illu_mobile ? `url(${illu_mobile.full_url});` : undefined}`}"
|
||
/>
|
||
</div>
|
||
</div>
|
||
{/if}
|
||
</section>
|
||
|
||
<section class="photos photos--{layoutSetting || 'list'}">
|
||
<div class="photos__sidewrap wrap">
|
||
<aside class="photos__side">
|
||
<Switcher type="switcher--side" />
|
||
|
||
{#if photos.length}
|
||
<p class="updated style-caps">
|
||
<strong>Updated</strong>
|
||
<time datetime={dateUpdatedDatetime} title={dateUpdatedFull}>{dateUpdatedRelative}</time>
|
||
</p>
|
||
{/if}
|
||
</aside>
|
||
</div>
|
||
|
||
{#if photos}
|
||
<div class="photos__view wrap">
|
||
{#each paginatedPhotos as photo, index}
|
||
<Photo {photo} index={photos.length - photos.indexOf(photo)} />
|
||
{/each}
|
||
</div>
|
||
|
||
<Pagination {photos} {paginatedPhotos} {photosPerPage}
|
||
on:updatePagination={updatePagination}
|
||
/>
|
||
|
||
{:else}
|
||
<div class="wrap" style="padding-top: 20vw; padding-bottom: 20vw;">
|
||
<p style="text-align: center; color: #333;">No photo for {location.name}</p>
|
||
</div>
|
||
{/if}
|
||
</section>
|
||
|
||
<Footer />
|
||
</main> |