You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
4.2 KiB

  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. export default function UpdatePasswordForm({ className = '' }: { className?: string }) {
  9. const passwordInput = useRef<HTMLInputElement>(null);
  10. const currentPasswordInput = useRef<HTMLInputElement>(null);
  11. const { data, setData, errors, put, reset, processing, recentlySuccessful } = useForm({
  12. current_password: '',
  13. password: '',
  14. password_confirmation: '',
  15. });
  16. const updatePassword: FormEventHandler = (e) => {
  17. e.preventDefault();
  18. put(route('password.update'), {
  19. preserveScroll: true,
  20. onSuccess: () => reset(),
  21. onError: (errors) => {
  22. if (errors.password) {
  23. reset('password', 'password_confirmation');
  24. passwordInput.current?.focus();
  25. }
  26. if (errors.current_password) {
  27. reset('current_password');
  28. currentPasswordInput.current?.focus();
  29. }
  30. },
  31. });
  32. };
  33. return (
  34. <section className={className}>
  35. <header>
  36. <h2 className="text-lg font-medium text-gray-900">Update Password</h2>
  37. <p className="mt-1 text-sm text-gray-600">
  38. Ensure your account is using a long, random password to stay secure.
  39. </p>
  40. </header>
  41. <form onSubmit={updatePassword} className="mt-6 space-y-6">
  42. <div>
  43. <InputLabel htmlFor="current_password" value="Current Password" />
  44. <TextInput
  45. id="current_password"
  46. ref={currentPasswordInput}
  47. value={data.current_password}
  48. onChange={(e) => setData('current_password', e.target.value)}
  49. type="password"
  50. className="mt-1 block w-full"
  51. autoComplete="current-password"
  52. />
  53. <InputError message={errors.current_password} className="mt-2" />
  54. </div>
  55. <div>
  56. <InputLabel htmlFor="password" value="New Password" />
  57. <TextInput
  58. id="password"
  59. ref={passwordInput}
  60. value={data.password}
  61. onChange={(e) => setData('password', e.target.value)}
  62. type="password"
  63. className="mt-1 block w-full"
  64. autoComplete="new-password"
  65. />
  66. <InputError message={errors.password} className="mt-2" />
  67. </div>
  68. <div>
  69. <InputLabel htmlFor="password_confirmation" value="Confirm Password" />
  70. <TextInput
  71. id="password_confirmation"
  72. value={data.password_confirmation}
  73. onChange={(e) => setData('password_confirmation', e.target.value)}
  74. type="password"
  75. className="mt-1 block w-full"
  76. autoComplete="new-password"
  77. />
  78. <InputError message={errors.password_confirmation} className="mt-2" />
  79. </div>
  80. <div className="flex items-center gap-4">
  81. <PrimaryButton disabled={processing}>Save</PrimaryButton>
  82. <Transition
  83. show={recentlySuccessful}
  84. enter="transition ease-in-out"
  85. enterFrom="opacity-0"
  86. leave="transition ease-in-out"
  87. leaveTo="opacity-0"
  88. >
  89. <p className="text-sm text-gray-600">Saved.</p>
  90. </Transition>
  91. </div>
  92. </form>
  93. </section>
  94. );
  95. }