bananas-commerce-admin
Version:
What's this, an admin for apes?
173 lines • 10.2 kB
JavaScript
import React, { useEffect, useState } from "react";
import ListAltOutlinedIcon from "@mui/icons-material/ListAltOutlined";
import Checkbox from "@mui/material/Checkbox";
import IconButton from "@mui/material/IconButton";
import Input from "@mui/material/Input";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableRow from "@mui/material/TableRow";
import Typography from "@mui/material/Typography";
import { TableCell } from "../../../components/Table/TableCell";
import TableHead from "../../../components/Table/TableHead";
import TableHeading from "../../../components/Table/TableHeading";
import { useDialog } from "../../../contexts/DialogContext";
import { useI18n } from "../../../contexts/I18nContext";
export const HIDDEN_ITEM_TYPES = ["SHIPPING", "PICKUP"];
export const ReceiptTable = ({ lines, currency, editable, onSelect, }) => {
const [selected, setSelected] = useState([]);
const { t } = useI18n();
const openDialog = useDialog();
const refundableLines = lines.filter((line) => Boolean(line.adjustments.reduce((t, v) => t + v.quantity, line.quantity)));
const sortedLines = lines.sort((a, b) => a.line_number - b.line_number);
// Group lines by their whole number part, sorted by their decimal part
const groupedLines = sortedLines.reduce((lines, line) => {
const lineNumber = Math.floor(line.line_number);
lines[lineNumber] ??= [];
lines[lineNumber].push(line);
return lines;
}, []);
const toggleSelectAll = (_, checked) => {
setSelected(checked ? refundableLines : []);
};
const toggleLine = (item, checked) => {
const index = selected.map(({ line_number }) => line_number).indexOf(item.line_number);
if (checked && index === -1) {
setSelected([...selected, item]);
}
else {
const unselected = [...selected];
unselected.splice(index, 1);
setSelected(unselected);
}
};
const lineQuantityChange = (item) => {
const index = selected.map(({ line_number }) => line_number).indexOf(item.line_number);
const changed = [...selected];
changed[index] = item;
setSelected(changed);
};
useEffect(() => {
if (onSelect != null)
onSelect(selected);
}, [onSelect, selected]);
const showItemProperties = async (title, itemProperties) => {
await openDialog(title, React.createElement(Table, { size: "small", sx: { "& td": { border: 0 } } }, Object.entries(itemProperties ?? {}).map(([key, value]) => (React.createElement(TableRow, { key: key },
React.createElement(TableCell, { variant: "head" }, key.toUpperCase()),
React.createElement(TableCell, { variant: "body" }, `${value}`))))), {
ok: false,
cancel: "Close",
});
};
return (React.createElement(Table, null,
React.createElement(TableHead, null,
editable && (React.createElement(TableHeading, { align: "left", padding: "checkbox" },
React.createElement(Checkbox, { checked: lines.length !== 0 && selected.length === refundableLines.length, color: "secondary", disabled: lines.length === 0, indeterminate: selected.length > 0 && selected.length < refundableLines.length, onChange: toggleSelectAll }))),
React.createElement(TableHeading, { align: "left" }, t("Item")),
React.createElement(TableHeading, { align: "left" }, t("Reference")),
["Quantity", "Unit Price", "Total", "Debit"].map((v, i) => (React.createElement(TableHeading, { key: i, align: "right" }, v)))),
React.createElement(TableBody, null, groupedLines.flatMap((lines) => lines.flatMap((line, index) => {
const isSelected = selected
.map(({ line_number }) => line_number)
.includes(line.line_number);
const currentQuantity = line.adjustments.reduce((t, v) => t + v.quantity, line.quantity);
const firstLine = index === 0;
const subLine = !firstLine;
const finalLine = index === lines.length - 1;
const borderBottom = {
borderBottomStyle: !finalLine ? "dotted" : undefined,
borderBottomWidth: !finalLine ? 2 : undefined,
};
const disabled = currentQuantity === 0;
const firstRow = (React.createElement(TableRow, { key: line.line_number, sx: {
"& td": {
...borderBottom,
borderBottom: editable || line.adjustments.length ? "none" : undefined,
paddingY: 0,
paddingTop: 1,
paddingBottom: line.adjustments.length ? undefined : 1,
whiteSpace: "nowrap",
},
} },
editable ? (React.createElement(TableCell, { align: "left", padding: "checkbox", sx: { verticalAlign: "top" } }, disabled ? null : (React.createElement(Checkbox, { checked: isSelected && currentQuantity !== 0, color: "secondary", onChange: (_, checked) => toggleLine({ ...line, quantity: currentQuantity }, checked) })))) : null,
React.createElement(TableCell, { align: "left" },
React.createElement(Typography, { fontSize: "0.875rem", paddingLeft: subLine ? 2 : undefined },
line.title,
line.item_properties && (React.createElement(IconButton, { "aria-label": "Show line item properties", size: "small", onClick: () => showItemProperties(line.title, line.item_properties) },
React.createElement(ListAltOutlinedIcon, { fontSize: "small" }))))),
React.createElement(TableCell, { align: "left" }, ["SHIPPING", "PICKUP"].includes(line.item_type) ? null : line.reference),
React.createElement(TableCell, { align: "right", typographyProps: { fontSize: "0.875rem" } }, line.quantity),
React.createElement(TableCell, { align: "right" },
line.unit_price,
" ",
currency),
React.createElement(TableCell, { align: "right" },
React.createElement(Typography, { fontSize: "0.875rem" },
line.total_amount,
" ",
currency)),
React.createElement(TableCell, { align: "right" },
React.createElement(Typography, { fontSize: "0.875rem" },
line.total_amount,
" ",
currency))));
const adjustmentsRows = line.adjustments.map((adjustment, i) => {
const lastRow = !editable && i == line.adjustments.length - 1;
const typeNameMap = {
CANCELLATION: "Cancellation",
RETURN: "Return",
REFUND: "Refund",
DISCOUNT: "Discount",
};
const withTitle = (name, title) => {
if (title) {
return `${typeNameMap[name]}: ${title}`;
}
else {
return typeNameMap[name];
}
};
const pending = adjustment.receipt_number === null;
return (React.createElement(TableRow, { key: line.line_number + String(i), sx: {
"& td": {
...borderBottom,
borderBottom: lastRow ? undefined : "none",
color: "grey.600",
fontStyle: pending ? "italic" : undefined,
py: 0,
pb: lastRow ? 1 : undefined,
whiteSpace: "nowrap",
},
} },
editable && (React.createElement(TableCell, { align: "left", padding: "checkbox", sx: { paddingTop: 0.7 } })),
React.createElement(TableCell, { typographyProps: { pl: subLine ? 4 : 2, fontSize: "0.875rem" } }, withTitle(adjustment.adjustment_type, adjustment.title)),
React.createElement(TableCell, null),
React.createElement(TableCell, { align: "right" }, adjustment.quantity),
React.createElement(TableCell, null),
React.createElement(TableCell, { align: "right", style: { verticalAlign: "top" } },
adjustment.total_amount,
" ",
currency),
React.createElement(TableCell, { align: "right", typographyProps: { fontSize: "0.875rem" } }, Boolean(lastRow && line.remaining_amount != line.total_amount) &&
`${line?.remaining_amount} ${currency}`)));
});
const rows = [firstRow, ...adjustmentsRows];
if (editable) {
rows.push(React.createElement(TableRow, { sx: { "& td": { pt: 0, pb: 1 } } },
React.createElement(TableCell, null),
React.createElement(TableCell, null),
React.createElement(TableCell, null),
React.createElement(TableCell, { align: "right" }, !disabled && (React.createElement(Input, { defaultValue: currentQuantity * -1, disabled: !isSelected, inputProps: {
max: Math.max(currentQuantity * -1, -1),
min: currentQuantity * -1,
}, type: "number", onChange: (event) => lineQuantityChange({
...line,
quantity: Number.parseInt(event.target.value) * -1,
}) }))),
React.createElement(TableCell, null),
React.createElement(TableCell, null),
React.createElement(TableCell, null)));
}
return rows;
})))));
};
//# sourceMappingURL=ReceiptTable.js.map