@simple-auth-kit/cli 1.3.2 → 1.4.1

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.
Files changed (80) hide show
  1. package/lib/copy.ts +67 -10
  2. package/package.json +1 -1
  3. package/registry/admin-apps/nextjs/shared/.husky/commit-msg +1 -0
  4. package/registry/admin-apps/nextjs/shared/.husky/pre-commit +1 -0
  5. package/registry/admin-apps/nextjs/shared/.lintstagedrc.json +4 -0
  6. package/registry/admin-apps/nextjs/shared/.prettierrc.json +3 -0
  7. package/registry/admin-apps/nextjs/shared/commitlint.config.js +5 -0
  8. package/registry/admin-apps/nextjs/shared/eslint.config.js +28 -0
  9. package/registry/admin-apps/nextjs/shared/gitignore +11 -0
  10. package/registry/admin-apps/nextjs/variants/base/package.json +11 -2
  11. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/audit-log/page.tsx +72 -16
  12. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/edit/page.tsx +107 -26
  13. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/page.tsx +131 -29
  14. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/edit/page.tsx +111 -25
  15. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/page.tsx +97 -22
  16. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/edit/page.tsx +129 -46
  17. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/page.tsx +64 -14
  18. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/page.tsx +91 -22
  19. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/edit/page.tsx +94 -23
  20. package/registry/admin-apps/nextjs/variants/workspaces/package.json +11 -2
  21. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/account/page.tsx +179 -41
  22. package/registry/admin-apps/react/shared/.husky/commit-msg +1 -0
  23. package/registry/admin-apps/react/shared/.husky/pre-commit +1 -0
  24. package/registry/admin-apps/react/shared/.lintstagedrc.json +4 -0
  25. package/registry/admin-apps/react/shared/.prettierrc.json +3 -0
  26. package/registry/admin-apps/react/shared/commitlint.config.js +3 -0
  27. package/registry/admin-apps/react/shared/eslint.config.js +38 -0
  28. package/registry/admin-apps/react/shared/gitignore +17 -0
  29. package/registry/admin-apps/react/variants/base/package.json +15 -2
  30. package/registry/admin-apps/react/variants/base/src/pages/CountryDetailPage.tsx +76 -19
  31. package/registry/admin-apps/react/variants/base/src/pages/CustomerDetailPage.tsx +110 -26
  32. package/registry/admin-apps/react/variants/base/src/pages/EditCountryPage.tsx +115 -29
  33. package/registry/admin-apps/react/variants/base/src/pages/EditCustomerPage.tsx +123 -31
  34. package/registry/admin-apps/react/variants/base/src/pages/EditLanguagePage.tsx +100 -24
  35. package/registry/admin-apps/react/variants/base/src/pages/EditRolePage.tsx +99 -26
  36. package/registry/admin-apps/react/variants/base/src/pages/EditUserPage.tsx +126 -31
  37. package/registry/admin-apps/react/variants/base/src/pages/LanguageDetailPage.tsx +75 -19
  38. package/registry/admin-apps/react/variants/base/src/pages/PermissionDetailPage.tsx +58 -13
  39. package/registry/admin-apps/react/variants/base/src/pages/PermissionsPage.tsx +132 -29
  40. package/registry/admin-apps/react/variants/base/src/pages/RoleDetailPage.tsx +70 -17
  41. package/registry/admin-apps/react/variants/base/src/pages/RolesPage.tsx +277 -59
  42. package/registry/admin-apps/react/variants/workspaces/package.json +15 -2
  43. package/registry/combos/express-drizzle/eslint.config.js +18 -0
  44. package/registry/combos/express-drizzle/package.json +5 -1
  45. package/registry/combos/express-drizzle/shared/src/request-context.ts +3 -0
  46. package/registry/combos/express-prisma/eslint.config.js +18 -0
  47. package/registry/combos/express-prisma/package.json +5 -1
  48. package/registry/combos/express-prisma/shared/src/request-context.ts +3 -0
  49. package/registry/combos/nestjs-drizzle/eslint.config.js +18 -0
  50. package/registry/combos/nestjs-drizzle/package.json +5 -1
  51. package/registry/combos/nestjs-drizzle/shared/src/auth.controller.ts +138 -33
  52. package/registry/combos/nestjs-drizzle/shared/src/route-tiers.ts +71 -18
  53. package/registry/combos/nestjs-prisma/eslint.config.js +18 -0
  54. package/registry/combos/nestjs-prisma/package.json +5 -1
  55. package/registry/combos/nestjs-prisma/shared/src/auth.controller.ts +148 -35
  56. package/registry/combos/nestjs-prisma/shared/src/route-tiers.ts +72 -18
  57. package/registry/mobile-apps/bare-rn/shared/.husky/commit-msg +1 -0
  58. package/registry/mobile-apps/bare-rn/shared/.husky/pre-commit +1 -0
  59. package/registry/mobile-apps/bare-rn/shared/.lintstagedrc.json +4 -0
  60. package/registry/mobile-apps/bare-rn/shared/.prettierrc.json +5 -0
  61. package/registry/mobile-apps/bare-rn/shared/commitlint.config.js +3 -0
  62. package/registry/mobile-apps/bare-rn/shared/eslint.config.js +19 -0
  63. package/registry/mobile-apps/bare-rn/shared/gitignore +78 -0
  64. package/registry/mobile-apps/bare-rn/variants/base/package.json +17 -12
  65. package/registry/mobile-apps/bare-rn/variants/workspaces/package.json +17 -12
  66. package/registry/mobile-apps/expo/shared/.husky/commit-msg +1 -0
  67. package/registry/mobile-apps/expo/shared/.husky/pre-commit +1 -0
  68. package/registry/mobile-apps/expo/shared/.lintstagedrc.json +4 -0
  69. package/registry/mobile-apps/expo/shared/.prettierrc.json +5 -0
  70. package/registry/mobile-apps/expo/shared/commitlint.config.js +3 -0
  71. package/registry/mobile-apps/expo/shared/eslint.config.js +9 -0
  72. package/registry/mobile-apps/expo/shared/gitignore +44 -0
  73. package/registry/mobile-apps/expo/shared/src/screens/SessionsScreen.tsx +6 -17
  74. package/registry/mobile-apps/expo/shared/src/store/sessionsStore.ts +35 -0
  75. package/registry/mobile-apps/expo/variants/base/package.json +12 -3
  76. package/registry/mobile-apps/expo/variants/workspaces/package.json +12 -3
  77. package/registry/mobile-apps/expo/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +1 -1
  78. package/registry.json +13 -36
  79. package/registry/mobile-apps/bare-rn/shared/.eslintrc.js +0 -4
  80. package/registry/mobile-apps/bare-rn/shared/.prettierrc.js +0 -5
