Currency setting is now utilized in filament/spool lists, edit pages etc

This commit is contained in:
Donkie
2024-02-02 23:06:06 +01:00
parent 220457c1ac
commit c65bc4201b
11 changed files with 96 additions and 8 deletions

View File

@@ -153,7 +153,7 @@
"archived": "Archived"
},
"fields_help": {
"price": "Price of a full spool in the system configured currency. If not set, the price of the filament will be assumed instead.",
"price": "Price of a full spool. If not set, the price of the filament will be assumed instead.",
"weight_to_use": "Select what weight value to enter. Measured weight is only available if the spool weight is set for the selected filament.",
"used_weight": "How much filament has been used from the spool. A new spool should have 0g used.",
"remaining_weight": "How much filament is left on the spool. For a new spool this should match the spool weight.",
@@ -202,7 +202,7 @@
"fields_help": {
"name": "Filament name, to distinguish this filament type among others from the same vendor. Should contain the color for example.",
"material": "E.g. PLA, ABS, PETG, etc.",
"price": "Price of a full spool in the system configured currency.",
"price": "Price of a full spool.",
"weight": "The filament weight of a full spool (net weight). This should not include the weight of the spool itself, only the filament. It is what is usually written on the packaging.",
"spool_weight": "The weight of an empty spool. Used to determine measured weight of a spool.",
"article_number": "E.g. EAN, UPC, etc."

View File

@@ -53,6 +53,7 @@ interface BaseColumnProps<Obj extends Entity> {
width?: number;
actions?: (record: Obj) => Action[];
transform?: (value: unknown) => unknown;
render?: (rawValue: string | undefined, record: Obj) => React.ReactNode;
}
interface FilteredColumnProps {

View File

@@ -10,6 +10,7 @@ import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
dayjs.extend(utc);
@@ -20,6 +21,7 @@ interface CreateOrCloneProps {
export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps> = (props) => {
const t = useTranslate();
const extraFields = useGetFields(EntityType.filament);
const currency = useCurrency();
const { form, formProps, formLoading, onFinish, redirect } = useForm<
IFilament,
@@ -149,7 +151,12 @@ export const FilamentCreate: React.FC<IResourceComponentsProps & CreateOrClonePr
},
]}
>
<InputNumber precision={2} formatter={numberFormatter} parser={numberParser} />
<InputNumber
addonAfter={getCurrencySymbol(undefined, currency)}
precision={2}
formatter={numberFormatter}
parser={numberParser}
/>
</Form.Item>
<Form.Item
label={t("filament.fields.density")}

View File

@@ -10,6 +10,7 @@ import { IFilament, IFilamentParsedExtras } from "./model";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
import { ParsedExtras } from "../../components/extraFields";
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
/*
The API returns the extra fields as JSON values, but we need to parse them into their real types
@@ -23,6 +24,7 @@ export const FilamentEdit: React.FC<IResourceComponentsProps> = () => {
const [messageApi, contextHolder] = message.useMessage();
const [hasChanged, setHasChanged] = useState(false);
const extraFields = useGetFields(EntityType.filament);
const currency = useCurrency();
const { formProps, saveButtonProps } = useForm<IFilament, HttpError, IFilament, IFilament>({
liveMode: "manual",
@@ -168,7 +170,12 @@ export const FilamentEdit: React.FC<IResourceComponentsProps> = () => {
},
]}
>
<InputNumber precision={2} formatter={numberFormatter} parser={numberParser} />
<InputNumber
addonAfter={getCurrencySymbol(undefined, currency)}
precision={2}
formatter={numberFormatter}
parser={numberParser}
/>
</Form.Item>
<Form.Item
label={t("filament.fields.density")}

View File

@@ -27,6 +27,7 @@ import { useLiveify } from "../../components/liveify";
import { removeUndefined } from "../../utils/filtering";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { useNavigate } from "react-router-dom";
import { useCurrency } from "../../utils/settings";
dayjs.extend(utc);
@@ -76,6 +77,7 @@ export const FilamentList: React.FC<IResourceComponentsProps> = () => {
const invalidate = useInvalidate();
const navigate = useNavigate();
const extraFields = useGetFields(EntityType.filament);
const currency = useCurrency();
const allColumnsWithExtraFields = [...allColumns, ...(extraFields.data?.map((field) => "extra." + field.key) ?? [])];
@@ -253,6 +255,14 @@ export const FilamentList: React.FC<IResourceComponentsProps> = () => {
id: "price",
i18ncat: "filament",
width: 80,
render: (_, obj: IFilamentCollapsed) => {
return obj.price?.toLocaleString(undefined, {
style: "currency",
currencyDisplay: "narrowSymbol",
currency: currency,
notation: "compact",
});
},
}),
NumberColumn({
...commonProps,

View File

@@ -10,6 +10,7 @@ import { enrichText } from "../../utils/parsing";
import { useNavigate } from "react-router-dom";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldDisplay } from "../../components/extraFields";
import { useCurrency } from "../../utils/settings";
dayjs.extend(utc);
const { Title } = Typography;
@@ -18,6 +19,7 @@ export const FilamentShow: React.FC<IResourceComponentsProps> = () => {
const t = useTranslate();
const navigate = useNavigate();
const extraFields = useGetFields(EntityType.filament);
const currency = useCurrency();
const { queryResult } = useShow<IFilament>({
liveMode: "auto",
});
@@ -82,7 +84,15 @@ export const FilamentShow: React.FC<IResourceComponentsProps> = () => {
<Title level={5}>{t("filament.fields.material")}</Title>
<TextField value={record?.material} />
<Title level={5}>{t("filament.fields.price")}</Title>
<NumberField value={record?.price ?? ""} />
<NumberField
value={record?.price ?? ""}
options={{
style: "currency",
currency: currency,
currencyDisplay: "narrowSymbol",
notation: "compact",
}}
/>
<Title level={5}>{t("filament.fields.density")}</Title>
<NumberFieldUnit
value={record?.density ?? ""}

View File

@@ -13,6 +13,7 @@ import "../../utils/overrides.css";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
import utc from "dayjs/plugin/utc";
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
dayjs.extend(utc);
@@ -23,6 +24,7 @@ interface CreateOrCloneProps {
export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps> = (props) => {
const t = useTranslate();
const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency();
const { form, formProps, formLoading, onFinish, redirect } = useForm<
ISpool,
@@ -245,7 +247,12 @@ export const SpoolCreate: React.FC<IResourceComponentsProps & CreateOrCloneProps
},
]}
>
<InputNumber precision={2} formatter={numberFormatter} parser={numberParser} />
<InputNumber
addonAfter={getCurrencySymbol(undefined, currency)}
precision={2}
formatter={numberFormatter}
parser={numberParser}
/>
</Form.Item>
<Form.Item hidden={true} name={["used_weight"]} initialValue={0}>
<InputNumber value={usedWeight} />

View File

@@ -12,6 +12,7 @@ import { message } from "antd/lib";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldFormItem, StringifiedExtras } from "../../components/extraFields";
import { ParsedExtras } from "../../components/extraFields";
import { getCurrencySymbol, useCurrency } from "../../utils/settings";
/*
The API returns the extra fields as JSON values, but we need to parse them into their real types
@@ -31,6 +32,7 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
const [messageApi, contextHolder] = message.useMessage();
const [hasChanged, setHasChanged] = useState(false);
const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency();
const { form, formProps, saveButtonProps } = useForm<ISpool, HttpError, ISpool, ISpool>({
liveMode: "manual",
@@ -229,7 +231,12 @@ export const SpoolEdit: React.FC<IResourceComponentsProps> = () => {
},
]}
>
<InputNumber precision={2} formatter={numberFormatter} parser={numberParser} />
<InputNumber
addonAfter={getCurrencySymbol(undefined, currency)}
precision={2}
formatter={numberFormatter}
parser={numberParser}
/>
</Form.Item>
<Form.Item hidden={true} name={["used_weight"]} initialValue={0}>
<InputNumber value={usedWeight} />

View File

@@ -37,6 +37,7 @@ import { useLiveify } from "../../components/liveify";
import { removeUndefined } from "../../utils/filtering";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { useNavigate } from "react-router-dom";
import { useCurrency } from "../../utils/settings";
dayjs.extend(utc);
@@ -100,6 +101,7 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
const invalidate = useInvalidate();
const navigate = useNavigate();
const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency();
const allColumnsWithExtraFields = [...allColumns, ...(extraFields.data?.map((field) => "extra." + field.key) ?? [])];
@@ -356,6 +358,14 @@ export const SpoolList: React.FC<IResourceComponentsProps> = () => {
id: "price",
i18ncat: "spool",
width: 80,
render: (_, obj: ISpoolCollapsed) => {
return obj.price?.toLocaleString(undefined, {
style: "currency",
currencyDisplay: "narrowSymbol",
currency: currency,
notation: "compact",
});
},
}),
NumberColumn({
...commonProps,

View File

@@ -10,6 +10,7 @@ import { enrichText } from "../../utils/parsing";
import { IFilament } from "../filaments/model";
import { EntityType, useGetFields } from "../../utils/queryFields";
import { ExtraFieldDisplay } from "../../components/extraFields";
import { useCurrency } from "../../utils/settings";
dayjs.extend(utc);
@@ -18,6 +19,7 @@ const { Title } = Typography;
export const SpoolShow: React.FC<IResourceComponentsProps> = () => {
const t = useTranslate();
const extraFields = useGetFields(EntityType.spool);
const currency = useCurrency();
const { queryResult } = useShow<ISpool>({
liveMode: "auto",
@@ -71,7 +73,15 @@ export const SpoolShow: React.FC<IResourceComponentsProps> = () => {
<Title level={5}>{t("spool.fields.filament")}</Title>
<TextField value={record ? filamentURL(record?.filament) : ""} />
<Title level={5}>{t("spool.fields.price")}</Title>
<NumberField value={record ? spoolPrice(record) : ""} />
<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()}

View File

@@ -0,0 +1,19 @@
import { useGetSetting } from "./querySettings";
export function useCurrency() {
const { data: currency } = useGetSetting("currency");
return JSON.parse(currency?.value ?? '"EUR"');
}
export function getCurrencySymbol(locale: string | undefined, currency: string) {
return (0)
.toLocaleString(locale, {
style: "currency",
currency,
currencyDisplay: "narrowSymbol",
minimumFractionDigits: 0,
maximumFractionDigits: 0,
})
.replace(/\d/g, "")
.trim();
}