Currency setting is now utilized in filament/spool lists, edit pages etc
This commit is contained in:
@@ -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."
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")}
|
||||
|
||||
@@ -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")}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 ?? ""}
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()}
|
||||
|
||||
19
client/src/utils/settings.ts
Normal file
19
client/src/utils/settings.ts
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user