From 11210c09f62f5ba35bf091109741a312607c689d Mon Sep 17 00:00:00 2001 From: Umang Khemka Date: Sun, 24 May 2026 20:38:23 +0530 Subject: [PATCH 1/2] feat: add long word validation for name input in onboarding and settings --- .../components/Navigation/Navbar/Navbar.tsx | 8 +++- .../OnboardingSteps/AvatarSelectionStep.tsx | 25 ++++++++---- .../components/AccountSettingsCard.tsx | 40 +++++++++++-------- 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/Navigation/Navbar/Navbar.tsx b/frontend/src/components/Navigation/Navbar/Navbar.tsx index d32d0777d..7b1c76c7d 100644 --- a/frontend/src/components/Navigation/Navbar/Navbar.tsx +++ b/frontend/src/components/Navigation/Navbar/Navbar.tsx @@ -81,7 +81,13 @@ export function Navbar() {
- Welcome {userName} + Welcome{' '} + + {userName.split(' ')[0]} + = ({ const isEditing = useSelector( (state: RootState) => state.onboarding.isEditing, ); + const [longWordError, setLongWordError] = useState(false); useEffect(() => { if ( @@ -56,6 +57,13 @@ export const AvatarSelectionStep: React.FC = ({ }; const handleNameChange = (value: string) => { + const words = value.split(' '); + const hasLongWord = words.some((word) => word.length > 30); + if (hasLongWord) { + setLongWordError(true); + return; + } + setLongWordError(false); setLocalName(value); }; @@ -115,6 +123,11 @@ export const AvatarSelectionStep: React.FC = ({ onChange={(e) => handleNameChange(e.target.value)} className="h-8 text-sm placeholder:text-sm" /> + {longWordError && ( +

+ A single word in your name cannot exceed 30 characters. +

+ )}
{/* Avatar Grid */} @@ -128,18 +141,16 @@ export const AvatarSelectionStep: React.FC = ({ type="button" key={avatar} onClick={() => handleAvatarSelect(avatar)} - className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 ${ - isSelected + className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 ${isSelected ? 'border-primary ring-primary ring-offset-background ring-2 ring-offset-2' : 'border-muted' - }`} + }`} > Avatar ); @@ -152,7 +163,7 @@ export const AvatarSelectionStep: React.FC = ({ diff --git a/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx b/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx index 65070f8a4..82d1f762c 100644 --- a/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx +++ b/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx @@ -19,6 +19,7 @@ const AccountSettingsCard: React.FC = () => { return avatars.includes(stored) ? stored : ''; }); const [nameError, setNameError] = useState(false); + const [longWordError, setLongWordError] = useState(false); // The redundant useEffect has been removed. @@ -27,10 +28,15 @@ const AccountSettingsCard: React.FC = () => { }; const handleNameChange = (value: string) => { - setLocalName(value); - if (nameError) { - setNameError(false); + const words = value.split(' '); + const hasLongWord = words.some((word) => word.length > 30); + if (hasLongWord) { + setLongWordError(true); + return; } + setLongWordError(false); + setLocalName(value); + if (nameError) setNameError(false); }; const handleSave = () => { @@ -72,12 +78,16 @@ const AccountSettingsCard: React.FC = () => { } value={name} onChange={(e) => handleNameChange(e.target.value)} - className={`h-10 w-full text-sm placeholder:text-sm ${ - nameError - ? 'border-red-500 placeholder:text-red-500/80 focus-visible:ring-red-500' - : '' - }`} + className={`h-10 w-full text-sm placeholder:text-sm ${nameError + ? 'border-red-500 placeholder:text-red-500/80 focus-visible:ring-red-500' + : '' + }`} /> + {longWordError && ( +

+ A single word in your name cannot exceed 30 characters. +

+ )} {/* Avatar Section */} @@ -91,18 +101,16 @@ const AccountSettingsCard: React.FC = () => { type="button" key={avatar} onClick={() => handleAvatarSelect(avatar)} - className={`bg-background relative inline-flex h-24 w-24 items-center justify-center rounded-full transition-all duration-300 ${ - isSelected - ? 'ring-offset-background scale-90 ring-2 ring-blue-500 ring-offset-4' - : 'hover:ring-4 hover:ring-blue-500 hover:ring-offset-4' - }`} + className={`bg-background relative inline-flex h-24 w-24 items-center justify-center rounded-full transition-all duration-300 ${isSelected + ? 'ring-offset-background scale-90 ring-2 ring-blue-500 ring-offset-4' + : 'hover:ring-4 hover:ring-blue-500 hover:ring-offset-4' + }`} > Avatar ); From f917de946dd7d3af49e23e22f2ae893c6d3a945f Mon Sep 17 00:00:00 2001 From: Umang Khemka Date: Sun, 24 May 2026 21:46:23 +0530 Subject: [PATCH 2/2] fix: handle potential undefined userName and improve className formatting in Navbar and AccountSettingsCard --- .../components/Navigation/Navbar/Navbar.tsx | 2 +- .../OnboardingSteps/AvatarSelectionStep.tsx | 10 +++++--- .../components/AccountSettingsCard.tsx | 25 +++++++++++-------- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/Navigation/Navbar/Navbar.tsx b/frontend/src/components/Navigation/Navbar/Navbar.tsx index 7b1c76c7d..e399b24fd 100644 --- a/frontend/src/components/Navigation/Navbar/Navbar.tsx +++ b/frontend/src/components/Navigation/Navbar/Navbar.tsx @@ -86,7 +86,7 @@ export function Navbar() { className="text-muted-foreground inline-block max-w-[150px] truncate align-bottom" title={userName} > - {userName.split(' ')[0]} + {userName?.split(' ')[0] ?? ''} diff --git a/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx b/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx index fb1dbe310..4309bbc74 100644 --- a/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx +++ b/frontend/src/components/OnboardingSteps/AvatarSelectionStep.tsx @@ -141,16 +141,18 @@ export const AvatarSelectionStep: React.FC = ({ type="button" key={avatar} onClick={() => handleAvatarSelect(avatar)} - className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 ${isSelected + className={`bg-background relative inline-flex h-20 w-20 items-center justify-center rounded-full transition-all duration-300 ${ + isSelected ? 'border-primary ring-primary ring-offset-background ring-2 ring-offset-2' : 'border-muted' - }`} + }`} > Avatar ); diff --git a/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx b/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx index 82d1f762c..0a2ffcfeb 100644 --- a/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx +++ b/frontend/src/pages/SettingsPage/components/AccountSettingsCard.tsx @@ -78,10 +78,11 @@ const AccountSettingsCard: React.FC = () => { } value={name} onChange={(e) => handleNameChange(e.target.value)} - className={`h-10 w-full text-sm placeholder:text-sm ${nameError - ? 'border-red-500 placeholder:text-red-500/80 focus-visible:ring-red-500' - : '' - }`} + className={`h-10 w-full text-sm placeholder:text-sm ${ + nameError + ? 'border-red-500 placeholder:text-red-500/80 focus-visible:ring-red-500' + : '' + }`} /> {longWordError && (

@@ -101,16 +102,18 @@ const AccountSettingsCard: React.FC = () => { type="button" key={avatar} onClick={() => handleAvatarSelect(avatar)} - className={`bg-background relative inline-flex h-24 w-24 items-center justify-center rounded-full transition-all duration-300 ${isSelected - ? 'ring-offset-background scale-90 ring-2 ring-blue-500 ring-offset-4' - : 'hover:ring-4 hover:ring-blue-500 hover:ring-offset-4' - }`} + className={`bg-background relative inline-flex h-24 w-24 items-center justify-center rounded-full transition-all duration-300 ${ + isSelected + ? 'ring-offset-background scale-90 ring-2 ring-blue-500 ring-offset-4' + : 'hover:ring-4 hover:ring-blue-500 hover:ring-offset-4' + }`} > Avatar ); @@ -123,7 +126,7 @@ const AccountSettingsCard: React.FC = () => {