bananas-commerce-admin
Version:
What's this, an admin for apes?
94 lines • 4.58 kB
JavaScript
import React, { useCallback, useMemo } from "react";
import { Button, Stack, TableBody, TableRow } from "@mui/material";
import { useDashboardFilter } from "../contexts/DashboardFilterContext";
import { formatDate } from "../util/format_date";
import { TableCell } from "./Table/TableCell";
import TableHead from "./Table/TableHead";
import TableHeading from "./Table/TableHeading";
import Table from "./Table";
export default function StatsDataTable({ data, dateKey, csvFileName }) {
const { filter } = useDashboardFilter();
const mappedData = useMemo(() => {
return data
.map((item) => {
const dateEntry = getDateEntry(item, dateKey);
if (dateEntry === undefined)
return undefined;
const [key, date] = dateEntry;
const { [key]: _, ...rest } = item;
return { [key]: date, ...rest };
})
.filter((item) => item !== undefined);
}, [data, dateKey]);
const handleExportToCSV = useCallback(() => {
if (mappedData.length === 0)
return;
const headers = Object.keys(mappedData[0]);
const csvRows = [
headers.join(","), // Header row
...mappedData.map((row) => headers
.map((key) => {
const value = row[key];
if (value instanceof Date)
return `"${value.toISOString()}"`;
if (typeof value === "string")
return `"${value.replace(/"/g, '""')}"`; // Escape quotes
return value;
})
.join(",")),
];
const csvContent = csvRows.join("\n");
const blob = new Blob([csvContent], { type: "text/csv" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = `${csvFileName || "data"}_${filter.startDate.toISO()?.split("T")[0]}_${filter.endDate.toISO()?.split("T")[0]}.csv`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}, [mappedData, filter.startDate, filter.endDate, filter.granularity]);
return (React.createElement(Stack, { maxHeight: 300 },
React.createElement(Table, { count: mappedData.length },
React.createElement(TableHead, { tableRowProps: {
sx: {
position: "sticky",
top: 0,
bgcolor: "background.paper",
backgroundImage: "var(--Paper-overlay)",
boxShadow: "inset 0 -1px var(--mui-palette-divider)",
},
} }, mappedData.length > 0 &&
Object.keys(mappedData[0]).map((key) => {
return React.createElement(TableHeading, { key: key }, formatKey(key));
})),
React.createElement(TableBody, { sx: { overflowY: "auto" } }, mappedData.map((item, i) => (React.createElement(TableRow, { key: i }, Object.entries(item).map(([key, value]) => (React.createElement(TableCell, { key: key, sx: { borderBottomWidth: i === mappedData.length - 1 ? 0 : 1 } }, value instanceof Date ? formatDate(value, filter.granularity) : value.toString())))))))),
React.createElement(Stack, { alignItems: "flex-end", pt: 2, px: 2, spacing: 1, sx: { borderTop: "1px solid", borderColor: "divider" } },
React.createElement(Button, { color: "inherit", variant: "outlined", onClick: handleExportToCSV }, "Export to CSV"))));
}
function formatKey(key) {
return key
.split("_")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
}
function getDateEntry(item, dateKey) {
if (dateKey !== undefined && item.hasOwnProperty(dateKey)) {
let date = item[dateKey];
date = typeof date === "string" ? new Date(date) : date;
if (!(date instanceof Date))
return undefined;
return [dateKey, date];
}
const dateEntry = Object.entries(item).find(([_, value]) => isDateOrString(value));
if (dateEntry === undefined) {
return undefined;
}
const dateObj = dateEntry[1] instanceof Date ? dateEntry[1] : new Date(dateEntry[1]);
return [dateEntry[0], dateObj];
}
function isDateOrString(value) {
return ((value instanceof Date && !Number.isNaN(value.getTime())) ||
(typeof value === "string" && !Number.isNaN(Date.parse(value))));
}
//# sourceMappingURL=StatsDataTable.js.map