import { zodResolver } from "@hookform/resolvers/zod"
import { Alert, Button, Heading, Input, Text, toast } from "@medusajs/ui"
import { useForm } from "react-hook-form"
import { Trans, useTranslation } from "react-i18next"
import { Link, useNavigate, useSearchParams } from "react-router-dom"
import * as z from "zod"
import { useState } from "react"
import { decodeToken } from "react-jwt"
import { Form } from "../../components/common/form"
import { LogoBox } from "../../components/common/logo-box"
import { i18n } from "../../components/utilities/i18n"
import {
useResetPasswordForEmailPass,
useUpdateProviderForEmailPass,
} from "../../hooks/api/auth"
const ResetPasswordInstructionsSchema = z.object({
email: z.string().email(),
})
const ResetPasswordSchema = z
.object({
password: z.string().min(1),
repeat_password: z.string().min(1),
})
.superRefine(({ password, repeat_password }, ctx) => {
if (password !== repeat_password) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: i18n.t("resetPassword.passwordMismatch"),
path: ["repeat_password"],
})
}
})
const ResetPasswordTokenSchema = z.object({
entity_id: z.string(),
provider: z.string(),
exp: z.number(),
iat: z.number(),
})
type DecodedResetPasswordToken = {
entity_id: string // -> email in here
provider: string
exp: string
iat: string
}
const validateDecodedResetPasswordToken = (
decoded: any
): decoded is DecodedResetPasswordToken => {
return ResetPasswordTokenSchema.safeParse(decoded).success
}
const InvalidResetToken = () => {
const { t } = useTranslation()
const navigate = useNavigate()
return (
{t("resetPassword.invalidLinkTitle")}
{t("resetPassword.invalidLinkHint")}
,
]}
/>
)
}
const ChooseNewPassword = ({ token }: { token: string }) => {
const { t } = useTranslation()
const [showAlert, setShowAlert] = useState(false)
const invite: DecodedResetPasswordToken | null = token
? decodeToken(token)
: null
const isValidResetPasswordToken =
invite && validateDecodedResetPasswordToken(invite)
const form = useForm>({
resolver: zodResolver(ResetPasswordSchema),
defaultValues: {
password: "",
repeat_password: "",
},
})
const { mutateAsync, isPending } = useUpdateProviderForEmailPass(token)
const handleSubmit = form.handleSubmit(async ({ password }) => {
if (!invite) {
return
}
await mutateAsync(
{
password,
},
{
onSuccess: () => {
form.setValue("password", "")
form.setValue("repeat_password", "")
setShowAlert(true)
},
onError: (error) => {
toast.error(error.message)
},
}
)
})
if (!isValidResetPasswordToken) {
return
}
return (
{t("resetPassword.resetPassword")}
{t("resetPassword.newPasswordHint")}
,
]}
/>
)
}
export const ResetPassword = () => {
const { t } = useTranslation()
const [searchParams] = useSearchParams()
const [showAlert, setShowAlert] = useState(false)
const token = searchParams.get("token")
const form = useForm>({
resolver: zodResolver(ResetPasswordInstructionsSchema),
defaultValues: {
email: "",
},
})
const { mutateAsync, isPending } = useResetPasswordForEmailPass()
const handleSubmit = form.handleSubmit(async ({ email }) => {
await mutateAsync(
{
email,
},
{
onSuccess: () => {
form.setValue("email", "")
setShowAlert(true)
},
onError: (error) => {
toast.error(error.message)
},
}
)
})
if (token) {
return
}
return (
{t("resetPassword.resetPassword")}
{t("resetPassword.hint")}
,
]}
/>
)
}