UNPKG

bananas-commerce-admin

Version:

What's this, an admin for apes?

173 lines 10.2 kB
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