@betterstart/cli 0.1.78 → 0.1.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/init/pages/profile/profile-form.tsx +188 -190
package/package.json
CHANGED
|
@@ -18,7 +18,14 @@ import {
|
|
|
18
18
|
FormMessage,
|
|
19
19
|
} from '@cms/components/ui/form'
|
|
20
20
|
import { ImageUploadField } from '@cms/components/ui/image-upload-field'
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
Card,
|
|
23
|
+
CardContent,
|
|
24
|
+
CardDescription,
|
|
25
|
+
CardFooter,
|
|
26
|
+
CardHeader,
|
|
27
|
+
CardTitle,
|
|
28
|
+
} from '@cms/components/ui/card'
|
|
22
29
|
import { useRouter } from 'next/navigation'
|
|
23
30
|
import { useState } from 'react'
|
|
24
31
|
|
|
@@ -80,12 +87,12 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
80
87
|
})
|
|
81
88
|
|
|
82
89
|
const emailDirty = profileForm.watch('email') !== user.email
|
|
90
|
+
const imageValue = profileForm.watch('image')
|
|
83
91
|
|
|
84
92
|
async function onProfileSubmit(values: ProfileValues) {
|
|
85
93
|
setProfilePending(true)
|
|
86
94
|
|
|
87
95
|
try {
|
|
88
|
-
// Update name and image via Better Auth
|
|
89
96
|
const { error } = await authClient.updateUser({
|
|
90
97
|
name: values.name,
|
|
91
98
|
image: values.image ?? null,
|
|
@@ -97,7 +104,6 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
97
104
|
return
|
|
98
105
|
}
|
|
99
106
|
|
|
100
|
-
// If email changed, update via server action
|
|
101
107
|
if (values.email !== user.email) {
|
|
102
108
|
if (!values.currentPasswordForEmail) {
|
|
103
109
|
profileForm.setError('currentPasswordForEmail', {
|
|
@@ -158,202 +164,194 @@ export function ProfileForm({ user }: ProfileFormProps) {
|
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
|
|
161
|
-
const imageValue = profileForm.watch('image')
|
|
162
|
-
|
|
163
167
|
return (
|
|
164
168
|
<div className="space-y-6">
|
|
165
|
-
{/* Profile Section */}
|
|
166
169
|
<Form {...profileForm}>
|
|
167
|
-
<form
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
)}
|
|
245
|
-
/>
|
|
246
|
-
|
|
247
|
-
{emailDirty && (
|
|
248
|
-
<FormField
|
|
249
|
-
control={profileForm.control}
|
|
250
|
-
name="currentPasswordForEmail"
|
|
251
|
-
render={({ field: formField }) => (
|
|
252
|
-
<FormItem>
|
|
253
|
-
<FormLabel>Current Password</FormLabel>
|
|
254
|
-
<FormControl>
|
|
255
|
-
<Input
|
|
256
|
-
type="password"
|
|
257
|
-
placeholder="Enter current password to change email"
|
|
258
|
-
autoComplete="current-password"
|
|
259
|
-
disabled={profilePending}
|
|
260
|
-
{...formField}
|
|
261
|
-
/>
|
|
262
|
-
</FormControl>
|
|
263
|
-
<FormMessage />
|
|
264
|
-
</FormItem>
|
|
170
|
+
<form onSubmit={profileForm.handleSubmit(onProfileSubmit)}>
|
|
171
|
+
<Card className="material-sm!">
|
|
172
|
+
<CardHeader>
|
|
173
|
+
<div className="flex items-center gap-4">
|
|
174
|
+
<Avatar className="size-12">
|
|
175
|
+
<AvatarImage src={imageValue || undefined} />
|
|
176
|
+
<AvatarFallback className="text-lg font-semibold">
|
|
177
|
+
{user.name?.charAt(0) ?? '?'}
|
|
178
|
+
</AvatarFallback>
|
|
179
|
+
</Avatar>
|
|
180
|
+
<div>
|
|
181
|
+
<CardTitle>Profile</CardTitle>
|
|
182
|
+
<CardDescription>
|
|
183
|
+
Update your name, email, and profile picture
|
|
184
|
+
</CardDescription>
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
</CardHeader>
|
|
188
|
+
<CardContent className="space-y-6">
|
|
189
|
+
<FormField
|
|
190
|
+
control={profileForm.control}
|
|
191
|
+
name="name"
|
|
192
|
+
render={({ field: formField }) => (
|
|
193
|
+
<FormItem>
|
|
194
|
+
<FormLabel>Name</FormLabel>
|
|
195
|
+
<FormControl>
|
|
196
|
+
<Input
|
|
197
|
+
type="text"
|
|
198
|
+
placeholder="Your name"
|
|
199
|
+
disabled={profilePending}
|
|
200
|
+
{...formField}
|
|
201
|
+
/>
|
|
202
|
+
</FormControl>
|
|
203
|
+
<FormMessage />
|
|
204
|
+
</FormItem>
|
|
205
|
+
)}
|
|
206
|
+
/>
|
|
207
|
+
|
|
208
|
+
<FormField
|
|
209
|
+
control={profileForm.control}
|
|
210
|
+
name="email"
|
|
211
|
+
render={({ field: formField }) => (
|
|
212
|
+
<FormItem>
|
|
213
|
+
<FormLabel>Email</FormLabel>
|
|
214
|
+
<FormControl>
|
|
215
|
+
<Input
|
|
216
|
+
type="email"
|
|
217
|
+
placeholder="you@example.com"
|
|
218
|
+
disabled={profilePending}
|
|
219
|
+
{...formField}
|
|
220
|
+
/>
|
|
221
|
+
</FormControl>
|
|
222
|
+
<FormMessage />
|
|
223
|
+
</FormItem>
|
|
224
|
+
)}
|
|
225
|
+
/>
|
|
226
|
+
|
|
227
|
+
{emailDirty && (
|
|
228
|
+
<FormField
|
|
229
|
+
control={profileForm.control}
|
|
230
|
+
name="currentPasswordForEmail"
|
|
231
|
+
render={({ field: formField }) => (
|
|
232
|
+
<FormItem>
|
|
233
|
+
<FormLabel>Current Password</FormLabel>
|
|
234
|
+
<FormControl>
|
|
235
|
+
<Input
|
|
236
|
+
type="password"
|
|
237
|
+
placeholder="Enter current password to change email"
|
|
238
|
+
autoComplete="current-password"
|
|
239
|
+
disabled={profilePending}
|
|
240
|
+
{...formField}
|
|
241
|
+
/>
|
|
242
|
+
</FormControl>
|
|
243
|
+
<FormMessage />
|
|
244
|
+
</FormItem>
|
|
245
|
+
)}
|
|
246
|
+
/>
|
|
265
247
|
)}
|
|
266
|
-
/>
|
|
267
|
-
)}
|
|
268
248
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
249
|
+
<FormField
|
|
250
|
+
control={profileForm.control}
|
|
251
|
+
name="image"
|
|
252
|
+
render={({ field: formField }) => (
|
|
253
|
+
<FormItem>
|
|
254
|
+
<FormLabel>Profile Picture</FormLabel>
|
|
255
|
+
<FormControl>
|
|
256
|
+
<ImageUploadField
|
|
257
|
+
value={formField.value}
|
|
258
|
+
onChange={formField.onChange}
|
|
259
|
+
onBlur={formField.onBlur}
|
|
260
|
+
disabled={profilePending}
|
|
261
|
+
maxSizeInMB={5}
|
|
262
|
+
label=""
|
|
263
|
+
/>
|
|
264
|
+
</FormControl>
|
|
265
|
+
<FormMessage />
|
|
266
|
+
</FormItem>
|
|
267
|
+
)}
|
|
268
|
+
/>
|
|
269
|
+
</CardContent>
|
|
270
|
+
<CardFooter>
|
|
271
|
+
<Button type="submit" disabled={profilePending || !profileForm.formState.isDirty} size="sm" className="ml-auto min-w-25">
|
|
272
|
+
{profilePending ? 'Saving...' : 'Save'}
|
|
273
|
+
</Button>
|
|
274
|
+
</CardFooter>
|
|
275
|
+
</Card>
|
|
274
276
|
</form>
|
|
275
277
|
</Form>
|
|
276
278
|
|
|
277
|
-
{/* Password Section */}
|
|
278
279
|
<Form {...passwordForm}>
|
|
279
|
-
<form
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
{passwordPending ? 'Changing...' : 'Change Password'}
|
|
355
|
-
</Button>
|
|
356
|
-
</div>
|
|
280
|
+
<form onSubmit={passwordForm.handleSubmit(onPasswordSubmit)}>
|
|
281
|
+
<Card className="material-sm!">
|
|
282
|
+
<CardHeader>
|
|
283
|
+
<CardTitle>Change Password</CardTitle>
|
|
284
|
+
<CardDescription>
|
|
285
|
+
Update your password to keep your account secure
|
|
286
|
+
</CardDescription>
|
|
287
|
+
</CardHeader>
|
|
288
|
+
<CardContent className="space-y-6">
|
|
289
|
+
<FormField
|
|
290
|
+
control={passwordForm.control}
|
|
291
|
+
name="currentPassword"
|
|
292
|
+
render={({ field: formField }) => (
|
|
293
|
+
<FormItem>
|
|
294
|
+
<FormLabel>Current Password</FormLabel>
|
|
295
|
+
<FormControl>
|
|
296
|
+
<Input
|
|
297
|
+
type="password"
|
|
298
|
+
placeholder="Enter current password"
|
|
299
|
+
autoComplete="current-password"
|
|
300
|
+
disabled={passwordPending}
|
|
301
|
+
{...formField}
|
|
302
|
+
/>
|
|
303
|
+
</FormControl>
|
|
304
|
+
<FormMessage />
|
|
305
|
+
</FormItem>
|
|
306
|
+
)}
|
|
307
|
+
/>
|
|
308
|
+
|
|
309
|
+
<FormField
|
|
310
|
+
control={passwordForm.control}
|
|
311
|
+
name="newPassword"
|
|
312
|
+
render={({ field: formField }) => (
|
|
313
|
+
<FormItem>
|
|
314
|
+
<FormLabel>New Password</FormLabel>
|
|
315
|
+
<FormControl>
|
|
316
|
+
<Input
|
|
317
|
+
type="password"
|
|
318
|
+
placeholder="Enter new password"
|
|
319
|
+
autoComplete="new-password"
|
|
320
|
+
disabled={passwordPending}
|
|
321
|
+
{...formField}
|
|
322
|
+
/>
|
|
323
|
+
</FormControl>
|
|
324
|
+
<FormMessage />
|
|
325
|
+
</FormItem>
|
|
326
|
+
)}
|
|
327
|
+
/>
|
|
328
|
+
|
|
329
|
+
<FormField
|
|
330
|
+
control={passwordForm.control}
|
|
331
|
+
name="confirmPassword"
|
|
332
|
+
render={({ field: formField }) => (
|
|
333
|
+
<FormItem>
|
|
334
|
+
<FormLabel>Confirm New Password</FormLabel>
|
|
335
|
+
<FormControl>
|
|
336
|
+
<Input
|
|
337
|
+
type="password"
|
|
338
|
+
placeholder="Confirm new password"
|
|
339
|
+
autoComplete="new-password"
|
|
340
|
+
disabled={passwordPending}
|
|
341
|
+
{...formField}
|
|
342
|
+
/>
|
|
343
|
+
</FormControl>
|
|
344
|
+
<FormMessage />
|
|
345
|
+
</FormItem>
|
|
346
|
+
)}
|
|
347
|
+
/>
|
|
348
|
+
</CardContent>
|
|
349
|
+
<CardFooter>
|
|
350
|
+
<Button type="submit" disabled={passwordPending || !passwordForm.formState.isDirty} size="sm" className="ml-auto min-w-25">
|
|
351
|
+
{passwordPending ? 'Changing...' : 'Change Password'}
|
|
352
|
+
</Button>
|
|
353
|
+
</CardFooter>
|
|
354
|
+
</Card>
|
|
357
355
|
</form>
|
|
358
356
|
</Form>
|
|
359
357
|
</div>
|