Skip to content

Commit e70e69a

Browse files
gokulvijclaudeabishekve
authored
fix: Enhance User Management UI with improved styling and state management (#144)
Co-authored-by: Claude <[email protected]> Co-authored-by: abishek <[email protected]>
1 parent a29382d commit e70e69a

File tree

6 files changed

+322
-327
lines changed

6 files changed

+322
-327
lines changed

thingconnect.pulse.client/src/features/users/components/CreateUserModal.tsx

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
} from '@chakra-ui/react';
1212
import { useState, useCallback } from 'react';
1313
import { useForm } from 'react-hook-form';
14-
import { LoadingButton } from '@/components/ui/LoadingButton';
1514
import { Field } from '@/components/ui/field';
1615
import { PasswordInput } from '@/components/form/PasswordInput';
1716
import { NativeSelectRoot, NativeSelectField } from '@/components/ui/native-select';
@@ -89,26 +88,26 @@ export function CreateUserModal({
8988
);
9089

9190
return (
92-
<Dialog.Root open={isOpen} onOpenChange={(e) => !e.open && handleClose()}>
91+
<Dialog.Root open={isOpen} onOpenChange={e => !e.open && handleClose()}>
9392
<Dialog.Backdrop />
9493
<Dialog.Positioner>
95-
<DialogContent maxW="md">
94+
<DialogContent maxW='md'>
9695
<DialogHeader>
9796
<DialogTitle>Create New User</DialogTitle>
9897
</DialogHeader>
9998

10099
<form onSubmit={handleSubmit(onSubmit)}>
101-
<VStack gap={4} py={4}>
100+
<VStack gap={4} pb={4} px={6} align='stretch'>
102101
{submitError && (
103-
<Alert.Root status="error" variant="subtle">
102+
<Alert.Root status='error' variant='subtle'>
104103
<Alert.Indicator />
105104
<Alert.Title>{submitError}</Alert.Title>
106105
</Alert.Root>
107106
)}
108107

109108
{/* Username */}
110109
<Field
111-
label="Username"
110+
label='Username'
112111
errorText={errors.username?.message}
113112
invalid={!!errors.username}
114113
>
@@ -120,19 +119,15 @@ export function CreateUserModal({
120119
message: 'Username must be 256 characters or less',
121120
},
122121
})}
123-
placeholder="Enter username"
122+
placeholder='Enter username'
124123
disabled={isSubmitting || loading}
125124
/>
126125
</Field>
127126

128127
{/* Email */}
129-
<Field
130-
label="Email"
131-
errorText={errors.email?.message}
132-
invalid={!!errors.email}
133-
>
128+
<Field label='Email' errorText={errors.email?.message} invalid={!!errors.email}>
134129
<Input
135-
type="email"
130+
type='email'
136131
{...register('email', {
137132
required: 'Email is required',
138133
pattern: {
@@ -144,14 +139,14 @@ export function CreateUserModal({
144139
message: 'Email must be 256 characters or less',
145140
},
146141
})}
147-
placeholder="Enter email address"
142+
placeholder='Enter email address'
148143
disabled={isSubmitting || loading}
149144
/>
150145
</Field>
151146

152147
{/* Password */}
153148
<Field
154-
label="Password"
149+
label='Password'
155150
errorText={errors.password?.message}
156151
invalid={!!errors.password}
157152
>
@@ -167,68 +162,67 @@ export function CreateUserModal({
167162
message: 'Password must be 100 characters or less',
168163
},
169164
})}
170-
placeholder="Enter password"
165+
placeholder='Enter password'
171166
disabled={isSubmitting || loading}
172167
/>
173168
</Field>
174169

175170
{/* Confirm Password */}
176171
<Field
177-
label="Confirm Password"
172+
label='Confirm Password'
178173
errorText={errors.confirmPassword?.message}
179174
invalid={!!errors.confirmPassword}
180175
>
181176
<PasswordInput
182177
{...register('confirmPassword', {
183178
required: 'Please confirm your password',
184-
validate: (value) =>
185-
value === password || 'Passwords do not match',
179+
validate: value => value === password || 'Passwords do not match',
186180
})}
187-
placeholder="Confirm password"
181+
placeholder='Confirm password'
188182
disabled={isSubmitting || loading}
189183
/>
190184
</Field>
191185

