Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14 visualizar processos pela data vencimento por etapa #57

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ exit

## Contribuição

Certifique-se de ler o [Guia de Contribuição](https://github.com/fga-eps-mds/2023-1-CAPJu-Front/blob/main/.github/CONTRIBUTING.md) antes de realizar qualquer atividade no projeto!
Certifique-se de ler o [Guia de Contribuição](https://github.com/fga-eps-mds/2023-2-CAPJu-Front/blob/main/.github/CONTRIBUTING.md) antes de realizar qualquer atividade no projeto!

## Licença

O CAPJu está sob as regras aplicadas na licença [MIT](https://github.com/fga-eps-mds/2023-1-CAPJu-Front/blob/main/LICENSE)
O CAPJu está sob as regras aplicadas na licença [MIT](https://github.com/fga-eps-mds/2023-2-CAPJu-Front/blob/main/LICENSE)

## Contribuidores

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"react-input-mask": "^2.0.4",
"react-paginate": "^8.2.0",
"react-query": "^3.39.3",
"react-router-dom": "^6.10.0",
"react-router-dom": "^6.17.0",
"react-select-event": "^5.5.1",
"react-table": "^7.8.0",
"reactflow": "^11.7.2",
Expand Down Expand Up @@ -78,7 +78,7 @@
"jsdom": "^22.0.0",
"lint-staged": "^11.1.2",
"prettier": "^2.4.0",
"typescript": "^4.4.2",
"typescript": "^4.9.5",
"vitest": "^0.31.1"
}
}
52 changes: 52 additions & 0 deletions src/components/CustomAccordion/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
Accordion,
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
} from "@chakra-ui/react";

interface CustomAccordionProps {
title: String;
children: JSX.Element;
marginBottom: number;
}
export default function CustomAccordion({
title,
children,
marginBottom,
}: CustomAccordionProps) {
return (
<Accordion
marginBottom={marginBottom}
defaultIndex={[0]}
allowMultiple
width="100%"
backgroundColor="#FFF"
borderRadius="8px"
>
<AccordionItem>
<h2>
<AccordionButton>
<AccordionIcon />
<Box
as="span"
textAlign="left"
marginLeft="18"
fontSize="17px"
fontWeight="600"
fontStyle="normal"
lineHeight="24px"
>
{title}
</Box>
</AccordionButton>
</h2>
<AccordionPanel pb={4} width="100%">
{children}
</AccordionPanel>
</AccordionItem>
</Accordion>
);
}
292 changes: 292 additions & 0 deletions src/pages/Statistics/StepDeadlineReports/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
import { useEffect, useState, useMemo } from "react";
import { useToast, Box, Flex, Button, Text, Input } from "@chakra-ui/react";
import CustomAccordion from "components/CustomAccordion";
import { DataTable } from "components/DataTable";
import { getFlows } from "services/processManagement/flows";
import { createColumnHelper } from "@tanstack/react-table";
import { useQuery } from "react-query";
import { useAuth } from "hooks/useAuth";
import { isActionAllowedToUser } from "utils/permissions";
import { ViewIcon } from "@chakra-ui/icons";
import { Pagination } from "components/Pagination";
import { getProcessesByDueDate } from "services/processManagement/statistics";
import { useLocation } from "react-router-dom";

export default function StepDeadlineReports() {
const toast = useToast();
const { getUserData } = useAuth();
const { data: userData, isFetched: isUserFetched } = useQuery({
queryKey: ["user-data"],
queryFn: getUserData,
});

const [flows, setFlows] = useState([] as Flow[]);
const { state } = useLocation();
const [tableVisible, setTableVisible] = useState(false);
const [minDate, setMinDate] = useState<string>("");
const [isFetching, setIsFetching] = useState<boolean>(true);
const [maxDate, setMaxDate] = useState<string>("");
const [processData, setProcessData] = useState<Process[]>([]);
const [processDueTotalPages, setProcessDueTotalPages] = useState<
number | undefined
>();
const [loading, setLoading] = useState(false);
const [currentPage, setCurrentPage] = useState(0);

useEffect(() => {
const handlePageChange = async () => {
setLoading(true);
await handleProcessByDueDate();
setLoading(false);
};

if (minDate && maxDate) handlePageChange();
}, [currentPage]);

const getDataFlows = async () => {
const dataFlows = await getFlows();
if (dataFlows.value) setFlows(dataFlows.value);
};

const handleProcessByDueDate = async () => {
const res = await getProcessesByDueDate(minDate, maxDate, {
offset: currentPage * 5,
limit: 5,
});

if (res.type === "error") throw new Error(res.error.message);

setProcessData(res.value);
setProcessDueTotalPages(res.totalPages);
};

useEffect(() => {
if (flows.length === 0) getDataFlows();
}, []);

const tableColumnHelper = createColumnHelper<TableRow<any>>();
const tableActions = useMemo<TableAction[]>(
() => [
{
label: "Visualizar Processo",
icon: <ViewIcon boxSize={4} />,
isNavigate: true,
actionName: "see-process",
disabled: !isActionAllowedToUser(
userData?.value?.allowedActions || [],
"see-process"
),
},
],
[isUserFetched, userData]
);

const tableColumns = [
tableColumnHelper.accessor("record", {
cell: (info) => info.getValue(),
header: "Registro",
meta: {
isSortable: true,
},
}),
tableColumnHelper.accessor("nickname", {
cell: (info) => info.getValue(),
header: "Apelido",
meta: {
isSortable: true,
},
}),
tableColumnHelper.accessor("nameFlow", {
cell: (info) => info.getValue(),
header: "Fluxo",
meta: {
isSortable: true,
},
}),
tableColumnHelper.accessor("nameStage", {
cell: (info) => info.getValue(),
header: "Etapa Atual",
meta: {
isSortable: true,
},
}),
tableColumnHelper.accessor("tableActions", {
cell: (info) => info.getValue(),
header: "Ações",
meta: {
isTableActions: true,
isSortable: false,
},
}),
];

const filteredStepDeadlineReports = useMemo<TableRow<Process>[]>(() => {
if (processData.length <= 0) return [];

return (
(processData.reduce(
(
acc: TableRow<Process>[] | Process[],
curr: TableRow<Process> | Process
) => {
return [
...acc,
{
...curr,
tableActions,
actionsProps: {
process: curr,
pathname: `/processos/${curr.record}`,
state: {
process: curr,
...(state || {}),
},
},
record: curr.record,
},
];
},
[]
) as TableRow<Process>[]) || []
);
}, [processData, tableActions]);

const handleConfirmClick = async () => {
const minDateValue = Date.parse(minDate);
const maxDateValue = Date.parse(maxDate);

if (
Number.isNaN(minDateValue) ||
Number.isNaN(maxDateValue) ||
minDateValue > maxDateValue
) {
toast({
id: "date-validation-error",
title: "Erro",
description:
"Por favor, insira datas válidas e data da direita menor que a da esquerda",
status: "error",
isClosable: true,
});
} else {
setTableVisible(true);
try {
setIsFetching(true);
await handleProcessByDueDate();
setIsFetching(false);
} catch (error) {
toast({
id: "processes-error",
title: "Erro ao carregar processos",
description: "Insira o período de validade.",
status: "error",
isClosable: true,
});
}
}
};

return (
<Flex
justifyContent="flex-start"
w="90%"
maxW={1120}
flexDir="column"
gap="3"
mb="4"
>
<Flex w="100%" justifyContent="space-between" gap="2" flexWrap="wrap">
<Text
fontSize="lg"
fontWeight="600"
fontStyle="normal"
lineHeight="24px"
>
Estatísticas
</Text>
</Flex>
<Box borderRadius="8px">
<Flex justifyContent="flex-start" w="100%" flexDirection="column">
<CustomAccordion
title="Visualizar processos filtrados por data de vencimento"
marginBottom={18}
>
<>
<Flex justifyContent="space-between">
<Flex w="70%" flexDirection="column">
<Flex alignItems="center" gap="5" marginTop="15">
<Input
w="50%"
type="date"
color="gray.500"
onChange={(event) => {
const novoValor = event.target.value;
setMinDate(novoValor);
}}
/>
<Text>até</Text>
<Input
w="50%"
type="date"
color="gray.500"
onChange={(event) => {
const novoValor = event.target.value;
setMaxDate(novoValor);
}}
/>
<Button
colorScheme="whatsapp"
w="20%"
onClick={() => handleConfirmClick()}
>
Confirmar
</Button>
</Flex>
</Flex>
<Flex>
<Flex
gap="2"
alignItems="flex-end"
alignSelf="end"
marginEnd={-5}
>
{tableVisible && (
<>
<Button colorScheme="facebook" w="10%">
PDF
</Button>
<Button colorScheme="facebook" w="10%">
CSV
</Button>
</>
)}
</Flex>
</Flex>
</Flex>
<Flex w="110%" marginTop="15">
{tableVisible && (
<DataTable
data={filteredStepDeadlineReports}
columns={tableColumns}
isDataFetching={isFetching || loading}
emptyTableMessage="Não foram encontrados processos"
/>
)}
</Flex>
<Flex justifyContent={"center"}>

Check failure on line 276 in src/pages/Statistics/StepDeadlineReports/index.tsx

View workflow job for this annotation

GitHub Actions / lint

Curly braces are unnecessary here
{processDueTotalPages !== undefined ? (
<Pagination
pageCount={processDueTotalPages}
onPageChange={(selectedPage) =>
setCurrentPage(selectedPage.selected)
}
/>
) : null}
</Flex>
</>
</CustomAccordion>
</Flex>
</Box>
</Flex>
);
}
10 changes: 10 additions & 0 deletions src/pages/Statistics/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { PrivateLayout } from "layouts/Private";
import StepDeadlineReports from "./StepDeadlineReports";

export default function Statistics() {
return (
<PrivateLayout>
<StepDeadlineReports />
</PrivateLayout>
);
}
Loading
Loading