Show photos when editing a tag
This commit is contained in:
parent
7c5ec62bda
commit
9e3989e0c1
@ -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',
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@ -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>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user