@simple-auth-kit/cli 1.3.2 → 1.4.0

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 (75) hide show
  1. package/package.json +1 -1
  2. package/registry/admin-apps/nextjs/shared/.husky/commit-msg +1 -0
  3. package/registry/admin-apps/nextjs/shared/.husky/pre-commit +1 -0
  4. package/registry/admin-apps/nextjs/shared/.lintstagedrc.json +4 -0
  5. package/registry/admin-apps/nextjs/shared/.prettierrc.json +3 -0
  6. package/registry/admin-apps/nextjs/shared/commitlint.config.js +5 -0
  7. package/registry/admin-apps/nextjs/shared/eslint.config.js +28 -0
  8. package/registry/admin-apps/nextjs/variants/base/package.json +11 -2
  9. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/audit-log/page.tsx +72 -16
  10. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/edit/page.tsx +107 -26
  11. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/customers/[id]/page.tsx +131 -29
  12. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/edit/page.tsx +111 -25
  13. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/languages/[id]/page.tsx +97 -22
  14. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/edit/page.tsx +129 -46
  15. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/permissions/[id]/page.tsx +64 -14
  16. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/roles/[id]/page.tsx +91 -22
  17. package/registry/admin-apps/nextjs/variants/base/src/app/(console)/users/[id]/edit/page.tsx +94 -23
  18. package/registry/admin-apps/nextjs/variants/workspaces/package.json +11 -2
  19. package/registry/admin-apps/nextjs/variants/workspaces/src/app/(console)/account/page.tsx +179 -41
  20. package/registry/admin-apps/react/shared/.husky/commit-msg +1 -0
  21. package/registry/admin-apps/react/shared/.husky/pre-commit +1 -0
  22. package/registry/admin-apps/react/shared/.lintstagedrc.json +4 -0
  23. package/registry/admin-apps/react/shared/.prettierrc.json +3 -0
  24. package/registry/admin-apps/react/shared/commitlint.config.js +3 -0
  25. package/registry/admin-apps/react/shared/eslint.config.js +38 -0
  26. package/registry/admin-apps/react/variants/base/package.json +15 -2
  27. package/registry/admin-apps/react/variants/base/src/pages/CountryDetailPage.tsx +76 -19
  28. package/registry/admin-apps/react/variants/base/src/pages/CustomerDetailPage.tsx +110 -26
  29. package/registry/admin-apps/react/variants/base/src/pages/EditCountryPage.tsx +115 -29
  30. package/registry/admin-apps/react/variants/base/src/pages/EditCustomerPage.tsx +123 -31
  31. package/registry/admin-apps/react/variants/base/src/pages/EditLanguagePage.tsx +100 -24
  32. package/registry/admin-apps/react/variants/base/src/pages/EditRolePage.tsx +99 -26
  33. package/registry/admin-apps/react/variants/base/src/pages/EditUserPage.tsx +126 -31
  34. package/registry/admin-apps/react/variants/base/src/pages/LanguageDetailPage.tsx +75 -19
  35. package/registry/admin-apps/react/variants/base/src/pages/PermissionDetailPage.tsx +58 -13
  36. package/registry/admin-apps/react/variants/base/src/pages/PermissionsPage.tsx +132 -29
  37. package/registry/admin-apps/react/variants/base/src/pages/RoleDetailPage.tsx +70 -17
  38. package/registry/admin-apps/react/variants/base/src/pages/RolesPage.tsx +277 -59
  39. package/registry/admin-apps/react/variants/workspaces/package.json +15 -2
  40. package/registry/combos/express-drizzle/eslint.config.js +18 -0
  41. package/registry/combos/express-drizzle/package.json +5 -1
  42. package/registry/combos/express-drizzle/shared/src/request-context.ts +3 -0
  43. package/registry/combos/express-prisma/eslint.config.js +18 -0
  44. package/registry/combos/express-prisma/package.json +5 -1
  45. package/registry/combos/express-prisma/shared/src/request-context.ts +3 -0
  46. package/registry/combos/nestjs-drizzle/eslint.config.js +18 -0
  47. package/registry/combos/nestjs-drizzle/package.json +5 -1
  48. package/registry/combos/nestjs-drizzle/shared/src/auth.controller.ts +138 -33
  49. package/registry/combos/nestjs-drizzle/shared/src/route-tiers.ts +71 -18
  50. package/registry/combos/nestjs-prisma/eslint.config.js +18 -0
  51. package/registry/combos/nestjs-prisma/package.json +5 -1
  52. package/registry/combos/nestjs-prisma/shared/src/auth.controller.ts +148 -35
  53. package/registry/combos/nestjs-prisma/shared/src/route-tiers.ts +72 -18
  54. package/registry/mobile-apps/bare-rn/shared/.husky/commit-msg +1 -0
  55. package/registry/mobile-apps/bare-rn/shared/.husky/pre-commit +1 -0
  56. package/registry/mobile-apps/bare-rn/shared/.lintstagedrc.json +4 -0
  57. package/registry/mobile-apps/bare-rn/shared/.prettierrc.json +5 -0
  58. package/registry/mobile-apps/bare-rn/shared/commitlint.config.js +3 -0
  59. package/registry/mobile-apps/bare-rn/shared/eslint.config.js +19 -0
  60. package/registry/mobile-apps/bare-rn/variants/base/package.json +17 -12
  61. package/registry/mobile-apps/bare-rn/variants/workspaces/package.json +17 -12
  62. package/registry/mobile-apps/expo/shared/.husky/commit-msg +1 -0
  63. package/registry/mobile-apps/expo/shared/.husky/pre-commit +1 -0
  64. package/registry/mobile-apps/expo/shared/.lintstagedrc.json +4 -0
  65. package/registry/mobile-apps/expo/shared/.prettierrc.json +5 -0
  66. package/registry/mobile-apps/expo/shared/commitlint.config.js +3 -0
  67. package/registry/mobile-apps/expo/shared/eslint.config.js +9 -0
  68. package/registry/mobile-apps/expo/shared/src/screens/SessionsScreen.tsx +6 -17
  69. package/registry/mobile-apps/expo/shared/src/store/sessionsStore.ts +35 -0
  70. package/registry/mobile-apps/expo/variants/base/package.json +12 -3
  71. package/registry/mobile-apps/expo/variants/workspaces/package.json +12 -3
  72. package/registry/mobile-apps/expo/variants/workspaces/src/screens/WorkspaceSelectScreen.tsx +1 -1
  73. package/registry.json +13 -36
  74. package/registry/mobile-apps/bare-rn/shared/.eslintrc.js +0 -4
  75. package/registry/mobile-apps/bare-rn/shared/.prettierrc.js +0 -5
