@@ -2,7 +2,7 @@ import { createFileRoute } from '@tanstack/react-router'
22import { SquarePen } from 'lucide-react'
33import { getUser } from '#/util.ts'
44import { useImmer } from 'use-immer'
5- import { Button } from " #/components/Buttons.tsx" ;
5+ import { Button } from ' #/components/Buttons.tsx'
66
77export const Route = createFileRoute ( '/profile' ) ( {
88 component : ProfilePage ,
@@ -14,11 +14,13 @@ function ProfileField({
1414 value,
1515 type = 'text' ,
1616 onChange,
17+ error,
1718} : {
1819 label : string
1920 value : string
2021 type ?: string
2122 onChange : ( val : string ) => void
23+ error ?: string
2224} ) {
2325 return (
2426 < div >
@@ -27,8 +29,9 @@ function ProfileField({
2729 type = { type }
2830 value = { value }
2931 onChange = { ( e ) => onChange ( e . target . value ) }
30- className = " w-full border border-gray-300 rounded-lg px-4 py-2 text-sm disabled:bg-white disabled:text-gray-700"
32+ className = { ` w-full border ${ error ? ' border-red-600' : 'border- gray-300' } rounded-lg px-4 py-2 text-sm disabled:bg-white disabled:text-gray-700` }
3133 />
34+ < p className = "text-red-600 min-h-6" > { error } </ p >
3235 </ div >
3336 )
3437}
@@ -52,22 +55,59 @@ function ProfilePage() {
5255 }
5356
5457 function handleCancel ( ) {
55- const confirmCancel = confirm ( " Are you sure you want to cancel?" ) ;
58+ const confirmCancel = confirm ( ' Are you sure you want to cancel?' )
5659
5760 if ( confirmCancel ) {
5861 setUser ( {
5962 ...loaderData ,
6063 password : '' ,
6164 confirmPassword : '' ,
62- } ) ;
65+ } )
6366 }
6467 }
6568
69+ function getUserErrors ( field : string ) : string | undefined {
70+ switch ( field ) {
71+ case 'username' :
72+ case 'role' :
73+ case 'email' :
74+ if ( user [ field ] === '' ) {
75+ return `Field cannot be empty.`
76+ }
77+ break
78+ case 'password' :
79+ if ( user [ 'password' ] . length !== 0 ) {
80+ if ( user [ 'password' ] . length < 8 ) {
81+ return 'Password must be at least 8 characters long'
82+ }
83+ }
84+ break
85+ case 'confirmPassword' :
86+ if (
87+ user [ 'password' ] . length !== 0 &&
88+ user [ 'confirmPassword' ] !== user [ 'password' ]
89+ ) {
90+ return 'Passwords do not match.'
91+ }
92+ break
93+ }
94+ }
95+
96+ function hasError ( ) : boolean {
97+ for ( const field in user ) {
98+ if ( getUserErrors ( field ) ) {
99+ return true
100+ }
101+ }
102+
103+ return false
104+ }
105+
66106 return (
67107 < div className = "w-fit mx-auto py-8 px-8" >
68108 < div className = "flex gap-16 items-start" >
69109 { /* Left: form fields */ }
70- < div className = "flex-1 min-w-80 flex flex-col gap-5 " >
110+ < div className = "flex-1 min-w-80 flex flex-col" >
71111 < ProfileField
72112 label = "Username"
73113 value = { user . username }
@@ -76,6 +116,7 @@ function ProfilePage() {
76116 draft . username = username
77117 } )
78118 }
119+ error = { getUserErrors ( 'username' ) }
79120 />
80121 < ProfileField
81122 label = "Role"
@@ -85,6 +126,7 @@ function ProfilePage() {
85126 draft . role = role
86127 } )
87128 }
129+ error = { getUserErrors ( 'role' ) }
88130 />
89131 < ProfileField
90132 label = "Email"
@@ -95,6 +137,7 @@ function ProfilePage() {
95137 draft . email = email
96138 } )
97139 }
140+ error = { getUserErrors ( 'email' ) }
98141 />
99142 < ProfileField
100143 label = "Password"
@@ -105,6 +148,7 @@ function ProfilePage() {
105148 draft . password = password
106149 } )
107150 }
151+ error = { getUserErrors ( 'password' ) }
108152 />
109153 < ProfileField
110154 label = "Confirm Password"
@@ -115,18 +159,18 @@ function ProfilePage() {
115159 draft . confirmPassword = confirmPassword
116160 } )
117161 }
162+ error = { getUserErrors ( 'confirmPassword' ) }
118163 />
119164
120165 < div className = "flex gap-3 mt-2" >
121166 < Button
122167 onClick = { handleSave }
123- variant = " normal"
168+ variant = { hasError ( ) ? 'disabled' : ' normal' }
124169 fontSize = "base"
125- > Save</ Button >
126- < Button
127- onClick = { handleCancel }
128- variant = "danger"
129- fontSize = "base" >
170+ >
171+ Save
172+ </ Button >
173+ < Button onClick = { handleCancel } variant = "danger" fontSize = "base" >
130174 Cancel
131175 </ Button >
132176 </ div >
0 commit comments