
All checks were successful
Publish Docker Image / Publish Docker Image (push) Successful in 26s
120 lines
3.2 KiB
TypeScript
120 lines
3.2 KiB
TypeScript
import { useEffect, useRef, useState } from 'react'
|
|
|
|
import { mdiKey } from '@mdi/js'
|
|
import Icon from '@mdi/react'
|
|
|
|
import {
|
|
Form,
|
|
Label,
|
|
PasswordField,
|
|
Submit,
|
|
FieldError,
|
|
} from '@redwoodjs/forms'
|
|
import { navigate, routes } from '@redwoodjs/router'
|
|
import { Metadata } from '@redwoodjs/web'
|
|
import { toast } from '@redwoodjs/web/toast'
|
|
|
|
import { useAuth } from 'src/auth'
|
|
|
|
const ResetPasswordPage = ({ resetToken }: { resetToken: string }) => {
|
|
const { isAuthenticated, reauthenticate, validateResetToken, resetPassword } =
|
|
useAuth()
|
|
const [enabled, setEnabled] = useState(true)
|
|
|
|
useEffect(() => {
|
|
if (isAuthenticated) navigate(routes.home())
|
|
}, [isAuthenticated])
|
|
|
|
useEffect(() => {
|
|
const validateToken = async () => {
|
|
const response = await validateResetToken(resetToken)
|
|
if (response.error) {
|
|
setEnabled(false)
|
|
toast.error(response.error)
|
|
} else {
|
|
setEnabled(true)
|
|
}
|
|
}
|
|
validateToken()
|
|
}, [resetToken, validateResetToken])
|
|
|
|
const passwordRef = useRef<HTMLInputElement>(null)
|
|
useEffect(() => {
|
|
passwordRef.current?.focus()
|
|
}, [])
|
|
|
|
const onSubmit = async (data: Record<string, string>) => {
|
|
const response = await resetPassword({
|
|
resetToken,
|
|
password: data.password,
|
|
})
|
|
|
|
if (response.error) {
|
|
toast.error(response.error)
|
|
} else {
|
|
toast.success('Password changed!')
|
|
await reauthenticate()
|
|
navigate(routes.login())
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<Metadata title="Reset Password" />
|
|
|
|
<div className="mx-auto my-32 flex w-fit flex-wrap items-center justify-center rounded-xl bg-base-100 p-2">
|
|
<Form onSubmit={onSubmit} className="space-y-2">
|
|
<Label
|
|
name="password"
|
|
className={`${
|
|
!enabled ? 'input-disabled' : ''
|
|
} input input-bordered flex items-center gap-2`}
|
|
errorClassName={`${
|
|
!enabled ? 'input-disabled' : ''
|
|
} input input-bordered flex items-center gap-2 input-error`}
|
|
>
|
|
<Label
|
|
name="password"
|
|
className="size-4 opacity-70"
|
|
errorClassName="size-4 text-error"
|
|
>
|
|
<Icon path={mdiKey} />
|
|
</Label>
|
|
<PasswordField
|
|
name="password"
|
|
className="grow"
|
|
placeholder="New Password"
|
|
ref={passwordRef}
|
|
disabled={!enabled}
|
|
validation={{
|
|
required: {
|
|
value: true,
|
|
message: 'Required',
|
|
},
|
|
minLength: {
|
|
value: 8,
|
|
message: 'Must be 8 or more characters',
|
|
},
|
|
}}
|
|
/>
|
|
</Label>
|
|
<FieldError name="password" className="text-sm text-error" />
|
|
|
|
<div className="flex w-full">
|
|
<Submit
|
|
className={`btn btn-primary btn-sm uppercase mx-auto ${
|
|
!enabled ? 'btn-disabled' : ''
|
|
}`}
|
|
disabled={!enabled}
|
|
>
|
|
Submit
|
|
</Submit>
|
|
</div>
|
|
</Form>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default ResetPasswordPage
|