@@ -1,6 +1,16 @@
1
- import { type FormEvent, useCallback, useEffect, useState } from "react";
1
+ import {
2
+ type FormEvent,
3
+ startTransition,
4
+ useCallback,
5
+ useEffect,
6
+ useState,
7
+ } from "react";
2
8
  import { useNavigate, useParams } from "react-router-dom";
3
- import { AuthApiError, type CountrySummary, type UpdateCountryInput } from "@simple-auth-kit/auth-client";
9
+ import {
10
+ AuthApiError,
11
+ type CountrySummary,
12
+ type UpdateCountryInput,
13
+ } from "@simple-auth-kit/auth-client";
4
14
  import { toast } from "sonner";
5
15
  import { authClient } from "@/lib/auth-client";
6
16
  import { errorMessage, errorMessages } from "@/lib/error";
@@ -8,7 +18,14 @@ import { Breadcrumb } from "@/components/breadcrumb";
8
18
  import { FormErrorAlert } from "@/components/form-error-alert";
9
19
  import { PhotoUpload } from "@/components/photo-upload";
10
20
  import { Button } from "@/components/ui/button";
11
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
21
+ import {
22
+ Card,
23
+ CardContent,
24
+ CardDescription,
25
+ CardFooter,
26
+ CardHeader,
27
+ CardTitle,
28
+ } from "@/components/ui/card";
12
29
  import { Checkbox } from "@/components/ui/checkbox";
