From f42fdcf74e5c0b8113180a255210ed848e3ec582 Mon Sep 17 00:00:00 2001 From: Vasily Zubarev Date: Fri, 9 May 2025 16:43:03 +0200 Subject: [PATCH] feat: isRequired for fields now respected --- app/(app)/settings/actions.ts | 2 ++ app/(app)/settings/fields/page.tsx | 7 ++++ components/forms/select-category.tsx | 3 ++ components/forms/select-currency.tsx | 3 ++ components/forms/select-project.tsx | 3 ++ components/forms/select-type.tsx | 10 +++++- components/forms/simple.tsx | 29 +++++++++++----- components/transactions/edit.tsx | 51 ++++++++++++++++++++++++---- components/transactions/list.tsx | 19 ++++++++++- forms/settings.ts | 1 + models/defaults.ts | 4 +-- 11 files changed, 114 insertions(+), 18 deletions(-) diff --git a/app/(app)/settings/actions.ts b/app/(app)/settings/actions.ts index 730d392..4907e43 100644 --- a/app/(app)/settings/actions.ts +++ b/app/(app)/settings/actions.ts @@ -240,6 +240,7 @@ export async function addFieldAction(userId: string, data: Prisma.FieldCreateInp llm_prompt: validatedForm.data.llm_prompt, isVisibleInList: validatedForm.data.isVisibleInList, isVisibleInAnalysis: validatedForm.data.isVisibleInAnalysis, + isRequired: validatedForm.data.isRequired, isExtra: true, }) revalidatePath("/settings/fields") @@ -260,6 +261,7 @@ export async function editFieldAction(userId: string, code: string, data: Prisma llm_prompt: validatedForm.data.llm_prompt, isVisibleInList: validatedForm.data.isVisibleInList, isVisibleInAnalysis: validatedForm.data.isVisibleInAnalysis, + isRequired: validatedForm.data.isRequired, }) revalidatePath("/settings/fields") diff --git a/app/(app)/settings/fields/page.tsx b/app/(app)/settings/fields/page.tsx index 70dc27f..9a1e34d 100644 --- a/app/(app)/settings/fields/page.tsx +++ b/app/(app)/settings/fields/page.tsx @@ -48,6 +48,13 @@ export default async function FieldsSettingsPage() { defaultValue: false, editable: true, }, + { + key: "isRequired", + label: "Is required", + type: "checkbox", + defaultValue: false, + editable: true, + }, ]} onDelete={async (code) => { "use server" diff --git a/components/forms/select-category.tsx b/components/forms/select-category.tsx index 5d48bde..4cfa92f 100644 --- a/components/forms/select-category.tsx +++ b/components/forms/select-category.tsx @@ -11,6 +11,7 @@ export const FormSelectCategory = ({ emptyValue, placeholder, hideIfEmpty = false, + isRequired = false, ...props }: { title: string @@ -18,6 +19,7 @@ export const FormSelectCategory = ({ emptyValue?: string placeholder?: string hideIfEmpty?: boolean + isRequired?: boolean } & SelectProps) => { const items = useMemo( () => categories.map((category) => ({ code: category.code, name: category.name, color: category.color })), @@ -30,6 +32,7 @@ export const FormSelectCategory = ({ emptyValue={emptyValue} placeholder={placeholder} hideIfEmpty={hideIfEmpty} + isRequired={isRequired} {...props} /> ) diff --git a/components/forms/select-currency.tsx b/components/forms/select-currency.tsx index 715559c..d5a002a 100644 --- a/components/forms/select-currency.tsx +++ b/components/forms/select-currency.tsx @@ -8,6 +8,7 @@ export const FormSelectCurrency = ({ emptyValue, placeholder, hideIfEmpty = false, + isRequired = false, ...props }: { currencies: { code: string; name: string }[] @@ -15,6 +16,7 @@ export const FormSelectCurrency = ({ emptyValue?: string placeholder?: string hideIfEmpty?: boolean + isRequired?: boolean } & SelectProps) => { const items = useMemo( () => @@ -32,6 +34,7 @@ export const FormSelectCurrency = ({ emptyValue={emptyValue} placeholder={placeholder} hideIfEmpty={hideIfEmpty} + isRequired={isRequired} {...props} /> ) diff --git a/components/forms/select-project.tsx b/components/forms/select-project.tsx index a74b218..28b737f 100644 --- a/components/forms/select-project.tsx +++ b/components/forms/select-project.tsx @@ -8,6 +8,7 @@ export const FormSelectProject = ({ emptyValue, placeholder, hideIfEmpty = false, + isRequired = false, ...props }: { title: string @@ -15,6 +16,7 @@ export const FormSelectProject = ({ emptyValue?: string placeholder?: string hideIfEmpty?: boolean + isRequired?: boolean } & SelectProps) => { return ( ) diff --git a/components/forms/select-type.tsx b/components/forms/select-type.tsx index 7dc01d4..4f725e9 100644 --- a/components/forms/select-type.tsx +++ b/components/forms/select-type.tsx @@ -6,8 +6,15 @@ export const FormSelectType = ({ emptyValue, placeholder, hideIfEmpty = false, + isRequired = false, ...props -}: { title: string; emptyValue?: string; placeholder?: string; hideIfEmpty?: boolean } & SelectProps) => { +}: { + title: string + emptyValue?: string + placeholder?: string + hideIfEmpty?: boolean + isRequired?: boolean +} & SelectProps) => { const items = [ { code: "expense", name: "Expense", badge: "↓" }, { code: "income", name: "Income", badge: "↑" }, @@ -22,6 +29,7 @@ export const FormSelectType = ({ emptyValue={emptyValue} placeholder={placeholder} hideIfEmpty={hideIfEmpty} + isRequired={isRequired} {...props} /> ) diff --git a/components/forms/simple.tsx b/components/forms/simple.tsx index 9e2103a..4556e78 100644 --- a/components/forms/simple.tsx +++ b/components/forms/simple.tsx @@ -16,17 +16,20 @@ import { InputHTMLAttributes, TextareaHTMLAttributes, useEffect, useRef, useStat type FormInputProps = InputHTMLAttributes & { title?: string hideIfEmpty?: boolean + isRequired?: boolean } -export function FormInput({ title, hideIfEmpty = false, ...props }: FormInputProps) { - if (hideIfEmpty && (!props.defaultValue || props.defaultValue.toString().trim() === "") && !props.value) { +export function FormInput({ title, hideIfEmpty = false, isRequired = false, ...props }: FormInputProps) { + const isEmpty = (!props.defaultValue || props.defaultValue.toString().trim() === "") && !props.value + + if (hideIfEmpty && isEmpty) { return null } return ( ) } @@ -34,10 +37,12 @@ export function FormInput({ title, hideIfEmpty = false, ...props }: FormInputPro type FormTextareaProps = TextareaHTMLAttributes & { title?: string hideIfEmpty?: boolean + isRequired?: boolean } -export function FormTextarea({ title, hideIfEmpty = false, ...props }: FormTextareaProps) { +export function FormTextarea({ title, hideIfEmpty = false, isRequired = false, ...props }: FormTextareaProps) { const textareaRef = useRef(null) + const isEmpty = (!props.defaultValue || props.defaultValue.toString().trim() === "") && !props.value useEffect(() => { const textarea = textareaRef.current @@ -54,14 +59,18 @@ export function FormTextarea({ title, hideIfEmpty = false, ...props }: FormTexta return () => textarea.removeEventListener("input", resize) }, [props.value, props.defaultValue]) - if (hideIfEmpty && (!props.defaultValue || props.defaultValue.toString().trim() === "") && !props.value) { + if (hideIfEmpty && isEmpty) { return null } return (