Untitled
unknown
plain_text
2 years ago
12 kB
12
Indexable
import React from 'react';
import {
Text,
Input,
FormControl,
FormErrorMessage,
Switch,
VStack,
Button,
Flex,
HStack,
Spacer,
Icon,
useToast,
} from '@chakra-ui/react';
import AdminLayout from 'layouts/admin';
import { useRouter } from 'next/router';
import { useTranslation } from 'react-i18next';
import { FormGroup } from 'components';
import { Formik } from 'formik';
import * as yup from 'yup';
import { useAppDispatch } from 'store/store';
import { setAppLoading } from 'store/slices/appSlice';
import { EMode, RoleTypeEnum } from 'constant';
import { debounce } from 'lodash';
import { Select, chakraComponents, ChakraStylesConfig } from 'chakra-react-select';
import { IconArrowDown } from 'components/icons/Icons';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
GetListPartnerResponse,
createAccount,
getAccount,
getPartners,
updateAccount,
} from 'api/account';
import { IPartner } from 'types/model';
import { error, success } from 'utils/toast';
type SelectRoleType = {
label: string;
value: RoleTypeEnum;
};
interface FormValues {
id: string;
username: string;
password: string;
email: string;
partner: IPartner | null;
role: SelectRoleType | null;
locked: boolean;
mode: EMode | null;
}
const initialValues: FormValues = {
id: '',
username: '',
password: '',
email: '',
partner: undefined,
role: undefined,
locked: true,
mode: EMode.CREATE,
};
export default function CreateUpdateAccount() {
const router = useRouter();
const toast = useToast();
const dispatch = useAppDispatch();
const queryClient = useQueryClient();
const { t } = useTranslation(['common', 'account']);
const id = router.query ? router.query : undefined;
const { data: partners } = useQuery<GetListPartnerResponse>({
queryKey: ['list-partner'],
queryFn: getPartners,
retry: 1,
});
const roles: SelectRoleType[] = [
{
label: t('common:customer'),
value: RoleTypeEnum.CUSTOMER,
},
{
label: t('common:provider'),
value: RoleTypeEnum.PROVIDER,
},
];
const customComponents = {
DropdownIndicator: (props: any) => (
<chakraComponents.DropdownIndicator {...props}>
<Icon as={IconArrowDown} w="12px" />
</chakraComponents.DropdownIndicator>
),
Option: (props: any) => {
const { isFocused } = props;
return (
<chakraComponents.Option {...props}>
<Text color={isFocused ? 'primary' : 'text-title'}>{props.children}</Text>
</chakraComponents.Option>
);
},
};
const chakraStyles: ChakraStylesConfig = {
dropdownIndicator: (provided, state) => ({
...provided,
p: 0,
borderRight: '0px',
borderWidth: '1px',
color: state.isFocused ? 'primary' : 'text-note',
marginLeft: '-1px',
borderColor: 'bg-1',
w: '40px',
}),
};
const { mutate: createAccountMutate } = useMutation({
mutationKey: ['create-account'],
mutationFn: createAccount,
retry: 1,
onSuccess: () => {
queryClient.invalidateQueries(['list-account']);
dispatch(setAppLoading(false));
toast(
success({
title: t('common:create_successfully'),
onCloseComplete: () => {
router.back();
},
})
);
},
onError: () => {
dispatch(setAppLoading(false));
toast(error({ title: t('common:create_failed') }));
},
});
const { mutate: updateAccountMutate } = useMutation({
mutationKey: ['update-account'],
mutationFn: updateAccount,
retry: 1,
onSuccess: () => {
queryClient.invalidateQueries(['list-account']);
dispatch(setAppLoading(false));
toast(
success({
title: t('common:update_successfully'),
onCloseComplete: () => {
router.back();
},
})
);
},
onError: () => {
dispatch(setAppLoading(false));
toast(error({ title: t('common:update_failed') }));
},
});
const { mutate: getAccountMutate } = useMutation({
mutationKey: ['get-account'],
mutationFn: getAccount,
retry: 1,
});
const handleSubmitVoucher = React.useCallback(
async ({ mode, id, username, email, password, partner, role, locked }: FormValues) => {
dispatch(setAppLoading(true));
if (mode === EMode.EDIT) {
createAccountMutate({
username: username,
email: email,
password: password,
partnerId: partner.id,
role: role.value,
locked: locked,
});
} else {
updateAccountMutate({
id: id,
username: username,
partnerId: partner.id,
role: role.value,
locked: locked,
});
}
},
[]
);
const validationSchema = yup.object().shape({
username: yup.string().required(t('common:error_field_empty')),
email: yup.string().required(t('common:error_field_empty')).email(t('common:invalid_email')),
password: yup.string().required(t('common:error_field_empty')),
partner: yup.object().shape({
label: yup.string().required(t('common:error_field_empty')),
value: yup.number().required(t('common:error_field_empty')),
}),
role: yup.object().shape({
label: yup.string().required(t('common:error_field_empty')),
value: yup.string().required(t('common:error_field_empty')),
}),
});
return (
<Formik
validateOnChange={false}
validationSchema={validationSchema}
enableReinitialize={true}
initialValues={initialValues}
onSubmit={handleSubmitVoucher}>
{({ handleChange, handleSubmit, setFieldValue, validateField, values, errors, dirty }) => {
const validateDebounced = debounce(validateField, 300);
React.useEffect(() => {
if (router.query.mode) {
setFieldValue('mode', router.query.mode);
}
}, [router.query.mode]);
React.useEffect(() => {
if (router.query.mode) {
setFieldValue('mode', router.query.mode);
}
}, [router.query.mode]);
getAccountMutate;
// username: username,
// email: email,
// password: password,
// partnerId: partner.id,
// role: role.value,
// locked: locked,
//TODO: when mode = edit if dirty then submit, if not router back
//console.log('quang debug dirty', dirty);
return (
<AdminLayout>
<Flex flexDirection="column" pt={{ base: '12px', md: '90px', xl: '90px' }} minH="90vh">
<Text color="title-title" textStyle="h4-sb" textTransform="uppercase">
{values.mode === EMode.CREATE
? t('account:add_new_account')
: values.mode === EMode.EDIT
? t('account:edit_account')
: t('account:account_information')}
</Text>
<VStack spacing="6" mt="6" alignItems="normal" maxW="5xl" mx="auto" w="100%">
<FormGroup isRequire title={t('common:user_name')}>
<FormControl isInvalid={!!errors.username}>
<Input
id="username"
name="username"
placeholder={t('account:input_username')}
autoComplete="off"
value={values.username}
onChange={(e) => {
handleChange(e);
validateDebounced('username');
}}
maxLength={120}
/>
<FormErrorMessage>{errors.username}</FormErrorMessage>
</FormControl>
</FormGroup>
<FormGroup isRequire title={t('common:email')}>
<FormControl isInvalid={!!errors.email}>
<Input
id="email"
name="email"
type="email"
placeholder={t('account:input_email')}
autoComplete="off"
value={values.email}
onChange={(e) => {
handleChange(e);
validateDebounced('email');
}}
/>
<FormErrorMessage>{errors.email}</FormErrorMessage>
</FormControl>
</FormGroup>
<FormGroup isRequire title={t('common:password')}>
<FormControl isInvalid={!!errors.password}>
<Input
type="password"
id="password"
name="password"
placeholder={t('account:input_password')}
autoComplete="off"
value={values.password}
onChange={(e) => {
handleChange(e);
validateDebounced('password');
}}
/>
<FormErrorMessage>{errors.password}</FormErrorMessage>
</FormControl>
</FormGroup>
<FormGroup isRequire title={t('common:partner')}>
<FormControl isInvalid={!!errors.partner}>
<Select
id="partner"
name="partner"
instanceId="partner"
inputId="partner"
chakraStyles={chakraStyles}
options={partners?.data as any}
value={values.partner}
onChange={(e) => {
setFieldValue('partner', e);
validateDebounced('partner');
}}
placeholder={t('account:select_partner')}
components={customComponents}
/>
<FormErrorMessage>{errors.partner.id}</FormErrorMessage>
</FormControl>
</FormGroup>
<FormGroup isRequire title={t('common:role')}>
<FormControl isInvalid={!!errors.role}>
<Select
id="role"
name="role"
instanceId="role"
inputId="role"
chakraStyles={chakraStyles}
options={roles}
value={values.role}
onChange={(e) => {
setFieldValue('role', e);
validateDebounced('role');
}}
placeholder={t('account:select_role')}
components={customComponents}
/>
<FormErrorMessage>{errors.role.value}</FormErrorMessage>
</FormControl>
</FormGroup>
<FormGroup title={t('common:status')}>
<Switch
id="locked"
name="locked"
isChecked={values.locked}
onChange={handleChange('locked')}
variant="success"
/>
</FormGroup>
</VStack>
<Spacer />
<HStack mt="6" gap="8" w="100%" maxW="xl" mx="auto">
<Button
flex="1"
variant="outline"
children={t('common:back')}
onClick={() => router.back()}
/>
<Button
flex="1"
children={
values.mode === EMode.DETAIL
? t('common:edit_information')
: t('common:save_information')
}
onClick={() => {
if (values.mode === EMode.DETAIL) {
setFieldValue('mode', EMode.EDIT);
} else {
handleSubmit();
}
}}
/>
</HStack>
</Flex>
</AdminLayout>
);
}}
</Formik>
);
}
Editor is loading...