Show photos when editing a tag

This commit is contained in:
Sam Becker 2023-10-06 13:35:01 -05:00
parent 7c5ec62bda
commit 9e3989e0c1
7 changed files with 104 additions and 70 deletions

View File

@ -20,7 +20,7 @@ export default function AdminNav({
<SiteGrid
contentMain={
<div className={cc(
'border-b border-gray-800 pb-3',
'border-b border-gray-200 dark:border-gray-800 pb-3',
)}>
<div className={cc(
'flex gap-2 md:gap-4',

View File

@ -35,7 +35,7 @@ export default async function AdminLayout({
: [navItemPhotos];
return (
<div className="mt-4 space-y-6">
<div className="mt-4 space-y-5">
<AdminNav items={navItems} />
{children}
</div>

View File

@ -20,6 +20,7 @@ export default async function PhotoPageEdit({ params: { photoId } }: Props) {
<AdminChildPage
backPath={PATH_ADMIN_PHOTOS}
backLabel="Photos"
breadcrumb={photo.title || photo.id}
>
<PhotoForm
type="edit"

View File

@ -1,8 +1,12 @@
import AdminChildPage from '@/components/AdminChildPage';
import { redirect } from 'next/navigation';
import { getUniqueTagsWithCountCached } from '@/cache';
import { getPhotosCached } from '@/cache';
import TagForm from '@/tag/TagForm';
import { PATH_ADMIN, PATH_ADMIN_TAGS } from '@/site/paths';
import { getPhotosTagCount } from '@/services/postgres';
import PhotoTag from '@/tag/PhotoTag';
import { photoQuantityText } from '@/photo';
import PhotoGrid from '@/photo/PhotoGrid';
export const runtime = 'edge';
@ -11,17 +15,35 @@ interface Props {
}
export default async function PhotoPageEdit({ params: { tag } }: Props) {
const tags = await getUniqueTagsWithCountCached();
const tagData = tags.find(t => t.tag === tag);
const [
count,
photos,
] = await Promise.all([
getPhotosTagCount(tag),
getPhotosCached({ tag }),
]);
if (!tagData) { redirect(PATH_ADMIN); }
if (count === 0) { redirect(PATH_ADMIN); }
return (
<AdminChildPage
backPath={PATH_ADMIN_TAGS}
backLabel="Tags"
breadcrumb={<div className="flex item gap-2">
<PhotoTag {...{ tag }} />
<div className="text-dim uppercase">
{photoQuantityText(count, false)}
</div>
</div>}
>
<TagForm {...tagData} />
<div className="space-y-8">
<PhotoGrid
photos={photos.slice(0, 12)}
animate={false}
small
/>
<TagForm {...{ tag, photos }} />
</div>
</AdminChildPage>
);
};

View File

@ -1,30 +1,49 @@
import { ReactNode } from 'react';
import Link from 'next/link';
import { FiArrowLeft } from 'react-icons/fi';
import SiteGrid from './SiteGrid';
import { cc } from '@/utility/css';
function AdminChildPage({
backPath,
backLabel,
breadcrumb,
children,
}: {
backPath?: string
backLabel?: string
breadcrumb?: ReactNode
children: ReactNode,
}) {
return (
<div className="space-y-8">
{backPath &&
<Link
href={backPath}
className="flex gap-1 items-center"
>
<FiArrowLeft size={16} />
{backLabel || 'Back'}
</Link>}
<div>
{children}
</div>
</div>
<SiteGrid
contentMain={
<div className="space-y-6">
{backPath &&
<div className="flex gap-3 items-center h-9">
<Link
href={backPath}
className="flex gap-1.5 items-center"
>
<FiArrowLeft size={16} />
{backLabel || 'Back'}
</Link>
{breadcrumb &&
<>
<span>/</span>
<span className={cc(
'py-0.5 px-2 rounded-md bg-gray-100 dark:bg-gray-900',
'border border-gray-200 dark:border-gray-800'
)}>
{breadcrumb}
</span>
</>}
</div>}
<div>
{children}
</div>
</div>}
/>
);
};

View File

@ -15,6 +15,7 @@ export default function PhotoGrid({
animateOnFirstLoadOnly,
staggerOnFirstLoadOnly = true,
showMorePath,
small,
}: {
photos: Photo[]
selectedPhoto?: Photo
@ -25,13 +26,16 @@ export default function PhotoGrid({
animateOnFirstLoadOnly?: boolean
staggerOnFirstLoadOnly?: boolean
showMorePath?: string
small?: boolean
}) {
return (
<div className="space-y-4">
<AnimateItems
className={cc(
'grid gap-1',
'grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
small
? 'grid-cols-4 xs:grid-cols-6'
: 'grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
'items-center',
)}
type={animate === false ? 'none' : undefined}

View File

@ -1,7 +1,5 @@
'use client';
import { photoQuantityText } from '@/photo';
import PhotoTag from './PhotoTag';
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
import Link from 'next/link';
import { PATH_ADMIN_TAGS } from '@/site/paths';
@ -12,10 +10,8 @@ import { parameterize } from '@/utility/string';
export default function TagForm({
tag,
count,
}: {
tag: string
count: number
}) {
const [updatedTagRaw, setUpdatedTagRaw] = useState(tag);
@ -29,51 +25,43 @@ export default function TagForm({
);
return (
<div className="space-y-8 max-w-[38rem]">
<div className="flex item gap-2">
<PhotoTag {...{ tag }} />
<div className="text-dim uppercase">
{photoQuantityText(count, false)}
</div>
<form
action={renamePhotoTagGloballyAction}
className="space-y-8"
>
<FieldSetWithStatus
id="updatedTagRaw"
label="New Tag Name"
value={updatedTagRaw}
onChange={setUpdatedTagRaw}
/>
{/* Form data: tag to be replaced */}
<input
name="tag"
value={tag}
hidden
readOnly
/>
{/* Form data: updated tag */}
<input
name="updatedTag"
value={updatedTag}
hidden
readOnly
/>
<div className="flex gap-3">
<Link
className="button"
href={PATH_ADMIN_TAGS}
>
Cancel
</Link>
<SubmitButtonWithStatus
disabled={!isFormValid}
>
Update
</SubmitButtonWithStatus>
</div>
<form
action={renamePhotoTagGloballyAction}
className="space-y-11"
>
<FieldSetWithStatus
id="updatedTagRaw"
label="New Tag Name"
value={updatedTagRaw}
onChange={setUpdatedTagRaw}
/>
{/* Form data: tag to be replaced */}
<input
name="tag"
value={tag}
hidden
readOnly
/>
{/* Form data: updated tag */}
<input
name="updatedTag"
value={updatedTag}
hidden
readOnly
/>
<div className="flex gap-3">
<Link
className="button"
href={PATH_ADMIN_TAGS}
>
Cancel
</Link>
<SubmitButtonWithStatus
disabled={!isFormValid}
>
Update
</SubmitButtonWithStatus>
</div>
</form>
</div>
</form>
);
}