13
30
  import { Heading } from "@/components/ui/heading";
14
31
  import { Input } from "@/components/ui/input";
@@ -34,7 +51,8 @@ function toForm(country: CountrySummary): CountryFormFields {
34
51
  };
35
52
  }
36
53
 
37
- const inputClassName = "bg-background border-2 focus:border-purple-500 transition-colors";
54
+ const inputClassName =
55
+ "bg-background border-2 focus:border-purple-500 transition-colors";
38
56
  const upperInputClassName = `${inputClassName} uppercase`;
39
57
 
40
58
  export function EditCountryPage() {
@@ -62,7 +80,7 @@ export function EditCountryPage() {
62
80
  }, [id]);
63
81
 
64
82
  useEffect(() => {
65
- void load();
83
+ startTransition(() => void load());
66
84
  }, [load]);
67
85
 
68
86
  if (!id) return null;
@@ -108,7 +126,9 @@ export function EditCountryPage() {
108
126
  </div>
109
127
  <Separator />
110
128
 
111
- {loading && !country && <p className="text-sm text-muted-foreground">Loading…</p>}
129
+ {loading && !country && (
130
+ <p className="text-sm text-muted-foreground">Loading…</p>
131
+ )}
112
132
 
113
133
  {country && (
114
134
  <Card>
@@ -118,13 +138,19 @@ export function EditCountryPage() {
118
138
  <form onSubmit={handleSubmit} className="space-y-8 w-full">
119
139
  <Card className="w-full">
120
140
  <CardHeader className="border-b bg-muted/50">
121
- <CardTitle className="text-2xl">Country Information</CardTitle>
122
- <CardDescription className="text-base">Enter country details</CardDescription>
141
+ <CardTitle className="text-2xl">
142
+ Country Information
143
+ </CardTitle>
144
+ <CardDescription className="text-base">
145
+ Enter country details
146
+ </CardDescription>
123
147
  </CardHeader>
124
148
  <CardContent className="pt-6">
125
149
  <div className="space-y-6">
126
150
  <div className="space-y-4">
127
- <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">Basic Information</h3>
151
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
152
+ Basic Information
153
+ </h3>
128
154
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
129
155
  <div className="flex flex-col gap-2">
130
156
  <Label htmlFor="name">Country Name</Label>
@@ -134,7 +160,9 @@ export function EditCountryPage() {
134
160
  placeholder="e.g., Bangladesh"
135
161
  required
136
162
  value={form.name}
137
- onChange={(e) => setForm({ ...form, name: e.target.value })}
163
+ onChange={(e) =>
164
+ setForm({ ...form, name: e.target.value })
165
+ }
138
166
  type="text"
139
167
  className={inputClassName}
140
168
  />
@@ -142,7 +170,9 @@ export function EditCountryPage() {
142
170
  <div className="flex flex-col gap-2">
143
171
  <Label htmlFor="code">
144
172
  Country Code &nbsp;
145
- <span className="text-xs text-destructive dark:text-destructive-foreground">(2-3 characters, e.g., BD, USA)</span>
173
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
174
+ (2-3 characters, e.g., BD, USA)
175
+ </span>
146
176
  </Label>
147
177
  <Input
148
178
  id="code"
@@ -150,7 +180,12 @@ export function EditCountryPage() {
150
180
  placeholder="e.g., BD"
151
181
  required
152
182
  value={form.code}
153
- onChange={(e) => setForm({ ...form, code: e.target.value.toUpperCase() })}
183
+ onChange={(e) =>
184
+ setForm({
185
+ ...form,
186
+ code: e.target.value.toUpperCase(),
187
+ })
188
+ }
154
189
  type="text"
155
190
  maxLength={3}
156
191
  className={upperInputClassName}
@@ -159,7 +194,9 @@ export function EditCountryPage() {
159
194
  <div className="flex flex-col gap-2">
160
195
  <Label htmlFor="emoji">
161
196
  Country Emoji &nbsp;
162
- <span className="text-xs text-muted-foreground">(Stands in wherever no flag image is set)</span>
197
+ <span className="text-xs text-muted-foreground">
198
+ (Stands in wherever no flag image is set)
199
+ </span>
163
200
  </Label>
164
201
  <Input
165
202
  id="emoji"
@@ -167,7 +204,9 @@ export function EditCountryPage() {
167
204
  placeholder="e.g., 🇧🇩"
168
205
  required
169
206
  value={form.emoji}
170
- onChange={(e) => setForm({ ...form, emoji: e.target.value })}
207
+ onChange={(e) =>
208
+ setForm({ ...form, emoji: e.target.value })
209
+ }
171
210
  type="text"
172
211
  className={inputClassName}
173
212
  />
@@ -175,7 +214,9 @@ export function EditCountryPage() {
175
214
  <div className="flex flex-col gap-2">
176
215
  <Label htmlFor="phoneCode">
177
216
  Country Phone Code &nbsp;
178
- <span className="text-xs text-destructive dark:text-destructive-foreground">(2-3 characters, e.g., +880, +60)</span>
217
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
218
+ (2-3 characters, e.g., +880, +60)
219
+ </span>
179
220
  </Label>
180
221
  <Input
181
222
  id="phoneCode"
@@ -183,7 +224,9 @@ export function EditCountryPage() {
183
224
  placeholder="e.g., +880"
184
225
  required
185
226
  value={form.phoneCode}
186
- onChange={(e) => setForm({ ...form, phoneCode: e.target.value })}
227
+ onChange={(e) =>
228
+ setForm({ ...form, phoneCode: e.target.value })
229
+ }
187
230
  type="text"
188
231
  className={upperInputClassName}
189
232
  />
@@ -191,7 +234,9 @@ export function EditCountryPage() {
191
234
  <div className="flex flex-col gap-2">
192
235
  <Label htmlFor="currency">
193
236
  Country Currency &nbsp;
194
- <span className="text-xs text-destructive dark:text-destructive-foreground">(e.g., USD, EUR)</span>
237
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
238
+ (e.g., USD, EUR)
239
+ </span>
195
240
  </Label>
196
241
  <Input
197
242
  id="currency"
@@ -199,7 +244,12 @@ export function EditCountryPage() {
199
244
  placeholder="e.g., USD, EUR"
200
245
  required
201
246
  value={form.currency}
202
- onChange={(e) => setForm({ ...form, currency: e.target.value.toUpperCase() })}
247
+ onChange={(e) =>
248
+ setForm({
249
+ ...form,
250
+ currency: e.target.value.toUpperCase(),
251
+ })
252
+ }
203
253
  type="text"
204
254
  maxLength={3}
205
255
  className={upperInputClassName}
@@ -208,7 +258,9 @@ export function EditCountryPage() {
208
258
  <div className="flex flex-col gap-2">
209
259
  <Label htmlFor="currencyName">
210
260
  Country Currency Name &nbsp;
211
- <span className="text-xs text-destructive dark:text-destructive-foreground">(e.g., US Dollar, Euro)</span>
261
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
262
+ (e.g., US Dollar, Euro)
263
+ </span>
212
264
  </Label>
213
265
  <Input
214
266
  id="currencyName"
@@ -216,7 +268,9 @@ export function EditCountryPage() {
216
268
  placeholder="e.g., US Dollar, Euro"
217
269
  required
218
270
  value={form.currencyName}
219
- onChange={(e) => setForm({ ...form, currencyName: e.target.value })}
271
+ onChange={(e) =>
272
+ setForm({ ...form, currencyName: e.target.value })
273
+ }
220
274
  type="text"
221
275
  className={inputClassName}
222
276
  />
@@ -224,7 +278,9 @@ export function EditCountryPage() {
224
278
  <div className="flex flex-col gap-2">
225
279
  <Label htmlFor="isoCode">
226
280
  Country ISO Code &nbsp;
227
- <span className="text-xs text-destructive dark:text-destructive-foreground">(ISO code, e.g., BDT, USD)</span>
281
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
282
+ (ISO code, e.g., BDT, USD)
283
+ </span>
228
284
  </Label>
229
285
  <Input
230
286
  id="isoCode"
@@ -232,7 +288,12 @@ export function EditCountryPage() {
232
288
  placeholder="e.g., BDT, USD"
233
289
  required
234
290
  value={form.isoCode}
235
- onChange={(e) => setForm({ ...form, isoCode: e.target.value.toUpperCase() })}
291
+ onChange={(e) =>
292
+ setForm({
293
+ ...form,
294
+ isoCode: e.target.value.toUpperCase(),
295
+ })
296
+ }
236
297
  type="text"
237
298
  maxLength={3}
238
299
  className={upperInputClassName}
@@ -245,27 +306,52 @@ export function EditCountryPage() {
245
306
 
246
307
  <CardHeader className="border-b bg-muted/50 mt-6">
247
308
  <CardTitle className="text-2xl">Country Flag</CardTitle>
248
- <CardDescription className="text-base">Upload country flag (Max size: 2MB, Formats: JPG, PNG, SVG)</CardDescription>
309
+ <CardDescription className="text-base">
310
+ Upload country flag (Max size: 2MB, Formats: JPG, PNG, SVG)
311
+ </CardDescription>
249
312
  </CardHeader>
250
313
  <CardContent className="pt-6">
251
- <PhotoUpload photo={form.flag} fallback={form.emoji || "?"} onChange={(next) => setForm({ ...form, flag: next })} disabled={saving} />
314
+ <PhotoUpload
315
+ photo={form.flag}
316
+ fallback={form.emoji || "?"}
317
+ onChange={(next) => setForm({ ...form, flag: next })}
318
+ disabled={saving}
319
+ />
252
320
  </CardContent>
253
321
 
254
322
  <div className="flex justify-center mt-6">
255
323
  <label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
256
- <Checkbox checked={form.isActive} onCheckedChange={(checked) => setForm({ ...form, isActive: checked === true })} />
324
+ <Checkbox
325
+ checked={form.isActive}
326
+ onCheckedChange={(checked) =>
327
+ setForm({ ...form, isActive: checked === true })
328
+ }
329
+ />
257
330
  <span className="space-y-1 leading-none">
258
- <span className="block text-base font-medium">Active Status</span>
259
- <span className="block text-sm text-muted-foreground">Country will be active and available for selection</span>
331
+ <span className="block text-base font-medium">
332
+ Active Status
333
+ </span>
334
+ <span className="block text-sm text-muted-foreground">
335
+ Country will be active and available for selection
336
+ </span>
260
337
  </span>
261
338
  </label>
262
339
  </div>
263
340
 
264
341
  <CardFooter className="flex justify-center gap-4 mt-8 pb-8">
265
- <Button type="button" variant="outline" onClick={() => navigate(`/countries/${id}`)} disabled={saving}>
342
+ <Button
343
+ type="button"
344
+ variant="outline"
345
+ onClick={() => navigate(`/countries/${id}`)}
346
+ disabled={saving}
347
+ >
266
348
  Cancel
267
349
  </Button>
268
- <Button disabled={saving} className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32" type="submit">
350
+ <Button
351
+ disabled={saving}
352
+ className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32"
353
+ type="submit"
354
+ >
269
355
  {saving ? "Updating..." : "Update Country"}
270
356
  </Button>
271
357
  </CardFooter>
@@ -1,6 +1,16 @@
1
- import { type FormEvent, useCallback, useEffect, useState } from "react";
1
+ import {
2
+ type FormEvent,
3
+ startTransition,
4
+ useCallback,
5
+ useEffect,
6
+ useState,
7
+ } from "react";
2
8
  import { useNavigate, useParams } from "react-router-dom";
3
- import { AuthApiError, type CustomerSummary, type UpdateCustomerInput } from "@simple-auth-kit/auth-client";
9
+ import {
10
+ AuthApiError,
11
+ type CustomerSummary,
12
+ type UpdateCustomerInput,
13
+ } from "@simple-auth-kit/auth-client";
4
14
  import { format } from "date-fns";
5
15
  import { toast } from "sonner";
6
16
  import { authClient } from "@/lib/auth-client";
@@ -9,7 +19,14 @@ import { Breadcrumb } from "@/components/breadcrumb";
9
19
  import { FormErrorAlert } from "@/components/form-error-alert";
10
20
  import { PhotoUpload } from "@/components/photo-upload";
11
21
  import { Button } from "@/components/ui/button";
12
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
22
+ import {
23
+ Card,
24
+ CardContent,
25
+ CardDescription,
26
+ CardFooter,
27
+ CardHeader,
28
+ CardTitle,
29
+ } from "@/components/ui/card";
13
30
  import { Checkbox } from "@/components/ui/checkbox";
14
31
  import { Combobox } from "@/components/ui/combobox";
15
32
  import { DatePicker } from "@/components/ui/date-picker";
@@ -17,7 +34,11 @@ import { Heading } from "@/components/ui/heading";
17
34
  import { Input } from "@/components/ui/input";
18
35
  import { Label } from "@/components/ui/label";
19
36
  import { Separator } from "@/components/ui/separator";
20
- import { emptyCustomerFields, GENDER_OPTIONS, type CustomerFormFields } from "./customer-schema";
37
+ import {
38
+ emptyCustomerFields,
39
+ GENDER_OPTIONS,
40
+ type CustomerFormFields,
41
+ } from "./customer-schema";
21
42
 
22
43
  function apiErrorMessage(err: unknown, fallback: string): string {
23
44
  return err instanceof AuthApiError ? err.message : fallback;
@@ -38,7 +59,8 @@ function toForm(customer: CustomerSummary): CustomerFormFields {
38
59
  };
39
60
  }
40
61
 
41
- const inputClassName = "bg-background border-2 focus:border-purple-500 transition-colors";
62
+ const inputClassName =
63
+ "bg-background border-2 focus:border-purple-500 transition-colors";
42
64
 
43
65
  export function EditCustomerPage() {
44
66
  const { id } = useParams<{ id: string }>();
@@ -65,7 +87,7 @@ export function EditCustomerPage() {
65
87
  }, [id]);
66
88
 
67
89
  useEffect(() => {
68
- void load();
90
+ startTransition(() => void load());
69
91
  }, [load]);
70
92
 
71
93
  if (!id) return null;
@@ -84,7 +106,9 @@ export function EditCustomerPage() {
84
106
  phone: form.phone || null,
85
107
  dob: form.dob ? format(form.dob, "yyyy-MM-dd") : null,
86
108
  gender: form.gender || null,
87
- joinedDate: form.joinedDate ? format(form.joinedDate, "yyyy-MM-dd") : undefined,
109
+ joinedDate: form.joinedDate
110
+ ? format(form.joinedDate, "yyyy-MM-dd")
111
+ : undefined,
88
112
  photo: form.photo || null,
89
113
  isActive: form.isActive,
90
114
  };
@@ -113,7 +137,9 @@ export function EditCustomerPage() {
113
137
  </div>
114
138
  <Separator />
115
139
 
116
- {loading && !customer && <p className="text-sm text-muted-foreground">Loading…</p>}
140
+ {loading && !customer && (
141
+ <p className="text-sm text-muted-foreground">Loading…</p>
142
+ )}
117
143
 
118
144
  {customer && (
119
145
  <Card>
@@ -123,13 +149,19 @@ export function EditCustomerPage() {
123
149
  <form onSubmit={handleSubmit} className="space-y-8 w-full">
124
150
  <Card className="w-full">
125
151
  <CardHeader className="border-b bg-muted/50">
126
- <CardTitle className="text-2xl">Customer Information</CardTitle>
127
- <CardDescription className="text-base">Update customer&apos;s basic information</CardDescription>
152
+ <CardTitle className="text-2xl">
153
+ Customer Information
154
+ </CardTitle>
155
+ <CardDescription className="text-base">
156
+ Update customer&apos;s basic information
157
+ </CardDescription>
128
158
  </CardHeader>
129
159
  <CardContent className="pt-6">
130
160
  <div className="space-y-6">
131
161
  <div className="space-y-4">
132
- <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">Personal Information</h3>
162
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
163
+ Personal Information
164
+ </h3>
133
165
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
134
166
  <div className="flex flex-col gap-2">
135
167
  <Label htmlFor="firstName">First Name</Label>
@@ -138,7 +170,9 @@ export function EditCustomerPage() {
138
170
  disabled={saving}
139
171
  placeholder="First Name"
140
172
  value={form.firstName}
141
- onChange={(e) => setForm({ ...form, firstName: e.target.value })}
173
+ onChange={(e) =>
174
+ setForm({ ...form, firstName: e.target.value })
175
+ }
142
176
  type="text"
143
177
  className={inputClassName}
144
178
  />
@@ -150,7 +184,9 @@ export function EditCustomerPage() {
150
184
  disabled={saving}
151
185
  placeholder="Last Name"
152
186
  value={form.lastName}
153
- onChange={(e) => setForm({ ...form, lastName: e.target.value })}
187
+ onChange={(e) =>
188
+ setForm({ ...form, lastName: e.target.value })
189
+ }
154
190
  type="text"
155
191
  className={inputClassName}
156
192
  />
@@ -158,14 +194,18 @@ export function EditCustomerPage() {
158
194
  <div className="flex flex-col gap-2">
159
195
  <Label htmlFor="username">
160
196
  Username &nbsp;
161
- <span className="text-xs text-destructive dark:text-destructive-foreground">(Must be unique)</span>
197
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
198
+ (Must be unique)
199
+ </span>
162
200
  </Label>
163
201
  <Input
164
202
  id="username"
165
203
  disabled={saving}
166
204
  placeholder="Username"
167
205
  value={form.username}
168
- onChange={(e) => setForm({ ...form, username: e.target.value })}
206
+ onChange={(e) =>
207
+ setForm({ ...form, username: e.target.value })
208
+ }
169
209
  className={inputClassName}
170
210
  />
171
211
  </div>
@@ -173,12 +213,16 @@ export function EditCustomerPage() {
173
213
  </div>
174
214
 
175
215
  <div className="space-y-4">
176
- <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">Contact Information</h3>
216
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
217
+ Contact Information
218
+ </h3>
177
219
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
178
220
  <div className="flex flex-col gap-2">
179
221
  <Label htmlFor="email">
180
222
  Email &nbsp;
181
- <span className="text-xs text-destructive dark:text-destructive-foreground">(Must be unique)</span>
223
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
224
+ (Must be unique)
225
+ </span>
182
226
  </Label>
183
227
  <Input
184
228
  id="email"
@@ -186,7 +230,9 @@ export function EditCustomerPage() {
186
230
  placeholder="customer@example.com"
187
231
  required
188
232
  value={form.email}
189
- onChange={(e) => setForm({ ...form, email: e.target.value })}
233
+ onChange={(e) =>
234
+ setForm({ ...form, email: e.target.value })
235
+ }
190
236
  type="email"
191
237
  className={inputClassName}
192
238
  />
@@ -194,14 +240,18 @@ export function EditCustomerPage() {
194
240
  <div className="flex flex-col gap-2">
195
241
  <Label htmlFor="phone">
196
242
  Phone &nbsp;
197
- <span className="text-xs text-muted-foreground">(With country code)</span>
243
+ <span className="text-xs text-muted-foreground">
244
+ (With country code)
245
+ </span>
198
246
  </Label>
199
247
  <Input
200
248
  id="phone"
201
249
  type="text"
202
250
  disabled={saving}
203
251
  value={form.phone}
204
- onChange={(e) => setForm({ ...form, phone: e.target.value })}
252
+ onChange={(e) =>
253
+ setForm({ ...form, phone: e.target.value })
254
+ }
205
255
  placeholder="+1234567890"
206
256
  className={inputClassName}
207
257
  />
@@ -210,15 +260,29 @@ export function EditCustomerPage() {
210
260
  </div>
211
261
 
212
262
  <div className="space-y-4">
213
- <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">Additional Details</h3>
263
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
264
+ Additional Details
265
+ </h3>
214
266
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
215
267
  <div className="flex flex-col gap-2 p-2">
216
268
  <Label>Joined Date</Label>
217
- <DatePicker placeholder="Joined Date" value={form.joinedDate} onChange={(date) => setForm({ ...form, joinedDate: date })} displayFormat="dd-MM-yyyy" />
269
+ <DatePicker
270
+ placeholder="Joined Date"
271
+ value={form.joinedDate}
272
+ onChange={(date) =>
273
+ setForm({ ...form, joinedDate: date })
274
+ }
275
+ displayFormat="dd-MM-yyyy"
276
+ />
218
277
  </div>
219
278
  <div className="flex flex-col gap-2 p-2">
220
279
  <Label>Date of birth</Label>
221
- <DatePicker placeholder="Date of birth" value={form.dob} onChange={(date) => setForm({ ...form, dob: date })} displayFormat="dd-MM-yyyy" />
280
+ <DatePicker
281
+ placeholder="Date of birth"
282
+ value={form.dob}
283
+ onChange={(date) => setForm({ ...form, dob: date })}
284
+ displayFormat="dd-MM-yyyy"
285
+ />
222
286
  </div>
223
287
  <div className="flex flex-col gap-2">
224
288
  <Label>Gender</Label>
@@ -226,7 +290,9 @@ export function EditCustomerPage() {
226
290
  options={GENDER_OPTIONS}
227
291
  selected={form.gender}
228
292
  placeholder="Select Gender"
229
- onChange={(option) => setForm({ ...form, gender: option.value })}
293
+ onChange={(option) =>
294
+ setForm({ ...form, gender: option.value })
295
+ }
230
296
  showCreate={false}
231
297
  popoverClassName="min-w-[200px]"
232
298
  />
@@ -238,27 +304,53 @@ export function EditCustomerPage() {
238
304
 
239
305
  <CardHeader className="border-b bg-muted/50 mt-6">
240
306
  <CardTitle className="text-2xl">Profile Photo</CardTitle>
241
- <CardDescription className="text-base">Upload customer&apos;s profile picture (Max size: 2MB, Formats: JPG, PNG)</CardDescription>
307
+ <CardDescription className="text-base">
308
+ Upload customer&apos;s profile picture (Max size: 2MB,
309
+ Formats: JPG, PNG)
310
+ </CardDescription>
242
311
  </CardHeader>
243
312
  <CardContent className="pt-6">
244
- <PhotoUpload photo={form.photo} fallback="?" onChange={(next) => setForm({ ...form, photo: next })} disabled={saving} />
313
+ <PhotoUpload
314
+ photo={form.photo}
315
+ fallback="?"
316
+ onChange={(next) => setForm({ ...form, photo: next })}
317
+ disabled={saving}
318
+ />
245
319
  </CardContent>
246
320
 
247
321
  <div className="flex justify-center mt-6">
248
322
  <label className="flex flex-row items-center space-x-3 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
249
- <Checkbox checked={form.isActive} onCheckedChange={(checked) => setForm({ ...form, isActive: checked === true })} />
323
+ <Checkbox
324
+ checked={form.isActive}
325
+ onCheckedChange={(checked) =>
326
+ setForm({ ...form, isActive: checked === true })
327
+ }
328
+ />
250
329
  <span className="space-y-1 leading-none">
251
- <span className="block text-base font-medium">Active Status</span>
252
- <span className="block text-sm text-muted-foreground">Customer will be active and available for selection</span>
330
+ <span className="block text-base font-medium">
331
+ Active Status
332
+ </span>
333
+ <span className="block text-sm text-muted-foreground">
334
+ Customer will be active and available for selection
335
+ </span>
253
336
  </span>
254
337
  </label>
255
338
  </div>
256
339
 
257
340
  <CardFooter className="flex justify-center gap-4 mt-8 pb-8">
258
- <Button type="button" variant="outline" onClick={() => navigate(`/customers/${id}`)} disabled={saving}>
341
+ <Button
342
+ type="button"
343
+ variant="outline"
344
+ onClick={() => navigate(`/customers/${id}`)}
345
+ disabled={saving}
346
+ >
259
347
  Cancel
260
348
  </Button>
261
- <Button disabled={saving} className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32" type="submit">
349
+ <Button
350
+ disabled={saving}
351
+ className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32"
352
+ type="submit"
353
+ >
262
354
  {saving ? "Updating..." : "Update Customer"}
263
355
  </Button>
264
356
  </CardFooter>