kaze 0.4.0 → 0.6.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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kaze/commands/install_command.rb +25 -13
  3. data/lib/kaze/commands/installs_hotwire_stack.rb +11 -8
  4. data/lib/kaze/commands/installs_inertia_stacks.rb +34 -24
  5. data/lib/kaze/commands/version_command.rb +6 -0
  6. data/lib/kaze/version.rb +1 -1
  7. data/lib/kaze.rb +1 -3
  8. data/stubs/default/app/forms/auth/login_form.rb +2 -8
  9. data/stubs/default/app/forms/auth/new_password_form.rb +1 -1
  10. data/stubs/default/app/forms/update_profile_information_form.rb +1 -1
  11. data/stubs/default/app/mailers/application_mailer.rb +4 -4
  12. data/stubs/default/app/mailers/user_mailer.rb +1 -1
  13. data/stubs/default/app/models/auth.rb +57 -0
  14. data/stubs/default/app/models/current.rb +1 -1
  15. data/stubs/default/app/validators/current_password_validator.rb +1 -1
  16. data/stubs/default/app/validators/email_validator.rb +1 -1
  17. data/stubs/default/app/validators/lowercase_validator.rb +2 -2
  18. data/stubs/default/app/views/layouts/mailer.html.erb +367 -372
  19. data/stubs/default/app/views/layouts/mailer.text.erb +1 -4
  20. data/stubs/default/app/views/user_mailer/reset_password.html.erb +21 -26
  21. data/stubs/default/config/routes.rb +16 -16
  22. data/stubs/default/db/migrate/20240101000001_create_delayed_jobs.rb +1 -1
  23. data/stubs/default/test/factories/users.rb +7 -0
  24. data/stubs/default/test/integration/auth/authentication_test.rb +43 -0
  25. data/stubs/default/test/integration/auth/password_reset_test.rb +41 -0
  26. data/stubs/default/test/integration/auth/registration_test.rb +21 -0
  27. data/stubs/default/test/integration/password_update_test.rb +28 -0
  28. data/stubs/default/test/integration/profile_test.rb +51 -0
  29. data/stubs/default/test/test_helper.rb +38 -0
  30. data/stubs/hotwire/app/components/danger_button_component.rb +1 -1
  31. data/stubs/hotwire/app/components/dropdown_component.html.erb +17 -18
  32. data/stubs/hotwire/app/components/dropdown_component.rb +7 -7
  33. data/stubs/hotwire/app/components/modal_component.html.erb +55 -59
  34. data/stubs/hotwire/app/components/modal_component.rb +6 -6
  35. data/stubs/hotwire/app/components/primary_button_component.rb +1 -1
  36. data/stubs/hotwire/app/components/secondary_button_component.rb +1 -1
  37. data/stubs/hotwire/app/controllers/application_controller.rb +1 -0
  38. data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +12 -9
  39. data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +7 -5
  40. data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +7 -5
  41. data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +7 -5
  42. data/stubs/hotwire/app/controllers/concerns/authenticate.rb +5 -20
  43. data/stubs/hotwire/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
  44. data/stubs/hotwire/app/controllers/concerns/set_current_auth.rb +9 -0
  45. data/stubs/hotwire/app/controllers/password_controller.rb +3 -3
  46. data/stubs/hotwire/app/controllers/profile_controller.rb +11 -9
  47. data/stubs/hotwire/app/controllers/welcome_controller.rb +1 -1
  48. data/stubs/hotwire/app/javascript/application.js +3 -3
  49. data/stubs/hotwire/app/views/auth/forgot_password.html.erb +12 -17
  50. data/stubs/hotwire/app/views/auth/login.html.erb +0 -9
  51. data/stubs/hotwire/app/views/auth/register.html.erb +0 -13
  52. data/stubs/hotwire/app/views/auth/reset_password.html.erb +0 -7
  53. data/stubs/hotwire/app/views/dashboard/index.html.erb +9 -10
  54. data/stubs/hotwire/app/views/layouts/_navigation.html.erb +77 -87
  55. data/stubs/hotwire/app/views/layouts/application.html.erb +0 -9
  56. data/stubs/hotwire/app/views/layouts/guest.html.erb +0 -6
  57. data/stubs/hotwire/app/views/profile/edit.html.erb +19 -22
  58. data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +32 -42
  59. data/stubs/hotwire/app/views/profile/partials/_update_password_form.html.erb +42 -55
  60. data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +36 -46
  61. data/stubs/hotwire/app/views/welcome/index.html.erb +34 -46
  62. data/stubs/hotwire/config/importmap.rb +3 -3
  63. data/stubs/hotwire/config/tailwind.config.js +2 -2
  64. data/stubs/inertia-common/app/controllers/application_controller.rb +1 -0
  65. data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +11 -8
  66. data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +5 -3
  67. data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +5 -3
  68. data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +5 -3
  69. data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +5 -20
  70. data/stubs/inertia-common/app/controllers/concerns/handle_inertia_requests.rb +1 -1
  71. data/stubs/inertia-common/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
  72. data/stubs/inertia-common/app/controllers/concerns/set_current_auth.rb +9 -0
  73. data/stubs/inertia-common/app/controllers/concerns/verify_csrf_token.rb +4 -4
  74. data/stubs/inertia-common/app/controllers/dashboard_controller.rb +1 -1
  75. data/stubs/inertia-common/app/controllers/password_controller.rb +1 -1
  76. data/stubs/inertia-common/app/controllers/profile_controller.rb +7 -5
  77. data/stubs/inertia-common/app/controllers/welcome_controller.rb +2 -2
  78. data/stubs/inertia-common/bin/vite +6 -6
  79. data/stubs/inertia-common/test/integration/password_update_test.rb +28 -0
  80. data/stubs/inertia-common/test/integration/profile_test.rb +51 -0
  81. data/stubs/inertia-react-ts/app/javascript/Components/ApplicationLogo.tsx +13 -9
  82. data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +15 -12
  83. data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +20 -15
  84. data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +119 -87
  85. data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +14 -7
  86. data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +18 -7
  87. data/stubs/inertia-react-ts/app/javascript/Components/Modal.tsx +60 -60
  88. data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +21 -16
  89. data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +20 -15
  90. data/stubs/inertia-react-ts/app/javascript/Components/ResponsiveNavLink.tsx +19 -14
  91. data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +22 -16
  92. data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +35 -24
  93. data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +157 -117
  94. data/stubs/inertia-react-ts/app/javascript/Layouts/GuestLayout.tsx +15 -15
  95. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +52 -49
  96. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +90 -82
  97. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +118 -115
  98. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +63 -60
  99. data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +23 -17
  100. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +31 -27
  101. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +109 -99
  102. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +121 -113
  103. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +76 -69
  104. data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +87 -63
  105. data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +32 -25
  106. data/stubs/inertia-react-ts/app/views/layouts/application.html.erb +0 -4
  107. data/stubs/inertia-react-ts/config/tailwind.config.js +2 -2
  108. data/stubs/inertia-react-ts/vite.config.ts +2 -5
  109. data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +10 -6
  110. data/stubs/inertia-vue-ts/app/javascript/Components/Checkbox.vue +18 -18
  111. data/stubs/inertia-vue-ts/app/javascript/Components/DangerButton.vue +5 -5
  112. data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +60 -57
  113. data/stubs/inertia-vue-ts/app/javascript/Components/DropdownLink.vue +9 -9
  114. data/stubs/inertia-vue-ts/app/javascript/Components/InputError.vue +7 -7
  115. data/stubs/inertia-vue-ts/app/javascript/Components/InputLabel.vue +6 -6
  116. data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +84 -74
  117. data/stubs/inertia-vue-ts/app/javascript/Components/NavLink.vue +12 -12
  118. data/stubs/inertia-vue-ts/app/javascript/Components/PrimaryButton.vue +5 -5
  119. data/stubs/inertia-vue-ts/app/javascript/Components/ResponsiveNavLink.vue +12 -12
  120. data/stubs/inertia-vue-ts/app/javascript/Components/SecondaryButton.vue +13 -13
  121. data/stubs/inertia-vue-ts/app/javascript/Components/TextInput.vue +13 -13
  122. data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +168 -136
  123. data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +15 -13
  124. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +56 -49
  125. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +78 -72
  126. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +101 -97
  127. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +71 -68
  128. data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +22 -14
  129. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +34 -30
  130. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +87 -83
  131. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +105 -98
  132. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +69 -59
  133. data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +74 -47
  134. data/stubs/inertia-vue-ts/app/views/layouts/application.html.erb +0 -4
  135. data/stubs/inertia-vue-ts/config/tailwind.config.js +2 -2
  136. data/stubs/inertia-vue-ts/vite.config.ts +2 -5
  137. metadata +19 -6
  138. data/stubs/hotwire/bin/vite +0 -27
  139. data/stubs/inertia-common/Procfile.dev +0 -3
  140. /data/stubs/{hotwire → default}/Procfile.dev +0 -0
  141. /data/stubs/hotwire/app/javascript/{alpinejs.js → alpinejs.stub} +0 -0
