kaze 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/kaze/commands/install_command.rb +8 -0
- data/lib/kaze/commands/installs_hotwire_stack.rb +5 -2
- data/lib/kaze/commands/installs_inertia_stacks.rb +13 -3
- data/lib/kaze/version.rb +1 -1
- data/stubs/default/app/forms/auth/login_form.rb +2 -8
- data/stubs/default/app/forms/update_profile_information_form.rb +1 -1
- data/stubs/default/app/models/auth.rb +57 -0
- data/stubs/default/app/models/current.rb +1 -1
- data/stubs/default/app/validators/current_password_validator.rb +1 -1
- data/stubs/default/app/views/layouts/mailer.html.erb +367 -372
- data/stubs/default/app/views/layouts/mailer.text.erb +1 -4
- data/stubs/default/app/views/user_mailer/reset_password.html.erb +21 -26
- data/stubs/default/test/factories/users.rb +7 -0
- data/stubs/default/test/integration/auth/authentication_test.rb +43 -0
- data/stubs/default/test/integration/auth/password_reset_test.rb +41 -0
- data/stubs/default/test/integration/auth/registration_test.rb +21 -0
- data/stubs/default/test/integration/password_update_test.rb +28 -0
- data/stubs/default/test/integration/profile_test.rb +51 -0
- data/stubs/default/test/test_helper.rb +38 -0
- data/stubs/hotwire/app/components/dropdown_component.html.erb +17 -18
- data/stubs/hotwire/app/components/modal_component.html.erb +55 -59
- data/stubs/hotwire/app/controllers/application_controller.rb +1 -0
- data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +10 -7
- data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +3 -1
- data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +3 -1
- data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +4 -2
- data/stubs/hotwire/app/controllers/concerns/authenticate.rb +5 -20
- data/stubs/hotwire/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
- data/stubs/hotwire/app/controllers/concerns/set_current_auth.rb +9 -0
- data/stubs/hotwire/app/controllers/password_controller.rb +1 -1
- data/stubs/hotwire/app/controllers/profile_controller.rb +6 -4
- data/stubs/hotwire/app/controllers/welcome_controller.rb +1 -1
- data/stubs/hotwire/app/javascript/application.js +3 -3
- data/stubs/hotwire/app/views/auth/forgot_password.html.erb +12 -17
- data/stubs/hotwire/app/views/auth/login.html.erb +0 -9
- data/stubs/hotwire/app/views/auth/register.html.erb +0 -13
- data/stubs/hotwire/app/views/auth/reset_password.html.erb +0 -7
- data/stubs/hotwire/app/views/dashboard/index.html.erb +9 -10
- data/stubs/hotwire/app/views/layouts/_navigation.html.erb +77 -87
- data/stubs/hotwire/app/views/layouts/application.html.erb +0 -9
- data/stubs/hotwire/app/views/layouts/guest.html.erb +0 -6
- data/stubs/hotwire/app/views/profile/edit.html.erb +19 -22
- data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +32 -42
- data/stubs/hotwire/app/views/profile/partials/_update_password_form.html.erb +42 -55
- data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +36 -46
- data/stubs/hotwire/app/views/welcome/index.html.erb +34 -46
- data/stubs/hotwire/config/tailwind.config.js +2 -2
- data/stubs/inertia-common/app/controllers/application_controller.rb +1 -0
- data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +10 -7
- data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +3 -1
- data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +3 -1
- data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +4 -2
- data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +5 -20
- data/stubs/inertia-common/app/controllers/concerns/handle_inertia_requests.rb +1 -1
- data/stubs/inertia-common/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
- data/stubs/inertia-common/app/controllers/concerns/set_current_auth.rb +9 -0
- data/stubs/inertia-common/app/controllers/password_controller.rb +1 -1
- data/stubs/inertia-common/app/controllers/profile_controller.rb +5 -3
- data/stubs/inertia-common/app/controllers/welcome_controller.rb +1 -1
- data/stubs/inertia-common/test/integration/password_update_test.rb +28 -0
- data/stubs/inertia-common/test/integration/profile_test.rb +51 -0
- data/stubs/inertia-react-ts/app/javascript/Components/ApplicationLogo.tsx +13 -9
- data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +15 -12
- data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +20 -15
- data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +119 -87
- data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +14 -7
- data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +18 -7
- data/stubs/inertia-react-ts/app/javascript/Components/Modal.tsx +60 -60
- data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +21 -16
- data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +20 -15
- data/stubs/inertia-react-ts/app/javascript/Components/ResponsiveNavLink.tsx +19 -14
- data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +22 -16
- data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +35 -24
- data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +157 -117
- data/stubs/inertia-react-ts/app/javascript/Layouts/GuestLayout.tsx +15 -15
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +52 -49
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +90 -82
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +118 -115
- data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +63 -60
- data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +23 -17
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +31 -27
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +109 -99
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +121 -113
- data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +76 -69
- data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +87 -63
- data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +32 -25
- data/stubs/inertia-react-ts/app/views/layouts/application.html.erb +0 -4
- data/stubs/inertia-react-ts/config/tailwind.config.js +2 -2
- data/stubs/inertia-react-ts/vite.config.ts +2 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +10 -6
- data/stubs/inertia-vue-ts/app/javascript/Components/Checkbox.vue +18 -18
- data/stubs/inertia-vue-ts/app/javascript/Components/DangerButton.vue +5 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +60 -57
- data/stubs/inertia-vue-ts/app/javascript/Components/DropdownLink.vue +9 -9
- data/stubs/inertia-vue-ts/app/javascript/Components/InputError.vue +7 -7
- data/stubs/inertia-vue-ts/app/javascript/Components/InputLabel.vue +6 -6
- data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +84 -74
- data/stubs/inertia-vue-ts/app/javascript/Components/NavLink.vue +12 -12
- data/stubs/inertia-vue-ts/app/javascript/Components/PrimaryButton.vue +5 -5
- data/stubs/inertia-vue-ts/app/javascript/Components/ResponsiveNavLink.vue +12 -12
- data/stubs/inertia-vue-ts/app/javascript/Components/SecondaryButton.vue +13 -13
- data/stubs/inertia-vue-ts/app/javascript/Components/TextInput.vue +13 -13
- data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +168 -136
- data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +15 -13
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +56 -49
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +78 -72
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +101 -97
- data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +71 -68
- data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +22 -14
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +34 -30
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +87 -83
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +105 -98
- data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +69 -59
- data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +74 -47
- data/stubs/inertia-vue-ts/app/views/layouts/application.html.erb +0 -4
- data/stubs/inertia-vue-ts/config/tailwind.config.js +2 -2
- data/stubs/inertia-vue-ts/vite.config.ts +2 -5
- metadata +18 -6
- data/stubs/hotwire/bin/vite +0 -27
- data/stubs/inertia-common/Procfile.dev +0 -3
- /data/stubs/{hotwire → default}/Procfile.dev +0 -0
- /data/stubs/hotwire/app/javascript/{alpinejs.js → alpinejs.stub} +0 -0
@@ -1,33 +1,37 @@
|
|
1
|
-
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
|
2
|
-
import DeleteUserForm from './Partials/DeleteUserForm'
|
3
|
-
import UpdatePasswordForm from './Partials/UpdatePasswordForm'
|
4
|
-
import UpdateProfileInformationForm from './Partials/UpdateProfileInformationForm'
|
5
|
-
import { Head } from '@inertiajs/react'
|
6
|
-
import { PageProps } from '@/types'
|
1
|
+
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'
|
2
|
+
import DeleteUserForm from './Partials/DeleteUserForm'
|
3
|
+
import UpdatePasswordForm from './Partials/UpdatePasswordForm'
|
4
|
+
import UpdateProfileInformationForm from './Partials/UpdateProfileInformationForm'
|
5
|
+
import { Head } from '@inertiajs/react'
|
6
|
+
import { PageProps } from '@/types'
|
7
7
|
|
8
8
|
export default function Edit({ auth }: PageProps) {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
>
|
14
|
-
|
9
|
+
return (
|
10
|
+
<AuthenticatedLayout
|
11
|
+
user={auth.user}
|
12
|
+
header={
|
13
|
+
<h2 className="font-semibold text-xl text-gray-800 leading-tight">
|
14
|
+
Profile
|
15
|
+
</h2>
|
16
|
+
}
|
17
|
+
>
|
18
|
+
<Head title="Profile" />
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
20
|
+
<div className="py-12">
|
21
|
+
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-6">
|
22
|
+
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
23
|
+
<UpdateProfileInformationForm className="max-w-xl" />
|
24
|
+
</div>
|
21
25
|
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
27
|
+
<UpdatePasswordForm className="max-w-xl" />
|
28
|
+
</div>
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
<div className="p-4 sm:p-8 bg-white shadow sm:rounded-lg">
|
31
|
+
<DeleteUserForm className="max-w-xl" />
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
</AuthenticatedLayout>
|
36
|
+
)
|
33
37
|
}
|
@@ -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({
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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({
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
}
|