@betterstart/cli 0.1.79 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@betterstart/cli",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "description": "Scaffold a full-featured CMS into any Next.js 16 application",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -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 { Separator } from '@cms/components/ui/separator'
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
- onSubmit={profileForm.handleSubmit(onProfileSubmit)}
169
- className="space-y-6 p-6 rounded-2xl border bg-card"
170
- >
171
- <div className="flex items-center gap-4">
172
- <Avatar className="size-16">
173
- <AvatarImage src={imageValue || undefined} />
174
- <AvatarFallback className="text-lg font-semibold">
175
- {user.name?.charAt(0) ?? '?'}
176
- </AvatarFallback>
177
- </Avatar>
178
- <div>
179
- <h2 className="text-lg font-semibold">Profile</h2>
180
- <p className="text-sm text-muted-foreground">
181
- Update your name, email, and profile picture
182
- </p>
183
- </div>
184
- </div>
185
-
186
- <Separator />
187
-
188
- <FormField
189
- control={profileForm.control}
190
- name="image"
191
- render={({ field: formField }) => (
192
- <FormItem>
193
- <FormLabel>Profile Picture</FormLabel>
194
- <FormControl>
195
- <ImageUploadField
196
- value={formField.value}
197
- onChange={formField.onChange}
198
- onBlur={formField.onBlur}
199
- disabled={profilePending}
200
- maxSizeInMB={5}
201
- label=""
202
- />
203
- </FormControl>
204
- <FormMessage />
205
- </FormItem>
206
- )}
207
- />
208
-
209
- <FormField
210
- control={profileForm.control}
211
- name="name"
212
- render={({ field: formField }) => (
213
- <FormItem>
214
- <FormLabel>Name</FormLabel>
215
- <FormControl>
216
- <Input
217
- type="text"
218
- placeholder="Your name"
219
- disabled={profilePending}
220
- {...formField}
221
- />
222
- </FormControl>
223
- <FormMessage />
224
- </FormItem>
225
- )}
226
- />
227
-
228
- <FormField
229
- control={profileForm.control}
230
- name="email"
231
- render={({ field: formField }) => (
232
- <FormItem>
233
- <FormLabel>Email</FormLabel>
234
- <FormControl>
235
- <Input
236
- type="email"
237
- placeholder="you@example.com"
238
- disabled={profilePending}
239
- {...formField}
240
- />
241
- </FormControl>
242
- <FormMessage />
243
- </FormItem>
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
- <div className="flex justify-end">
270
- <Button type="submit" disabled={profilePending}>
271
- {profilePending ? 'Saving...' : 'Save Profile'}
272
- </Button>
273
- </div>
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
- onSubmit={passwordForm.handleSubmit(onPasswordSubmit)}
281
- className="space-y-6 p-6 rounded-2xl border bg-card"
282
- >
283
- <div>
284
- <h2 className="text-lg font-semibold">Change Password</h2>
285
- <p className="text-sm text-muted-foreground">
286
- Update your password to keep your account secure
287
- </p>
288
- </div>
289
-
290
- <Separator />
291
-
292
- <FormField
293
- control={passwordForm.control}
294
- name="currentPassword"
295
- render={({ field: formField }) => (
296
- <FormItem>
297
- <FormLabel>Current Password</FormLabel>
298
- <FormControl>
299
- <Input
300
- type="password"
301
- placeholder="Enter current password"
302
- autoComplete="current-password"
303
- disabled={passwordPending}
304
- {...formField}
305
- />
306
- </FormControl>
307
- <FormMessage />
308
- </FormItem>
309
- )}
310
- />
311
-
312
- <FormField
313
- control={passwordForm.control}
314
- name="newPassword"
315
- render={({ field: formField }) => (
316
- <FormItem>
317
- <FormLabel>New Password</FormLabel>
318
- <FormControl>
319
- <Input
320
- type="password"
321
- placeholder="Enter new password"
322
- autoComplete="new-password"
323
- disabled={passwordPending}
324
- {...formField}
325
- />
326
- </FormControl>
327
- <FormMessage />
328
- </FormItem>
329
- )}
330
- />
331
-
332
- <FormField
333
- control={passwordForm.control}
334
- name="confirmPassword"
335
- render={({ field: formField }) => (
336
- <FormItem>
337
- <FormLabel>Confirm New Password</FormLabel>
338
- <FormControl>
339
- <Input
340
- type="password"
341
- placeholder="Confirm new password"
342
- autoComplete="new-password"
343
- disabled={passwordPending}
344
- {...formField}
345
- />
346
- </FormControl>
347
- <FormMessage />
348
- </FormItem>
349
- )}
350
- />
351
-
352
- <div className="flex justify-end">
353
- <Button type="submit" disabled={passwordPending}>
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>