Create admin recipe detail page
This commit is contained in:
parent
2c35587f5d
commit
769d6b64bb
@ -1,31 +1,31 @@
|
||||
import AdminChildPage from '@/components/AdminChildPage';
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getPhotosCached } from '@/photo/cache';
|
||||
import TagForm from '@/tag/TagForm';
|
||||
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/app/paths';
|
||||
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForRecipe } from '@/app/paths';
|
||||
import PhotoLightbox from '@/photo/PhotoLightbox';
|
||||
import { getPhotosMeta } from '@/photo/db/query';
|
||||
import AdminTagBadge from '@/admin/AdminTagBadge';
|
||||
import AdminRecipeBadge from '@/admin/AdminRecipeBadge';
|
||||
import AdminRecipeForm from '@/admin/AdminRecipeForm';
|
||||
|
||||
const MAX_PHOTO_TO_SHOW = 6;
|
||||
|
||||
interface Props {
|
||||
params: Promise<{ tag: string }>
|
||||
params: Promise<{ recipe: string }>
|
||||
}
|
||||
|
||||
export default async function PhotoPageEdit({
|
||||
export default async function RecipePageEdit({
|
||||
params,
|
||||
}: Props) {
|
||||
const { tag: tagFromParams } = await params;
|
||||
const { recipe: recipeFromParams } = await params;
|
||||
|
||||
const tag = decodeURIComponent(tagFromParams);
|
||||
const recipe = decodeURIComponent(recipeFromParams);
|
||||
|
||||
const [
|
||||
{ count },
|
||||
photos,
|
||||
] = await Promise.all([
|
||||
getPhotosMeta({ tag }),
|
||||
getPhotosCached({ tag, limit: MAX_PHOTO_TO_SHOW }),
|
||||
getPhotosMeta({ recipe }),
|
||||
getPhotosCached({ recipe, limit: MAX_PHOTO_TO_SHOW }),
|
||||
]);
|
||||
|
||||
if (count === 0) { redirect(PATH_ADMIN); }
|
||||
@ -34,15 +34,15 @@ export default async function PhotoPageEdit({
|
||||
<AdminChildPage
|
||||
backPath={PATH_ADMIN_TAGS}
|
||||
backLabel="Tags"
|
||||
breadcrumb={<AdminTagBadge {...{ tag, count, hideBadge: true }} />}
|
||||
breadcrumb={<AdminRecipeBadge {...{ recipe, count, hideBadge: true }} />}
|
||||
>
|
||||
<TagForm {...{ tag, photos }}>
|
||||
<AdminRecipeForm {...{ recipe, photos }}>
|
||||
<PhotoLightbox
|
||||
{...{ count, photos, tag }}
|
||||
{...{ count, photos, recipe }}
|
||||
maxPhotosToShow={MAX_PHOTO_TO_SHOW}
|
||||
moreLink={pathForTag(tag)}
|
||||
moreLink={pathForRecipe(recipe)}
|
||||
/>
|
||||
</TagForm>
|
||||
</AdminRecipeForm>
|
||||
</AdminChildPage>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import AdminChildPage from '@/components/AdminChildPage';
|
||||
import { redirect } from 'next/navigation';
|
||||
import { getPhotosCached } from '@/photo/cache';
|
||||
import TagForm from '@/tag/TagForm';
|
||||
import AdminTagForm from '@/admin/AdminTagForm';
|
||||
import { PATH_ADMIN, PATH_ADMIN_TAGS, pathForTag } from '@/app/paths';
|
||||
import PhotoLightbox from '@/photo/PhotoLightbox';
|
||||
import { getPhotosMeta } from '@/photo/db/query';
|
||||
@ -36,13 +36,13 @@ export default async function PhotoPageEdit({
|
||||
backLabel="Tags"
|
||||
breadcrumb={<AdminTagBadge {...{ tag, count, hideBadge: true }} />}
|
||||
>
|
||||
<TagForm {...{ tag, photos }}>
|
||||
<AdminTagForm {...{ tag, photos }}>
|
||||
<PhotoLightbox
|
||||
{...{ count, photos, tag }}
|
||||
maxPhotosToShow={MAX_PHOTO_TO_SHOW}
|
||||
moreLink={pathForTag(tag)}
|
||||
/>
|
||||
</TagForm>
|
||||
</AdminTagForm>
|
||||
</AdminChildPage>
|
||||
);
|
||||
};
|
||||
|
||||
74
src/admin/AdminRecipeForm.tsx
Normal file
74
src/admin/AdminRecipeForm.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
'use client';
|
||||
|
||||
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
|
||||
import Link from 'next/link';
|
||||
import { PATH_ADMIN_RECIPES } from '@/app/paths';
|
||||
import FieldSetWithStatus from '@/components/FieldSetWithStatus';
|
||||
import { ReactNode, useMemo, useState } from 'react';
|
||||
import { renamePhotoTagGloballyAction } from '@/photo/actions';
|
||||
import { parameterize } from '@/utility/string';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
|
||||
export default function AdminRecipeForm({
|
||||
recipe,
|
||||
children,
|
||||
}: {
|
||||
recipe: string
|
||||
children?: ReactNode
|
||||
}) {
|
||||
const { invalidateSwr } = useAppState();
|
||||
|
||||
const [updatedRecipeRaw, setUpdatedRecipeRaw] = useState(recipe);
|
||||
|
||||
const updatedRecipe = useMemo(() =>
|
||||
parameterize(updatedRecipeRaw)
|
||||
, [updatedRecipeRaw]);
|
||||
|
||||
const isFormValid = (
|
||||
updatedRecipe &&
|
||||
updatedRecipe !== recipe
|
||||
);
|
||||
|
||||
return (
|
||||
<form
|
||||
action={renamePhotoTagGloballyAction}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FieldSetWithStatus
|
||||
id="updatedTagRaw"
|
||||
label="New Tag Name"
|
||||
value={updatedRecipeRaw}
|
||||
onChange={setUpdatedRecipeRaw}
|
||||
/>
|
||||
{/* Form data: tag to be replaced */}
|
||||
<input
|
||||
name="recipe"
|
||||
value={recipe}
|
||||
hidden
|
||||
readOnly
|
||||
/>
|
||||
{/* Form data: updated tag */}
|
||||
<input
|
||||
name="updatedRecipe"
|
||||
value={updatedRecipe}
|
||||
hidden
|
||||
readOnly
|
||||
/>
|
||||
{children}
|
||||
<div className="flex gap-3">
|
||||
<Link
|
||||
className="button"
|
||||
href={PATH_ADMIN_RECIPES}
|
||||
>
|
||||
Cancel
|
||||
</Link>
|
||||
<SubmitButtonWithStatus
|
||||
disabled={!isFormValid}
|
||||
onFormSubmit={invalidateSwr}
|
||||
>
|
||||
Update
|
||||
</SubmitButtonWithStatus>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@ -9,7 +9,7 @@ import { renamePhotoTagGloballyAction } from '@/photo/actions';
|
||||
import { parameterize } from '@/utility/string';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
|
||||
export default function TagForm({
|
||||
export default function AdminTagForm({
|
||||
tag,
|
||||
children,
|
||||
}: {
|
||||
Loading…
Reference in New Issue
Block a user