@@ -1,100 +1,110 @@
1
- import { useRef, useState, FormEventHandler } from 'react';
2
- import DangerButton from '@/Components/DangerButton';
3
- import InputError from '@/Components/InputError';
4
- import InputLabel from '@/Components/InputLabel';
5
- import Modal from '@/Components/Modal';
6
- import SecondaryButton from '@/Components/SecondaryButton';
7
- import TextInput from '@/Components/TextInput';
8
- import { useForm } from '@inertiajs/react';
9
- import { profile_destroy_path } from '@/routes';
10
-
11
- export default function DeleteUserForm({ className = '' }: { className?: string }) {
12
- const [confirmingUserDeletion, setConfirmingUserDeletion] = useState(false);
13
- const passwordInput = useRef<HTMLInputElement>(null);
14
-
15
- const {
16
- data,
17
- setData,
18
- delete: destroy,
19
- processing,
20
- reset,
21
- errors,
22
- } = useForm({
23
- password: '',
24
- });
25
-
26
- const confirmUserDeletion = () => {
27
- setConfirmingUserDeletion(true);
28
- };
29
-
30
- const deleteUser: FormEventHandler = (e) => {
31
- e.preventDefault();
32
-
33
- destroy(profile_destroy_path(), {
34
- preserveScroll: true,
35
- onSuccess: () => closeModal(),
36
- onError: () => passwordInput.current?.focus(),
37
- onFinish: () => reset(),
38
- });
39
- };
40
-
41
- const closeModal = () => {
42
- setConfirmingUserDeletion(false);
43
-
44
- reset();
45
- };
46
-
47
- return (
48
- <section className={`space-y-6 ${className}`}>
49
- <header>
50
- <h2 className="text-lg font-medium text-gray-900">Delete Account</h2>
51
-
52
- <p className="mt-1 text-sm text-gray-600">
53
- Once your account is deleted, all of its resources and data will be permanently deleted. Before
54
- deleting your account, please download any data or information that you wish to retain.
55
- </p>
56
- </header>
57
-
58
- <DangerButton onClick={confirmUserDeletion}>Delete Account</DangerButton>
59
-
60
- <Modal show={confirmingUserDeletion} onClose={closeModal}>
61
- <form onSubmit={deleteUser} className="p-6">
62
- <h2 className="text-lg font-medium text-gray-900">
63
- Are you sure you want to delete your account?
64
- </h2>
65
-
66
- <p className="mt-1 text-sm text-gray-600">
67
- Once your account is deleted, all of its resources and data will be permanently deleted. Please
68
- enter your password to confirm you would like to permanently delete your account.
69
- </p>
70
-
71
- <div className="mt-6">
72
- <InputLabel htmlFor="password" value="Password" className="sr-only" />
73
-
74
- <TextInput
75
- id="password"
76
- type="password"
77
- name="password"
78
- ref={passwordInput}
79
- value={data.password}
80
- onChange={(e) => setData('password', e.target.value)}
81
- className="mt-1 block w-3/4"
82
- isFocused
83
- placeholder="Password"
84
- />
85
-
86
- <InputError message={errors.password} className="mt-2" />
87
- </div>
88
-
89
- <div className="mt-6 flex justify-end">
90
- <SecondaryButton onClick={closeModal}>Cancel</SecondaryButton>
91
-
92
- <DangerButton className="ms-3" disabled={processing}>
93
- Delete Account
94
- </DangerButton>
95
- </div>
96
- </form>
97
- </Modal>
98
- </section>
99
- );
1
+ import { useRef, useState, FormEventHandler } from 'react'
2
+ import DangerButton from '@/Components/DangerButton'
3
+ import InputError from '@/Components/InputError'
4
+ import InputLabel from '@/Components/InputLabel'
5
+ import Modal from '@/Components/Modal'
6
+ import SecondaryButton from '@/Components/SecondaryButton'
7
+ import TextInput from '@/Components/TextInput'
8
+ import { useForm } from '@inertiajs/react'
9
+ import { profile_destroy_path } from '@/routes'
10
+
11
+ export default function DeleteUserForm({
12
+ className = '',
13
+ }: {
14
+ className?: string
15
+ }) {
16
+ const [confirmingUserDeletion, setConfirmingUserDeletion] = useState(false)
17
+ const passwordInput = useRef<HTMLInputElement>(null)
18
+
19
+ const {
20
+ data,
21
+ setData,
22
+ delete: destroy,
23
+ processing,
24
+ reset,
25
+ errors,
26
+ } = useForm({
27
+ password: '',
28
+ })
29
+
30
+ const confirmUserDeletion = () => {
31
+ setConfirmingUserDeletion(true)
32
+ }
33
+
34
+ const deleteUser: FormEventHandler = (e) => {
35
+ e.preventDefault()
36
+
37
+ destroy(profile_destroy_path(), {
38
+ preserveScroll: true,
39
+ onSuccess: () => closeModal(),
40
+ onError: () => passwordInput.current?.focus(),
41
+ onFinish: () => reset(),
42
+ })
43
+ }
44
+
45
+ const closeModal = () => {
46
+ setConfirmingUserDeletion(false)
47
+
48
+ reset()
49
+ }
50
+
51
+ return (
52
+ <section className={`space-y-6 ${className}`}>
53
+ <header>
54
+ <h2 className="text-lg font-medium text-gray-900">Delete Account</h2>
55
+
56
+ <p className="mt-1 text-sm text-gray-600">
57
+ Once your account is deleted, all of its resources and data will be
58
+ permanently deleted. Before deleting your account, please download any
59
+ data or information that you wish to retain.
60
+ </p>
61
+ </header>
62
+
63
+ <DangerButton onClick={confirmUserDeletion}>Delete Account</DangerButton>
64
+
65
+ <Modal show={confirmingUserDeletion} onClose={closeModal}>
66
+ <form onSubmit={deleteUser} className="p-6">
67
+ <h2 className="text-lg font-medium text-gray-900">
68
+ Are you sure you want to delete your account?
69
+ </h2>
70
+
71
+ <p className="mt-1 text-sm text-gray-600">
72
+ Once your account is deleted, all of its resources and data will be
73
+ permanently deleted. Please enter your password to confirm you would
74
+ like to permanently delete your account.
75
+ </p>
76
+
77
+ <div className="mt-6">
78
+ <InputLabel
79
+ htmlFor="password"
80
+ value="Password"
81
+ className="sr-only"
82
+ />
83
+
84
+ <TextInput
85
+ id="password"
86
+ type="password"
87
+ name="password"
88
+ ref={passwordInput}
89
+ value={data.password}
90
+ onChange={(e) => setData('password', e.target.value)}
91
+ className="mt-1 block w-3/4"
92
+ isFocused
93
+ placeholder="Password"
94
+ />
95
+
96
+ <InputError message={errors.password} className="mt-2" />
97
+ </div>
98
+
99
+ <div className="mt-6 flex justify-end">
100
+ <SecondaryButton onClick={closeModal}>Cancel</SecondaryButton>
101
+
102
+ <DangerButton className="ms-3" disabled={processing}>
103
+ Delete Account
104
+ </DangerButton>
105
+ </div>
106
+ </form>
107
+ </Modal>
108
+ </section>
109
+ )
100
110
  }
@@ -1,114 +1,122 @@
1
- import { useRef, FormEventHandler } from 'react';
2
- import InputError from '@/Components/InputError';
3
- import InputLabel from '@/Components/InputLabel';
4
- import PrimaryButton from '@/Components/PrimaryButton';
5
- import TextInput from '@/Components/TextInput';
6
- import { useForm } from '@inertiajs/react';
7
- import { Transition } from '@headlessui/react';
8
- import { password_update_path } from '@/routes';
9
-
10
- export default function UpdatePasswordForm({ className = '' }: { className?: string }) {
11
- const passwordInput = useRef<HTMLInputElement>(null);
12
- const currentPasswordInput = useRef<HTMLInputElement>(null);
13
-
14
- const { data, setData, errors, put, reset, processing, recentlySuccessful } = useForm({
15
- current_password: '',
16
- password: '',
17
- password_confirmation: '',
18
- });
19
-
20
- const updatePassword: FormEventHandler = (e) => {
21
- e.preventDefault();
22
-
23
- put(password_update_path(), {
24
- preserveScroll: true,
25
- onSuccess: () => reset(),
26
- onError: (errors) => {
27
- if (errors.password) {
28
- reset('password', 'password_confirmation');
29
- passwordInput.current?.focus();
30
- }
31
-
32
- if (errors.current_password) {
33
- reset('current_password');
34
- currentPasswordInput.current?.focus();
35
- }
36
- },
37
- });
38
- };
39
-
40
- return (
41
- <section className={className}>
42
- <header>
43
- <h2 className="text-lg font-medium text-gray-900">Update Password</h2>
44
-
45
- <p className="mt-1 text-sm text-gray-600">
46
- Ensure your account is using a long, random password to stay secure.
47
- </p>
48
- </header>
49
-
50
- <form onSubmit={updatePassword} className="mt-6 space-y-6">
51
- <div>
52
- <InputLabel htmlFor="current_password" value="Current Password" />
53
-
54
- <TextInput
55
- id="current_password"
56
- ref={currentPasswordInput}
57
- value={data.current_password}
58
- onChange={(e) => setData('current_password', e.target.value)}
59
- type="password"
60
- className="mt-1 block w-full"
61
- autoComplete="current-password"
62
- />
63
-
64
- <InputError message={errors.current_password} className="mt-2" />
65
- </div>
66
-
67
- <div>
68
- <InputLabel htmlFor="password" value="New Password" />
69
-
70
- <TextInput
71
- id="password"
72
- ref={passwordInput}
73
- value={data.password}
74
- onChange={(e) => setData('password', e.target.value)}
75
- type="password"
76
- className="mt-1 block w-full"
77
- autoComplete="new-password"
78
- />
79
-
80
- <InputError message={errors.password} className="mt-2" />
81
- </div>
82
-
83
- <div>
84
- <InputLabel htmlFor="password_confirmation" value="Confirm Password" />
85
-
86
- <TextInput
87
- id="password_confirmation"
88
- value={data.password_confirmation}
89
- onChange={(e) => setData('password_confirmation', e.target.value)}
90
- type="password"
91
- className="mt-1 block w-full"
92
- autoComplete="new-password"
93
- />
94
-
95
- <InputError message={errors.password_confirmation} className="mt-2" />
96
- </div>
97
-
98
- <div className="flex items-center gap-4">
99
- <PrimaryButton disabled={processing}>Save</PrimaryButton>
100
-
101
- <Transition
102
- show={recentlySuccessful}
103
- enter="transition ease-in-out"
104
- enterFrom="opacity-0"
105
- leave="transition ease-in-out"
106
- leaveTo="opacity-0"
107
- >
108
- <p className="text-sm text-gray-600">Saved.</p>
109
- </Transition>
110
- </div>
111
- </form>
112
- </section>
113
- );
1
+ import { useRef, FormEventHandler } from 'react'
2
+ import InputError from '@/Components/InputError'
3
+ import InputLabel from '@/Components/InputLabel'
4
+ import PrimaryButton from '@/Components/PrimaryButton'
5
+ import TextInput from '@/Components/TextInput'
6
+ import { useForm } from '@inertiajs/react'
7
+ import { Transition } from '@headlessui/react'
8
+ import { password_update_path } from '@/routes'
9
+
10
+ export default function UpdatePasswordForm({
11
+ className = '',
12
+ }: {
13
+ className?: string
14
+ }) {
15
+ const passwordInput = useRef<HTMLInputElement>(null)
16
+ const currentPasswordInput = useRef<HTMLInputElement>(null)
17
+
18
+ const { data, setData, errors, put, reset, processing, recentlySuccessful } =
19
+ useForm({
20
+ current_password: '',
21
+ password: '',
22
+ password_confirmation: '',
23
+ })
24
+
25
+ const updatePassword: FormEventHandler = (e) => {
26
+ e.preventDefault()
27
+
28
+ put(password_update_path(), {
29
+ preserveScroll: true,
30
+ onSuccess: () => reset(),
31
+ onError: (errors) => {
32
+ if (errors.password) {
33
+ reset('password', 'password_confirmation')
34
+ passwordInput.current?.focus()
35
+ }
36
+
37
+ if (errors.current_password) {
38
+ reset('current_password')
39
+ currentPasswordInput.current?.focus()
40
+ }
41
+ },
42
+ })
43
+ }
44
+
45
+ return (
46
+ <section className={className}>
47
+ <header>
48
+ <h2 className="text-lg font-medium text-gray-900">Update Password</h2>
49
+
50
+ <p className="mt-1 text-sm text-gray-600">
51
+ Ensure your account is using a long, random password to stay secure.
52
+ </p>
53
+ </header>
54
+
55
+ <form onSubmit={updatePassword} className="mt-6 space-y-6">
56
+ <div>
57
+ <InputLabel htmlFor="current_password" value="Current Password" />
58
+
59
+ <TextInput
60
+ id="current_password"
61
+ ref={currentPasswordInput}
62
+ value={data.current_password}
63
+ onChange={(e) => setData('current_password', e.target.value)}
64
+ type="password"
65
+ className="mt-1 block w-full"
66
+ autoComplete="current-password"
67
+ />
68
+
69
+ <InputError message={errors.current_password} className="mt-2" />
70
+ </div>
71
+
72
+ <div>
73
+ <InputLabel htmlFor="password" value="New Password" />
74
+
75
+ <TextInput
76
+ id="password"
77
+ ref={passwordInput}
78
+ value={data.password}
79
+ onChange={(e) => setData('password', e.target.value)}
80
+ type="password"
81
+ className="mt-1 block w-full"
82
+ autoComplete="new-password"
83
+ />
84
+
85
+ <InputError message={errors.password} className="mt-2" />
86
+ </div>
87
+
88
+ <div>
89
+ <InputLabel
90
+ htmlFor="password_confirmation"
91
+ value="Confirm Password"
92
+ />
93
+
94
+ <TextInput
95
+ id="password_confirmation"
96
+ value={data.password_confirmation}
97
+ onChange={(e) => setData('password_confirmation', e.target.value)}
98
+ type="password"
99
+ className="mt-1 block w-full"
100
+ autoComplete="new-password"
101
+ />
102
+
103
+ <InputError message={errors.password_confirmation} className="mt-2" />
104
+ </div>
105
+
106
+ <div className="flex items-center gap-4">
107
+ <PrimaryButton disabled={processing}>Save</PrimaryButton>
108
+
109
+ <Transition
110
+ show={recentlySuccessful}
111
+ enter="transition ease-in-out"
112
+ enterFrom="opacity-0"
113
+ leave="transition ease-in-out"
114
+ leaveTo="opacity-0"
115
+ >
116
+ <p className="text-sm text-gray-600">Saved.</p>
117
+ </Transition>
118
+ </div>
119
+ </form>
120
+ </section>
121
+ )
114
122
  }
@@ -1,84 +1,91 @@
1
- import InputError from '@/Components/InputError';
2
- import InputLabel from '@/Components/InputLabel';
3
- import PrimaryButton from '@/Components/PrimaryButton';
4
- import TextInput from '@/Components/TextInput';
5
- import { useForm, usePage } from '@inertiajs/react';
6
- import { Transition } from '@headlessui/react';
7
- import { FormEventHandler } from 'react';
8
- import { PageProps } from '@/types';
9
- import { profile_update_path } from '@/routes';
1
+ import InputError from '@/Components/InputError'
2
+ import InputLabel from '@/Components/InputLabel'
3
+ import PrimaryButton from '@/Components/PrimaryButton'
4
+ import TextInput from '@/Components/TextInput'
5
+ import { useForm, usePage } from '@inertiajs/react'
6
+ import { Transition } from '@headlessui/react'
7
+ import { FormEventHandler } from 'react'
8
+ import { PageProps } from '@/types'
9
+ import { profile_update_path } from '@/routes'
10
10
 
11
- export default function UpdateProfileInformation({ className = '' }: { className?: string }) {
12
- const user = usePage<PageProps>().props.auth.user;
11
+ export default function UpdateProfileInformation({
12
+ className = '',
13
+ }: {
14
+ className?: string
15
+ }) {
16
+ const user = usePage<PageProps>().props.auth.user
13
17
 
14
- const { data, setData, patch, errors, processing, recentlySuccessful } = useForm({
15
- name: user.name,
16
- email: user.email,
17
- });
18
+ const { data, setData, patch, errors, processing, recentlySuccessful } =
19
+ useForm({
20
+ name: user.name,
21
+ email: user.email,
22
+ })
18
23
 
19
- const submit: FormEventHandler = (e) => {
20
- e.preventDefault();
24
+ const submit: FormEventHandler = (e) => {
25
+ e.preventDefault()
21
26
 
22
- patch(profile_update_path());
23
- };
27
+ patch(profile_update_path())
28
+ }
24
29
 
25
- return (
26
- <section className={className}>
27
- <header>
28
- <h2 className="text-lg font-medium text-gray-900">Profile Information</h2>
30
+ return (
31
+ <section className={className}>
32
+ <header>
33
+ <h2 className="text-lg font-medium text-gray-900">
34
+ Profile Information
35
+ </h2>
29
36
 
30
- <p className="mt-1 text-sm text-gray-600">
31
- Update your account's profile information and email address.
32
- </p>
33
- </header>
37
+ <p className="mt-1 text-sm text-gray-600">
38
+ Update your account's profile information and email address.
39
+ </p>
40
+ </header>
34
41
 
35
- <form onSubmit={submit} className="mt-6 space-y-6">
36
- <div>
37
- <InputLabel htmlFor="name" value="Name" />
42
+ <form onSubmit={submit} className="mt-6 space-y-6">
43
+ <div>
44
+ <InputLabel htmlFor="name" value="Name" />
38
45
 
39
- <TextInput
40
- id="name"
41
- className="mt-1 block w-full"
42
- value={data.name}
43
- onChange={(e) => setData('name', e.target.value)}
44
- required
45
- isFocused
46
- autoComplete="name"
47
- />
46
+ <TextInput
47
+ id="name"
48
+ className="mt-1 block w-full"
49
+ value={data.name}
50
+ onChange={(e) => setData('name', e.target.value)}
51
+ required
52
+ isFocused
53
+ autoComplete="name"
54
+ />
48
55
 
49
- <InputError className="mt-2" message={errors.name} />
50
- </div>
56
+ <InputError className="mt-2" message={errors.name} />
57
+ </div>
51
58
 
52
- <div>
53
- <InputLabel htmlFor="email" value="Email" />
59
+ <div>
60
+ <InputLabel htmlFor="email" value="Email" />
54
61
 
55
- <TextInput
56
- id="email"
57
- type="email"
58
- className="mt-1 block w-full"
59
- value={data.email}
60
- onChange={(e) => setData('email', e.target.value)}
61
- required
62
- autoComplete="username"
63
- />
62
+ <TextInput
63
+ id="email"
64
+ type="email"
65
+ className="mt-1 block w-full"
66
+ value={data.email}
67
+ onChange={(e) => setData('email', e.target.value)}
68
+ required
69
+ autoComplete="username"
70
+ />
64
71
 
65
- <InputError className="mt-2" message={errors.email} />
66
- </div>
72
+ <InputError className="mt-2" message={errors.email} />
73
+ </div>
67
74
 
68
- <div className="flex items-center gap-4">
69
- <PrimaryButton disabled={processing}>Save</PrimaryButton>
75
+ <div className="flex items-center gap-4">
76
+ <PrimaryButton disabled={processing}>Save</PrimaryButton>
70
77
 
71
- <Transition
72
- show={recentlySuccessful}
73
- enter="transition ease-in-out"
74
- enterFrom="opacity-0"
75
- leave="transition ease-in-out"
76
- leaveTo="opacity-0"
77
- >
78
- <p className="text-sm text-gray-600">Saved.</p>
79
- </Transition>
80
- </div>
81
- </form>
82
- </section>
83
- );
78
+ <Transition
79
+ show={recentlySuccessful}
80
+ enter="transition ease-in-out"
81
+ enterFrom="opacity-0"
82
+ leave="transition ease-in-out"
83
+ leaveTo="opacity-0"
84
+ >
85
+ <p className="text-sm text-gray-600">Saved.</p>
86
+ </Transition>
87
+ </div>
88
+ </form>
89
+ </section>
90
+ )
84
91
  }