Place: Add photo Transition In, Add Illustration system, Visual fixes
- Add a transition in on each photo component (scale down + fade in), TODO: Parallax on number - Illustration takes two images and changes the source depending on the viewport size
This commit is contained in:
211
src/routes/location/[country]/[place].svelte
Normal file
211
src/routes/location/[country]/[place].svelte
Normal file
@@ -0,0 +1,211 @@
|
||||
<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 req = await this.fetch(apiEndpoints.gql, {
|
||||
method: 'post',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ query: `{
|
||||
photos (filter: { slug_has: "${page.params.place}" }, limit: -1) {
|
||||
data {
|
||||
id
|
||||
name
|
||||
slug
|
||||
date
|
||||
created_on
|
||||
modified_on
|
||||
}
|
||||
}
|
||||
}`})
|
||||
})
|
||||
const photos = await req.json()
|
||||
console.log(photos)
|
||||
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]
|
||||
$: dateUpdatedFull = latestPhoto ? formatDate(latestPhoto.modified_on, 'FULL') : ''
|
||||
$: dateUpdatedDatetime = latestPhoto ? formatDate(latestPhoto.modified_on, 'DATETIME') : ''
|
||||
$: dateUpdatedRelative = latestPhoto ? relativeTime(latestPhoto.modified_on, 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" 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>
|
||||
|
||||
<div class="place__illustration"
|
||||
style="--url-desktop: url({location.illustration_desktop.full_url}); --url-mobile: url({location.illustration_mobile.full_url});"
|
||||
/>
|
||||
</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 />
|
||||
Reference in New Issue
Block a user