Files
spoolman2/client/src/pages/spools/show.tsx

227 lines
7.3 KiB
TypeScript

import { getBasePath } from "../../utils/url";
import { InboxOutlined, PrinterOutlined, ToTopOutlined } from "@ant-design/icons";
import { DateField, NumberField, Show, TextField } from "@refinedev/antd";
import { IResourceComponentsProps, useInvalidate, useShow, useTranslate } from "@refinedev/core";
import { Button, Modal, Typography } from "antd";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import React from "react";
import { ExtraFieldDisplay } from "../../components/extraFields";
import { NumberFieldUnit } from "../../components/numberField";
import SpoolIcon from "../../components/spoolIcon";
import { enrichText } from "../../utils/parsing";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { useCurrency } from "../../utils/settings";
import { IFilament } from "../filaments/model";
import { setSpoolArchived } from "./functions";
import { ISpool } from "./model";
dayjs.extend(utc);
const { Title } = Typography;
const { confirm } = Modal;
export const SpoolShow: React.FC<IResourceComponentsProps> = () => {
const t = useTranslate();
const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency();
const invalidate = useInvalidate();
const { queryResult } = useShow<ISpool>({
liveMode: "auto",
});
const { data, isLoading } = queryResult;
const record = data?.data;
const spoolPrice = (item: ISpool) => {
let spoolPrice = "";
if (item.price === undefined) {
spoolPrice = `${item.filament.price}`;
return spoolPrice;
}
return item.price;
};
// Function for opening an ant design modal that asks for confirmation for archiving a spool
const archiveSpool = async (spool: ISpool, archive: boolean) => {
await setSpoolArchived(spool, archive);
invalidate({
resource: "spool",
id: spool.id,
invalidates: ["list", "detail"],
});
};
const archiveSpoolPopup = async (spool: ISpool | undefined) => {
if (spool === undefined) {
return;
}
// If the spool has no remaining weight, archive it immediately since it's likely not a mistake
if (spool.remaining_weight != undefined && spool.remaining_weight <= 0) {
await archiveSpool(spool, true);
} else {
confirm({
title: t("spool.titles.archive"),
content: t("spool.messages.archive"),
okText: t("buttons.archive"),
okType: "primary",
cancelText: t("buttons.cancel"),
onOk() {
return archiveSpool(spool, true);
},
});
}
};
const formatFilament = (item: IFilament) => {
let vendorPrefix = "";
if (item.vendor) {
vendorPrefix = `${item.vendor.name} - `;
}
let name = item.name;
if (!name) {
name = `ID: ${item.id}`;
}
let material = "";
if (item.material) {
material = ` - ${item.material}`;
}
return `${vendorPrefix}${name}${material}`;
};
const filamentURL = (item: IFilament) => {
const URL = `/filament/show/${item.id}`;
return <a href={URL}>{formatFilament(item)}</a>;
};
const formatTitle = (item: ISpool) => {
return t("spool.titles.show_title", {
id: item.id,
name: formatFilament(item.filament),
interpolation: { escapeValue: false },
});
};
const colorObj = record?.filament.multi_color_hexes
? {
colors: record.filament.multi_color_hexes.split(","),
vertical: record.filament.multi_color_direction === "longitudinal",
}
: record?.filament.color_hex;
return (
<Show
isLoading={isLoading}
title={record ? formatTitle(record) : ""}
headerButtons={({ defaultButtons }) => (
<>
<Button
type="primary"
icon={<PrinterOutlined />}
href={getBasePath() + "/spool/print?spools=" + record?.id + "&return=" + encodeURIComponent(window.location.pathname)}
>
{t("printing.qrcode.button")}
</Button>
{record?.archived ? (
<Button icon={<ToTopOutlined />} onClick={() => archiveSpool(record, false)}>
{t("buttons.unArchive")}
</Button>
) : (
<Button danger icon={<InboxOutlined />} onClick={() => archiveSpoolPopup(record)}>
{t("buttons.archive")}
</Button>
)}
{defaultButtons}
</>
)}
>
<Title level={5}>{t("spool.fields.id")}</Title>
<NumberField value={record?.id ?? ""} />
<Title level={5}>{t("spool.fields.filament")}</Title>
{colorObj && <SpoolIcon color={colorObj} />} <TextField value={record ? filamentURL(record?.filament) : ""} />
<Title level={5}>{t("spool.fields.price")}</Title>
<NumberField
value={record ? spoolPrice(record) : ""}
options={{
style: "currency",
currency: currency,
currencyDisplay: "narrowSymbol",
notation: "compact",
}}
/>
<Title level={5}>{t("spool.fields.registered")}</Title>
<DateField
value={dayjs.utc(record?.registered).local()}
title={dayjs.utc(record?.registered).local().format()}
format="YYYY-MM-DD HH:mm:ss"
/>
<Title level={5}>{t("spool.fields.first_used")}</Title>
<DateField
hidden={!record?.first_used}
value={dayjs.utc(record?.first_used).local()}
title={dayjs.utc(record?.first_used).local().format()}
format="YYYY-MM-DD HH:mm:ss"
/>
<Title level={5}>{t("spool.fields.last_used")}</Title>
<DateField
hidden={!record?.last_used}
value={dayjs.utc(record?.last_used).local()}
title={dayjs.utc(record?.last_used).local().format()}
format="YYYY-MM-DD HH:mm:ss"
/>
<Title level={5}>{t("spool.fields.remaining_length")}</Title>
<NumberFieldUnit
value={record?.remaining_length ?? ""}
unit="mm"
options={{
maximumFractionDigits: 1,
minimumFractionDigits: 1,
}}
/>
<Title level={5}>{t("spool.fields.used_length")}</Title>
<NumberFieldUnit
value={record?.used_length ?? ""}
unit="mm"
options={{
maximumFractionDigits: 1,
minimumFractionDigits: 1,
}}
/>
<Title level={5}>{t("spool.fields.remaining_weight")}</Title>
<NumberFieldUnit
value={record?.remaining_weight ?? ""}
unit="g"
options={{
maximumFractionDigits: 1,
minimumFractionDigits: 1,
}}
/>
<Title level={5}>{t("spool.fields.used_weight")}</Title>
<NumberFieldUnit
value={record?.used_weight ?? ""}
unit="g"
options={{
maximumFractionDigits: 1,
minimumFractionDigits: 1,
}}
/>
<Title level={5}>{t("spool.fields.location")}</Title>
<TextField value={record?.location} />
<Title level={5}>{t("spool.fields.lot_nr")}</Title>
<TextField value={record?.lot_nr} />
<Title level={5}>{t("spool.fields.comment")}</Title>
<TextField value={enrichText(record?.comment)} />
<Title level={5}>{t("spool.fields.archived")}</Title>
<TextField value={record?.archived ? t("yes") : t("no")} />
<Title level={4}>{t("settings.extra_fields.tab")}</Title>
{extraFields?.data?.map((field, index) => (
<ExtraFieldDisplay key={index} field={field} value={record?.extra[field.key]} />
))}
</Show>
);
};
export default SpoolShow;