@tower_74/cms-app 0.1.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 (189) hide show
  1. package/README.md +102 -0
  2. package/package.json +49 -0
  3. package/src/components/AppContent.vue +21 -0
  4. package/src/components/AppLogoIcon.vue +24 -0
  5. package/src/components/AppShell.vue +37 -0
  6. package/src/components/AppearanceTabs.vue +37 -0
  7. package/src/components/AuthBar.vue +58 -0
  8. package/src/components/BlockEditor.vue +95 -0
  9. package/src/components/DeleteUser.vue +87 -0
  10. package/src/components/FieldBuilder.vue +105 -0
  11. package/src/components/Heading.vue +20 -0
  12. package/src/components/HeadingSmall.vue +17 -0
  13. package/src/components/Icon.vue +30 -0
  14. package/src/components/InputError.vue +13 -0
  15. package/src/components/MenuItemsEditor.vue +59 -0
  16. package/src/components/NavUser.vue +30 -0
  17. package/src/components/Pagination.vue +28 -0
  18. package/src/components/PlaceholderPattern.vue +16 -0
  19. package/src/components/Seo.vue +28 -0
  20. package/src/components/TextLink.vue +24 -0
  21. package/src/components/UserInfo.vue +34 -0
  22. package/src/components/UserMenuContent.vue +37 -0
  23. package/src/components/commerce/OptionsEditor.vue +55 -0
  24. package/src/components/commerce/VariantsEditor.vue +71 -0
  25. package/src/components/ui/avatar/Avatar.vue +24 -0
  26. package/src/components/ui/avatar/AvatarFallback.vue +11 -0
  27. package/src/components/ui/avatar/AvatarImage.vue +9 -0
  28. package/src/components/ui/avatar/index.ts +24 -0
  29. package/src/components/ui/breadcrumb/Breadcrumb.vue +13 -0
  30. package/src/components/ui/breadcrumb/BreadcrumbEllipsis.vue +18 -0
  31. package/src/components/ui/breadcrumb/BreadcrumbItem.vue +14 -0
  32. package/src/components/ui/breadcrumb/BreadcrumbLink.vue +15 -0
  33. package/src/components/ui/breadcrumb/BreadcrumbList.vue +14 -0
  34. package/src/components/ui/breadcrumb/BreadcrumbPage.vue +14 -0
  35. package/src/components/ui/breadcrumb/BreadcrumbSeparator.vue +17 -0
  36. package/src/components/ui/breadcrumb/index.ts +7 -0
  37. package/src/components/ui/button/Button.vue +22 -0
  38. package/src/components/ui/button/index.ts +31 -0
  39. package/src/components/ui/card/Card.vue +14 -0
  40. package/src/components/ui/card/CardContent.vue +14 -0
  41. package/src/components/ui/card/CardDescription.vue +14 -0
  42. package/src/components/ui/card/CardFooter.vue +14 -0
  43. package/src/components/ui/card/CardHeader.vue +14 -0
  44. package/src/components/ui/card/CardTitle.vue +14 -0
  45. package/src/components/ui/card/index.ts +6 -0
  46. package/src/components/ui/checkbox/Checkbox.vue +36 -0
  47. package/src/components/ui/checkbox/index.ts +1 -0
  48. package/src/components/ui/collapsible/Collapsible.vue +15 -0
  49. package/src/components/ui/collapsible/CollapsibleContent.vue +14 -0
  50. package/src/components/ui/collapsible/CollapsibleTrigger.vue +11 -0
  51. package/src/components/ui/collapsible/index.ts +3 -0
  52. package/src/components/ui/dialog/Dialog.vue +14 -0
  53. package/src/components/ui/dialog/DialogClose.vue +11 -0
  54. package/src/components/ui/dialog/DialogContent.vue +51 -0
  55. package/src/components/ui/dialog/DialogDescription.vue +21 -0
  56. package/src/components/ui/dialog/DialogFooter.vue +12 -0
  57. package/src/components/ui/dialog/DialogHeader.vue +14 -0
  58. package/src/components/ui/dialog/DialogScrollContent.vue +59 -0
  59. package/src/components/ui/dialog/DialogTitle.vue +21 -0
  60. package/src/components/ui/dialog/DialogTrigger.vue +11 -0
  61. package/src/components/ui/dialog/index.ts +9 -0
  62. package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  63. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +42 -0
  64. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +40 -0
  65. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  66. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +30 -0
  67. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +21 -0
  68. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +14 -0
  69. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +43 -0
  70. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +21 -0
  71. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  72. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +14 -0
  73. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  74. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +31 -0
  75. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  76. package/src/components/ui/dropdown-menu/index.ts +16 -0
  77. package/src/components/ui/input/Input.vue +32 -0
  78. package/src/components/ui/input/index.ts +1 -0
  79. package/src/components/ui/label/Label.vue +22 -0
  80. package/src/components/ui/label/index.ts +1 -0
  81. package/src/components/ui/navigation-menu/NavigationMenu.vue +25 -0
  82. package/src/components/ui/navigation-menu/NavigationMenuContent.vue +31 -0
  83. package/src/components/ui/navigation-menu/NavigationMenuIndicator.vue +29 -0
  84. package/src/components/ui/navigation-menu/NavigationMenuItem.vue +11 -0
  85. package/src/components/ui/navigation-menu/NavigationMenuLink.vue +14 -0
  86. package/src/components/ui/navigation-menu/NavigationMenuList.vue +21 -0
  87. package/src/components/ui/navigation-menu/NavigationMenuTrigger.vue +24 -0
  88. package/src/components/ui/navigation-menu/NavigationMenuViewport.vue +29 -0
  89. package/src/components/ui/navigation-menu/index.ts +14 -0
  90. package/src/components/ui/separator/Separator.vue +31 -0
  91. package/src/components/ui/separator/index.ts +1 -0
  92. package/src/components/ui/sheet/Sheet.vue +14 -0
  93. package/src/components/ui/sheet/SheetClose.vue +11 -0
  94. package/src/components/ui/sheet/SheetContent.vue +53 -0
  95. package/src/components/ui/sheet/SheetDescription.vue +19 -0
  96. package/src/components/ui/sheet/SheetFooter.vue +12 -0
  97. package/src/components/ui/sheet/SheetHeader.vue +12 -0
  98. package/src/components/ui/sheet/SheetTitle.vue +19 -0
  99. package/src/components/ui/sheet/SheetTrigger.vue +11 -0
  100. package/src/components/ui/sheet/index.ts +29 -0
  101. package/src/components/ui/sidebar/Sidebar.vue +99 -0
  102. package/src/components/ui/sidebar/SidebarContent.vue +17 -0
  103. package/src/components/ui/sidebar/SidebarFooter.vue +14 -0
  104. package/src/components/ui/sidebar/SidebarGroup.vue +14 -0
  105. package/src/components/ui/sidebar/SidebarGroupAction.vue +31 -0
  106. package/src/components/ui/sidebar/SidebarGroupContent.vue +14 -0
  107. package/src/components/ui/sidebar/SidebarGroupLabel.vue +29 -0
  108. package/src/components/ui/sidebar/SidebarHeader.vue +14 -0
  109. package/src/components/ui/sidebar/SidebarInput.vue +15 -0
  110. package/src/components/ui/sidebar/SidebarInset.vue +22 -0
  111. package/src/components/ui/sidebar/SidebarMenu.vue +14 -0
  112. package/src/components/ui/sidebar/SidebarMenuAction.vue +41 -0
  113. package/src/components/ui/sidebar/SidebarMenuBadge.vue +27 -0
  114. package/src/components/ui/sidebar/SidebarMenuButton.vue +52 -0
  115. package/src/components/ui/sidebar/SidebarMenuButtonChild.vue +33 -0
  116. package/src/components/ui/sidebar/SidebarMenuItem.vue +14 -0
  117. package/src/components/ui/sidebar/SidebarMenuSkeleton.vue +22 -0
  118. package/src/components/ui/sidebar/SidebarMenuSub.vue +23 -0
  119. package/src/components/ui/sidebar/SidebarMenuSubButton.vue +42 -0
  120. package/src/components/ui/sidebar/SidebarMenuSubItem.vue +7 -0
  121. package/src/components/ui/sidebar/SidebarProvider.vue +89 -0
  122. package/src/components/ui/sidebar/SidebarRail.vue +34 -0
  123. package/src/components/ui/sidebar/SidebarSeparator.vue +15 -0
  124. package/src/components/ui/sidebar/SidebarTrigger.vue +20 -0
  125. package/src/components/ui/sidebar/index.ts +51 -0
  126. package/src/components/ui/sidebar/utils.ts +19 -0
  127. package/src/components/ui/skeleton/Skeleton.vue +14 -0
  128. package/src/components/ui/skeleton/index.ts +1 -0
  129. package/src/components/ui/tooltip/Tooltip.vue +14 -0
  130. package/src/components/ui/tooltip/TooltipContent.vue +39 -0
  131. package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  132. package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  133. package/src/components/ui/tooltip/index.ts +4 -0
  134. package/src/composables/useAppearance.ts +53 -0
  135. package/src/composables/useInitials.ts +14 -0
  136. package/src/index.ts +22 -0
  137. package/src/layouts/AdminLayout.vue +170 -0
  138. package/src/layouts/AuthLayout.vue +14 -0
  139. package/src/layouts/PublicLayout.vue +53 -0
  140. package/src/layouts/auth/AuthCardLayout.vue +36 -0
  141. package/src/layouts/auth/AuthSimpleLayout.vue +31 -0
  142. package/src/layouts/auth/AuthSplitLayout.vue +40 -0
  143. package/src/layouts/settings/Layout.vue +56 -0
  144. package/src/lib/utils.ts +6 -0
  145. package/src/pages/Admin/Appearance/Theme.vue +58 -0
  146. package/src/pages/Admin/Appearance/Widgets.vue +48 -0
  147. package/src/pages/Admin/Commerce/Orders/Index.vue +80 -0
  148. package/src/pages/Admin/Commerce/Orders/Show.vue +200 -0
  149. package/src/pages/Admin/Commerce/Products/Edit.vue +167 -0
  150. package/src/pages/Admin/Commerce/Products/Index.vue +65 -0
  151. package/src/pages/Admin/Content/Edit.vue +170 -0
  152. package/src/pages/Admin/Content/Index.vue +88 -0
  153. package/src/pages/Admin/Content/Preview.vue +25 -0
  154. package/src/pages/Admin/Dashboard.vue +26 -0
  155. package/src/pages/Admin/Forms/Edit.vue +98 -0
  156. package/src/pages/Admin/Forms/Index.vue +68 -0
  157. package/src/pages/Admin/Forms/Submissions/Index.vue +68 -0
  158. package/src/pages/Admin/Forms/Submissions/Show.vue +47 -0
  159. package/src/pages/Admin/Media/Index.vue +75 -0
  160. package/src/pages/Admin/Menus/Create.vue +37 -0
  161. package/src/pages/Admin/Menus/Edit.vue +54 -0
  162. package/src/pages/Admin/Menus/Index.vue +52 -0
  163. package/src/pages/Admin/Settings/Index.vue +184 -0
  164. package/src/pages/Admin/Taxonomy/Edit.vue +83 -0
  165. package/src/pages/Admin/Taxonomy/Index.vue +68 -0
  166. package/src/pages/Admin/Users/Edit.vue +82 -0
  167. package/src/pages/Admin/Users/Index.vue +74 -0
  168. package/src/pages/Public/Cart/Index.vue +108 -0
  169. package/src/pages/Public/Checkout/Confirmation.vue +110 -0
  170. package/src/pages/Public/Checkout/Index.vue +174 -0
  171. package/src/pages/Public/Index.vue +54 -0
  172. package/src/pages/Public/Shop/Index.vue +39 -0
  173. package/src/pages/Public/Shop/Show.vue +46 -0
  174. package/src/pages/Public/Show.vue +41 -0
  175. package/src/pages/Setup/Complete.vue +53 -0
  176. package/src/pages/Setup/Index.vue +85 -0
  177. package/src/pages/Welcome.vue +787 -0
  178. package/src/pages/auth/ConfirmPassword.vue +53 -0
  179. package/src/pages/auth/ForgotPassword.vue +54 -0
  180. package/src/pages/auth/Login.vue +91 -0
  181. package/src/pages/auth/Register.vue +83 -0
  182. package/src/pages/auth/ResetPassword.vue +81 -0
  183. package/src/pages/auth/VerifyEmail.vue +36 -0
  184. package/src/pages/settings/Appearance.vue +23 -0
  185. package/src/pages/settings/Password.vue +120 -0
  186. package/src/pages/settings/Profile.vue +105 -0
  187. package/src/pages.ts +9 -0
  188. package/src/types/index.ts +42 -0
  189. package/src/types/ziggy.ts +12 -0
