Skip to content

Commit

Permalink
Docx Export (#241)
Browse files Browse the repository at this point in the history
* add option to export logs as docx and include sort direction

* run the linter
  • Loading branch information
Connor Bechthold authored Apr 22, 2024
1 parent 348ba3f commit d8aa43d
Show file tree
Hide file tree
Showing 8 changed files with 318 additions and 97 deletions.
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"bootstrap": "^4.6.0",
"date-fns": "^2.30.0",
"dayzed": "^3.2.3",
"docx": "8.0.0",
"framer-motion": "^4.1.17",
"graphql": "^15.5.0",
"humps": "^2.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,21 @@ import {
ModalCloseButton,
Spinner,
FormLabel,
Flex,
} from "@chakra-ui/react";
import { ArrowDownIcon, ArrowUpIcon } from "@chakra-ui/icons";
import { TiExport } from "react-icons/ti";
import LogRecordAPIClient from "../../APIClients/LogRecordAPIClient";
import { singleDatePickerStyle } from "../../theme/forms/datePickerStyles";
import convertLogsToCSV from "../../helper/csvHelpers";
import {
convertLogsToDOCX,
convertLogsToCSV,
} from "../../helper/exportHelpers";
import CreateToast from "../common/Toasts";
import { getFormattedDateAndTime } from "../../helper/dateHelpers";
import { SingleDatepicker } from "../common/Datepicker";