192186
{/* Role */}
193-
<Field
194-
label="Role"
195-
errorText={errors.role?.message}
196-
invalid={!!errors.role}
197-
>
187+
<Field label='Role' errorText={errors.role?.message} invalid={!!errors.role}>
198188
<NativeSelectRoot>
199189
<NativeSelectField
200-
placeholder="Select role"
201-
defaultValue="User"
202-
onChange={(e) => setValue('role', e.target.value as 'User' | 'Administrator')}
203-
_disabled={isSubmitting || loading ? { opacity: 0.6, cursor: 'not-allowed' } : {}}
190+
placeholder='Select role'
191+
defaultValue='User'
192+
onChange={e => setValue('role', e.target.value as 'User' | 'Administrator')}
193+
_disabled={
194+
isSubmitting || loading ? { opacity: 0.6, cursor: 'not-allowed' } : {}
195+
}
204196
>
205-
<option value="User">User</option>
206-
<option value="Administrator">Administrator</option>
197+
<option value='User'>User</option>
198+
<option value='Administrator'>Administrator</option>
207199
</NativeSelectField>
208200
</NativeSelectRoot>
209201
</Field>
210202
</VStack>
211203

212204
<DialogFooter>
213205
<Button
214-
variant="outline"
206+
variant='outline'
215207
onClick={handleClose}
216208
disabled={isSubmitting || loading}
209+
size={'md'}
217210
>
218211
Cancel
219212
</Button>
220-
<LoadingButton
221-
type="submit"
222-
colorPalette="blue"
213+
<Button
214+
type='submit'
215+
colorPalette='blue'
223216
loading={isSubmitting || loading}
224-
loadingText="Creating..."
217+
loadingText='Creating...'
218+
size={'md'}
225219
>
226220
Create User
227-
</LoadingButton>
221+
</Button>
228222
</DialogFooter>
229223
</form>
230224
</DialogContent>
231225
</Dialog.Positioner>
232226
</Dialog.Root>
233227
);
234-
}
228+
}

thingconnect.pulse.client/src/features/users/components/EditUserModal.tsx

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
} from '@chakra-ui/react';
1515
import { useState, useCallback, useEffect } from 'react';
1616
import { useForm } from 'react-hook-form';
17-
import { LoadingButton } from '@/components/ui/LoadingButton';
1817
import { Field } from '@/components/ui/field';
1918
import type { UserInfo, UpdateUserRequest } from '@/api/types';
2019

