UNPKG

bananas-commerce-admin

Version:

What's this, an admin for apes?

147 lines 7.49 kB
import React, { useCallback, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; import Box from "@mui/material/Box"; import Button from "@mui/material/Button"; import Card from "@mui/material/Card"; import CardActions from "@mui/material/CardActions"; import Stack from "@mui/material/Stack"; import { useTheme } from "@mui/material/styles"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableContainer from "@mui/material/TableContainer"; import TableRow from "@mui/material/TableRow"; import { TableCell } from "../../../components/Table/TableCell"; import TableHead from "../../../components/Table/TableHead"; import TableHeading from "../../../components/Table/TableHeading"; import TableCardHeader from "../../../components/TableCardHeader"; import { useApi } from "../../../contexts/ApiContext"; import { useDialog } from "../../../contexts/DialogContext"; import { useI18n } from "../../../contexts/I18nContext"; import { useUser } from "../../../contexts/UserContext"; import { hasPermission } from "../../../util/has_permission"; import { PriceRow } from "./PriceRow"; export const PricesCard = ({ prices, setPrices }) => { const theme = useTheme(); const openDialog = useDialog(); const api = useApi(); const params = useParams(); const { t } = useI18n(); const { user } = useUser(); const [isEditing, setIsEditing] = useState(false); const [isDisabled, setIsDisabled] = useState(false); const [changedPrices, setChangedPrices] = useState({}); const [deletedPrices, setDeletedPrices] = useState([]); const [createdPrices, setCreatedPrices] = useState([]); const hasChanges = useMemo(() => Object.entries(changedPrices).length > 0 || deletedPrices.length > 0 || createdPrices.length > 0, [changedPrices, deletedPrices, createdPrices]); const shownPrices = useMemo(() => { if (!isEditing) return prices; return prices .map(({ amount, ...price }) => { if (deletedPrices.includes(price.article_code)) { return null; } return { ...price, amount: changedPrices[price.article_code] ?? amount, }; }) .filter((price) => price !== null); }, [prices, isEditing, changedPrices, deletedPrices]); const clear = useCallback(() => { setChangedPrices({}); setDeletedPrices([]); setCreatedPrices([]); setIsEditing(false); }, []); const save = useCallback(async () => { const action = api.operations["pricing.contrib:prices-update"]; if (!action) { throw new Error('Invalid action "pricing.contrib:prices-update".'); } setIsDisabled(true); const response = await action.call({ params, body: { updates: [ ...Object.entries(changedPrices).map(([article_code, amount]) => ({ article_code, amount, })), ...createdPrices, ], deleted: deletedPrices, }, }); setIsDisabled(false); if (response.ok) { const updatedPrices = await response.json(); setPrices(updatedPrices); clear(); } else { console.error("[PRICES_CARD]", response); } }, [changedPrices, deletedPrices, createdPrices]); return (React.createElement(Card, { sx: { boxShadow: 0, borderRadius: 3, borderWidth: "1px", borderStyle: "solid", borderColor: theme.palette.divider, backgroundColor: theme.palette.background.paper, overflow: "visible", width: "100%", } }, React.createElement(TableCardHeader, { isDisabled: isDisabled, isEditable: hasPermission(user, "pricing.change_price"), title: "Prices", toggled: isEditing, onChange: async (isEditing) => { if (hasChanges) { if (await openDialog("Unsaved changes", "You have unsaved changes. Are you sure you want to discard your changes?", { ok: "Discard changes", cancel: "Cancel" })) { clear(); } } else { setIsEditing(isEditing); } } }), React.createElement(TableContainer, null, React.createElement(Table, null, React.createElement(TableHead, null, React.createElement(TableHeading, null, t("Article number")), React.createElement(TableHeading, { align: "right" }, t("Amount")), React.createElement(TableHeading, null)), React.createElement(TableBody, { sx: { ".MuiTableRow-root:last-child > .MuiTableCell-root": { borderBottom: "none" }, } }, shownPrices.length === 0 && (React.createElement(TableRow, null, React.createElement(TableCell, { align: "center", colSpan: 3, sx: { color: "GrayText" } }, t("No prices")))), shownPrices.map((price, i) => (React.createElement(PriceRow, { key: i, isDisabled: isDisabled, isEditing: isEditing, price: price, onChangeAmount: (amount) => { setChangedPrices((prev) => ({ ...prev, [price.article_code]: amount })); }, onDelete: () => { setDeletedPrices((prev) => [...prev, price.article_code]); } }))), isEditing && (React.createElement(React.Fragment, null, createdPrices.map((price, i) => (React.createElement(PriceRow, { key: i, isDisabled: isDisabled, isEditing: true, price: price, onChangeAmount: (amount) => { setCreatedPrices((prev) => prev.map((p, j) => (i === j ? { ...p, amount } : p))); }, onChangeArticleCode: (article_code) => { setCreatedPrices((prev) => prev.map((p, j) => (i === j ? { ...p, article_code } : p))); }, onDelete: () => { setCreatedPrices((prev) => prev.filter((_, j) => j !== i)); } })))))))), isEditing && (React.createElement(Stack, { direction: "row", justifyContent: "space-between" }, React.createElement(Box, { p: [1, 2, 3, 2] }, React.createElement(Button, { disabled: isDisabled, size: "medium", variant: "outlined", onClick: () => { setCreatedPrices((prev) => [ ...prev, { article_code: "", amount: "", currency: shownPrices[0]?.currency ?? "" }, ]); } }, "Add price")), React.createElement(CardActions, { sx: { p: [1, 2, 3, 2], display: "flex", justifyContent: "flex-end", } }, React.createElement(Button, { disabled: isDisabled, size: "medium", variant: "outlined", onClick: clear }, t("Cancel")), React.createElement(Button, { disabled: isDisabled, size: "medium", variant: "contained", onClick: save }, t("Save"))))))); }; //# sourceMappingURL=PricesCard.js.map