const ExportToCSV = (): React.ReactElement => {
const ExportLogs = (): React.ReactElement => {
const [startDate, setStartDate] = useState<Date | undefined>();
const [isStartDateEmpty, setIsStartDateEmpty] = useState<boolean>(true);
const [endDate, setEndDate] = useState<Date | undefined>();
Expand All @@ -39,6 +44,8 @@ const ExportToCSV = (): React.ReactElement => {
const [endDateError, setEndDateError] = useState<boolean>(false);
const [dateError, setDateError] = useState<boolean>(false);

const [sortDirection, setSortDirection] = useState("desc");

const [isOpen, setOpen] = useState(false);

const [loading, setLoading] = useState(false);
Expand All @@ -47,6 +54,7 @@ const ExportToCSV = (): React.ReactElement => {
const handleClear = () => {
setStartDate(undefined);
setEndDate(undefined);
setSortDirection("desc");
setDateError(false);
setStartDateError(false);
setEndDateError(false);
Expand Down Expand Up @@ -93,20 +101,23 @@ const ExportToCSV = (): React.ReactElement => {
setOpen(false);
};

const handleSubmit = async () => {
const validateDates = (): boolean => {
if (!startDate && !isStartDateEmpty) {
setStartDateError(true);
return;
return false;
}
if (!endDate && !isEndDateEmpty) {
setEndDateError(true);
return;
return false;
}
if (startDate && endDate && startDate > endDate) {
setDateError(true);
return;
return false;
}
return true;
};

const constructDateRange = (): (string | null)[] | undefined => {
let dateRange;
if (startDate || endDate) {
startDate?.setHours(0, 0, 0, 0);
Expand All @@ -117,10 +128,57 @@ const ExportToCSV = (): React.ReactElement => {
endDate ? endDate.toISOString() : null,
];
}

return dateRange;
};

const handleDocxExport = async () => {
if (!validateDates()) {
return;
}

setLoading(true);
const data = await LogRecordAPIClient.filterLogRecords({
dateRange,
returnAll: true, // return all data
dateRange: constructDateRange(),
sortDirection,
returnAll: true,
});

if (!data || data.logRecords.length === 0) {
newToast(
"Error downloading DOCX",
"No records found in the provided date range.",
"error",
);
} else {
const formattedLogRecords = data.logRecords.map((logRecord) => {
const { date, time } = getFormattedDateAndTime(
new Date(logRecord.datetime),
true,
);
return { ...logRecord, datetime: `${date}, ${time}` };
});
const success = await convertLogsToDOCX(formattedLogRecords);
if (success) {
newToast("DOCX downloaded", "Successfully downloaded DOCX.", "success");
handleClose();
} else {
newToast("Error downloading DOCX", "Unable to download DOCX.", "error");
}
}
setLoading(false);
};

const handleCsvExport = async () => {
if (!validateDates()) {
return;
}

setLoading(true);
const data = await LogRecordAPIClient.filterLogRecords({
dateRange: constructDateRange(),
sortDirection,
returnAll: true,
});

if (!data || data.logRecords.length === 0) {
Expand Down Expand Up @@ -150,9 +208,9 @@ const ExportToCSV = (): React.ReactElement => {

return (
<>
<Tooltip label="Export to CSV">
<Tooltip label="Export Logs">
<IconButton
aria-label="Export to CSV"
aria-label="Export Logs"
icon={<Icon boxSize="36px" as={TiExport} />}
variant="tertiary"
onClick={handleOpen}
Expand All @@ -163,7 +221,7 @@ const ExportToCSV = (): React.ReactElement => {
<Modal isOpen={isOpen} onClose={handleClose} size="xl">
<ModalOverlay />
<ModalContent>
<ModalHeader>Export to CSV File</ModalHeader>
<ModalHeader>Export Logs</ModalHeader>
<ModalCloseButton size="lg" />
<ModalBody>
<FormControl isInvalid={dateError}>
Expand Down Expand Up @@ -225,6 +283,32 @@ const ExportToCSV = (): React.ReactElement => {
Note: If a range is not selected, all records will be printed.
</FormHelperText>
</FormControl>
<FormControl>
<FormLabel mt={4}>Sort Direction</FormLabel>
<Flex alignItems="center" gap="10px">
<IconButton
aria-label="calendar"
size="sm"
variant="secondary"
fontSize="20px"
icon={
sortDirection === "desc" ? (
<ArrowDownIcon />
) : (
<ArrowUpIcon />
)
}
onClick={() =>
setSortDirection(
sortDirection === "desc" ? "asc" : "desc",
)
}
/>
<Text>
{sortDirection === "desc" ? "Descending" : "Ascending"}
</Text>
</Flex>
</FormControl>
</ModalBody>

<ModalFooter>
Expand All @@ -237,8 +321,16 @@ const ExportToCSV = (): React.ReactElement => {
marginRight="10px"
/>
)}
<Button onClick={handleSubmit} variant="primary" type="submit">
Export
<Button
onClick={handleDocxExport}
variant="primary"
type="submit"
marginRight="10px"
>
Export As DOCX
</Button>
<Button onClick={handleCsvExport} variant="primary" type="submit">
Export As CSV
</Button>
</ModalFooter>
</ModalContent>
Expand All @@ -248,4 +340,4 @@ const ExportToCSV = (): React.ReactElement => {
);
};

export default ExportToCSV;
export default ExportLogs;
4 changes: 2 additions & 2 deletions frontend/src/components/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import CreateLog from "../../forms/CreateLog";
import { LogRecord } from "../../../types/LogRecordTypes";
import LogRecordsTable from "./LogRecordsTable";
import HomePageFilters from "./HomePageFilters";
import ExportToCSV from "../../forms/ExportToCSV";
import ExportLogs from "../../forms/ExportLogs";
import LogRecordAPIClient from "../../../APIClients/LogRecordAPIClient";
import { SelectLabel } from "../../../types/SharedTypes";

Expand Down Expand Up @@ -219,7 +219,7 @@ const HomePage = (): React.ReactElement => {
countRecords={countLogRecords}
setUserPageNum={setUserPageNum}
/>
<ExportToCSV />
<ExportLogs />
</Flex>
</Flex>

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/pages/HomePage/LogRecordsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ const LogRecordsTable = ({
<Th>Tenants</Th>
<Th>Note</Th>
<Th>Employee</Th>
<Th>Attn To</Th>
<Th>Attn Tos</Th>
<Th>Tags</Th>
<Th> </Th>
</Tr>
Expand Down
68 changes: 0 additions & 68 deletions frontend/src/helper/csvHelpers.ts

This file was deleted.

Loading

0 comments on commit d8aa43d

Please sign in to comment.