refactor: replace payment dropdown with independent toggles

- Replace showPaymentInstructionsInMonthlyStatement dropdown with enableIbanPayment and enableRevolutPayment boolean toggles
- Update UserSettingsForm to use separate fieldsets for IBAN and Revolut with independent toggle switches
- Add hidden inputs to preserve values when toggles are disabled
- Update validation logic to check enableIbanPayment instead of show2dCodeInMonthlyStatement
- Reorganize translation keys to match new structure (iban-* and revolut-* prefixes)
- Update ViewLocationCard to use enableIbanPayment field

This provides better UX by allowing users to enable both payment methods simultaneously if needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-24 14:45:59 +01:00
parent 686bec6c10
commit 632f8888b5
6 changed files with 168 additions and 101 deletions

View File

@@ -19,7 +19,6 @@ export type State = {
ownerTown?: string[]; ownerTown?: string[];
ownerIBAN?: string[]; ownerIBAN?: string[];
currency?: string[]; currency?: string[];
show2dCodeInMonthlyStatement?: string[];
}; };
message?: string | null; message?: string | null;
success?: boolean; success?: boolean;
@@ -29,6 +28,8 @@ export type State = {
* Schema for validating user settings form fields * Schema for validating user settings form fields
*/ */
const FormSchema = (t: IntlTemplateFn) => z.object({ const FormSchema = (t: IntlTemplateFn) => z.object({
currency: z.string().optional(),
enableIbanPayment: z.boolean().optional(),
ownerName: z.string().max(25).optional(), ownerName: z.string().max(25).optional(),
ownerStreet: z.string().max(25).optional(), ownerStreet: z.string().max(25).optional(),
ownerTown: z.string().max(27).optional(), ownerTown: z.string().max(27).optional(),
@@ -43,11 +44,11 @@ const FormSchema = (t: IntlTemplateFn) => z.object({
}, },
{ message: t("owner-iban-invalid") } { message: t("owner-iban-invalid") }
), ),
currency: z.string().optional(), enableRevolutPayment: z.boolean().optional(),
show2dCodeInMonthlyStatement: z.boolean().optional().nullable(), ownerRevolutProfileName: z.string().max(25).optional(),
}) })
.refine((data) => { .refine((data) => {
if (data.show2dCodeInMonthlyStatement) { if (data.enableIbanPayment) {
return !!data.ownerName && data.ownerName.trim().length > 0; return !!data.ownerName && data.ownerName.trim().length > 0;
} }
return true; return true;
@@ -56,7 +57,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({
path: ["ownerName"], path: ["ownerName"],
}) })
.refine((data) => { .refine((data) => {
if (data.show2dCodeInMonthlyStatement) { if (data.enableIbanPayment) {
return !!data.ownerStreet && data.ownerStreet.trim().length > 0; return !!data.ownerStreet && data.ownerStreet.trim().length > 0;
} }
return true; return true;
@@ -65,7 +66,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({
path: ["ownerStreet"], path: ["ownerStreet"],
}) })
.refine((data) => { .refine((data) => {
if (data.show2dCodeInMonthlyStatement) { if (data.enableIbanPayment) {
return !!data.ownerTown && data.ownerTown.trim().length > 0; return !!data.ownerTown && data.ownerTown.trim().length > 0;
} }
return true; return true;
@@ -74,7 +75,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({
path: ["ownerTown"], path: ["ownerTown"],
}) })
.refine((data) => { .refine((data) => {
if (data.show2dCodeInMonthlyStatement) { if (data.enableIbanPayment) {
if (!data.ownerIBAN || data.ownerIBAN.trim().length === 0) { if (!data.ownerIBAN || data.ownerIBAN.trim().length === 0) {
return false; return false;
} }
@@ -88,7 +89,7 @@ const FormSchema = (t: IntlTemplateFn) => z.object({
path: ["ownerIBAN"], path: ["ownerIBAN"],
}) })
.refine((data) => { .refine((data) => {
if (data.show2dCodeInMonthlyStatement) { if (data.enableIbanPayment) {
return !!data.currency && data.currency.trim().length > 0; return !!data.currency && data.currency.trim().length > 0;
} }
return true; return true;
@@ -141,7 +142,9 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS
ownerTown: formData.get('ownerTown') || undefined, ownerTown: formData.get('ownerTown') || undefined,
ownerIBAN: formData.get('ownerIBAN') || undefined, ownerIBAN: formData.get('ownerIBAN') || undefined,
currency: formData.get('currency') || undefined, currency: formData.get('currency') || undefined,
show2dCodeInMonthlyStatement: formData.get('generateTenantCode') === 'on', enableIbanPayment: formData.get('enableIbanPayment') === 'on' ? true : false,
enableRevolutPayment: formData.get('enableRevolutPayment') === 'on' ? true : false,
ownerRevolutProfileName: formData.get('ownerRevolutProfileName') || undefined,
}); });
// If form validation fails, return errors early. Otherwise, continue... // If form validation fails, return errors early. Otherwise, continue...
@@ -153,7 +156,7 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS
}; };
} }
const { ownerName, ownerStreet, ownerTown, ownerIBAN, currency, show2dCodeInMonthlyStatement } = validatedFields.data; const { enableIbanPayment, ownerName, ownerStreet, ownerTown, ownerIBAN, currency, enableRevolutPayment, ownerRevolutProfileName } = validatedFields.data;
// Normalize IBAN: remove spaces and convert to uppercase // Normalize IBAN: remove spaces and convert to uppercase
const normalizedOwnerIBAN = ownerIBAN ? ownerIBAN.replace(/\s/g, '').toUpperCase() : null; const normalizedOwnerIBAN = ownerIBAN ? ownerIBAN.replace(/\s/g, '').toUpperCase() : null;
@@ -164,12 +167,14 @@ export const updateUserSettings = withUser(async (user: AuthenticatedUser, prevS
const userSettings: UserSettings = { const userSettings: UserSettings = {
userId, userId,
ownerName: ownerName || null, enableIbanPayment: enableIbanPayment ?? false,
ownerStreet: ownerStreet || null, ownerName: ownerName ?? undefined,
ownerTown: ownerTown || null, ownerStreet: ownerStreet ?? undefined,
ownerTown: ownerTown ?? undefined,
ownerIBAN: normalizedOwnerIBAN, ownerIBAN: normalizedOwnerIBAN,
currency: currency || null, currency: currency ?? undefined,
show2dCodeInMonthlyStatement: show2dCodeInMonthlyStatement ?? false, enableRevolutPayment: enableRevolutPayment ?? false,
ownerRevolutProfileName: ownerRevolutProfileName ?? undefined,
}; };
await dbClient.collection<UserSettings>("userSettings") await dbClient.collection<UserSettings>("userSettings")

View File

@@ -18,6 +18,8 @@ export interface YearMonth {
export interface UserSettings { export interface UserSettings {
/** user's ID */ /** user's ID */
userId: string; userId: string;
/** whether enableshow IBAN payment instructions in monthly statement */
enableIbanPayment?: boolean | null;
/** owner name */ /** owner name */
ownerName?: string | null; ownerName?: string | null;
/** owner street */ /** owner street */
@@ -28,18 +30,10 @@ export interface UserSettings {
ownerIBAN?: string | null; ownerIBAN?: string | null;
/** currency (ISO 4217) */ /** currency (ISO 4217) */
currency?: string | null; currency?: string | null;
/** whether to enable Revolut payment instructions in monthly statement */
enableRevolutPayment?: boolean | null;
/** owner Revolut payment link */ /** owner Revolut payment link */
ownerRevolutProfileName?: string | null; ownerRevolutProfileName?: string | null;
/** whether to show 2D code in monthly statement */
show2dCodeInMonthlyStatement?: boolean | null;
/** whether to show payment instructions in monthly statement */
showPaymentInstructionsInMonthlyStatement?: "disabled" | "iban" | "revolut" | null;
// /** whether enableshow IBAN payment instructions in monthly statement */
// enableIbanPaymentInstructionsInMonthlyStatement?: boolean | null;
// /** whether to enable Revolut payment instructions in monthly statement */
// enableRevolutPaymentInstructionsInMonthlyStatement?: boolean | null;
}; };
/** bill object in the form returned by MongoDB */ /** bill object in the form returned by MongoDB */

View File

@@ -28,18 +28,20 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
// Track current form values for real-time validation // Track current form values for real-time validation
const [formValues, setFormValues] = useState({ const [formValues, setFormValues] = useState({
enableIbanPayment: userSettings?.enableIbanPayment ?? false,
ownerName: userSettings?.ownerName ?? "", ownerName: userSettings?.ownerName ?? "",
ownerStreet: userSettings?.ownerStreet ?? "", ownerStreet: userSettings?.ownerStreet ?? "",
ownerTown: userSettings?.ownerTown ?? "", ownerTown: userSettings?.ownerTown ?? "",
ownerIBAN: formatIban(userSettings?.ownerIBAN) ?? "", ownerIBAN: formatIban(userSettings?.ownerIBAN) ?? "",
currency: userSettings?.currency ?? "EUR", currency: userSettings?.currency ?? "EUR",
enableRevolutPayment: userSettings?.enableRevolutPayment ?? false,
ownerRevolutProfileName: userSettings?.ownerRevolutProfileName ?? "", ownerRevolutProfileName: userSettings?.ownerRevolutProfileName ?? "",
showPaymentInstructions: userSettings?.showPaymentInstructionsInMonthlyStatement ?? "disabled",
}); });
// https://revolut.me/aderezic?currency=EUR&amount=70000 // https://revolut.me/aderezic?currency=EUR&amount=70000
const handleInputChange = (field: keyof typeof formValues, value: string) => { const handleInputChange = (field: keyof typeof formValues, value: string | boolean) => {
setFormValues(prev => ({ ...prev, [field]: value })); setFormValues(prev => ({ ...prev, [field]: value }));
}; };
@@ -106,39 +108,38 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
</div> </div>
</div> </div>
</fieldset> </fieldset>
<fieldset className="fieldset bg-base-200 border-base-300 rounded-box w-xs border p-4 pb-2 mt-4"> <fieldset className="fieldset bg-base-200 border-base-300 rounded-box w-xs border p-4 pb-2 mt-4">
<legend className="fieldset-legend font-semibold uppercase">{t("tenant-payment-instructions--legend")}</legend> <legend className="fieldset-legend font-semibold uppercase">{t("iban-payment-instructions--legend")}</legend>
<InfoBox className="p-1 mb-1">{t("info-box-message")}</InfoBox> <InfoBox className="p-1 mb-1">{t("iban-payment-instructions--intro-message")}</InfoBox>
<fieldset className="form-control w-full"> <fieldset className="fieldset">
<select <label className="label cursor-pointer justify-start gap-3">
id="showPaymentInstructions" <input
name="showPaymentInstructions" type="checkbox"
className="select select-bordered w-full" name="enableIbanPayment"
defaultValue={formValues.showPaymentInstructions} className="toggle toggle-primary"
onChange={(e) => handleInputChange("showPaymentInstructions", e.target.value)} checked={formValues.enableIbanPayment}
disabled={pending} onChange={(e) => handleInputChange("enableIbanPayment", e.target.checked)}
> />
<option value="disabled">{t("tenant-payment-instructions--show-no-instructions")}</option> <legend className="fieldset-legend">{t("iban-payment-instructions--toggle-label")}</legend>
<option value="iban">{t("tenant-payment-instructions--show-iban-instructions")}</option> </label>
<option value="revolut">{t("tenant-payment-instructions--show-revolut-instructions")}</option>
</select>
</fieldset> </fieldset>
{formValues.showPaymentInstructions === "iban" && (
{ formValues.enableIbanPayment ? (
<> <>
<div className="divider mt-6 mb-2 font-bold uppercase">Informacije za uplatu</div> <div className="divider mt-2 mb-2 font-bold uppercase">{t("iban-form-title")}</div>
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("owner-name-label")}</span> <span className="label-text">{t("iban-owner-name-label")}</span>
</label> </label>
<input <input
id="ownerName" id="ownerName"
name="ownerName" name="ownerName"
type="text" type="text"
maxLength={25} maxLength={25}
placeholder={t("owner-name-placeholder")} placeholder={t("iban-owner-name-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600" className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={formValues.ownerName} defaultValue={formValues.ownerName}
onChange={(e) => handleInputChange("ownerName", e.target.value)} onChange={(e) => handleInputChange("ownerName", e.target.value)}
@@ -156,14 +157,14 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("owner-street-label")} </span> <span className="label-text">{t("iban-owner-street-label")} </span>
</label> </label>
<input <input
id="ownerStreet" id="ownerStreet"
name="ownerStreet" name="ownerStreet"
type="text" type="text"
maxLength={25} maxLength={25}
placeholder={t("owner-street-placeholder")} placeholder={t("iban-owner-street-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600" className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={formValues.ownerStreet} defaultValue={formValues.ownerStreet}
onChange={(e) => handleInputChange("ownerStreet", e.target.value)} onChange={(e) => handleInputChange("ownerStreet", e.target.value)}
@@ -181,14 +182,14 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("owner-town-label")}</span> <span className="label-text">{t("iban-owner-town-label")}</span>
</label> </label>
<input <input
id="ownerTown" id="ownerTown"
name="ownerTown" name="ownerTown"
type="text" type="text"
maxLength={27} maxLength={27}
placeholder={t("owner-town-placeholder")} placeholder={t("iban-owner-town-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600" className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={formValues.ownerTown} defaultValue={formValues.ownerTown}
onChange={(e) => handleInputChange("ownerTown", e.target.value)} onChange={(e) => handleInputChange("ownerTown", e.target.value)}
@@ -206,13 +207,13 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("owner-iban-label")}</span> <span className="label-text">{t("iban-owner-iban-label")}</span>
</label> </label>
<input <input
id="ownerIBAN" id="ownerIBAN"
name="ownerIBAN" name="ownerIBAN"
type="text" type="text"
placeholder={t("owner-iban-placeholder")} placeholder={t("iban-owner-iban-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600" className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={formValues.ownerIBAN} defaultValue={formValues.ownerIBAN}
onChange={(e) => handleInputChange("ownerIBAN", e.target.value)} onChange={(e) => handleInputChange("ownerIBAN", e.target.value)}
@@ -230,20 +231,67 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
<NoteBox className="p-1 mt-1">{t("payment-additional-notes")}</NoteBox> <NoteBox className="p-1 mt-1">{t("payment-additional-notes")}</NoteBox>
</> </>
)} ) : // ELSE include hidden inputs to preserve existing values
{formValues.showPaymentInstructions === "revolut" && (
<> <>
<div className="divider mt-6 mb-2 font-bold uppercase">Informacije za uplatu</div> <input
id="ownerName"
name="ownerName"
type="hidden"
value={formValues.ownerName}
/>
<input
id="ownerStreet"
name="ownerStreet"
type="hidden"
value={formValues.ownerStreet}
/>
<input
id="ownerTown"
name="ownerTown"
type="hidden"
defaultValue={formValues.ownerTown}
/>
<input
id="ownerIBAN"
name="ownerIBAN"
type="hidden"
defaultValue={formValues.ownerIBAN}
/>
</>
}
</fieldset>
<fieldset className="fieldset bg-base-200 border-base-300 rounded-box w-xs border p-4 pb-2 mt-4">
<legend className="fieldset-legend font-semibold uppercase">{t("revolut-payment-instructions--legend")}</legend>
<InfoBox className="p-1 mb-1">{t("revolut-payment-instructions--intro-message")}</InfoBox>
<fieldset className="fieldset">
<label className="label cursor-pointer justify-start gap-3">
<input
type="checkbox"
name="enableRevolutPayment"
className="toggle toggle-primary"
checked={formValues.enableRevolutPayment}
onChange={(e) => handleInputChange("enableRevolutPayment", e.target.checked)}
/>
<legend className="fieldset-legend">{t("revolut-payment-instructions--toggle-label")}</legend>
</label>
</fieldset>
{ formValues.enableRevolutPayment ? (
<>
<div className="divider mt-2 mb-2 font-bold uppercase">{t("revolut-form-title")}</div>
<div className="form-control w-full"> <div className="form-control w-full">
<label className="label"> <label className="label">
<span className="label-text">{t("owner-revolut-link-label")}</span> <span className="label-text">{t("revolut-profile-label")}</span>
</label> </label>
<input <input
id="ownerRevolutProfileName" id="ownerRevolutProfileName"
name="ownerRevolutProfileName" name="ownerRevolutProfileName"
type="text" type="text"
maxLength={25} maxLength={25}
placeholder={t("owner-revolut-link-placeholder")} placeholder={t("revolut-profile-placeholder")}
className="input input-bordered w-full placeholder:text-gray-600" className="input input-bordered w-full placeholder:text-gray-600"
defaultValue={formValues.ownerRevolutProfileName} defaultValue={formValues.ownerRevolutProfileName}
onChange={(e) => handleInputChange("ownerRevolutProfileName", e.target.value)} onChange={(e) => handleInputChange("ownerRevolutProfileName", e.target.value)}
@@ -260,7 +308,17 @@ const FormFields: FC<FormFieldsProps> = ({ userSettings, errors, message }) => {
</div> </div>
<NoteBox className="p-1 mt-1">{t("payment-additional-notes")}</NoteBox> <NoteBox className="p-1 mt-1">{t("payment-additional-notes")}</NoteBox>
</> </>
)} )
: // ELSE include hidden input to preserve existing value
<>
<input
id="ownerRevolutProfileName"
name="ownerRevolutProfileName"
type="hidden"
value={formValues.ownerRevolutProfileName}
/>
</>
}
</fieldset> </fieldset>
<div id="general-error" aria-live="polite" aria-atomic="true"> <div id="general-error" aria-live="polite" aria-atomic="true">

View File

@@ -79,7 +79,7 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
const { hub3aText, paymentParams } = useMemo(() => { const { hub3aText, paymentParams } = useMemo(() => {
if(!userSettings?.show2dCodeInMonthlyStatement || !generateTenantCode) { if(!userSettings?.enableIbanPayment || !generateTenantCode) {
return { return {
hub3aText: "", hub3aText: "",
paymentParams: {} as PaymentParams paymentParams: {} as PaymentParams
@@ -107,7 +107,7 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
hub3aText: EncodePayment(paymentParams), hub3aText: EncodePayment(paymentParams),
paymentParams paymentParams
}); });
}, [userSettings?.show2dCodeInMonthlyStatement, generateTenantCode, locationName, tenantName, tenantStreet, tenantTown, userSettings, monthlyExpense, yearMonth]); }, []);
return( return(
<div data-key={_id } className="card card-compact card-bordered max-w-[30em] min-w-[330px] bg-base-100 border-1 border-neutral my-1"> <div data-key={_id } className="card card-compact card-bordered max-w-[30em] min-w-[330px] bg-base-100 border-1 border-neutral my-1">
@@ -126,7 +126,7 @@ export const ViewLocationCard:FC<ViewLocationCardProps> = ({location, userSettin
: null : null
} }
{ {
userSettings?.show2dCodeInMonthlyStatement && generateTenantCode ? userSettings?.enableIbanPayment && generateTenantCode ?
<> <>
<p className="max-w-[25em] ml-1 mt-1 mb-1">{t("payment-info-header")}</p> <p className="max-w-[25em] ml-1 mt-1 mb-1">{t("payment-info-header")}</p>
<ul className="ml-4 mb-3"> <ul className="ml-4 mb-3">

View File

@@ -191,28 +191,32 @@
}, },
"user-settings-form": { "user-settings-form": {
"title": "User settings", "title": "User settings",
"info-box-message": "By activating this option, a 2D barcode will be included in the monthly statement sent to the tenant, allowing them to make a direct payment to your bank account.",
"tenant-2d-code-legend": "TENANT 2D CODE",
"tenant-2d-code-toggle-label": "include 2D code in monthly statements",
"tenant-payment-instructions--legend": "Payment Instructions", "iban-payment-instructions--legend": "Payment to Your IBAN",
"tenant-payment-instructions--info": "If you enable this option, the monthly statement sent to the tenant will include payment instructions and a 2D barcode, allowing them to make a direct payment to your bank account.", "iban-payment-instructions--intro-message": "By activating this option, payment instructions will be included in the monthly statement sent to the tenant, allowing a direct payment via IBAN to be made to your bank account.",
"tenant-payment-instructions--show-no-instructions": "🚫 - do not show payment instructions", "iban-payment-instructions--toggle-label": "enable IBAN payment instructions",
"tenant-payment-instructions--show-iban-instructions": "🏦 - show payment instructions for IBAN",
"tenant-payment-instructions--show-revolut-instructions": "🆁 - show payment instructions for Revolut",
"owner-name-label": "Your First and Last Name", "iban-form-title": "Payment Information for IBAN",
"owner-name-placeholder": "enter your first and last name", "iban-owner-name-label": "Your First and Last Name",
"owner-street-label": "Your Street and House Number", "iban-owner-name-placeholder": "enter your first and last name",
"owner-street-placeholder": "enter your street and house number", "iban-owner-street-label": "Your Street and House Number",
"owner-town-label": "Your Postal Code and Town", "iban-owner-street-placeholder": "enter your street and house number",
"owner-town-placeholder": "enter your postal code and town", "iban-owner-town-label": "Your Postal Code and Town",
"owner-iban-label": "IBAN", "iban-owner-town-placeholder": "enter your postal code and town",
"owner-iban-placeholder": "enter your IBAN for receiving payments", "iban-owner-iban-label": "IBAN",
"iban-owner-iban-placeholder": "enter your IBAN for receiving payments",
"owner-revolut-profile-label": "Revolut profile name",
"owner-revolut-profile-placeholder": "enter your Revolut profile name for receiving payments", "revolut-form-title": "Payment Information for Revolut",
"owner-revolut-profile-tooltip": "You can find your Revolut profile name in the Revolut app under your user profile. It is displayed below your name and starts with the '@' symbol (e.g., '@john123').", "revolut-payment-instructions--legend": "Payment to Your Revolut Profile",
"revolut-payment-instructions--intro-message": "By activating this option, payment instructions will be included in the monthly statement sent to the tenant, allowing a direct payment via Revolut to be made to your Revolut profile.",
"revolut-payment-instructions--toggle-label": "enable Revolut payment instructions",
"revolut-profile-label": "Revolut profile name",
"revolut-profile-placeholder": "enter your Revolut profile name for receiving payments",
"revolut-profile-tooltip": "You can find your Revolut profile name in the Revolut app under your user profile. It is displayed below your name and starts with the '@' symbol (e.g., '@john123').",
"payment-additional-notes": "IMPORTANT: For the payment instructions to be displayed to the tenant, you must also enable this option in the property's settings.",
"general-settings-legend": "General Settings", "general-settings-legend": "General Settings",
"currency-label": "Currency", "currency-label": "Currency",
@@ -226,7 +230,6 @@
"owner-iban-invalid": "Invalid IBAN format. Please enter a valid IBAN", "owner-iban-invalid": "Invalid IBAN format. Please enter a valid IBAN",
"currency-required": "Currency is mandatory", "currency-required": "Currency is mandatory",
"validation-failed": "Validation failed. Please check the form and try again." "validation-failed": "Validation failed. Please check the form and try again."
}, }
"payment-additional-notes": "IMPORTANT: For the payment instructions to be displayed to the tenant, you must also enable this option in the property's settings."
} }
} }

View File

@@ -190,23 +190,30 @@
}, },
"user-settings-form": { "user-settings-form": {
"title": "Korisničke postavke", "title": "Korisničke postavke",
"info-box-message": "Ako uključite ovu opciju na mjesečnom obračunu koji se šalje podstanaru biti će prikazane upute za uplatu i 2D bar kod, putem kojeg će moći izvršiti izravnu uplatu na vaš bankovni račun.",
"tenant-payment-instructions--legend": "Upute za uplatu",
"tenant-payment-instructions--info": "Ako uključite ovu opciju na mjesečnom obračunu koji se šalje podstanaru biti će prikazane upute za uplatu i 2D bar kod, putem kojeg će moći izvršiti izravnu uplatu na vaš bankovni račun.", "iban-payment-instructions--legend": "Uplata na vaš IBAN",
"tenant-payment-instructions--show-no-instructions": "🚫 - Ne prikazivati upute za uplatu", "iban-payment-instructions--intro-message": "Aktiviranjem ove opcije, upute za uplatu bit će uključene u mjesečni izvještaj poslan podstanaru, omogućujući im da izvrše izravnu uplatu putem IBAN-a na vaš bankovni račun.",
"tenant-payment-instructions--show-iban-instructions": "🏦 - Prikazuj upute za uplatu na IBAN", "iban-payment-instructions--toggle-label": "uključi IBAN uplatu",
"tenant-payment-instructions--show-revolut-instructions": "🆁 - Prikazuj upute za uplatu na Revolut",
"owner-name-label": "Vaše ime i prezime", "iban-form-title": "Informacije za uplatu na IBAN",
"owner-name-placeholder": "unesite svoje ime i prezime", "iban-owner-name-label": "Vaše ime i prezime",
"owner-street-label": "Ulica i kućni broj", "iban-owner-name-placeholder": "unesite svoje ime i prezime",
"owner-street-placeholder": "unesite ulicu i kućni broj", "iban-owner-street-label": "Ulica i kućni broj",
"owner-town-label": "Poštanski broj i Grad", "iban-owner-street-placeholder": "unesite ulicu i kućni broj",
"owner-town-placeholder": "unesite poštanski broj i grad", "iban-owner-town-label": "Poštanski broj i Grad",
"owner-iban-label": "IBAN", "iban-owner-town-placeholder": "unesite poštanski broj i grad",
"owner-iban-placeholder": "IBAN putem kojeg ćete primate uplate", "iban-owner-iban-label": "IBAN",
"owner-revolut-profile-label": "Naziv vašeg Revolut profila", "iban-owner-iban-placeholder": "IBAN putem kojeg ćete primate uplate",
"owner-revolut-profile-placeholder": "profil putem kojeg ćete primati uplate",
"owner-revolut-profile-tooltip": "Naziv vašeg Revolute profila možete pronaći u aplikaciji Revolut u korisničkom profilu. Prikazan je ispod vašeg imena i prezimena - počinje sa znakom '@' (npr: '@ivan123').", "revolut-payment-instructions--legend": "Uplata na vaš Revolut profil",
"revolut-payment-instructions--intro-message": "Aktiviranjem ove opcije, upute za uplatu bit će uključene u mjesečni izvještaj poslan podstanaru, omogućujući im da izvrše izravnu uplatu putem Revolut-a na vaš profil.",
"revolut-payment-instructions--toggle-label": "uključi Revolut uplatu",
"revolut-form-title": "Informacije za uplatu na Revolut",
"revolut-profile-label": "Naziv vašeg Revolut profila",
"revolut-profile-placeholder": "profil putem kojeg ćete primati uplate",
"revolut-profile-tooltip": "Naziv vašeg Revolut profila možete pronaći u aplikaciji Revolut u korisničkom profilu. Prikazan je ispod vašeg imena i prezimena - počinje sa znakom '@' (npr: '@ivan123').",
"general-settings-legend": "Opće postavke", "general-settings-legend": "Opće postavke",
"currency-label": "Valuta", "currency-label": "Valuta",