From ee050b550e2bc13569c1dd507e7fbe8c9185f44e Mon Sep 17 00:00:00 2001 From: Sam Becker Date: Thu, 13 Mar 2025 21:55:27 -0500 Subject: [PATCH] Refine recipe scanning ux --- app/admin/uploads/[uploadPath]/page.tsx | 8 +- src/components/FieldSetWithStatus.tsx | 262 ++++++++++-------- src/photo/actions.ts | 15 +- src/photo/db/query.ts | 28 +- .../form/ApplyRecipesGloballyCheckbox.tsx | 41 ++- src/photo/form/PhotoForm.tsx | 53 +++- src/photo/form/index.ts | 16 +- src/photo/server.ts | 12 +- 8 files changed, 272 insertions(+), 163 deletions(-) diff --git a/app/admin/uploads/[uploadPath]/page.tsx b/app/admin/uploads/[uploadPath]/page.tsx index f3f1699b..7ed68f0c 100644 --- a/app/admin/uploads/[uploadPath]/page.tsx +++ b/app/admin/uploads/[uploadPath]/page.tsx @@ -10,6 +10,7 @@ import { } from '@/app/config'; import ErrorNote from '@/components/ErrorNote'; import { getRecipeTitleForData } from '@/photo/db/query'; +import { FilmSimulation } from '@/simulation'; export const maxDuration = 60; @@ -48,8 +49,11 @@ export default async function UploadPage({ params }: Params) { ] = await Promise.all([ getUniqueTagsCached(), getUniqueRecipesCached(), - formDataFromExif?.recipeData - ? getRecipeTitleForData(formDataFromExif.recipeData) + formDataFromExif?.recipeData && formDataFromExif.filmSimulation + ? getRecipeTitleForData( + formDataFromExif.recipeData, + formDataFromExif.filmSimulation as FilmSimulation, + ) : undefined, ]); diff --git a/src/components/FieldSetWithStatus.tsx b/src/components/FieldSetWithStatus.tsx index 332072a3..22c056a9 100644 --- a/src/components/FieldSetWithStatus.tsx +++ b/src/components/FieldSetWithStatus.tsx @@ -16,6 +16,7 @@ export default function FieldSetWithStatus({ value, isModified, onChange, + className, selectOptions, selectOptionsDefaultLabel, tagOptions, @@ -31,6 +32,7 @@ export default function FieldSetWithStatus({ inputRef, accessory, hideLabel, + checkboxAccessory, }: { id: string label?: string @@ -39,6 +41,7 @@ export default function FieldSetWithStatus({ value: string isModified?: boolean onChange?: (value: string) => void + className?: string selectOptions?: { value: string, label: string }[] selectOptionsDefaultLabel?: string tagOptions?: AnnotatedTag[] @@ -54,142 +57,157 @@ export default function FieldSetWithStatus({ inputRef?: Ref accessory?: React.ReactNode hideLabel?: boolean + checkboxAccessory?: React.ReactNode }) { const { pending } = useFormStatus(); + const renderInput = + onChange?.(type === 'checkbox' + ? e.target.value === 'true' ? 'false' : 'true' + : e.target.value)} + type={type} + spellCheck={spellCheck} + autoComplete="off" + autoCapitalize={!capitalize ? 'off' : undefined} + readOnly={readOnly || pending || loading} + disabled={type === 'checkbox' && ( + readOnly || pending || loading + )} + className={clsx( + ( + type === 'text' || + type === 'email' || + type === 'password' + ) && 'w-full', + type === 'checkbox' && ( + readOnly || pending || loading + ) && 'opacity-50 cursor-not-allowed', + Boolean(error) && 'error', + )} + />; + return ( -
- {!hideLabel && label && - } -
- {selectOptions - ?
- -
- -
-
- : tagOptions - ? - : type === 'textarea' - ?