diff --git a/app/lib/actions/userSettingsActions.ts b/app/lib/actions/userSettingsActions.ts index e4f1305..4e5ca44 100644 --- a/app/lib/actions/userSettingsActions.ts +++ b/app/lib/actions/userSettingsActions.ts @@ -17,7 +17,9 @@ export type State = { firstName?: string[]; lastName?: string[]; street?: string[]; + town?: string[]; iban?: string[]; + currency?: string[]; show2dCodeInMonthlyStatement?: string[]; }; message?: string | null; @@ -31,6 +33,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({ firstName: z.string().optional(), lastName: z.string().optional(), street: z.string().optional(), + town: z.string().optional(), iban: z.string() .optional() .refine( @@ -42,6 +45,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({ }, { message: t("iban-invalid") } ), + currency: z.string().optional(), show2dCodeInMonthlyStatement: z.boolean().optional().nullable(), }) .refine((data) => { @@ -71,6 +75,15 @@ const FormSchema = (t: IntlTemplateFn) => z.object({ message: t("street-required"), path: ["street"], }) +.refine((data) => { + if (data.show2dCodeInMonthlyStatement) { + return !!data.town && data.town.trim().length > 0; + } + return true; +}, { + message: t("town-required"), + path: ["town"], +}) .refine((data) => { if (data.show2dCodeInMonthlyStatement) { if (!data.iban || data.iban.trim().length === 0) { @@ -84,6 +97,15 @@ const FormSchema = (t: IntlTemplateFn) => z.object({ }, { message: t("iban-required"), path: ["iban"], +}) +.refine((data) => { + if (data.show2dCodeInMonthlyStatement) { + return !!data.currency && data.currency.trim().length > 0; + } + return true; +}, { + message: t("currency-required"), + path: ["currency"], }); /** @@ -113,7 +135,9 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS firstName: formData.get('firstName') || undefined, lastName: formData.get('lastName') || undefined, street: formData.get('street') || undefined, + town: formData.get('town') || undefined, iban: formData.get('iban') || undefined, + currency: formData.get('currency') || undefined, show2dCodeInMonthlyStatement: formData.get('generateTenantCode') === 'on', }); @@ -126,7 +150,7 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS }; } - const { firstName, lastName, street, iban, show2dCodeInMonthlyStatement } = validatedFields.data; + const { firstName, lastName, street, town, iban, currency, show2dCodeInMonthlyStatement } = validatedFields.data; // Normalize IBAN: remove spaces and convert to uppercase const normalizedIban = iban ? iban.replace(/\s/g, '').toUpperCase() : null; @@ -140,7 +164,9 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS firstName: firstName || null, lastName: lastName || null, street: street || null, + town: town || null, iban: normalizedIban, + currency: currency || null, show2dCodeInMonthlyStatement: show2dCodeInMonthlyStatement ?? false, }; diff --git a/app/lib/db-types.ts b/app/lib/db-types.ts index 7cc3344..6754305 100644 --- a/app/lib/db-types.ts +++ b/app/lib/db-types.ts @@ -24,8 +24,12 @@ export interface UserSettings { lastName?: string | null; /** street */ street?: string | null; + /** town */ + town?: string | null; /** IBAN */ iban?: string | null; + /** currency (ISO 4217) */ + currency?: string | null; /** whether to show 2D code in monthly statement */ show2dCodeInMonthlyStatement?: boolean | null; }; diff --git a/app/ui/UserSettingsForm.tsx b/app/ui/UserSettingsForm.tsx index 9087ed1..0f6953d 100644 --- a/app/ui/UserSettingsForm.tsx +++ b/app/ui/UserSettingsForm.tsx @@ -30,7 +30,9 @@ const FormFields: FC = ({ userSettings, errors, message }) => { firstName: userSettings?.firstName ?? "", lastName: userSettings?.lastName ?? "", street: userSettings?.street ?? "", + town: userSettings?.town ?? "", iban: formatIban(userSettings?.iban) ?? "", + currency: userSettings?.currency ?? "EUR", }); const handleInputChange = (field: keyof typeof formValues, value: string) => { @@ -39,7 +41,7 @@ const FormFields: FC = ({ userSettings, errors, message }) => { // Check if any required field is missing (clean IBAN of spaces for validation) const cleanedIban = formValues.iban.replace(/\s/g, ''); - const hasMissingData = !formValues.firstName || !formValues.lastName || !formValues.street || !cleanedIban; + const hasMissingData = !formValues.firstName || !formValues.lastName || !formValues.street || !formValues.town || !cleanedIban || !formValues.currency; // Track whether to generate 2D code for tenant (use persisted value from database) const [show2dCodeInMonthlyStatement, setShow2dCodeInMonthlyStatement] = useState( @@ -140,6 +142,30 @@ const FormFields: FC = ({ userSettings, errors, message }) => { +
+ + handleInputChange("town", e.target.value)} + disabled={pending} + /> +
+ {errors?.town && + errors.town.map((error: string) => ( +

+ {error} +

+ ))} +
+
+
+ +
+ + +
+ {errors?.currency && + errors.currency.map((error: string) => ( +

+ {error} +

+ ))} +
+
{t("additional-notes")} )} diff --git a/messages/en.json b/messages/en.json index d080540..2626dd2 100644 --- a/messages/en.json +++ b/messages/en.json @@ -192,16 +192,21 @@ "last-name-placeholder": "Enter your last name", "street-label": "Street", "street-placeholder": "Enter your street", + "town-label": "Town", + "town-placeholder": "Enter your town", "iban-label": "IBAN", "iban-placeholder": "Enter your IBAN", + "currency-label": "Currency", "save-button": "Save", "cancel-button": "Cancel", "validation": { "first-name-required": "First name is mandatory", "last-name-required": "Last name is mandatory", "street-required": "Street is mandatory", + "town-required": "Town is mandatory", "iban-required": "Valid IBAN is mandatory", "iban-invalid": "Invalid IBAN format. Please enter a valid IBAN", + "currency-required": "Currency is mandatory", "validation-failed": "Validation failed. Please check the form and try again." }, "additional-notes": "Note: For the 2D code to be displayed, you must enter both the tenant's first and last names in the settings of each property for which you want to use this functionality." diff --git a/messages/hr.json b/messages/hr.json index 4942887..fe0f6b8 100644 --- a/messages/hr.json +++ b/messages/hr.json @@ -191,16 +191,21 @@ "last-name-placeholder": "Unesite svoje prezime", "street-label": "Ulica", "street-placeholder": "Unesite ulicu", + "town-label": "Grad", + "town-placeholder": "Unesite grad", "iban-label": "IBAN", "iban-placeholder": "Unesite svoj IBAN", + "currency-label": "Valuta", "save-button": "Spremi", "cancel-button": "Odbaci", "validation": { "first-name-required": "Ime je obavezno", "last-name-required": "Prezime je obavezno", "street-required": "Ulica je obavezna", + "town-required": "Grad je obavezan", "iban-required": "Ispravan IBAN je obavezan", "iban-invalid": "Neispravan IBAN format. Molimo unesite ispravan IBAN.", + "currency-required": "Valuta je obavezna", "validation-failed": "Validacija nije uspjela. Molimo provjerite formu i pokušajte ponovno." }, "additional-notes": "Napomena: da bi 2D koda bio prikazan, morate unijeti i ime i prezime podstanara u postavkama svake nekretnine za koju želite koristiti ovu funkcionalnost."