Photo viewer
This commit is contained in:
148
src/routes/viewer/[country]/[location]/[photo].svelte
Normal file
148
src/routes/viewer/[country]/[location]/[photo].svelte
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
<script context="module">
|
||||||
|
// Svelte
|
||||||
|
import { api, locations, currentLocation } from '../../../../store'
|
||||||
|
|
||||||
|
// Define to preload data or load the store
|
||||||
|
let preloaded
|
||||||
|
currentLocation.subscribe(store => {
|
||||||
|
preloaded = (store) ? store : undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sapper preload data
|
||||||
|
export async function preload (page, session) {
|
||||||
|
if (preloaded === undefined) {
|
||||||
|
const photos = await this.fetch(`${api.rest}/items/photos?fields=id,name,slug,image.data,created_on&filter[location.slug][rlike]=%${page.params.location}%`)
|
||||||
|
const photosData = await photos.json()
|
||||||
|
return {
|
||||||
|
photos: photosData.data
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
photos: preloaded.photos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { stores } from '@sapper/app'
|
||||||
|
const { page, session, preloading } = stores()
|
||||||
|
|
||||||
|
// Dependencies
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import advancedFormat from 'dayjs/plugin/advancedFormat'
|
||||||
|
dayjs.extend(advancedFormat)
|
||||||
|
|
||||||
|
export let photos
|
||||||
|
let currentIndex
|
||||||
|
let indexFormated
|
||||||
|
let viewerPhotos
|
||||||
|
|
||||||
|
// Define current location
|
||||||
|
if ($currentLocation === undefined) {
|
||||||
|
currentLocation.set({
|
||||||
|
location: $locations.find(location => location.slug === $page.params.location),
|
||||||
|
photos: photos
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set current photo, index and siblings
|
||||||
|
const setCurrentPhotos = () => {
|
||||||
|
// Define index and prev/next photos
|
||||||
|
currentIndex = photos.findIndex(photo => photo.slug === $page.params.photo)
|
||||||
|
indexFormated = (currentIndex < 10) ? '0' + (currentIndex + 1) : currentIndex + 1
|
||||||
|
viewerPhotos = {
|
||||||
|
current: photos[currentIndex],
|
||||||
|
// Last photo if first, otherwise index-1
|
||||||
|
prev: (currentIndex === 0) ? photos[photos.length - 1] : photos[currentIndex - 1],
|
||||||
|
// First photo if last, otherwise index+1
|
||||||
|
next: (currentIndex === photos.length - 1) ? photos[0] : photos[currentIndex + 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On photo page change
|
||||||
|
page.subscribe(({ path, params, query }) => {
|
||||||
|
if (path.includes('/viewer/')) {
|
||||||
|
setCurrentPhotos()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Define things
|
||||||
|
const locationFull = `${$currentLocation.location.name}, ${$currentLocation.location.country.name}`
|
||||||
|
const path = `/viewer/${$currentLocation.location.country.slug}/${$currentLocation.location.slug}/`
|
||||||
|
|
||||||
|
// Get thumbnail
|
||||||
|
const getThumb = (photo, size) => {
|
||||||
|
if (photo) {
|
||||||
|
const thumbnail = photo.image.data.thumbnails.find(thumb => thumb.url.includes(`key=${size}`))
|
||||||
|
return thumbnail.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard navigation
|
||||||
|
const keyboardNav = event => {
|
||||||
|
const keyCode = event.keyCode
|
||||||
|
|
||||||
|
// Previous
|
||||||
|
if ([37,80].includes(keyCode)) document.getElementById('photo_prev').click()
|
||||||
|
// Next
|
||||||
|
else if ([39,78,32].includes(keyCode)) document.getElementById('photo_next').click()
|
||||||
|
// Close
|
||||||
|
else if ([27,67].includes(keyCode)) document.getElementById('photo_close').click()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- <pre>{JSON.stringify(viewerPhotos, null, 2)}</pre> -->
|
||||||
|
|
||||||
|
<svelte:window on:keydown={keyboardNav} />
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="nav content">
|
||||||
|
<a href="/choose" class="button is-info" id="photo_close">Change location</a>
|
||||||
|
<a href="/location/{$currentLocation.location.country.slug}/{$currentLocation.location.slug}" class="button is-dark" id="photo_close">Close</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="photo">
|
||||||
|
<div class="image">
|
||||||
|
<img src="{getThumb(viewerPhotos.current, 'large')}" srcset="{getThumb(viewerPhotos.current, 'large')} 1x, {getThumb(viewerPhotos.current, 'large-2x')} 2x" alt="{viewerPhotos.current.name}">
|
||||||
|
</div>
|
||||||
|
<div class="details content">
|
||||||
|
<strong class="is-size-5">{viewerPhotos.current.name}</strong> <br>
|
||||||
|
<span>{locationFull}</span> <br>
|
||||||
|
<span>{indexFormated}</span> <br>
|
||||||
|
<span>{dayjs(viewerPhotos.current.date).format('MMM Do, YYYY')}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section">
|
||||||
|
<div class="level">
|
||||||
|
<div class="level-left">
|
||||||
|
<a href="{path + viewerPhotos.prev.slug}" id="photo_prev">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<img src="{getThumb(viewerPhotos.prev, 'thumbnail')}" alt="{viewerPhotos.prev.name}" width="200">
|
||||||
|
</div>
|
||||||
|
<div class="media-content content">
|
||||||
|
<strong class="is-size-5">{viewerPhotos.prev.name}</strong> <br>
|
||||||
|
<span>{locationFull}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="level-right">
|
||||||
|
<a href="{path + viewerPhotos.next.slug}" id="photo_next">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-content content has-text-right">
|
||||||
|
<strong class="is-size-5">{viewerPhotos.next.name}</strong> <br>
|
||||||
|
<span>{locationFull}</span>
|
||||||
|
</div>
|
||||||
|
<div class="media-right">
|
||||||
|
<img src="{getThumb(viewerPhotos.next, 'thumbnail')}" alt="{viewerPhotos.next.name}" width="200">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user