mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: exipred seconds interval
This commit is contained in:
parent
cf81c3f5da
commit
da4335ce7f
@ -52,6 +52,12 @@ export interface IUpdatedContactsResult extends IDataResult {
|
|||||||
data: IUserContacts;
|
data: IUserContacts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IUpdatedEmailResult extends IDataResult {
|
||||||
|
data: {
|
||||||
|
expired_seconds: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export interface IUserResult extends IDataResult {
|
export interface IUserResult extends IDataResult {
|
||||||
data: Omit<IUser, 'fullname'>;
|
data: Omit<IUser, 'fullname'>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,24 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { PinInput, PinInputField } from '@chakra-ui/react';
|
import { PinInput, PinInputField } from '@chakra-ui/react';
|
||||||
import { Button } from '@chakra-ui/button';
|
import { Button } from '@chakra-ui/button';
|
||||||
import { Box, Flex, Heading, HStack, Text } from '@chakra-ui/layout';
|
import { Box, Flex, Heading, HStack, Text } from '@chakra-ui/layout';
|
||||||
|
import { ConfirmEmailContainerDataType } from 'types';
|
||||||
|
|
||||||
|
const ConfirmEmailContainer: React.FC<{ data: ConfirmEmailContainerDataType }> = ({ data }) => {
|
||||||
|
const [expired, setExpired] = useState(data.expired_seconds);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = window.setInterval(() => {
|
||||||
|
if (expired <= 0) {
|
||||||
|
window.clearInterval(interval);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setExpired(v => (v = v - 1));
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => window.clearInterval(interval);
|
||||||
|
});
|
||||||
|
|
||||||
const ConfirmEmailContainer: React.FC<{ newEmail: string }> = ({ newEmail }) => {
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
maxW='500px'
|
maxW='500px'
|
||||||
@ -17,7 +32,7 @@ const ConfirmEmailContainer: React.FC<{ newEmail: string }> = ({ newEmail }) =>
|
|||||||
<Heading as='h1'>Confirmation</Heading>
|
<Heading as='h1'>Confirmation</Heading>
|
||||||
<Box mt='3'>
|
<Box mt='3'>
|
||||||
<Text>
|
<Text>
|
||||||
Enter the 4-digit code we send to <Text as='b'>{newEmail}</Text>
|
Enter the 4-digit code we send to <Text as='b'>{data.newEmail}</Text>
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Flex alignItems='center' mt='10'>
|
<Flex alignItems='center' mt='10'>
|
||||||
@ -44,12 +59,15 @@ const ConfirmEmailContainer: React.FC<{ newEmail: string }> = ({ newEmail }) =>
|
|||||||
Verify
|
Verify
|
||||||
</Button>
|
</Button>
|
||||||
<Box mt='1.5'>
|
<Box mt='1.5'>
|
||||||
<Text as='small' color='red'>
|
{expired > 0 ? (
|
||||||
Expires in 1:59
|
<Text as='small' color='red'>
|
||||||
</Text>
|
Expires in {expired} seconds.
|
||||||
{/* <Button variant='link' size='sm' colorScheme='black' mt='3' textDecoration='underline'>
|
</Text>
|
||||||
Resend code
|
) : (
|
||||||
</Button> */}
|
<Button variant='link' size='sm' colorScheme='black' mt='3' textDecoration='underline'>
|
||||||
|
Resend code
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -2,10 +2,12 @@ import { Button } from '@chakra-ui/button';
|
|||||||
import { FormControl, FormHelperText, FormLabel } from '@chakra-ui/form-control';
|
import { FormControl, FormHelperText, FormLabel } from '@chakra-ui/form-control';
|
||||||
import { Input } from '@chakra-ui/input';
|
import { Input } from '@chakra-ui/input';
|
||||||
import { Box, Stack } from '@chakra-ui/layout';
|
import { Box, Stack } from '@chakra-ui/layout';
|
||||||
|
import { useToast } from '@chakra-ui/toast';
|
||||||
import { yupResolver } from '@hookform/resolvers/yup';
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
import { ProfilePageViewContext } from 'contexts';
|
import { ProfilePageViewContext } from 'contexts';
|
||||||
import { useRootStore } from 'hooks/useRootStore';
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
import UpdateEmailSchema from './UpdateEmailForm.validator';
|
import UpdateEmailSchema from './UpdateEmailForm.validator';
|
||||||
|
|
||||||
@ -18,9 +20,7 @@ type UpdateEmailInputType = {
|
|||||||
*/
|
*/
|
||||||
const UpdateEmailForm: React.FC = () => {
|
const UpdateEmailForm: React.FC = () => {
|
||||||
const { setStatusPageView } = useContext(ProfilePageViewContext);
|
const { setStatusPageView } = useContext(ProfilePageViewContext);
|
||||||
const {
|
const { userStore } = useRootStore();
|
||||||
userStore: { me },
|
|
||||||
} = useRootStore();
|
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
register,
|
register,
|
||||||
@ -28,10 +28,25 @@ const UpdateEmailForm: React.FC = () => {
|
|||||||
} = useForm<UpdateEmailInputType>({
|
} = useForm<UpdateEmailInputType>({
|
||||||
resolver: yupResolver(UpdateEmailSchema),
|
resolver: yupResolver(UpdateEmailSchema),
|
||||||
});
|
});
|
||||||
|
const toast = useToast();
|
||||||
|
const handleError = useErrorHandler();
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<UpdateEmailInputType> = async data => {
|
const onSubmit: SubmitHandler<UpdateEmailInputType> = async ({ email }) => {
|
||||||
console.log(data);
|
userStore
|
||||||
setStatusPageView({ status: 'confirm-email', data: { confirmEmailData: { newEmail: data.email } } });
|
.updateUserEmail(email)
|
||||||
|
.then(({ data }) => {
|
||||||
|
setStatusPageView({
|
||||||
|
status: 'confirm-email',
|
||||||
|
data: { confirmEmailData: { newEmail: email, expired_seconds: data.expired_seconds } },
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
if (error.response) {
|
||||||
|
toast({ title: `${error.message}`, status: 'error' });
|
||||||
|
} else {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -40,7 +55,7 @@ const UpdateEmailForm: React.FC = () => {
|
|||||||
<Stack spacing='15px' mt='10'>
|
<Stack spacing='15px' mt='10'>
|
||||||
<FormControl id='email'>
|
<FormControl id='email'>
|
||||||
<FormLabel>Current email</FormLabel>
|
<FormLabel>Current email</FormLabel>
|
||||||
<Input type='email' size='md' variant='filled' disabled value={me?.email} />
|
<Input type='email' size='md' variant='filled' disabled value={userStore.me?.email} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl id='new_email' isRequired>
|
<FormControl id='new_email' isRequired>
|
||||||
<FormLabel>New email</FormLabel>
|
<FormLabel>New email</FormLabel>
|
||||||
|
|||||||
@ -124,7 +124,7 @@ const ProfilePage: React.FC<IPageProps> = () => {
|
|||||||
{statusPageView.status === 'update-password' && <UpdatePasswordContainer />}
|
{statusPageView.status === 'update-password' && <UpdatePasswordContainer />}
|
||||||
{statusPageView.status === 'update-email' && <UpdateEmailContainer />}
|
{statusPageView.status === 'update-email' && <UpdateEmailContainer />}
|
||||||
{statusPageView.status === 'confirm-email' && statusPageView.data?.confirmEmailData && (
|
{statusPageView.status === 'confirm-email' && statusPageView.data?.confirmEmailData && (
|
||||||
<ConfirmEmailContainer newEmail={statusPageView.data.confirmEmailData.newEmail} />
|
<ConfirmEmailContainer data={statusPageView.data.confirmEmailData} />
|
||||||
)}
|
)}
|
||||||
</ProfilePageViewContext.Provider>
|
</ProfilePageViewContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import { IDataResult, IUpdatedContactsResult, IUserContacts, IUserResult } from 'interfaces';
|
import { IDataResult, IUpdatedContactsResult, IUpdatedEmailResult, IUserContacts, IUserResult } from 'interfaces';
|
||||||
import * as helpers from 'helpers';
|
import * as helpers from 'helpers';
|
||||||
|
|
||||||
export default class UserService {
|
export default class UserService {
|
||||||
@ -44,4 +44,17 @@ export default class UserService {
|
|||||||
});
|
});
|
||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateEmail(email: string): Promise<IUpdatedEmailResult> {
|
||||||
|
const result = await this.api.patch('v1/me/email', { email });
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateEmailConfirm(email: string, confirmationCode: number): Promise<IDataResult> {
|
||||||
|
const result = await this.api.post('v1/me/email/change/confirm', {
|
||||||
|
email,
|
||||||
|
confirmationCode,
|
||||||
|
});
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
import { makeAutoObservable, runInAction } from 'mobx';
|
import { makeAutoObservable, runInAction } from 'mobx';
|
||||||
import { IUserResult, IUser, IUserContacts, IUpdatedContactsResult, IDataResult } from 'interfaces';
|
import {
|
||||||
|
IUserResult,
|
||||||
|
IUser,
|
||||||
|
IUserContacts,
|
||||||
|
IUpdatedContactsResult,
|
||||||
|
IDataResult,
|
||||||
|
IUpdatedEmailResult,
|
||||||
|
} from 'interfaces';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Services
|
* Services
|
||||||
@ -77,6 +84,15 @@ export default class UserStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updateUserEmail(email: string): Promise<IUpdatedEmailResult> {
|
||||||
|
try {
|
||||||
|
const result = await this.userService.updateEmail(email);
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public reset(): void {
|
public reset(): void {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.me = null;
|
this.me = null;
|
||||||
|
|||||||
9
src/types/index.d.ts
vendored
9
src/types/index.d.ts
vendored
@ -7,15 +7,18 @@ export type LinkType = {
|
|||||||
icon: IconType;
|
icon: IconType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type ConfirmEmailContainerDataType = {
|
||||||
|
newEmail: string;
|
||||||
|
expired_seconds: number;
|
||||||
|
};
|
||||||
|
|
||||||
export type ProfilePageStatusType = {
|
export type ProfilePageStatusType = {
|
||||||
status: 'update-password' | 'update-email' | 'confirm-email' | 'default';
|
status: 'update-password' | 'update-email' | 'confirm-email' | 'default';
|
||||||
data?: {
|
data?: {
|
||||||
/**
|
/**
|
||||||
* The field that is set when trying to change the mail address through form
|
* The field that is set when trying to change the mail address through form
|
||||||
*/
|
*/
|
||||||
confirmEmailData?: {
|
confirmEmailData?: ConfirmEmailContainerDataType;
|
||||||
newEmail: string;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type ProfilePageViewStatusContextType = {
|
export type ProfilePageViewStatusContextType = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user