1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-01 08:31:59 +00:00

feat(web): places page (#6669)

Add a place overview page, like the "People" page.
This adds the same functionality as available on mobile.
This commit is contained in:
Emanuel Bennici 2024-01-26 19:11:54 +01:00 committed by GitHub
parent 8aef92affc
commit 77f11e3ae5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 74 additions and 1 deletions

View file

@ -21,6 +21,7 @@ export enum AppRoute {
ARCHIVE = '/archive',
FAVORITES = '/favorites',
PEOPLE = '/people',
PLACES = '/places',
PHOTOS = '/photos',
EXPLORE = '/explore',
SHARING = '/sharing',

View file

@ -72,8 +72,13 @@
{#if places.length > 0}
<div class="mb-6 mt-2">
<div>
<div class="flex justify-between">
<p class="mb-4 font-medium dark:text-immich-dark-fg">Places</p>
<a
href={AppRoute.PLACES}
class="pr-4 text-sm font-medium hover:text-immich-primary dark:text-immich-dark-fg dark:hover:text-immich-dark-primary"
draggable="false">View All</a
>
</div>
<div class="flex flex-row flex-wrap gap-4">
{#each places as item (item.data.id)}

View file

@ -0,0 +1,52 @@
<script lang="ts">
import type { SearchExploreResponseDto } from '@api';
import type { PageData } from './$types';
import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
import { mdiMapMarkerOff } from '@mdi/js';
import Icon from '$lib/components/elements/icon.svelte';
import { AppRoute } from '$lib/constants';
import Thumbnail from '$lib/components/assets/thumbnail/thumbnail.svelte';
export let data: PageData;
const CITY_FIELD = 'exifInfo.city';
const getFieldItems = (items: SearchExploreResponseDto[]) => {
const targetField = items.find((item) => item.fieldName === CITY_FIELD);
return targetField?.items || [];
};
$: places = getFieldItems(data.items);
$: hasPlaces = places.length > 0;
let innerHeight: number;
</script>
<svelte:window bind:innerHeight />
<UserPageLayout title="Places">
{#if hasPlaces}
<div class="flex flex-row flex-wrap gap-4">
{#each places as item (item.data.id)}
<a class="relative" href="{AppRoute.SEARCH}?q={item.value}" draggable="false">
<div
class="flex w-[calc((100vw-(72px+5rem))/2)] max-w-[156px] justify-center overflow-hidden rounded-xl brightness-75 filter"
>
<Thumbnail thumbnailSize={156} asset={item.data} readonly />
</div>
<span
class="w-100 absolute bottom-2 w-full text-ellipsis px-1 text-center text-sm font-medium capitalize text-white backdrop-blur-[1px] hover:cursor-pointer"
>
{item.value}
</span>
</a>
{/each}
</div>
{:else}
<div class="flex min-h-[calc(66vh_-_11rem)] w-full place-content-center items-center dark:text-white">
<div class="flex flex-col content-center items-center text-center">
<Icon path={mdiMapMarkerOff} size="3.5em" />
<p class="mt-5 text-3xl font-medium">No places</p>
</div>
</div>
{/if}
</UserPageLayout>

View file

@ -0,0 +1,15 @@
import { authenticate } from '$lib/utils/auth';
import { api } from '@api';
import type { PageLoad } from './$types';
export const load = (async () => {
await authenticate();
const { data: items } = await api.searchApi.getExploreData();
return {
items,
meta: {
title: 'Places',
},
};
}) satisfies PageLoad;