Add real-time warning for missing profile data in account form
Added conditional warning alert that displays when required fields are empty, updating in real-time as the user types: - Tracks form values with useState and onChange handlers - Displays warning when firstName, lastName, address, or IBAN is missing - Warning appears/disappears instantly as user fills or clears fields - Explains that 2D barcode won't be shown to tenants until all data is complete - Added translations in English and Croatian 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { FC, useState } from "react";
|
||||
import { UserProfile } from "../lib/db-types";
|
||||
import { updateUserProfile } from "../lib/actions/userProfileActions";
|
||||
import { useFormState, useFormStatus } from "react-dom";
|
||||
@@ -23,6 +23,21 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
const t = useTranslations("account-form");
|
||||
const locale = useLocale();
|
||||
|
||||
// Track current form values for real-time validation
|
||||
const [formValues, setFormValues] = useState({
|
||||
firstName: profile?.firstName ?? "",
|
||||
lastName: profile?.lastName ?? "",
|
||||
address: profile?.address ?? "",
|
||||
iban: profile?.iban ?? "",
|
||||
});
|
||||
|
||||
const handleInputChange = (field: keyof typeof formValues, value: string) => {
|
||||
setFormValues(prev => ({ ...prev, [field]: value }));
|
||||
};
|
||||
|
||||
// Check if any required field is missing
|
||||
const hasMissingData = !formValues.firstName || !formValues.lastName || !formValues.address || !formValues.iban;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="alert max-w-md flex flex-row items-start">
|
||||
@@ -42,6 +57,7 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
placeholder={t("first-name-placeholder")}
|
||||
className="input input-bordered w-full"
|
||||
defaultValue={profile?.firstName ?? ""}
|
||||
onChange={(e) => handleInputChange("firstName", e.target.value)}
|
||||
disabled={pending}
|
||||
/>
|
||||
<div id="firstName-error" aria-live="polite" aria-atomic="true">
|
||||
@@ -65,6 +81,7 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
placeholder={t("last-name-placeholder")}
|
||||
className="input input-bordered w-full"
|
||||
defaultValue={profile?.lastName ?? ""}
|
||||
onChange={(e) => handleInputChange("lastName", e.target.value)}
|
||||
disabled={pending}
|
||||
/>
|
||||
<div id="lastName-error" aria-live="polite" aria-atomic="true">
|
||||
@@ -87,6 +104,7 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
className="textarea textarea-bordered w-full"
|
||||
placeholder={t("address-placeholder")}
|
||||
defaultValue={profile?.address ?? ""}
|
||||
onChange={(e) => handleInputChange("address", e.target.value)}
|
||||
disabled={pending}
|
||||
></textarea>
|
||||
<div id="address-error" aria-live="polite" aria-atomic="true">
|
||||
@@ -110,6 +128,7 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
placeholder={t("iban-placeholder")}
|
||||
className="input input-bordered w-full"
|
||||
defaultValue={profile?.iban ?? ""}
|
||||
onChange={(e) => handleInputChange("iban", e.target.value)}
|
||||
disabled={pending}
|
||||
/>
|
||||
<div id="iban-error" aria-live="polite" aria-atomic="true">
|
||||
@@ -130,6 +149,15 @@ const FormFields: FC<FormFieldsProps> = ({ profile, errors, message }) => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{hasMissingData && (
|
||||
<div className="alert mt-4 max-w-md flex flex-row items-start">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="stroke-current shrink-0 w-6 h-6">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<span className="text-left">{t("warning-missing-data")}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="pt-4">
|
||||
<button className="btn btn-primary w-[5.5em]" disabled={pending}>
|
||||
{pending ? (
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
"account-form": {
|
||||
"title": "Profile Information",
|
||||
"info-box-message": "This information will be used to generate a 2D barcode displayed in the bill view, allowing tenants to scan it and refund the money you have spent on paying utility bills in their name.",
|
||||
"warning-missing-data": "Warning: Some profile fields are missing. The 2D barcode will not be displayed to tenants on the shared bill view until all fields are filled in.",
|
||||
"first-name-label": "First Name",
|
||||
"first-name-placeholder": "Enter your first name",
|
||||
"last-name-label": "Last Name",
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
"account-form": {
|
||||
"title": "Podaci o profilu",
|
||||
"info-box-message": "Ovi podaci će se koristiti za generiranje 2D barkoda koji će biti prikazan u pregledu računa, omogućujući podstanarima da ga skeniraju i vrate novac koji ste potrošili na plaćanje režija u njihovo ime.",
|
||||
"warning-missing-data": "Upozorenje: Neki podaci profila nedostaju. 2D barkod neće biti prikazan podstanarima u podijeljenom pregledu računa dok sva polja ne budu popunjena.",
|
||||
"first-name-label": "Ime",
|
||||
"first-name-placeholder": "Unesite svoje ime",
|
||||
"last-name-label": "Prezime",
|
||||
|
||||
Reference in New Issue
Block a user