sozsoft-platform/ui/src/views/auth/ExtendLogin.tsx

144 lines
4.8 KiB
TypeScript
Raw Normal View History

2026-02-24 20:44:16 +00:00
import ActionLink from '@/components/shared/ActionLink'
import Captcha from '@/components/shared/Captcha'
import TenantSelector from '@/components/shared/TenantSelector'
2026-02-24 20:44:16 +00:00
import Alert from '@/components/ui/Alert'
import Button from '@/components/ui/Button'
import { FormContainer, FormItem } from '@/components/ui/Form'
import Input from '@/components/ui/Input'
import { APP_NAME } from '@/constants/app.constant'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { sendExtendLoginRequest } from '@/services/account.service'
import { store } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import useTimeOutMessage from '@/utils/hooks/useTimeOutMessage'
import { TurnstileInstance } from '@marsidev/react-turnstile'
2026-02-24 20:44:16 +00:00
import { Field, Form, Formik } from 'formik'
import { useRef, useState } from 'react'
2026-02-24 20:44:16 +00:00
import { Helmet } from 'react-helmet'
import * as Yup from 'yup'
type ExtendLoginFormSchema = {
email: string
captchaResponse: string
}
const validationSchema = Yup.object().shape({
email: Yup.string().required(),
captchaResponse: Yup.string().required(),
})
const ExtendLogin = () => {
const { userName } = store.getState().auth.user
const disableSubmit = false
const signInUrl = ROUTES_ENUM.authenticated.login
const [emailSent, setEmailSent] = useState(false)
const [message, setMessage] = useTimeOutMessage(10000)
const { translate } = useLocalization()
const captchaRef = useRef<TurnstileInstance>(null)
2026-02-24 20:44:16 +00:00
const onSendMail = async (
values: ExtendLoginFormSchema,
setSubmitting: (isSubmitting: boolean) => void,
setFieldValue: (field: string, value: string) => void,
2026-02-24 20:44:16 +00:00
) => {
const { email, captchaResponse } = values
setSubmitting(true)
try {
await sendExtendLoginRequest({ email, captchaResponse })
setEmailSent(true)
2026-02-24 20:44:16 +00:00
} catch (error: any) {
setMessage(error?.response?.data || error.toString())
} finally {
setFieldValue('captchaResponse', '')
captchaRef.current?.reset()
2026-02-24 20:44:16 +00:00
setSubmitting(false)
}
}
return emailSent ? (
<>
<Helmet
titleTemplate={`%s | ${APP_NAME}`}
title={translate('AbpAccount::' + 'Abp.Account.ExtendLogin')}
defaultTitle={APP_NAME}
></Helmet>
<div>
<h3 className="mb-1">{translate('::Abp.Account.ExtendLogin.Title')}</h3>
<Alert showIcon className="mt-4 mb-4" type="success">
{translate('::Abp.Account.ExtendLogin.Description')}
</Alert>
2026-02-24 20:44:16 +00:00
<div className="mt-4 text-center">
<span>{translate('::Abp.Account.Backto')} </span>
<ActionLink to={signInUrl}>{translate('::Abp.Account.SignIn')}</ActionLink>
</div>
2026-02-24 20:44:16 +00:00
</div>
</>
) : (
<div>
<Helmet
titleTemplate={`%s | ${APP_NAME}`}
title={translate('::' + 'Abp.Account.ExtendLogin')}
defaultTitle={APP_NAME}
></Helmet>
<div className="mb-6">
<h3 className="mb-1">{translate('::Abp.Account.ExtendLogin')}</h3>
</div>
{message && (
<Alert showIcon className="mb-4" type="danger">
{message}
</Alert>
)}
<TenantSelector />
2026-02-24 20:44:16 +00:00
<Formik
initialValues={{
email: userName,
captchaResponse: '',
}}
validationSchema={validationSchema}
onSubmit={(values, { setSubmitting, setFieldValue }) => {
2026-02-24 20:44:16 +00:00
if (!disableSubmit) {
onSendMail(values, setSubmitting, setFieldValue)
2026-02-24 20:44:16 +00:00
} else {
setSubmitting(false)
}
}}
>
{({ touched, errors, isSubmitting, setFieldValue }) => (
<Form>
<FormContainer>
<div className={emailSent ? 'hidden' : ''}>
<FormItem invalid={errors.email && touched.email} errorMessage={errors.email}>
<Field
type="email"
autoComplete="off"
name="email"
placeholder={translate('::Abp.Account.EmailAddress')}
component={Input}
/>
</FormItem>
</div>
<Captcha
ref={captchaRef}
2026-02-24 20:44:16 +00:00
onError={() => setFieldValue('captchaResponse', '')}
onExpire={() => setFieldValue('captchaResponse', '')}
onSuccess={(token: string) => setFieldValue('captchaResponse', token)}
/>
<Button block loading={isSubmitting} variant="solid" type="submit">
{emailSent ? 'Resend Email' : 'Send Email'}
</Button>
<div className="mt-4 text-center">
<span>{translate('::Abp.Account.Backto')} </span>
<ActionLink to={signInUrl}>{translate('::Abp.Account.SignIn')}</ActionLink>
</div>
</FormContainer>
</Form>
)}
</Formik>
</div>
)
}
export default ExtendLogin