Finalize transition away from param-based infinite scroll
This commit is contained in:
parent
af7424315d
commit
0f43b1977b
@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { PATH_ADMIN_PHOTOS } from '@/site/paths';
|
||||
import InfinitePhotoScroll from '../photo/InfinitePhotoScroll';
|
||||
import AdminPhotosTable from './AdminPhotosTable';
|
||||
|
||||
@ -12,7 +13,7 @@ export default function AdminPhotosTableInfinite({
|
||||
}) {
|
||||
return (
|
||||
<InfinitePhotoScroll
|
||||
cacheKey="AdminPhotoTable"
|
||||
cacheKey={`page-${PATH_ADMIN_PHOTOS}`}
|
||||
initialOffset={initialOffset}
|
||||
itemsPerPage={itemsPerPage}
|
||||
useCachedPhotos={false}
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo';
|
||||
import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation';
|
||||
import FilmSimulationOverview from '@/simulation/FilmSimulationOverview';
|
||||
import {
|
||||
getPhotosFilmSimulationDataCached,
|
||||
getPhotosFilmSimulationDataCachedWithPagination,
|
||||
} from '@/simulation/data';
|
||||
import { PaginationParams } from '@/site/pagination';
|
||||
import { getPhotosFilmSimulationDataCached } from '@/simulation/data';
|
||||
import { Metadata } from 'next/types';
|
||||
|
||||
interface FilmSimulationProps {
|
||||
@ -49,16 +45,13 @@ export async function generateMetadata({
|
||||
|
||||
export default async function FilmSimulationPage({
|
||||
params: { simulation },
|
||||
searchParams,
|
||||
}: FilmSimulationProps & PaginationParams) {
|
||||
const {
|
||||
}: FilmSimulationProps) {
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
showMorePath,
|
||||
dateRange,
|
||||
} = await getPhotosFilmSimulationDataCachedWithPagination({
|
||||
{ count, dateRange },
|
||||
] = await getPhotosFilmSimulationDataCached({
|
||||
simulation,
|
||||
searchParams,
|
||||
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
|
||||
});
|
||||
|
||||
return (
|
||||
@ -67,7 +60,6 @@ export default async function FilmSimulationPage({
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,11 +2,7 @@ import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo';
|
||||
import { FilmSimulation, generateMetaForFilmSimulation } from '@/simulation';
|
||||
import FilmSimulationOverview from '@/simulation/FilmSimulationOverview';
|
||||
import FilmSimulationShareModal from '@/simulation/FilmSimulationShareModal';
|
||||
import {
|
||||
getPhotosFilmSimulationDataCached,
|
||||
getPhotosFilmSimulationDataCachedWithPagination,
|
||||
} from '@/simulation/data';
|
||||
import { PaginationParams } from '@/site/pagination';
|
||||
import { getPhotosFilmSimulationDataCached } from '@/simulation/data';
|
||||
import { Metadata } from 'next/types';
|
||||
|
||||
interface FilmSimulationProps {
|
||||
@ -50,22 +46,19 @@ export async function generateMetadata({
|
||||
|
||||
export default async function Share({
|
||||
params: { simulation },
|
||||
searchParams,
|
||||
}: FilmSimulationProps & PaginationParams) {
|
||||
const {
|
||||
}: FilmSimulationProps) {
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
} = await getPhotosFilmSimulationDataCachedWithPagination({
|
||||
{ count, dateRange },
|
||||
] = await getPhotosFilmSimulationDataCached({
|
||||
simulation,
|
||||
searchParams,
|
||||
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
|
||||
});
|
||||
|
||||
return <>
|
||||
<FilmSimulationShareModal {...{ simulation, photos, count, dateRange }} />
|
||||
<FilmSimulationOverview
|
||||
{...{ simulation, photos, count, dateRange, showMorePath }}
|
||||
{...{ simulation, photos, count, dateRange }}
|
||||
animateOnFirstLoadOnly
|
||||
/>
|
||||
</>;
|
||||
|
||||
@ -10,6 +10,7 @@ import { getPhotoSidebarData } from '@/photo/data';
|
||||
import { getPhotos } from '@/photo/db';
|
||||
import { cache } from 'react';
|
||||
import PhotoGridPage from '@/photo/PhotoGridPage';
|
||||
import { PATH_GRID } from '@/site/paths';
|
||||
|
||||
export const dynamic = 'force-static';
|
||||
|
||||
@ -38,6 +39,7 @@ export default async function GridPage() {
|
||||
return (
|
||||
photos.length > 0
|
||||
? <PhotoGridPage
|
||||
cacheKey={`page-${PATH_GRID}`}
|
||||
photos={photos}
|
||||
count={photosCount}
|
||||
sidebar={<div className="sticky top-4 space-y-4 mt-[-4px]">
|
||||
|
||||
@ -1,36 +1,30 @@
|
||||
import { getPhotosCached, getPhotosCountCached } from '@/photo/cache';
|
||||
import MoreComponentsFromSearchParams from
|
||||
'@/components/MoreComponentsFromSearchParams';
|
||||
import StaggeredOgPhotos from '@/photo/StaggeredOgPhotos';
|
||||
import {
|
||||
PaginationParams,
|
||||
getPaginationFromSearchParams,
|
||||
} from '@/site/pagination';
|
||||
import { pathForOg } from '@/site/paths';
|
||||
|
||||
export default async function GridPage({ searchParams }: PaginationParams) {
|
||||
const { offset, limit } = getPaginationFromSearchParams(searchParams);
|
||||
INFINITE_SCROLL_INITIAL_GRID,
|
||||
INFINITE_SCROLL_MULTIPLE_GRID,
|
||||
} from '@/photo';
|
||||
import { getPhotosCached, getPhotosCountCached } from '@/photo/cache';
|
||||
import StaggeredOgPhotos from '@/photo/StaggeredOgPhotos';
|
||||
import StaggeredOgPhotosInfinite from '@/photo/StaggeredOgPhotosInfinite';
|
||||
|
||||
export default async function GridPage() {
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
] = await Promise.all([
|
||||
getPhotosCached({ limit }),
|
||||
getPhotosCached({ limit: INFINITE_SCROLL_INITIAL_GRID }),
|
||||
getPhotosCountCached(),
|
||||
]);
|
||||
|
||||
const showMorePhotos = count > photos.length;
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="grid gap-3 grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
||||
<StaggeredOgPhotos photos={photos} />
|
||||
</div>
|
||||
{showMorePhotos &&
|
||||
<MoreComponentsFromSearchParams
|
||||
label="More photos"
|
||||
path={pathForOg(offset + 1)}
|
||||
/>}
|
||||
</div>
|
||||
<>
|
||||
<StaggeredOgPhotos {...{ photos }} />
|
||||
{count > photos.length &&
|
||||
<div className="mt-3">
|
||||
<StaggeredOgPhotosInfinite
|
||||
initialOffset={photos.length}
|
||||
itemsPerPage={INFINITE_SCROLL_MULTIPLE_GRID}
|
||||
/>
|
||||
</div>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo';
|
||||
import { PaginationParams } from '@/site/pagination';
|
||||
import { PATH_ROOT } from '@/site/paths';
|
||||
import { generateMetaForTag } from '@/tag';
|
||||
import TagOverview from '@/tag/TagOverview';
|
||||
import {
|
||||
getPhotosTagDataCached,
|
||||
getPhotosTagDataCachedWithPagination,
|
||||
} from '@/tag/data';
|
||||
import { getPhotosTagDataCached } from '@/tag/data';
|
||||
import type { Metadata } from 'next';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
@ -55,23 +51,20 @@ export async function generateMetadata({
|
||||
|
||||
export default async function TagPage({
|
||||
params: { tag: tagFromParams },
|
||||
searchParams,
|
||||
}:TagProps & PaginationParams) {
|
||||
}:TagProps) {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const {
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
showMorePath,
|
||||
dateRange,
|
||||
} = await getPhotosTagDataCachedWithPagination({
|
||||
{ count, dateRange },
|
||||
] = await getPhotosTagDataCached({
|
||||
tag,
|
||||
searchParams,
|
||||
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
|
||||
});
|
||||
|
||||
if (photos.length === 0) { redirect(PATH_ROOT); }
|
||||
|
||||
return (
|
||||
<TagOverview {...{ tag, photos, count, dateRange, showMorePath }} />
|
||||
<TagOverview {...{ tag, photos, count, dateRange }} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,12 +1,8 @@
|
||||
import { GRID_THUMBNAILS_TO_SHOW_MAX } from '@/photo';
|
||||
import { PaginationParams } from '@/site/pagination';
|
||||
import { generateMetaForTag } from '@/tag';
|
||||
import TagOverview from '@/tag/TagOverview';
|
||||
import TagShareModal from '@/tag/TagShareModal';
|
||||
import {
|
||||
getPhotosTagDataCached,
|
||||
getPhotosTagDataCachedWithPagination,
|
||||
} from '@/tag/data';
|
||||
import { getPhotosTagDataCached } from '@/tag/data';
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
interface TagProps {
|
||||
@ -52,24 +48,21 @@ export async function generateMetadata({
|
||||
|
||||
export default async function Share({
|
||||
params: { tag: tagFromParams },
|
||||
searchParams,
|
||||
}: TagProps & PaginationParams) {
|
||||
}: TagProps) {
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
|
||||
const {
|
||||
|
||||
const [
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
} = await getPhotosTagDataCachedWithPagination({
|
||||
{ count, dateRange },
|
||||
] = await getPhotosTagDataCached({
|
||||
tag,
|
||||
searchParams,
|
||||
limit: GRID_THUMBNAILS_TO_SHOW_MAX,
|
||||
});
|
||||
|
||||
return <>
|
||||
<TagShareModal {...{ tag, photos, count, dateRange }} />
|
||||
<TagOverview
|
||||
{...{ tag, photos, count, dateRange, showMorePath }}
|
||||
{...{ tag, photos, count, dateRange }}
|
||||
animateOnFirstLoadOnly
|
||||
/>
|
||||
</>;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Photo, PhotoDateRange } from '@/photo';
|
||||
import { Camera } from '.';
|
||||
import { Camera, createCameraKey } from '.';
|
||||
import CameraHeader from './CameraHeader';
|
||||
import PhotoGridPage from '@/photo/PhotoGridPage';
|
||||
|
||||
@ -18,11 +18,17 @@ export default function CameraOverview({
|
||||
}) {
|
||||
return (
|
||||
<PhotoGridPage {...{
|
||||
cacheKey: `camera-${createCameraKey(camera)}`,
|
||||
photos,
|
||||
count,
|
||||
camera,
|
||||
animateOnFirstLoadOnly,
|
||||
header: <CameraHeader {...{ camera, photos, count, dateRange }} />,
|
||||
header: <CameraHeader {...{
|
||||
camera,
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
}} />,
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import Link from 'next/link';
|
||||
import { BiError } from 'react-icons/bi';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import { IMAGE_OG_DIMENSION } from '../image-response';
|
||||
import useOnVisible from '@/utility/useOnVisible';
|
||||
|
||||
export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
|
||||
|
||||
@ -19,6 +20,7 @@ export default function OGTile({
|
||||
onLoad,
|
||||
onFail,
|
||||
retryTime,
|
||||
onVisible,
|
||||
}: {
|
||||
title: string
|
||||
description: string
|
||||
@ -29,7 +31,10 @@ export default function OGTile({
|
||||
onFail?: () => void
|
||||
riseOnHover?: boolean
|
||||
retryTime?: number
|
||||
onVisible?: () => void
|
||||
}) {
|
||||
const ref = useRef<HTMLAnchorElement>(null);
|
||||
|
||||
const [loadingStateInternal, setLoadingStateInternal] =
|
||||
useState(loadingStateExternal ?? 'unloaded');
|
||||
|
||||
@ -46,8 +51,11 @@ export default function OGTile({
|
||||
|
||||
const { width, height, aspectRatio } = IMAGE_OG_DIMENSION;
|
||||
|
||||
useOnVisible(ref, onVisible);
|
||||
|
||||
return (
|
||||
<Link
|
||||
ref={ref}
|
||||
href={path}
|
||||
className={clsx(
|
||||
'group',
|
||||
|
||||
@ -31,7 +31,6 @@ export default function PhotoGrid({
|
||||
animate?: boolean
|
||||
animateOnFirstLoadOnly?: boolean
|
||||
staggerOnFirstLoadOnly?: boolean
|
||||
showMorePath?: string
|
||||
additionalTile?: JSX.Element
|
||||
small?: boolean
|
||||
onLastPhotoVisible?: () => void
|
||||
|
||||
@ -6,17 +6,19 @@ import InfinitePhotoScroll from './InfinitePhotoScroll';
|
||||
import PhotoGrid from './PhotoGrid';
|
||||
|
||||
export default function PhotoGridInfinite({
|
||||
cacheKey,
|
||||
initialOffset,
|
||||
camera,
|
||||
animateOnFirstLoadOnly,
|
||||
}: {
|
||||
initialOffset: number,
|
||||
camera?: Camera,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
cacheKey: string
|
||||
initialOffset: number
|
||||
camera?: Camera
|
||||
animateOnFirstLoadOnly?: boolean
|
||||
}) {
|
||||
return (
|
||||
<InfinitePhotoScroll
|
||||
cacheKey="Grid"
|
||||
cacheKey={cacheKey}
|
||||
initialOffset={initialOffset}
|
||||
itemsPerPage={INFINITE_SCROLL_MULTIPLE_GRID}
|
||||
camera={camera}
|
||||
|
||||
@ -7,6 +7,7 @@ import { clsx } from 'clsx/lite';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
|
||||
export default function PhotoGridPage({
|
||||
cacheKey,
|
||||
photos,
|
||||
count,
|
||||
camera,
|
||||
@ -14,6 +15,7 @@ export default function PhotoGridPage({
|
||||
header,
|
||||
sidebar,
|
||||
}: {
|
||||
cacheKey: string
|
||||
photos: Photo[]
|
||||
count: number
|
||||
camera?: Camera
|
||||
@ -36,6 +38,7 @@ export default function PhotoGridPage({
|
||||
<PhotoGrid {...{ photos, camera, animateOnFirstLoadOnly }} />
|
||||
{count > photos.length &&
|
||||
<PhotoGridInfinite {...{
|
||||
cacheKey,
|
||||
initialOffset: photos.length,
|
||||
camera,
|
||||
animateOnFirstLoadOnly,
|
||||
|
||||
@ -15,6 +15,7 @@ export default function PhotoOGTile({
|
||||
onLoad,
|
||||
onFail,
|
||||
retryTime,
|
||||
onVisible,
|
||||
}: {
|
||||
photo: Photo
|
||||
loadingState?: OGLoadingState
|
||||
@ -22,6 +23,7 @@ export default function PhotoOGTile({
|
||||
onFail?: () => void
|
||||
riseOnHover?: boolean
|
||||
retryTime?: number
|
||||
onVisible?: () => void
|
||||
}) {
|
||||
return (
|
||||
<OGTile {...{
|
||||
@ -34,6 +36,7 @@ export default function PhotoOGTile({
|
||||
onFail,
|
||||
riseOnHover,
|
||||
retryTime,
|
||||
onVisible,
|
||||
}}/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { PATH_ROOT } from '@/site/paths';
|
||||
import InfinitePhotoScroll from './InfinitePhotoScroll';
|
||||
import PhotosLarge from './PhotosLarge';
|
||||
|
||||
@ -12,7 +13,7 @@ export default function PhotosLargeInfinite({
|
||||
}) {
|
||||
return (
|
||||
<InfinitePhotoScroll
|
||||
cacheKey="PhotosLarge"
|
||||
cacheKey={`page-${PATH_ROOT}`}
|
||||
initialOffset={initialOffset}
|
||||
itemsPerPage={itemsPerPage}
|
||||
wrapMoreButtonInGrid
|
||||
|
||||
@ -11,9 +11,11 @@ type PhotoLoadingState = Record<string, OGLoadingState>;
|
||||
export default function StaggeredOgPhotos({
|
||||
photos,
|
||||
maxConcurrency = DEFAULT_MAX_CONCURRENCY,
|
||||
onLastPhotoVisible,
|
||||
}: {
|
||||
photos: Photo[]
|
||||
maxConcurrency?: number
|
||||
onLastPhotoVisible?: () => void
|
||||
}) {
|
||||
const [loadingState, setLoadingState] = useState(
|
||||
photos.reduce((acc, photo) => ({
|
||||
@ -52,13 +54,20 @@ export default function StaggeredOgPhotos({
|
||||
recomputeLoadingState();
|
||||
}, [recomputeLoadingState]);
|
||||
|
||||
return photos.map(photo =>
|
||||
<PhotoOGTile
|
||||
key={photo.id}
|
||||
photo={photo}
|
||||
loadingState={loadingState[photo.id]}
|
||||
onLoad={() => recomputeLoadingState({ [photo.id]: 'loaded' })}
|
||||
onFail={() => recomputeLoadingState({ [photo.id]: 'failed' })}
|
||||
riseOnHover
|
||||
/>);
|
||||
return (
|
||||
<div className="grid gap-3 grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
||||
{photos.map((photo, index) =>
|
||||
<PhotoOGTile
|
||||
key={photo.id}
|
||||
photo={photo}
|
||||
loadingState={loadingState[photo.id]}
|
||||
onLoad={() => recomputeLoadingState({ [photo.id]: 'loaded' })}
|
||||
onFail={() => recomputeLoadingState({ [photo.id]: 'failed' })}
|
||||
onVisible={index === photos.length - 1
|
||||
? onLastPhotoVisible
|
||||
:undefined}
|
||||
riseOnHover
|
||||
/>)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
27
src/photo/StaggeredOgPhotosInfinite.tsx
Normal file
27
src/photo/StaggeredOgPhotosInfinite.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
'use client';
|
||||
|
||||
import { PATH_OG } from '@/site/paths';
|
||||
import InfinitePhotoScroll from './InfinitePhotoScroll';
|
||||
import StaggeredOgPhotos from './StaggeredOgPhotos';
|
||||
|
||||
export default function StaggeredOgPhotosInfinite({
|
||||
initialOffset,
|
||||
itemsPerPage,
|
||||
}: {
|
||||
initialOffset: number
|
||||
itemsPerPage: number
|
||||
}) {
|
||||
return (
|
||||
<InfinitePhotoScroll
|
||||
cacheKey={`page-${PATH_OG}`}
|
||||
initialOffset={initialOffset}
|
||||
itemsPerPage={itemsPerPage}
|
||||
>
|
||||
{({ photos, onLastPhotoVisible }) =>
|
||||
<StaggeredOgPhotos
|
||||
photos={photos}
|
||||
onLastPhotoVisible={onLastPhotoVisible}
|
||||
/>}
|
||||
</InfinitePhotoScroll>
|
||||
);
|
||||
}
|
||||
@ -1,42 +1,33 @@
|
||||
import { Photo, PhotoDateRange } from '@/photo';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
import PhotoGrid from '@/photo/PhotoGrid';
|
||||
import FilmSimulationHeader from './FilmSimulationHeader';
|
||||
import { FilmSimulation } from '.';
|
||||
import PhotoGridPage from '@/photo/PhotoGridPage';
|
||||
|
||||
export default function FilmSimulationOverview({
|
||||
simulation,
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
animateOnFirstLoadOnly,
|
||||
}: {
|
||||
simulation: FilmSimulation,
|
||||
photos: Photo[],
|
||||
count: number,
|
||||
dateRange?: PhotoDateRange,
|
||||
showMorePath?: string,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
}) {
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className="space-y-8 mt-4">
|
||||
<AnimateItems
|
||||
type="bottom"
|
||||
items={[
|
||||
<FilmSimulationHeader
|
||||
key="FilmSimulationHeader"
|
||||
{...{ simulation, photos, count, dateRange }}
|
||||
/>,
|
||||
]}
|
||||
animateOnFirstLoadOnly
|
||||
/>
|
||||
<PhotoGrid
|
||||
{...{ photos, simulation, showMorePath, animateOnFirstLoadOnly }}
|
||||
/>
|
||||
</div>}
|
||||
/>
|
||||
<PhotoGridPage {...{
|
||||
cacheKey: `simulation-${simulation}`,
|
||||
photos,
|
||||
count,
|
||||
header: <FilmSimulationHeader {...{
|
||||
simulation,
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
}} />,
|
||||
animateOnFirstLoadOnly,
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,11 +2,6 @@ import {
|
||||
getPhotosCached,
|
||||
getPhotosFilmSimulationMetaCached,
|
||||
} from '@/photo/cache';
|
||||
import {
|
||||
PaginationSearchParams,
|
||||
getPaginationFromSearchParams,
|
||||
} from '@/site/pagination';
|
||||
import { pathForFilmSimulation } from '@/site/paths';
|
||||
import { FilmSimulation } from '.';
|
||||
|
||||
export const getPhotosFilmSimulationDataCached = ({
|
||||
@ -20,32 +15,3 @@ export const getPhotosFilmSimulationDataCached = ({
|
||||
getPhotosCached({ simulation, limit }),
|
||||
getPhotosFilmSimulationMetaCached(simulation),
|
||||
]);
|
||||
|
||||
export const getPhotosFilmSimulationDataCachedWithPagination = async ({
|
||||
simulation,
|
||||
limit: limitProp,
|
||||
searchParams,
|
||||
}: {
|
||||
simulation: FilmSimulation,
|
||||
limit?: number,
|
||||
searchParams?: PaginationSearchParams,
|
||||
}) => {
|
||||
const { offset, limit } = getPaginationFromSearchParams(searchParams);
|
||||
|
||||
const [photos, { count, dateRange }] =
|
||||
await getPhotosFilmSimulationDataCached({
|
||||
simulation,
|
||||
limit: limitProp ?? limit,
|
||||
});
|
||||
|
||||
const showMorePath = count > photos.length
|
||||
? pathForFilmSimulation(simulation, offset + 1)
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
export type PaginationSearchParams = { next: string };
|
||||
|
||||
export interface PaginationParams {
|
||||
searchParams?: PaginationSearchParams
|
||||
}
|
||||
|
||||
export const getPaginationFromSearchParams = (
|
||||
query?: PaginationSearchParams,
|
||||
limitPerOffset = 24,
|
||||
) => {
|
||||
const offsetInt = parseInt(query?.next ?? '0');
|
||||
const offset = (Number.isNaN(offsetInt) ? 0 : offsetInt);
|
||||
return {
|
||||
offset,
|
||||
limit: limitPerOffset + offset * limitPerOffset,
|
||||
};
|
||||
};
|
||||
@ -252,7 +252,8 @@ export const isPathAdminConfiguration = (pathname?: string) =>
|
||||
|
||||
export const isPathProtected = (pathname?: string) =>
|
||||
checkPathPrefix(pathname, PATH_ADMIN) ||
|
||||
checkPathPrefix(pathname, pathForTag(TAG_HIDDEN));
|
||||
checkPathPrefix(pathname, pathForTag(TAG_HIDDEN)) ||
|
||||
pathname === PATH_OG;
|
||||
|
||||
export const getPathComponents = (pathname = ''): {
|
||||
photoId?: string
|
||||
|
||||
@ -1,41 +1,32 @@
|
||||
import { Photo, PhotoDateRange } from '@/photo';
|
||||
import SiteGrid from '@/components/SiteGrid';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
import PhotoGrid from '@/photo/PhotoGrid';
|
||||
import TagHeader from './TagHeader';
|
||||
import PhotoGridPage from '@/photo/PhotoGridPage';
|
||||
|
||||
export default function TagOverview({
|
||||
tag,
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
animateOnFirstLoadOnly,
|
||||
}: {
|
||||
tag: string,
|
||||
photos: Photo[],
|
||||
count: number,
|
||||
dateRange?: PhotoDateRange,
|
||||
showMorePath?: string,
|
||||
animateOnFirstLoadOnly?: boolean,
|
||||
}) {
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className="space-y-8 mt-4">
|
||||
<AnimateItems
|
||||
type="bottom"
|
||||
items={[
|
||||
<TagHeader
|
||||
key="TagHeader"
|
||||
{...{ tag, photos, count, dateRange }}
|
||||
/>,
|
||||
]}
|
||||
animateOnFirstLoadOnly
|
||||
/>
|
||||
<PhotoGrid
|
||||
{...{ photos, tag, showMorePath, animateOnFirstLoadOnly }}
|
||||
/>
|
||||
</div>}
|
||||
/>
|
||||
<PhotoGridPage {...{
|
||||
cacheKey: `tag-${tag}`,
|
||||
photos,
|
||||
count,
|
||||
header: <TagHeader {...{
|
||||
tag,
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
}} />,
|
||||
animateOnFirstLoadOnly,
|
||||
}} />
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,11 +2,6 @@ import {
|
||||
getPhotosCachedCached,
|
||||
getPhotosTagMetaCached,
|
||||
} from '@/photo/cache';
|
||||
import {
|
||||
PaginationSearchParams,
|
||||
getPaginationFromSearchParams,
|
||||
} from '@/site/pagination';
|
||||
import { pathForTag } from '@/site/paths';
|
||||
|
||||
export const getPhotosTagDataCached = ({
|
||||
tag,
|
||||
@ -20,31 +15,3 @@ export const getPhotosTagDataCached = ({
|
||||
getPhotosTagMetaCached(tag),
|
||||
]);
|
||||
|
||||
export const getPhotosTagDataCachedWithPagination = async ({
|
||||
tag,
|
||||
limit: limitProp,
|
||||
searchParams,
|
||||
}: {
|
||||
tag: string,
|
||||
limit?: number,
|
||||
searchParams?: PaginationSearchParams,
|
||||
}) => {
|
||||
const { offset, limit } = getPaginationFromSearchParams(searchParams);
|
||||
|
||||
const [photos, { count, dateRange }] =
|
||||
await getPhotosTagDataCached({
|
||||
tag,
|
||||
limit: limitProp ?? limit,
|
||||
});
|
||||
|
||||
const showMorePath = count > photos.length
|
||||
? pathForTag(tag, offset + 1)
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
photos,
|
||||
count,
|
||||
dateRange,
|
||||
showMorePath,
|
||||
};
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user