@@ -121,26 +120,26 @@ export function EditUserModal({
121120
if (!user) return null;
122121

123122
return (
124-
<Dialog.Root open={isOpen} onOpenChange={(e) => !e.open && handleClose()}>
123+
<Dialog.Root open={isOpen} onOpenChange={e => !e.open && handleClose()}>
125124
<Dialog.Backdrop />
126125
<Dialog.Positioner>
127-
<DialogContent maxW="md">
126+
<DialogContent maxW='md'>
128127
<DialogHeader>
129128
<DialogTitle>Edit User</DialogTitle>
130129
</DialogHeader>
131130

132131
<form onSubmit={handleSubmit(onSubmit)}>
133-
<VStack gap={4} py={4}>
132+
<VStack gap={4} pb={4} px={6} align='stretch'>
134133
{submitError && (
135-
<Alert.Root status="error" variant="subtle">
134+
<Alert.Root status='error' variant='subtle'>
136135
<Alert.Indicator />
137136
<Alert.Title>{submitError}</Alert.Title>
138137
</Alert.Root>
139138
)}
140139

141140
{/* Username */}
142141
<Field
143-
label="Username"
142+
label='Username'
144143
errorText={errors.username?.message}
145144
invalid={!!errors.username}
146145
>
@@ -151,19 +150,15 @@ export function EditUserModal({
151150
message: 'Username must be 256 characters or less',
152151
},
153152
})}
154-
placeholder="Enter username"
153+
placeholder='Enter username'
155154
disabled={isSubmitting || loading}
156155
/>
157156
</Field>
158157

159158
{/* Email */}
160-
<Field
161-
label="Email"
162-
errorText={errors.email?.message}
163-
invalid={!!errors.email}
164-
>
159+
<Field label='Email' errorText={errors.email?.message} invalid={!!errors.email}>
165160
<Input
166-
type="email"
161+
type='email'
167162
{...register('email', {
168163
pattern: {
169164
value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
@@ -174,24 +169,24 @@ export function EditUserModal({
174169
message: 'Email must be 256 characters or less',
175170
},
176171
})}
177-
placeholder="Enter email address"
172+
placeholder='Enter email address'
178173
disabled={isSubmitting || loading}
179174
/>
180175
</Field>
181176

182177
{/* Active Status */}
183-
<Field label="Account Status">
184-
<HStack justify="space-between" w="full">
185-
<VStack align="start" gap={1}>
186-
<Text fontSize="sm" color="gray.600" _dark={{ color: "gray.400" }}>
178+
<Field label='Account Status'>
179+
<HStack justify='space-between' w='full'>
180+
<VStack align='start' gap={1}>
181+
<Text fontSize='sm' color='gray.600' _dark={{ color: 'gray.400' }}>
187182
{isActive ? 'User can log in' : 'User cannot log in'}
188183
</Text>
189184
</VStack>
190185
<Switch.Root
191186
checked={isActive}
192-
onCheckedChange={(details) => setValue('isActive', details.checked)}
193-
colorPalette="green"
194-
size="lg"
187+
onCheckedChange={details => setValue('isActive', details.checked)}
188+
colorPalette='green'
189+
size='lg'
195190
disabled={isSubmitting || loading}
196191
>
197192
<Switch.Control>
@@ -203,38 +198,35 @@ export function EditUserModal({
203198

204199
{/* Role Info (Read-only) */}
205200
<Field
206-
label="Role"
207-
helperText="Use the role change action in the user list to modify roles"
201+
label='Role'
202+
helperText='Use the role change action in the user list to modify roles'
208203
>
209-
<Input
210-
value={user.role}
211-
disabled
212-
bg="gray.50"
213-
_dark={{ bg: "gray.700" }}
214-
/>
204+
<Input value={user.role} disabled bg='gray.50' _dark={{ bg: 'gray.700' }} />
215205
</Field>
216206
</VStack>
217207

218208
<DialogFooter>
219209
<Button
220-
variant="outline"
210+
variant='outline'
221211
onClick={handleClose}
222212
disabled={isSubmitting || loading}
213+
size={'md'}
223214
>
224215
Cancel
225216
</Button>
226-
<LoadingButton
227-
type="submit"
228-
colorPalette="blue"
217+
<Button
218+
type='submit'
219+
colorPalette='blue'
229220
loading={isSubmitting || loading}
230-
loadingText="Updating..."
221+
loadingText='Updating...'
222+
size={'md'}
231223
>
232224
Update User
233-
</LoadingButton>
225+
</Button>
234226
</DialogFooter>
235227
</form>
236228
</DialogContent>
237229
</Dialog.Positioner>
238230
</Dialog.Root>
239231
);
240-
}
232+
}

thingconnect.pulse.client/src/features/users/components/UserActions.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ export function UserActions({
276276
</DialogHeader>
277277

278278
<form onSubmit={handleSubmitPassword(handleResetPassword)}>
279-
<VStack gap={4} py={4}>
279+
<VStack gap={4} pb={4} px={6} align="stretch">
280280
{error && (
281281
<Alert.Root status="error" variant="subtle">
282282
<Alert.Indicator />
@@ -328,6 +328,7 @@ export function UserActions({
328328
variant="outline"
329329
onClick={() => setResetPasswordDialogOpen(false)}
330330
disabled={actionLoading}
331+
size={'md'}
331332
>
332333
Cancel
333334
</Button>
@@ -336,6 +337,7 @@ export function UserActions({
336337
colorPalette="blue"
337338
loading={actionLoading}
338339
loadingText="Resetting..."
340+
size={'md'}
339341
>
340342
Reset Password
341343
</LoadingButton>
@@ -364,7 +366,7 @@ export function UserActions({
364366
</DialogHeader>
365367

366368
<form onSubmit={handleSubmitRole(handleChangeRole)}>
367-
<VStack gap={4} py={4}>
369+
<VStack gap={4} pb={4} px={6} align="stretch">
368370
{error && (
369371
<Alert.Root status="error" variant="subtle">
370372
<Alert.Indicator />
@@ -400,6 +402,7 @@ export function UserActions({
400402
variant="outline"
401403
onClick={() => setChangeRoleDialogOpen(false)}
402404
disabled={actionLoading}
405+
size={'md'}
403406
>
404407
Cancel
405408
</Button>
@@ -408,6 +411,7 @@ export function UserActions({
408411
colorPalette="blue"
409412
loading={actionLoading}
410413
loadingText="Changing..."
414+
size={'md'}
411415
>
412416
Change Role
413417
</LoadingButton>

0 commit comments

Comments
 (0)