Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
6.9 kB
4
Indexable
Never
import React from 'react';
import {
  Box,
  Icon,
  Input,
  InputGroup,
  InputRightElement,
  Button,
  Flex,
  useDisclosure,
  Center,
  useToast,
} from '@chakra-ui/react';
import AdminLayout from 'layouts/admin';
import { IconCirclePlus, IconReset } from 'components/icons/Icons';
import { Table, Thead, Tbody, Tr, Th } from '@chakra-ui/react';

import _ from 'lodash';
import { useRouter } from 'next/router';
import { AccountItem, MenuStatus, PaginationPanel, ProcessDialog } from 'components';
import { IoSearchOutline } from 'react-icons/io5';
import { PAGE_SIZE, StatusEnum } from 'constant';
import { usePagination } from '@ajna/pagination';
import { useTranslation } from 'react-i18next';
import { GetListAccountResponse, deleteAccount, getAccounts } from 'api/account';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { IAccount } from 'types/model';
import { useDispatch } from 'react-redux';
import { setAppLoading } from 'store/slices/appSlice';
import { error, success } from 'utils/toast';

export default function Account() {
  const router = useRouter();
  const toast = useToast();
  const dispatch = useDispatch();
  const queryClient = useQueryClient();
  const { t } = useTranslation(['common', 'account']);
  const { isOpen, onOpen, onClose } = useDisclosure();

  const [totalRecords, setTotalRecords] = React.useState<number>(0);
  const [search, setSearch] = React.useState<string>('');
  const [status, setStatus] = React.useState<StatusEnum | null>(null);
  const [account, setAccount] = React.useState<IAccount>(null);

  const headers = [
    t('common:user_name'),
    t('common:status'),
    t('common:permisstion'),
    t('common:created_date'),
    t('common:created_by'),
    t('common:action'),
  ];

  const { pages, pagesCount, currentPage, setCurrentPage, isDisabled } = usePagination({
    total: totalRecords,
    limits: {
      outer: 1,
      inner: 2,
    },
    initialState: {
      pageSize: PAGE_SIZE,
      isDisabled: false,
      currentPage: 1,
    },
  });

  const { data } = useQuery<GetListAccountResponse>({
    queryKey: ['list-account', status, currentPage, PAGE_SIZE],
    queryFn: () =>
      getAccounts({
        locked: status ? status !== StatusEnum.ACTIVE : null,
        page: currentPage,
        size: PAGE_SIZE,
      }),
  });

  const debouncedGetAccounts = _.debounce(async (searchValue) => {
    const response = await getAccounts({
      username: searchValue,
      locked: status ? status !== StatusEnum.ACTIVE : null,
      page: currentPage,
      size: PAGE_SIZE,
    });

    queryClient.setQueryData(
      ['list-account', searchValue, status, currentPage, PAGE_SIZE],
      response
    );
  }, 500);

  const { mutate: deleteAccountMutate } = useMutation({
    mutationKey: ['delete-account'],
    mutationFn: deleteAccount,
    onSuccess: () => {
      toast(success({ title: t('common:delete_successfully') }));
      queryClient.invalidateQueries({ queryKey: ['list-account'] });
    },
    onError: () => {
      toast(error({ title: t('common:delete_failed') }));
    },
  });

  React.useEffect(() => {
    if (data) {
      setTotalRecords(data.data.paging.totalRecord);
    }
  }, [data]);

  return (
    <AdminLayout>
      <Box pt={{ base: '12px', md: '90px', xl: '90px' }}>
        <Flex gap="6" justifyContent="space-between" flexDirection={{ base: 'column', md: 'row' }}>
          <InputGroup size="xs" maxW="480px">
            <Input
              value={search}
              onChange={(e) => {
                setSearch(e.target.value);
                debouncedGetAccounts(e.target.value);
              }}
              variant="search"
              size="md"
              placeholder={t('account:search_account_name')}
            />
            <InputRightElement h="100%" px="6">
              <Icon as={IoSearchOutline} boxSize="24px" color="black" />
            </InputRightElement>
          </InputGroup>
          <Flex gap="6">
            <MenuStatus status={status} onClick={(e) => setStatus(e)} />
            <Button
              boxSize="40px"
              onClick={() => {
                setSearch('');
                setStatus(null);
              }}>
              <Icon as={IconReset} boxSize="24px" color="black" />
            </Button>
            <Button
              leftIcon={
                <Center position="absolute" left="0" insetY="0" h="100%" pl="4">
                  <IconCirclePlus boxSize="20px" left="4" justifyContent="center" my="auto" />
                </Center>
              }
              width="150px"
              size="md"
              onClick={() => {
                router.push('/admin/account/create');
              }}>
              {t('common:add_new')}
            </Button>
          </Flex>
        </Flex>
      </Box>
      <Box mt="10" position="relative" bg="bg-1" minH="60vh" overflow="auto">
        <Table variant="simple">
          <Thead>
            <Tr>
              {headers.map((prop, index) => {
                return (
                  <Th
                    pt="4"
                    textStyle="h4-sb"
                    borderBottom="0.5px solid black"
                    key={index}
                    textTransform="capitalize"
                    color="text-title"
                    isNumeric={index === headers.length - 1}>
                    {prop}
                  </Th>
                );
              })}
            </Tr>
          </Thead>
          <Tbody>
            {data &&
              data.data.accountList &&
              data.data.accountList.map((item, index) => {
                return (
                  <AccountItem
                    key={index}
                    item={item}
                    onClick={() => {
                      router.push({
                        pathname: '/admin/account/detail',
                        query: item.id,
                      });
                    }}
                    onResetPassword={() => {}}
                    onDelete={() => {
                      setAccount(item);
                      onOpen();
                    }}
                  />
                );
              })}
          </Tbody>
        </Table>
      </Box>
      <Flex justifyContent="flex-end">
        <PaginationPanel
          pagesCount={pagesCount}
          currentPage={currentPage}
          isDisabled={isDisabled}
          onPageChange={setCurrentPage}
          pages={pages}
          mt="24px"
          mb="8px"
        />
      </Flex>
      <ProcessDialog
        title={t('account:description_delete_account')}
        isOpen={isOpen}
        onClose={onClose}
        onConfirm={() => {
          if (!account) {
            return;
          }
          dispatch(setAppLoading(true));
          deleteAccountMutate({ id: account.id });
        }}
      />
    </AdminLayout>
  );
}