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

198 lines
6.6 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">
import { apiEndpoints } from '../../../utils/store'
// Preload data
export async function preload (page, session) {
// Load photos
const req = await this.fetch(`${apiEndpoints.rest}/items/photos?fields=id,name,slug,date,image.*,location.*,location.country.*,created_on,modified_on&filter[location.slug][rlike]=%${page.params.place}%&limit=-1&sort=-created_on,name`)
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,
pageTransition
} from '../../../utils/store'
import { formatDate, relativeTime, getThumbnail } from '../../../utils/functions'
const { page } = stores()
// Dependencies
import lazySizes from 'lazysizes'
// 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'
pageTransition.onAnimationEnd = animateIn
// Props and variables
export let photos
let layoutSetting
// Update current location
const location = $locations.find(loc => loc.slug === $page.params.place)
currentLocation.set(location)
currentPhotos.set(photos)
// Define dates
$: latestPhoto = photos[0]
$: 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 = 2 // 12
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.paginatedPhotos
/*
** 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} Beautiful houses of {location.name}, {location.country.name}</title>
<meta name="description" content="{$site.seo_name} {location.name} {location.description}">
<SocialMetas
url="https://housesof.world/location/{location.country.slug}/{location.slug}"
title="{$site.seo_name} Beautiful houses of {location.name}, {location.country.name}"
description="{$site.seo_name} {location.name} {location.description}"
image={latestPhoto ? getThumbnail(latestPhoto.image.private_hash, 1200, 630) : null}
/>
</svelte:head>
<section class="place">
<div class="place__title">
<h1 class="title-location title-location--big" aria-label="Houses of {location.name}">
<span class="place__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>
<a href="/choose" class="button-control button-control--big button-control--dashed" aria-label="Change the location" sapper-noscroll>
<span class="center">
<IconGlobe width="44" color="#fff" />
<span>Change</span>
</span>
<svg>
<circle cx="50%" cy="50%" r="43%" />
</svg>
</a>
</div>
<div class="place__wrap wrap">
<div class="place__description">
<div class="wrapper">
<p>{$site.description}</p>
{#if location.description}
<p>
Houses Of
<LinkChange href="/choose" text={location.name} noScroll="true">
<IconGlobeSmall width="14" color="#999" />
</LinkChange>
{location.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 location.illustration_desktop && location.illustration_mobile}
<div class="place__illustration"
style="--url-desktop: url({location.illustration_desktop.full_url}); --url-mobile: url({location.illustration_mobile.full_url});"
/>
{/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.length}
<div class="photos__view wrap">
{#each paginatedPhotos as photo, index}
<Photo
photo={photo}
index={photos.length - photos.indexOf(photo)}
layout={layoutSetting}
/>
{/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 />