@@ -0,0 +1,53 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import { Button } from '@/components/ui/button';
4
+ import { Input } from '@/components/ui/input';
5
+ import { Label } from '@/components/ui/label';
6
+ import AuthLayout from '@/layouts/AuthLayout.vue';
7
+ import { Head, useForm } from '@inertiajs/vue3';
8
+ import { LoaderCircle } from 'lucide-vue-next';
9
+
10
+ const form = useForm({
11
+ password: '',
12
+ });
13
+
14
+ const submit = () => {
15
+ form.post(route('password.confirm'), {
16
+ onFinish: () => {
17
+ form.reset();
18
+ },
19
+ });
20
+ };
21
+ </script>
22
+
23
+ <template>
24
+ <AuthLayout title="Confirm your password" description="This is a secure area of the application. Please confirm your password before continuing.">
25
+ <Head title="Confirm password" />
26
+
27
+ <form @submit.prevent="submit">
28
+ <div class="space-y-6">
29
+ <div class="grid gap-2">
30
+ <Label htmlFor="password">Password</Label>
31
+ <Input
32
+ id="password"
33
+ type="password"
34
+ class="mt-1 block w-full"
35
+ v-model="form.password"
36
+ required
37
+ autocomplete="current-password"
38
+ autofocus
39
+ />
40
+
41
+ <InputError :message="form.errors.password" />
42
+ </div>
43
+
44
+ <div class="flex items-center">
45
+ <Button class="w-full" :disabled="form.processing">
46
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
47
+ Confirm Password
48
+ </Button>
49
+ </div>
50
+ </div>
51
+ </form>
52
+ </AuthLayout>
53
+ </template>
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import TextLink from '@/components/TextLink.vue';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Input } from '@/components/ui/input';
6
+ import { Label } from '@/components/ui/label';
7
+ import AuthLayout from '@/layouts/AuthLayout.vue';
8
+ import { Head, useForm } from '@inertiajs/vue3';
9
+ import { LoaderCircle } from 'lucide-vue-next';
10
+
11
+ defineProps<{
12
+ status?: string;
13
+ }>();
14
+
15
+ const form = useForm({
16
+ email: '',
17
+ });
18
+
19
+ const submit = () => {
20
+ form.post(route('password.email'));
21
+ };
22
+ </script>
23
+
24
+ <template>
25
+ <AuthLayout title="Forgot password" description="Enter your email to receive a password reset link">
26
+ <Head title="Forgot password" />
27
+
28
+ <div v-if="status" class="mb-4 text-center text-sm font-medium text-green-600">
29
+ {{ status }}
30
+ </div>
31
+
32
+ <div class="space-y-6">
33
+ <form @submit.prevent="submit">
34
+ <div class="grid gap-2">
35
+ <Label for="email">Email address</Label>
36
+ <Input id="email" type="email" name="email" autocomplete="off" v-model="form.email" autofocus placeholder="email@example.com" />
37
+ <InputError :message="form.errors.email" />
38
+ </div>
39
+
40
+ <div class="my-6 flex items-center justify-start">
41
+ <Button class="w-full" :disabled="form.processing">
42
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
43
+ Email password reset link
44
+ </Button>
45
+ </div>
46
+ </form>
47
+
48
+ <div class="space-x-1 text-center text-sm text-muted-foreground">
49
+ <span>Or, return to</span>
50
+ <TextLink :href="route('login')">log in</TextLink>
51
+ </div>
52
+ </div>
53
+ </AuthLayout>
54
+ </template>
@@ -0,0 +1,91 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import TextLink from '@/components/TextLink.vue';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Checkbox } from '@/components/ui/checkbox';
6
+ import { Input } from '@/components/ui/input';
7
+ import { Label } from '@/components/ui/label';
8
+ import AuthBase from '@/layouts/AuthLayout.vue';
9
+ import { Head, useForm } from '@inertiajs/vue3';
10
+ import { LoaderCircle } from 'lucide-vue-next';
11
+
12
+ defineProps<{
13
+ status?: string;
14
+ canResetPassword: boolean;
15
+ }>();
16
+
17
+ const form = useForm({
18
+ email: '',
19
+ password: '',
20
+ remember: false,
21
+ });
22
+
23
+ const submit = () => {
24
+ form.post(route('login'), {
25
+ onFinish: () => form.reset('password'),
26
+ });
27
+ };
28
+ </script>
29
+
30
+ <template>
31
+ <AuthBase title="Log in to your account" description="Enter your email and password below to log in">
32
+ <Head title="Log in" />
33
+
34
+ <div v-if="status" class="mb-4 text-center text-sm font-medium text-green-600">
35
+ {{ status }}
36
+ </div>
37
+
38
+ <form @submit.prevent="submit" class="flex flex-col gap-6">
39
+ <div class="grid gap-6">
40
+ <div class="grid gap-2">
41
+ <Label for="email">Email address</Label>
42
+ <Input
43
+ id="email"
44
+ type="email"
45
+ required
46
+ autofocus
47
+ tabindex="1"
48
+ autocomplete="email"
49
+ v-model="form.email"
50
+ placeholder="email@example.com"
51
+ />
52
+ <InputError :message="form.errors.email" />
53
+ </div>
54
+
55
+ <div class="grid gap-2">
56
+ <div class="flex items-center justify-between">
57
+ <Label for="password">Password</Label>
58
+ <TextLink v-if="canResetPassword" :href="route('password.request')" class="text-sm" tabindex="5"> Forgot password? </TextLink>
59
+ </div>
60
+ <Input
61
+ id="password"
62
+ type="password"
63
+ required
64
+ tabindex="2"
65
+ autocomplete="current-password"
66
+ v-model="form.password"
67
+ placeholder="Password"
68
+ />
69
+ <InputError :message="form.errors.password" />
70
+ </div>
71
+
72
+ <div class="flex items-center justify-between" tabindex="3">
73
+ <Label for="remember" class="flex items-center space-x-3">
74
+ <Checkbox id="remember" v-model:checked="form.remember" tabindex="4" />
75
+ <span>Remember me</span>
76
+ </Label>
77
+ </div>
78
+
79
+ <Button type="submit" class="mt-4 w-full" tabindex="4" :disabled="form.processing">
80
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
81
+ Log in
82
+ </Button>
83
+ </div>
84
+
85
+ <div class="text-center text-sm text-muted-foreground">
86
+ Don't have an account?
87
+ <TextLink :href="route('register')" :tabindex="5">Sign up</TextLink>
88
+ </div>
89
+ </form>
90
+ </AuthBase>
91
+ </template>
@@ -0,0 +1,83 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import TextLink from '@/components/TextLink.vue';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Input } from '@/components/ui/input';
6
+ import { Label } from '@/components/ui/label';
7
+ import AuthBase from '@/layouts/AuthLayout.vue';
8
+ import { Head, useForm } from '@inertiajs/vue3';
9
+ import { LoaderCircle } from 'lucide-vue-next';
10
+
11
+ const form = useForm({
12
+ name: '',
13
+ email: '',
14
+ password: '',
15
+ password_confirmation: '',
16
+ });
17
+
18
+ const submit = () => {
19
+ form.post(route('register'), {
20
+ onFinish: () => form.reset('password', 'password_confirmation'),
21
+ });
22
+ };
23
+ </script>
24
+
25
+ <template>
26
+ <AuthBase title="Create an account" description="Enter your details below to create your account">
27
+ <Head title="Register" />
28
+
29
+ <form @submit.prevent="submit" class="flex flex-col gap-6">
30
+ <div class="grid gap-6">
31
+ <div class="grid gap-2">
32
+ <Label for="name">Name</Label>
33
+ <Input id="name" type="text" required autofocus tabindex="1" autocomplete="name" v-model="form.name" placeholder="Full name" />
34
+ <InputError :message="form.errors.name" />
35
+ </div>
36
+
37
+ <div class="grid gap-2">
38
+ <Label for="email">Email address</Label>
39
+ <Input id="email" type="email" required tabindex="2" autocomplete="email" v-model="form.email" placeholder="email@example.com" />
40
+ <InputError :message="form.errors.email" />
41
+ </div>
42
+
43
+ <div class="grid gap-2">
44
+ <Label for="password">Password</Label>
45
+ <Input
46
+ id="password"
47
+ type="password"
48
+ required
49
+ tabindex="3"
50
+ autocomplete="new-password"
51
+ v-model="form.password"
52
+ placeholder="Password"
53
+ />
54
+ <InputError :message="form.errors.password" />
55
+ </div>
56
+
57
+ <div class="grid gap-2">
58
+ <Label for="password_confirmation">Confirm password</Label>
59
+ <Input
60
+ id="password_confirmation"
61
+ type="password"
62
+ required
63
+ tabindex="4"
64
+ autocomplete="new-password"
65
+ v-model="form.password_confirmation"
66
+ placeholder="Confirm password"
67
+ />
68
+ <InputError :message="form.errors.password_confirmation" />
69
+ </div>
70
+
71
+ <Button type="submit" class="mt-2 w-full" tabindex="5" :disabled="form.processing">
72
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
73
+ Create account
74
+ </Button>
75
+ </div>
76
+
77
+ <div class="text-center text-sm text-muted-foreground">
78
+ Already have an account?
79
+ <TextLink :href="route('login')" class="underline underline-offset-4" tabindex="6">Log in</TextLink>
80
+ </div>
81
+ </form>
82
+ </AuthBase>
83
+ </template>
@@ -0,0 +1,81 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import { Button } from '@/components/ui/button';
4
+ import { Input } from '@/components/ui/input';
5
+ import { Label } from '@/components/ui/label';
6
+ import AuthLayout from '@/layouts/AuthLayout.vue';
7
+ import { Head, useForm } from '@inertiajs/vue3';
8
+ import { LoaderCircle } from 'lucide-vue-next';
9
+
10
+ interface Props {
11
+ token: string;
12
+ email: string;
13
+ }
14
+
15
+ const props = defineProps<Props>();
16
+
17
+ const form = useForm({
18
+ token: props.token,
19
+ email: props.email,
20
+ password: '',
21
+ password_confirmation: '',
22
+ });
23
+
24
+ const submit = () => {
25
+ form.post(route('password.store'), {
26
+ onFinish: () => {
27
+ form.reset('password', 'password_confirmation');
28
+ },
29
+ });
30
+ };
31
+ </script>
32
+
33
+ <template>
34
+ <AuthLayout title="Reset password" description="Please enter your new password below">
35
+ <Head title="Reset password" />
36
+
37
+ <form @submit.prevent="submit">
38
+ <div class="grid gap-6">
39
+ <div class="grid gap-2">
40
+ <Label for="email">Email</Label>
41
+ <Input id="email" type="email" name="email" autocomplete="email" v-model="form.email" class="mt-1 block w-full" readonly />
42
+ <InputError :message="form.errors.email" class="mt-2" />
43
+ </div>
44
+
45
+ <div class="grid gap-2">
46
+ <Label for="password">Password</Label>
47
+ <Input
48
+ id="password"
49
+ type="password"
50
+ name="password"
51
+ autocomplete="new-password"
52
+ v-model="form.password"
53
+ class="mt-1 block w-full"
54
+ autofocus
55
+ placeholder="Password"
56
+ />
57
+ <InputError :message="form.errors.password" />
58
+ </div>
59
+
60
+ <div class="grid gap-2">
61
+ <Label for="password_confirmation"> Confirm Password </Label>
62
+ <Input
63
+ id="password_confirmation"
64
+ type="password"
65
+ name="password_confirmation"
66
+ autocomplete="new-password"
67
+ v-model="form.password_confirmation"
68
+ class="mt-1 block w-full"
69
+ placeholder="Confirm password"
70
+ />
71
+ <InputError :message="form.errors.password_confirmation" />
72
+ </div>
73
+
74
+ <Button type="submit" class="mt-4 w-full" :disabled="form.processing">
75
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
76
+ Reset password
77
+ </Button>
78
+ </div>
79
+ </form>
80
+ </AuthLayout>
81
+ </template>
@@ -0,0 +1,36 @@
1
+ <script setup lang="ts">
2
+ import TextLink from '@/components/TextLink.vue';
3
+ import { Button } from '@/components/ui/button';
4
+ import AuthLayout from '@/layouts/AuthLayout.vue';
5
+ import { Head, useForm } from '@inertiajs/vue3';
6
+ import { LoaderCircle } from 'lucide-vue-next';
7
+
8
+ defineProps<{
9
+ status?: string;
10
+ }>();
11
+
12
+ const form = useForm({});
13
+
14
+ const submit = () => {
15
+ form.post(route('verification.send'));
16
+ };
17
+ </script>
18
+
19
+ <template>
20
+ <AuthLayout title="Verify email" description="Please verify your email address by clicking on the link we just emailed to you.">
21
+ <Head title="Email verification" />
22
+
23
+ <div v-if="status === 'verification-link-sent'" class="mb-4 text-center text-sm font-medium text-green-600">
24
+ A new verification link has been sent to the email address you provided during registration.
25
+ </div>
26
+
27
+ <form @submit.prevent="submit" class="space-y-6 text-center">
28
+ <Button :disabled="form.processing" variant="secondary">
29
+ <LoaderCircle v-if="form.processing" class="h-4 w-4 animate-spin" />
30
+ Resend verification email
31
+ </Button>
32
+
33
+ <TextLink :href="route('logout')" method="post" as="button" class="mx-auto block text-sm"> Log out </TextLink>
34
+ </form>
35
+ </AuthLayout>
36
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { Head } from '@inertiajs/vue3';
3
+
4
+ import AppearanceTabs from '@/components/AppearanceTabs.vue';
5
+ import HeadingSmall from '@/components/HeadingSmall.vue';
6
+
7
+ import AdminLayout from '@/layouts/AdminLayout.vue';
8
+ import SettingsLayout from '@/layouts/settings/Layout.vue';
9
+ </script>
10
+
11
+ <template>
12
+ <AdminLayout>
13
+ <template #title>Settings</template>
14
+ <Head title="Appearance settings" />
15
+
16
+ <SettingsLayout>
17
+ <div class="space-y-6">
18
+ <HeadingSmall title="Appearance settings" description="Update your account's appearance settings" />
19
+ <AppearanceTabs />
20
+ </div>
21
+ </SettingsLayout>
22
+ </AdminLayout>
23
+ </template>
@@ -0,0 +1,120 @@
1
+ <script setup lang="ts">
2
+ import InputError from '@/components/InputError.vue';
3
+ import AdminLayout from '@/layouts/AdminLayout.vue';
4
+ import SettingsLayout from '@/layouts/settings/Layout.vue';
5
+ import { TransitionRoot } from '@headlessui/vue';
6
+ import { Head, useForm } from '@inertiajs/vue3';
7
+ import { ref } from 'vue';
8
+
9
+ import HeadingSmall from '@/components/HeadingSmall.vue';
10
+ import { Button } from '@/components/ui/button';
11
+ import { Input } from '@/components/ui/input';
12
+ import { Label } from '@/components/ui/label';
13
+
14
+ interface Props {
15
+ className?: string;
16
+ }
17
+
18
+ defineProps<Props>();
19
+
20
+ const passwordInput = ref<HTMLInputElement>();
21
+ const currentPasswordInput = ref<HTMLInputElement>();
22
+
23
+ const form = useForm({
24
+ current_password: '',
25
+ password: '',
26
+ password_confirmation: '',
27
+ });
28
+
29
+ const updatePassword = () => {
30
+ form.put(route('password.update'), {
31
+ preserveScroll: true,
32
+ onSuccess: () => form.reset(),
33
+ onError: (errors: any) => {
34
+ if (errors.password) {
35
+ form.reset('password', 'password_confirmation');
36
+ if (passwordInput.value instanceof HTMLInputElement) {
37
+ passwordInput.value.focus();
38
+ }
39
+ }
40
+
41
+ if (errors.current_password) {
42
+ form.reset('current_password');
43
+ if (currentPasswordInput.value instanceof HTMLInputElement) {
44
+ currentPasswordInput.value.focus();
45
+ }
46
+ }
47
+ },
48
+ });
49
+ };
50
+ </script>
51
+
52
+ <template>
53
+ <AdminLayout>
54
+ <template #title>Settings</template>
55
+ <Head title="Profile settings" />
56
+
57
+ <SettingsLayout>
58
+ <div class="space-y-6">
59
+ <HeadingSmall title="Update password" description="Ensure your account is using a long, random password to stay secure" />
60
+
61
+ <form @submit.prevent="updatePassword" class="space-y-6">
62
+ <div class="grid gap-2">
63
+ <Label for="current_password">Current Password</Label>
64
+ <Input
65
+ id="current_password"
66
+ ref="currentPasswordInput"
67
+ v-model="form.current_password"
68
+ type="password"
69
+ class="mt-1 block w-full"
70
+ autocomplete="current-password"
71
+ placeholder="Current password"
72
+ />
73
+ <InputError :message="form.errors.current_password" />
74
+ </div>
75
+
76
+ <div class="grid gap-2">
77
+ <Label for="password">New password</Label>
78
+ <Input
79
+ id="password"
80
+ ref="passwordInput"
81
+ v-model="form.password"
82
+ type="password"
83
+ class="mt-1 block w-full"
84
+ autocomplete="new-password"
85
+ placeholder="New password"
86
+ />
87
+ <InputError :message="form.errors.password" />
88
+ </div>
89
+
90
+ <div class="grid gap-2">
91
+ <Label for="password_confirmation">Confirm password</Label>
92
+ <Input
93
+ id="password_confirmation"
94
+ v-model="form.password_confirmation"
95
+ type="password"
96
+ class="mt-1 block w-full"
97
+ autocomplete="new-password"
98
+ placeholder="Confirm password"
99
+ />
100
+ <InputError :message="form.errors.password_confirmation" />
101
+ </div>
102
+
103
+ <div class="flex items-center gap-4">
104
+ <Button :disabled="form.processing">Save password</Button>
105
+
106
+ <TransitionRoot
107
+ :show="form.recentlySuccessful"
108
+ enter="transition ease-in-out"
109
+ enter-from="opacity-0"
110
+ leave="transition ease-in-out"
111
+ leave-to="opacity-0"
112
+ >
113
+ <p class="text-sm text-neutral-600">Saved</p>
114
+ </TransitionRoot>
115
+ </div>
116
+ </form>
117
+ </div>
118
+ </SettingsLayout>
119
+ </AdminLayout>
120
+ </template>
@@ -0,0 +1,105 @@
1
+ <script setup lang="ts">
2
+ import { TransitionRoot } from '@headlessui/vue';
3
+ import { Head, Link, useForm, usePage } from '@inertiajs/vue3';
4
+
5
+ import DeleteUser from '@/components/DeleteUser.vue';
6
+ import HeadingSmall from '@/components/HeadingSmall.vue';
7
+ import InputError from '@/components/InputError.vue';
8
+ import { Button } from '@/components/ui/button';
9
+ import { Input } from '@/components/ui/input';
10
+ import { Label } from '@/components/ui/label';
11
+ import AdminLayout from '@/layouts/AdminLayout.vue';
12
+ import SettingsLayout from '@/layouts/settings/Layout.vue';
13
+ import { type SharedData, type User } from '@/types';
14
+
15
+ interface Props {
16
+ mustVerifyEmail: boolean;
17
+ status?: string;
18
+ className?: string;
19
+ }
20
+
21
+ defineProps<Props>();
22
+
23
+ const page = usePage<SharedData>();
24
+ const user = page.props.auth.user as User;
25
+
26
+ const form = useForm({
27
+ name: user.name,
28
+ email: user.email,
29
+ });
30
+
31
+ const submit = () => {
32
+ form.patch(route('profile.update'), {
33
+ preserveScroll: true,
34
+ });
35
+ };
36
+ </script>
37
+
38
+ <template>
39
+ <AdminLayout>
40
+ <template #title>Settings</template>
41
+ <Head title="Profile settings" />
42
+
43
+ <SettingsLayout>
44
+ <div class="flex flex-col space-y-6">
45
+ <HeadingSmall title="Profile information" description="Update your name and email address" />
46
+
47
+ <form @submit.prevent="submit" class="space-y-6">
48
+ <div class="grid gap-2">
49
+ <Label for="name">Name</Label>
50
+ <Input id="name" class="mt-1 block w-full" v-model="form.name" required autocomplete="name" placeholder="Full name" />
51
+ <InputError class="mt-2" :message="form.errors.name" />
52
+ </div>
53
+
54
+ <div class="grid gap-2">
55
+ <Label for="email">Email address</Label>
56
+ <Input
57
+ id="email"
58
+ type="email"
59
+ class="mt-1 block w-full"
60
+ v-model="form.email"
61
+ required
62
+ autocomplete="username"
63
+ placeholder="Email address"
64
+ />
65
+ <InputError class="mt-2" :message="form.errors.email" />
66
+ </div>
67
+
68
+ <div v-if="mustVerifyEmail && !user.email_verified_at">
69
+ <p class="mt-2 text-sm text-neutral-800">
70
+ Your email address is unverified.
71
+ <Link
72
+ :href="route('verification.send')"
73
+ method="post"
74
+ as="button"
75
+ class="focus:outline-hidden rounded-md text-sm text-neutral-600 underline hover:text-neutral-900 focus:ring-2 focus:ring-offset-2"
76
+ >
77
+ Click here to re-send the verification email.
78
+ </Link>
79
+ </p>
80
+
81
+ <div v-if="status === 'verification-link-sent'" class="mt-2 text-sm font-medium text-green-600">
82
+ A new verification link has been sent to your email address.
83
+ </div>
84
+ </div>
85
+
86
+ <div class="flex items-center gap-4">
87
+ <Button :disabled="form.processing">Save</Button>
88
+
89
+ <TransitionRoot
90
+ :show="form.recentlySuccessful"
91
+ enter="transition ease-in-out"
92
+ enter-from="opacity-0"
93
+ leave="transition ease-in-out"
94
+ leave-to="opacity-0"
95
+ >
96
+ <p class="text-sm text-neutral-600">Saved.</p>
97
+ </TransitionRoot>
98
+ </div>
99
+ </form>
100
+ </div>
101
+
102
+ <DeleteUser />
103
+ </SettingsLayout>
104
+ </AdminLayout>
105
+ </template>
package/src/pages.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { DefineComponent } from 'vue';
2
+
3
+ /**
4
+ * Every Inertia page shipped by the CMS app shell. The glob is resolved relative to
5
+ * this file (packages/cms-app/src), so it captures the package's own pages. Client
6
+ * sites layer their own pages on top via {@link resolveCmsPage} in ./index.ts — keys
7
+ * from both globs share the `./pages/Name.vue` shape, so a same-named local page wins.
8
+ */
9
+ export const cmsPages = import.meta.glob<DefineComponent>('./pages/**/*.vue');