197 lines
6.6 KiB
TypeScript
197 lines
6.6 KiB
TypeScript
import Button from '@/components/ui/Button'
|
|
import { FormContainer } from '@/components/ui/Form'
|
|
import Input from '@/components/ui/Input'
|
|
import Notification from '@/components/ui/Notification'
|
|
import toast from '@/components/ui/toast'
|
|
import { changePassword } from '@/proxy/account/account.service'
|
|
import { useLocalization } from '@/utils/hooks/useLocalization'
|
|
import FormDesription from '@/views/shared/FormDesription'
|
|
import FormRow from '@/views/shared/FormRow'
|
|
import { Field, Form, Formik } from 'formik'
|
|
import {
|
|
HiOutlineDesktopComputer,
|
|
HiOutlineDeviceMobile,
|
|
HiOutlineDeviceTablet,
|
|
} from 'react-icons/hi'
|
|
import * as Yup from 'yup'
|
|
|
|
type LoginHistory = {
|
|
type: string
|
|
deviceName: string
|
|
time: number
|
|
location: string
|
|
}
|
|
|
|
type PasswordFormModel = {
|
|
password: string
|
|
newPassword: string
|
|
confirmNewPassword: string
|
|
}
|
|
|
|
const LoginHistoryIcon = ({ type }: { type: string }) => {
|
|
switch (type) {
|
|
case 'Desktop':
|
|
return <HiOutlineDesktopComputer />
|
|
case 'Mobile':
|
|
return <HiOutlineDeviceMobile />
|
|
case 'Tablet':
|
|
return <HiOutlineDeviceTablet />
|
|
default:
|
|
return <HiOutlineDesktopComputer />
|
|
}
|
|
}
|
|
|
|
const validationSchema = Yup.object().shape({
|
|
password: Yup.string().required('Password Required'),
|
|
newPassword: Yup.string()
|
|
.required('Enter your new password')
|
|
.min(6, 'Too Short!')
|
|
.matches(
|
|
/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*])(?=.{6,})/,
|
|
'Must Contain Uppercase, Lowercase, Number and Special Character',
|
|
),
|
|
confirmNewPassword: Yup.string().oneOf([Yup.ref('newPassword'), ''], 'Password not match'),
|
|
})
|
|
|
|
const Password = ({ data }: { data?: LoginHistory[] }) => {
|
|
const onFormSubmit = async (
|
|
values: PasswordFormModel,
|
|
setSubmitting: (isSubmitting: boolean) => void,
|
|
) => {
|
|
const resp = await changePassword(values.password, values.newPassword)
|
|
if (resp.status === 204) {
|
|
toast.push(<Notification title={'Password updated'} type="success" />, {
|
|
placement: 'top-center',
|
|
})
|
|
} else {
|
|
toast.push(<Notification title={resp?.error?.message} type="danger" />, {
|
|
placement: 'top-center',
|
|
})
|
|
}
|
|
setSubmitting(false)
|
|
}
|
|
|
|
const { translate } = useLocalization()
|
|
|
|
return (
|
|
<>
|
|
<Formik
|
|
initialValues={{
|
|
password: '',
|
|
newPassword: '',
|
|
confirmNewPassword: '',
|
|
}}
|
|
validationSchema={validationSchema}
|
|
onSubmit={(values, { setSubmitting }) => {
|
|
setSubmitting(true)
|
|
setTimeout(() => {
|
|
onFormSubmit(values, setSubmitting)
|
|
}, 1000)
|
|
}}
|
|
>
|
|
{({ touched, errors, isSubmitting, resetForm }) => {
|
|
const validatorProps = { touched, errors }
|
|
return (
|
|
<Form>
|
|
<FormContainer>
|
|
<FormDesription
|
|
title={translate('::Abp.Identity.Password')}
|
|
desc={translate('::Abp.Identity.Password.Description')}
|
|
/>
|
|
<FormRow
|
|
name="password"
|
|
label={translate('::Abp.Identity.Password.CurrentPassword')}
|
|
{...validatorProps}
|
|
>
|
|
<Field
|
|
type="password"
|
|
autoComplete="off"
|
|
name="password"
|
|
placeholder={translate('::Abp.Identity.Password.CurrentPassword')}
|
|
component={Input}
|
|
/>
|
|
</FormRow>
|
|
<FormRow
|
|
name="newPassword"
|
|
label={translate('::Abp.Identity.Password.NewPassword')}
|
|
{...validatorProps}
|
|
>
|
|
<Field
|
|
type="password"
|
|
autoComplete="off"
|
|
name="newPassword"
|
|
placeholder={translate('::Abp.Identity.Password.NewPassword')}
|
|
component={Input}
|
|
/>
|
|
</FormRow>
|
|
<FormRow
|
|
name="confirmNewPassword"
|
|
label={translate('::Abp.Identity.Password.ConfirmPassword')}
|
|
{...validatorProps}
|
|
>
|
|
<Field
|
|
type="password"
|
|
autoComplete="off"
|
|
name="confirmNewPassword"
|
|
placeholder={translate('::Abp.Identity.Password.ConfirmPassword')}
|
|
component={Input}
|
|
/>
|
|
</FormRow>
|
|
<div className="mt-4 ltr:text-right">
|
|
<Button className="ltr:mr-2 rtl:ml-2" type="button" onClick={() => resetForm()}>
|
|
{translate('::Cancel')}
|
|
</Button>
|
|
<Button variant="solid" loading={isSubmitting} type="submit">
|
|
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
|
|
</Button>
|
|
</div>
|
|
</FormContainer>
|
|
</Form>
|
|
)
|
|
}}
|
|
</Formik>
|
|
{/* <div className="mt-6">
|
|
<FormDesription
|
|
title="Where you're signed in"
|
|
desc="You're signed in to your account on these devices."
|
|
/>
|
|
{data && (
|
|
<div className="rounded-lg border border-gray-200 dark:border-gray-600 mt-6">
|
|
{data.map((log, index) => (
|
|
<div
|
|
key={log.deviceName}
|
|
className={classNames(
|
|
'flex items-center px-4 py-6',
|
|
!isLastChild(data, index) && 'border-b border-gray-200 dark:border-gray-600',
|
|
)}
|
|
>
|
|
<div className="flex items-center">
|
|
<div className="text-3xl">
|
|
<LoginHistoryIcon type={log.type} />
|
|
</div>
|
|
<div className="ml-3 rtl:mr-3">
|
|
<div className="flex items-center">
|
|
<div className="text-gray-900 dark:text-gray-100 font-semibold">
|
|
{log.deviceName}
|
|
</div>
|
|
{index === 0 && (
|
|
<Tag className="bg-emerald-100 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-100 rounded-md border-0 mx-2">
|
|
<span className="capitalize"> Current </span>
|
|
</Tag>
|
|
)}
|
|
</div>
|
|
<span>
|
|
{log.location} • {dayjs.unix(log.time).format('DD-MMM-YYYY, hh:mm A')}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div> */}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Password
|