@@ -3,8 +3,11 @@
3
3
  import { useAbility } from "@casl/react";
4
4
  import Link from "next/link";
5
5
  import { useParams, useRouter } from "next/navigation";
6
- import { useCallback, useEffect, useState } from "react";
7
- import { AuthApiError, type CustomerSummary } from "@simple-auth-kit/auth-client";
6
+ import { startTransition, useCallback, useEffect, useState } from "react";
7
+ import {
8
+ AuthApiError,
9
+ type CustomerSummary,
10
+ } from "@simple-auth-kit/auth-client";
8
11
  import { format } from "date-fns";
9
12
  import { PencilIcon } from "lucide-react";
10
13
  import { toast } from "sonner";
@@ -13,7 +16,13 @@ import { PermissionRequired } from "@/components/permission-required";
13
16
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
14
17
  import { Badge } from "@/components/ui/badge";
15
18
  import { Button, buttonVariants } from "@/components/ui/button";
16
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
19
+ import {
20
+ Card,
21
+ CardContent,
22
+ CardDescription,
23
+ CardHeader,
24
+ CardTitle,
25
+ } from "@/components/ui/card";
17
26
  import {
18
27
  Dialog,
19
28
  DialogContent,
@@ -23,7 +32,12 @@ import {
23
32
  DialogTitle,
24
33
  DialogTrigger,
25
34
  } from "@/components/ui/dialog";
26
- import { PERMISSIONS, hasPermission, missingPermissionHint, type AppAbility } from "@/lib/ability";
35
+ import {
36
+ PERMISSIONS,
37
+ hasPermission,
38
+ missingPermissionHint,
39
+ type AppAbility,
40
+ } from "@/lib/ability";
27
41
  import { authClient } from "@/lib/auth-client";
28
42
 
29
43
  function apiErrorMessage(err: unknown, fallback: string): string {
@@ -82,20 +96,35 @@ export default function CustomerDetailPage() {
82
96
 
83
97
  useEffect(() => {
84
98
  if (!canRead) return;
85
- void load();
99
+ startTransition(() => void load());
86
100
  }, [canRead, load]);
87
101
 
88
- if (!canRead) return <PermissionRequired permission={PERMISSIONS.customersRead} what="Customer details" />;
102
+ if (!canRead)
103
+ return (
104
+ <PermissionRequired
105
+ permission={PERMISSIONS.customersRead}
106
+ what="Customer details"
107
+ />
108
+ );
89
109
 
90
110
  async function toggleActive() {
91
111
  if (!customer) return;
92
112
  try {
93
113
  if (customer.isActive) await authClient.deactivateCustomer(id);
94
114
  else await authClient.activateCustomer(id);
95
- setCustomer((prev) => (prev ? { ...prev, isActive: !prev.isActive } : prev));
96
- toast.success(customer.isActive ? "Customer deactivated." : "Customer activated.");
115
+ setCustomer((prev) =>
116
+ prev ? { ...prev, isActive: !prev.isActive } : prev,
117
+ );
118
+ toast.success(
119
+ customer.isActive ? "Customer deactivated." : "Customer activated.",
120
+ );
97
121
  } catch (err) {
98
- toast.error(apiErrorMessage(err, "Couldn't change this customer's status. Try again."));
122
+ toast.error(
123
+ apiErrorMessage(
124
+ err,
125
+ "Couldn't change this customer's status. Try again.",
126
+ ),
127
+ );
99
128
  }
100
129
  }
101
130
 
@@ -106,7 +135,9 @@ export default function CustomerDetailPage() {
106
135
  toast.success("Customer deleted.");
107
136
  router.push("/customers");
108
137
  } catch (err) {
109
- toast.error(apiErrorMessage(err, "Couldn't delete this customer. Try again."));
138
+ toast.error(
139
+ apiErrorMessage(err, "Couldn't delete this customer. Try again."),
140
+ );
110
141
  setDeleting(false);
111
142
  setDeleteOpen(false);
112
143
  }
@@ -114,27 +145,44 @@ export default function CustomerDetailPage() {
114
145
 
115
146
  return (
116
147
  <div className="flex flex-col gap-4">
117
- <Breadcrumb items={[{ title: "Customers", href: "/customers" }, { title: customer?.email ?? "Details", href: `/customers/${id}` }]} />
148
+ <Breadcrumb
149
+ items={[
150
+ { title: "Customers", href: "/customers" },
151
+ { title: customer?.email ?? "Details", href: `/customers/${id}` },
152
+ ]}
153
+ />
118
154
 
119
- {loading && !customer && <p className="text-sm text-muted-foreground">Loading…</p>}
155
+ {loading && !customer && (
156
+ <p className="text-sm text-muted-foreground">Loading…</p>
157
+ )}
120
158
 
121
159
  {customer && (
122
160
  <>
123
161
  <Card>
124
162
  <CardHeader className="flex flex-row items-center justify-between">
125
163
  <div>
126
- <CardTitle>{customerName(customer) || customer.email}</CardTitle>
164
+ <CardTitle>
165
+ {customerName(customer) || customer.email}
166
+ </CardTitle>
127
167
  <CardDescription>
128
- Joined: {format(new Date(customer.joinedDate), "dd MMM yyyy")} · Created: {format(new Date(customer.createdAt), "dd MMM yyyy")} · Updated:{" "}
129
- {format(new Date(customer.updatedAt), "dd MMM yyyy")}
168
+ Joined: {format(new Date(customer.joinedDate), "dd MMM yyyy")}{" "}
169
+ · Created:{" "}
170
+ {format(new Date(customer.createdAt), "dd MMM yyyy")} ·
171
+ Updated: {format(new Date(customer.updatedAt), "dd MMM yyyy")}
130
172
  </CardDescription>
131
173
  </div>
132
174
  <div className="flex items-center gap-1.5">
133
- <Badge variant={customer.isActive ? "success" : "destructive"}>{customer.isActive ? "Active" : "Inactive"}</Badge>
175
+ <Badge variant={customer.isActive ? "success" : "destructive"}>
176
+ {customer.isActive ? "Active" : "Inactive"}
177
+ </Badge>
134
178
  <Link
135
179
  href={`/customers/${id}/edit`}
136
180
  className={buttonVariants({ variant: "outline", size: "sm" })}
137
- title={canManage ? undefined : missingPermissionHint(PERMISSIONS.customersManage)}
181
+ title={
182
+ canManage
183
+ ? undefined
184
+ : missingPermissionHint(PERMISSIONS.customersManage)
185
+ }
138
186
  aria-disabled={!canManage}
139
187
  onClick={(e) => !canManage && e.preventDefault()}
140
188
  >
@@ -145,8 +193,16 @@ export default function CustomerDetailPage() {
145
193
  </CardHeader>
146
194
  <CardContent className="flex flex-col gap-4">
147
195
  <Avatar className="size-16">
148
- {customer.photo && <AvatarImage src={customer.photo} alt="" className="object-cover" />}
149
- <AvatarFallback className="text-base">{initialsOf(customer)}</AvatarFallback>
196
+ {customer.photo && (
197
+ <AvatarImage
198
+ src={customer.photo}
199
+ alt=""
200
+ className="object-cover"
201
+ />
202
+ )}
203
+ <AvatarFallback className="text-base">
204
+ {initialsOf(customer)}
205
+ </AvatarFallback>
150
206
  </Avatar>
151
207
 
152
208
  <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
@@ -155,14 +211,39 @@ export default function CustomerDetailPage() {
155
211
  {field("First name", customer.firstName)}
156
212
  {field("Last name", customer.lastName)}
157
213
  {field("Phone", customer.phone)}
158
- {field("Gender", customer.gender && customer.gender.charAt(0).toUpperCase() + customer.gender.slice(1))}
159
- {field("Date of birth", customer.dob ? format(new Date(customer.dob), "dd MMM yyyy") : null)}
160
- {field("Joined date", format(new Date(customer.joinedDate), "dd MMM yyyy"))}
214
+ {field(
215
+ "Gender",
216
+ customer.gender &&
217
+ customer.gender.charAt(0).toUpperCase() +
218
+ customer.gender.slice(1),
219
+ )}
220
+ {field(
221
+ "Date of birth",
222
+ customer.dob
223
+ ? format(new Date(customer.dob), "dd MMM yyyy")
224
+ : null,
225
+ )}
226
+ {field(
227
+ "Joined date",
228
+ format(new Date(customer.joinedDate), "dd MMM yyyy"),
229
+ )}
161
230
  </div>
162
231
 
163
232
  <div className="flex flex-wrap gap-1.5">
164
- <Badge variant={customer.isEmailVerified ? "success" : "outline"}>{customer.isEmailVerified ? "Email verified" : "Email unverified"}</Badge>
165
- <Badge variant={customer.isPhoneVerified ? "success" : "outline"}>{customer.isPhoneVerified ? "Phone verified" : "Phone unverified"}</Badge>
233
+ <Badge
234
+ variant={customer.isEmailVerified ? "success" : "outline"}
235
+ >
236
+ {customer.isEmailVerified
237
+ ? "Email verified"
238
+ : "Email unverified"}
239
+ </Badge>
240
+ <Badge
241
+ variant={customer.isPhoneVerified ? "success" : "outline"}
242
+ >
243
+ {customer.isPhoneVerified
244
+ ? "Phone verified"
245
+ : "Phone unverified"}
246
+ </Badge>
166
247
  </div>
167
248
  </CardContent>
168
249
  </Card>
@@ -175,7 +256,11 @@ export default function CustomerDetailPage() {
175
256
  <Button
176
257
  variant={customer.isActive ? "destructive" : "outline"}
177
258
  disabled={!canStatus}
178
- title={canStatus ? undefined : missingPermissionHint(PERMISSIONS.customersStatus)}
259
+ title={
260
+ canStatus
261
+ ? undefined
262
+ : missingPermissionHint(PERMISSIONS.customersStatus)
263
+ }
179
264
  onClick={() => void toggleActive()}
180
265
  >
181
266
  {customer.isActive ? "Deactivate" : "Activate"}
@@ -183,7 +268,15 @@ export default function CustomerDetailPage() {
183
268
 
184
269
  <Dialog open={deleteOpen} onOpenChange={setDeleteOpen}>
185
270
  <DialogTrigger asChild>
186
- <Button variant="destructive" disabled={!canManage} title={canManage ? undefined : missingPermissionHint(PERMISSIONS.customersManage)}>
271
+ <Button
272
+ variant="destructive"
273
+ disabled={!canManage}
274
+ title={
275
+ canManage
276
+ ? undefined
277
+ : missingPermissionHint(PERMISSIONS.customersManage)
278
+ }
279
+ >
187
280
  Delete customer
188
281
  </Button>
189
282
  </DialogTrigger>
@@ -191,14 +284,23 @@ export default function CustomerDetailPage() {
191
284
  <DialogHeader>
192
285
  <DialogTitle>Delete {customer.email}?</DialogTitle>
193
286
  <DialogDescription>
194
- This soft-deletes the customer: they stop appearing in listings, but the row is kept for audit purposes.
287
+ This soft-deletes the customer: they stop appearing in
288
+ listings, but the row is kept for audit purposes.
195
289
  </DialogDescription>
196
290
  </DialogHeader>
197
291
  <DialogFooter>
198
- <Button variant="outline" onClick={() => setDeleteOpen(false)} disabled={deleting}>
292
+ <Button
293
+ variant="outline"
294
+ onClick={() => setDeleteOpen(false)}
295
+ disabled={deleting}
296
+ >
199
297
  Cancel
200
298
  </Button>
201
- <Button variant="destructive" onClick={() => void handleDelete()} disabled={deleting}>
299
+ <Button
300
+ variant="destructive"
301
+ onClick={() => void handleDelete()}
302
+ disabled={deleting}
303
+ >
202
304
  {deleting ? "Deleting…" : "Delete customer"}
203
305
  </Button>
204
306
  </DialogFooter>
@@ -3,25 +3,48 @@
3
3
  import { zodResolver } from "@hookform/resolvers/zod";
4
4
  import { useAbility } from "@casl/react";
5
5
  import { useParams, useRouter } from "next/navigation";
6
- import { useCallback, useEffect, useState } from "react";
6
+ import { startTransition, useCallback, useEffect, useState } from "react";
7
7
  import { useForm } from "react-hook-form";
8
- import { AuthApiError, type LanguageSummary, type UpdateLanguageInput } from "@simple-auth-kit/auth-client";
8
+ import {
9
+ AuthApiError,
10
+ type LanguageSummary,
11
+ type UpdateLanguageInput,
12
+ } from "@simple-auth-kit/auth-client";
9
13
  import { toast } from "sonner";
10
14
  import { Breadcrumb } from "@/components/breadcrumb";
11
15
  import { FormErrorAlert } from "@/components/form-error-alert";
12
16
  import { PermissionRequired } from "@/components/permission-required";
13
17
  import { Button } from "@/components/ui/button";
14
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
18
+ import {
19
+ Card,
20
+ CardContent,
21
+ CardDescription,
22
+ CardFooter,
23
+ CardHeader,
24
+ CardTitle,
25
+ } from "@/components/ui/card";
15
26
  import { Checkbox } from "@/components/ui/checkbox";
16
27
  import { Combobox } from "@/components/ui/combobox";
17
- import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
28
+ import {
29
+ Form,
30
+ FormControl,
31
+ FormDescription,
32
+ FormField,
33
+ FormItem,
34
+ FormLabel,
35
+ FormMessage,
36
+ } from "@/components/ui/form";
18
37
  import { Heading } from "@/components/ui/heading";
19
38
  import { Input } from "@/components/ui/input";
20
39
  import { Separator } from "@/components/ui/separator";
21
40
  import { PERMISSIONS, hasPermission, type AppAbility } from "@/lib/ability";
22
41
  import { authClient } from "@/lib/auth-client";
23
42
  import { errorMessage, errorMessages } from "@/lib/error";
24
- import { DIRECTION_OPTIONS, languageSchema, type LanguageFormValues } from "../../language-schema";
43
+ import {
44
+ DIRECTION_OPTIONS,
45
+ languageSchema,
46
+ type LanguageFormValues,
47
+ } from "../../language-schema";
25
48
 
26
49
  function apiErrorMessage(err: unknown, fallback: string): string {
27
50
  return err instanceof AuthApiError ? err.message : fallback;
@@ -50,7 +73,14 @@ export default function EditLanguagePage() {
50
73
 
51
74
  const form = useForm<LanguageFormValues>({
52
75
  resolver: zodResolver(languageSchema),
53
- defaultValues: { code: "", name: "", nativeName: "", direction: "ltr", isDefault: false, isActive: true },
76
+ defaultValues: {
77
+ code: "",
78
+ name: "",
79
+ nativeName: "",
80
+ direction: "ltr",
81
+ isDefault: false,
82
+ isActive: true,
83
+ },
54
84
  });
55
85
 
56
86
  const load = useCallback(async () => {
@@ -70,10 +100,16 @@ export default function EditLanguagePage() {
70
100
 
71
101
  useEffect(() => {
72
102
  if (!canManage) return;
73
- void load();
103
+ startTransition(() => void load());
74
104
  }, [canManage, load]);
75
105
 
76
- if (!canManage) return <PermissionRequired permission={PERMISSIONS.languagesManage} what="Editing a language" />;
106
+ if (!canManage)
107
+ return (
108
+ <PermissionRequired
109
+ permission={PERMISSIONS.languagesManage}
110
+ what="Editing a language"
111
+ />
112
+ );
77
113
 
78
114
  async function onSubmit(values: LanguageFormValues) {
79
115
  if (!language) return;
@@ -112,7 +148,9 @@ export default function EditLanguagePage() {
112
148
  </div>
113
149
  <Separator />
114
150
 
115
- {loading && !language && <p className="text-sm text-muted-foreground">Loading…</p>}
151
+ {loading && !language && (
152
+ <p className="text-sm text-muted-foreground">Loading…</p>
153
+ )}
116
154
 
117
155
  {language && (
118
156
  <Card>
@@ -120,16 +158,25 @@ export default function EditLanguagePage() {
120
158
  <CardContent>
121
159
  <FormErrorAlert messages={formError} />
122
160
  <Form {...form}>
123
- <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 w-full">
161
+ <form
162
+ onSubmit={form.handleSubmit(onSubmit)}
163
+ className="space-y-8 w-full"
164
+ >
124
165
  <Card className="w-full">
125
166
  <CardHeader className="border-b bg-muted/50">
126
- <CardTitle className="text-2xl">Language Information</CardTitle>
127
- <CardDescription className="text-base">Enter language details</CardDescription>
167
+ <CardTitle className="text-2xl">
168
+ Language Information
169
+ </CardTitle>
170
+ <CardDescription className="text-base">
171
+ Enter language details
172
+ </CardDescription>
128
173
  </CardHeader>
129
174
  <CardContent className="pt-6">
130
175
  <div className="space-y-6">
131
176
  <div className="space-y-4">
132
- <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">Basic Information</h3>
177
+ <h3 className="text-sm font-semibold text-muted-foreground uppercase tracking-wide">
178
+ Basic Information
179
+ </h3>
133
180
  <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
134
181
  <FormField
135
182
  control={form.control}
@@ -157,7 +204,9 @@ export default function EditLanguagePage() {
157
204
  <FormItem>
158
205
  <FormLabel>
159
206
  Language Code &nbsp;
160
- <span className="text-xs text-destructive dark:text-destructive-foreground">(ISO code, e.g., en, ar, bn)</span>
207
+ <span className="text-xs text-destructive dark:text-destructive-foreground">
208
+ (ISO code, e.g., en, ar, bn)
209
+ </span>
161
210
  </FormLabel>
162
211
  <FormControl>
163
212
  <Input
@@ -167,7 +216,11 @@ export default function EditLanguagePage() {
167
216
  type="text"
168
217
  maxLength={10}
169
218
  className="bg-background border-2 focus:border-purple-500 transition-colors lowercase"
170
- onChange={(e) => field.onChange(e.target.value.toLowerCase())}
219
+ onChange={(e) =>
220
+ field.onChange(
221
+ e.target.value.toLowerCase(),
222
+ )
223
+ }
171
224
  />
172
225
  </FormControl>
173
226
  <FormMessage />
@@ -181,7 +234,9 @@ export default function EditLanguagePage() {
181
234
  <FormItem>
182
235
  <FormLabel>
183
236
  Native Name &nbsp;
184
- <span className="text-xs text-muted-foreground">(e.g., العربية, বাংলা)</span>
237
+ <span className="text-xs text-muted-foreground">
238
+ (e.g., العربية, বাংলা)
239
+ </span>
185
240
  </FormLabel>
186
241
  <FormControl>
187
242
  <Input
@@ -208,7 +263,9 @@ export default function EditLanguagePage() {
208
263
  options={DIRECTION_OPTIONS}
209
264
  selected={field.value}
210
265
  placeholder="Select text direction"
211
- onChange={(option) => field.onChange(option.value)}
266
+ onChange={(option) =>
267
+ field.onChange(option.value)
268
+ }
212
269
  showCreate={false}
213
270
  popoverClassName="min-w-[250px]"
214
271
  />
@@ -230,11 +287,21 @@ export default function EditLanguagePage() {
230
287
  render={({ field }) => (
231
288
  <FormItem className="flex flex-row items-center space-x-3 space-y-0 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
232
289
  <FormControl>
233
- <Checkbox checked={field.value} onCheckedChange={(checked) => field.onChange(checked === true)} />
290
+ <Checkbox
291
+ checked={field.value}
292
+ onCheckedChange={(checked) =>
293
+ field.onChange(checked === true)
294
+ }
295
+ />
234
296
  </FormControl>
235
297
  <div className="space-y-1 leading-none">
236
- <FormLabel className="text-base font-medium">Default Language</FormLabel>
237
- <FormDescription className="text-sm">The default language is the one a new deployment&apos;s locale falls back to</FormDescription>
298
+ <FormLabel className="text-base font-medium">
299
+ Default Language
300
+ </FormLabel>
301
+ <FormDescription className="text-sm">
302
+ The default language is the one a new
303
+ deployment&apos;s locale falls back to
304
+ </FormDescription>
238
305
  </div>
239
306
  </FormItem>
240
307
  )}
@@ -245,11 +312,21 @@ export default function EditLanguagePage() {
245
312
  render={({ field }) => (
246
313
  <FormItem className="flex flex-row items-center space-x-3 space-y-0 rounded-lg border border-purple-500 bg-purple-50 dark:bg-purple-950/20 p-4">
247
314
  <FormControl>
248
- <Checkbox checked={field.value} onCheckedChange={(checked) => field.onChange(checked === true)} />
315
+ <Checkbox
316
+ checked={field.value}
317
+ onCheckedChange={(checked) =>
318
+ field.onChange(checked === true)
319
+ }
320
+ />
249
321
  </FormControl>
250
322
  <div className="space-y-1 leading-none">
251
- <FormLabel className="text-base font-medium">Active Status</FormLabel>
252
- <FormDescription className="text-sm">Language will be active and available for selection</FormDescription>
323
+ <FormLabel className="text-base font-medium">
324
+ Active Status
325
+ </FormLabel>
326
+ <FormDescription className="text-sm">
327
+ Language will be active and available for
328
+ selection
329
+ </FormDescription>
253
330
  </div>
254
331
  </FormItem>
255
332
  )}
@@ -257,10 +334,19 @@ export default function EditLanguagePage() {
257
334
  </div>
258
335
 
259
336
  <CardFooter className="flex justify-center gap-4 mt-8 pb-8">
260
- <Button type="button" variant="outline" onClick={() => router.push(`/languages/${id}`)} disabled={saving}>
337
+ <Button
338
+ type="button"
339
+ variant="outline"
340
+ onClick={() => router.push(`/languages/${id}`)}
341
+ disabled={saving}
342
+ >
261
343
  Cancel
262
344
  </Button>
263
- <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">
345
+ <Button
346
+ disabled={saving}
347
+ className="bg-purple-600 hover:bg-purple-700 dark:bg-purple-600 dark:hover:bg-purple-700 min-w-32"
348
+ type="submit"
349
+ >
264
350
  {saving ? "Updating..." : "Update Language"}
265
351
  </Button>
266
352
  </CardFooter>