🔥 Make Photos page completely dynamic with filters

- The page now reacts properly with default Select options (`default` was used to set current instead of `selected`)
- Make `filtered` variable reactive from filterCountry/filterSort
- Reset link goes to parameters and not just `/photos`
- Show latest updated date from first photo of the `photos` data
- Display the total of photo depending on the country (calculated from `__layout`)
This commit is contained in:
2021-10-12 00:17:04 +02:00
parent 80747ffaf4
commit ee851f2cfa

View File

@@ -1,5 +1,6 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores' import { page } from '$app/stores'
import { browser } from '$app/env'
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { getContext } from 'svelte' import { getContext } from 'svelte'
import { fly } from 'svelte/transition' import { fly } from 'svelte/transition'
@@ -18,7 +19,6 @@
import Newsletter from '$components/organisms/Newsletter.svelte' import Newsletter from '$components/organisms/Newsletter.svelte'
export let photos: any[] export let photos: any[]
export let lastUpdated: string
export let totalPhotos: number export let totalPhotos: number
export let filteredCountryExists: boolean export let filteredCountryExists: boolean
@@ -31,10 +31,13 @@
// Filters // Filters
const urlFiltersParams = new URLSearchParams() const urlFiltersParams = new URLSearchParams()
let filtered: boolean = false let filtered: boolean
let filterCountry: any = $page.query.get('country') || defaultCountry let filterCountry: any = $page.query.get('country') || defaultCountry
let filterSort: string = $page.query.get('sort') || defaultSort let filterSort: string = $page.query.get('sort') || defaultSort
let countryFlagId: string let countryFlagId: string
$: filtered = filterCountry !== defaultCountry || filterSort !== defaultSort
$: latestPhoto = photos[0]
// Pages related informations // Pages related informations
let currentPage: number = 1 let currentPage: number = 1
@@ -56,10 +59,10 @@
} }
// Update URL filtering params from filter values // Update URL filtering params from filter values
if (filtered && filterCountry && filterSort) { if (browser) {
urlFiltersParams.set('country', filterCountry) urlFiltersParams.set('country', filterCountry)
urlFiltersParams.set('sort', filterSort) urlFiltersParams.set('sort', filterSort)
goto(`${$page.path}?${urlFiltersParams.toString()}`, { keepfocus:true, replaceState:true, noscroll:true }) goto(`${$page.path}?${urlFiltersParams.toString()}`, { replaceState: true, keepfocus: true, noscroll: true })
} }
} }
@@ -69,53 +72,24 @@
*/ */
// Country select // Country select
const handleCountryChange = ({ detail: value }) => { const handleCountryChange = ({ detail: value }) => {
console.log('country change:', value) filterCountry = value === defaultCountry ? defaultCountry : value
filtered = true
filterCountry = value
} }
// Sort select // Sort select
const handleSortChange = ({ detail: value }) => { const handleSortChange = ({ detail: value }) => {
console.log('sort change:', value) filterSort = value === defaultSort ? defaultSort : value
filtered = true
filterSort = value
} }
// Reset filters
/**
* Reset filters
*/
const resetFiltered = () => { const resetFiltered = () => {
filtered = false
filterCountry = defaultCountry filterCountry = defaultCountry
filterSort = defaultSort filterSort = defaultSort
goto($page.path, { replaceState: true, noscroll: true })
} }
/** /**
* Load photos * Load photos
*/ */
// Load more photos from CTA
const loadMorePhotos = async () => {
// Append more photos from API including options and page
const newPhotos: any = await loadPhotos(currentPage + 1)
console.log(newPhotos)
if (newPhotos) {
photos = [...photos, ...newPhotos]
// Define actions if the number of new photos is the expected ones
if (newPhotos.length === Number(import.meta.env.VITE_GRID_INCREMENT)) {
// Increment the current page
currentPage++
}
// Increment the currently visible amount of photos
currentPhotosAmount += newPhotos.length
}
}
// [function] Load photos helper // [function] Load photos helper
const loadPhotos = async (page?: number) => { const loadPhotos = async (page?: number) => {
const res = fetchAPI(` const res = fetchAPI(`
@@ -151,6 +125,25 @@
throw new Error('Error while loading new photos') throw new Error('Error while loading new photos')
} }
} }
// Load more photos from CTA
const loadMorePhotos = async () => {
// Append more photos from API including options and page
const newPhotos: any = await loadPhotos(currentPage + 1)
if (newPhotos) {
photos = [...photos, ...newPhotos]
// Define actions if the number of new photos is the expected ones
if (newPhotos.length === Number(import.meta.env.VITE_GRID_INCREMENT)) {
// Increment the current page
currentPage++
}
// Increment the currently visible amount of photos
currentPhotosAmount += newPhotos.length
}
}
</script> </script>
<Metas <Metas
@@ -175,14 +168,15 @@
name="country" id="filter_country" name="country" id="filter_country"
options={[ options={[
{ {
value: 'all', value: defaultCountry,
name: 'Worldwide', name: 'Worldwide',
default: filterCountry === defaultCountry default: true,
selected: filterCountry === defaultCountry,
}, },
...countries.map(({ slug, name }) => ({ ...countries.map(({ slug, name }) => ({
value: slug, value: slug,
name, name,
default: filterCountry === slug, selected: filterCountry === slug,
})) }))
]} ]}
on:change={handleCountryChange} on:change={handleCountryChange}
@@ -199,8 +193,17 @@
<Select <Select
name="sort" id="filter_sort" name="sort" id="filter_sort"
options={[ options={[
{ value: 'latest', name: 'Latest photos', default: filterSort === defaultSort }, {
{ value: 'oldest', name: 'Oldest photos', default: filterSort === 'oldest' }, value: 'latest',
name: 'Latest photos',
default: true,
selected: filterSort === defaultSort
},
{
value: 'oldest',
name: 'Oldest photos',
selected: filterSort === 'oldest'
},
]} ]}
on:change={handleSortChange} on:change={handleSortChange}
value={filterSort} value={filterSort}
@@ -233,7 +236,7 @@
<section class="photos__content"> <section class="photos__content">
<div class="grid container"> <div class="grid container">
{#if photos} {#if photos.length}
<div class="photos__grid"> <div class="photos__grid">
{#each photos as { image, slug, location }} {#each photos as { image, slug, location }}
<div class="photo shadow-photo"> <div class="photo shadow-photo">
@@ -246,8 +249,8 @@
</div> </div>
<div class="controls grid"> <div class="controls grid">
<p class="controls__date" title={dayjs(lastUpdated).format('DD/MM/YYYY, hh:mm')}> <p class="controls__date" title={dayjs(latestPhoto.date_created).format('DD/MM/YYYY, hh:mm')}>
Last updated: <time datetime={dayjs(lastUpdated).format('YYYY-MM-DD')}>{dayjs().to(dayjs(lastUpdated))}</time> Last updated: <time datetime={dayjs(latestPhoto.date_created).format('YYYY-MM-DD')}>{dayjs().to(dayjs(latestPhoto.date_created))}</time>
</p> </p>
<Button <Button
@@ -316,10 +319,7 @@
slug slug
country { slug } country { slug }
} }
} date_created
total_published: photo_aggregated {
count { id }
} }
country: country ( country: country (
@@ -331,20 +331,25 @@
slug slug
} }
lastUpdated: photo (limit: 1, sort: "-date_created", filter: { status: { _eq: "published" }}) { # Total
date_created total_published: photo_aggregated {
count { id }
} }
} }
`) `)
const { data } = res const { data } = res
// Calculate total of photos (if default or specific)
const totalPhotos = queryCountry === 'all'
? data.total_published[0].count.id
: stuff.countries.find((country: any) => country.slug === queryCountry).count
return { return {
props: { props: {
photos: data.photos, photos: data.photos,
filteredCountryExists: data.country.length > 0, filteredCountryExists: data.country.length > 0,
totalPhotos: data.total_published[0].count.id, totalPhotos,
lastUpdated: data.lastUpdated[0].date_created,
} }
} }
} }