Added currency selection and auto-convertion

This commit is contained in:
DrMint 2022-03-06 18:23:10 +01:00
parent 250adfc746
commit f5c661c623
11 changed files with 241 additions and 153 deletions

View File

@ -13,7 +13,8 @@ import ReactTooltip from "react-tooltip";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import { ImageQuality } from "./Img"; import { ImageQuality } from "./Img";
import Popup from "./Popup"; import Popup from "./Popup";
import { useEffect } from "react"; import { useEffect, useState } from "react";
import Select from "./Select";
type AppLayoutProps = { type AppLayoutProps = {
subPanel?: React.ReactNode; subPanel?: React.ReactNode;
@ -96,7 +97,20 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
document.getElementsByTagName("html")[0].style.fontSize = `${ document.getElementsByTagName("html")[0].style.fontSize = `${
(appLayout.fontSize || 1) * 100 (appLayout.fontSize || 1) * 100
}%`; }%`;
}); }, [appLayout.fontSize]);
const currencyOptions = ["EUR", "USD", "CAD", "JPY"];
const [currencySelect, setCurrencySelect] = useState<number>(-1);
useEffect(() => {
appLayout.currency &&
setCurrencySelect(currencyOptions.indexOf(appLayout.currency));
}, [appLayout.currency]);
useEffect(() => {
currencySelect >= 0 &&
appLayout.setCurrency(currencyOptions[currencySelect]);
}, [currencySelect]);
return ( return (
<div <div
@ -268,7 +282,9 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
> >
<h2 className="text-2xl">Settings</h2> <h2 className="text-2xl">Settings</h2>
<h3 className="text-xl mt-4">Theme</h3> <div className="mt-4 grid gap-8 place-items-center text-center desktop:grid-cols-2">
<div>
<h3 className="text-xl">Theme</h3>
<div className="flex flex-row"> <div className="flex flex-row">
<Button <Button
onClick={() => { onClick={() => {
@ -306,8 +322,22 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
Dark Dark
</Button> </Button>
</div> </div>
</div>
<h3 className="text-xl mt-4">Font size</h3> <div>
<h3 className="text-xl">Currency</h3>
<div>
<Select
options={currencyOptions}
state={currencySelect}
setState={setCurrencySelect}
className="w-28"
/>
</div>
</div>
<div>
<h3 className="text-xl">Font size</h3>
<div className="flex flex-row"> <div className="flex flex-row">
<Button <Button
className="rounded-r-none" className="rounded-r-none"
@ -339,8 +369,11 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
<span className="material-icons">text_increase</span> <span className="material-icons">text_increase</span>
</Button> </Button>
</div> </div>
</div>
<h3 className="text-xl mt-4">Font</h3> <div>
<h3 className="text-xl">Font</h3>
<div className="grid gap-2">
<Button <Button
active={appLayout.dyslexic === false} active={appLayout.dyslexic === false}
onClick={() => appLayout.setDyslexic(false)} onClick={() => appLayout.setDyslexic(false)}
@ -355,6 +388,9 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
> >
OpenDyslexic OpenDyslexic
</Button> </Button>
</div>
</div>
</div>
</Popup> </Popup>
<ReactTooltip <ReactTooltip

View File

@ -1,8 +1,12 @@
import Link from "next/link"; import Link from "next/link";
import { GetLibraryItemsPreviewQuery } from "graphql/operations-types"; import {
GetCurrenciesQuery,
GetLibraryItemsPreviewQuery,
} from "graphql/operations-types";
import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers"; import { prettyDate, prettyPrice, prettyItemSubType } from "queries/helpers";
import Chip from "components/Chip"; import Chip from "components/Chip";
import Img, { ImageQuality } from "components/Img"; import Img, { ImageQuality } from "components/Img";
import { useAppLayout } from "contexts/AppLayoutContext";
export type LibraryItemsPreviewProps = { export type LibraryItemsPreviewProps = {
className?: string; className?: string;
@ -15,12 +19,14 @@ export type LibraryItemsPreviewProps = {
release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"]; release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"];
metadata?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"]; metadata?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"];
}; };
currencies?: GetCurrenciesQuery["currencies"]["data"];
}; };
export default function LibraryItemsPreview( export default function LibraryItemsPreview(
props: LibraryItemsPreviewProps props: LibraryItemsPreviewProps
): JSX.Element { ): JSX.Element {
const item = props.item; const item = props.item;
const appLayout = useAppLayout();
return ( return (
<Link href={"/library/" + item.slug} passHref> <Link href={"/library/" + item.slug} passHref>
@ -61,12 +67,16 @@ export default function LibraryItemsPreview(
) : ( ) : (
"" ""
)} )}
{item.price ? ( {item.price && props.currencies ? (
<p className="mobile:text-xs text-sm justify-self-end"> <p className="mobile:text-xs text-sm justify-self-end">
<span className="material-icons !text-base translate-y-[.15em] mr-1"> <span className="material-icons !text-base translate-y-[.15em] mr-1">
shopping_cart shopping_cart
</span> </span>
{prettyPrice(item.price)} {prettyPrice(
item.price,
props.currencies,
appLayout.currency
)}
</p> </p>
) : ( ) : (
"" ""

View File

@ -15,7 +15,7 @@ export default function Select(props: SelectProps): JSX.Element {
return ( return (
<div <div
className={`relative transition-[filter] ${ className={`relative text-center transition-[filter] ${
opened && "drop-shadow-shade-lg z-10" opened && "drop-shadow-shade-lg z-10"
} ${props.className}`} } ${props.className}`}
> >

View File

@ -12,6 +12,7 @@ export interface AppLayoutState {
selectedThemeMode: boolean | undefined; selectedThemeMode: boolean | undefined;
fontSize: number | undefined; fontSize: number | undefined;
dyslexic: boolean | undefined; dyslexic: boolean | undefined;
currency: string | undefined;
setSubPanelOpen: React.Dispatch<React.SetStateAction<boolean | undefined>>; setSubPanelOpen: React.Dispatch<React.SetStateAction<boolean | undefined>>;
setLanguagePanelOpen: React.Dispatch< setLanguagePanelOpen: React.Dispatch<
React.SetStateAction<boolean | undefined> React.SetStateAction<boolean | undefined>
@ -27,6 +28,7 @@ export interface AppLayoutState {
>; >;
setFontSize: React.Dispatch<React.SetStateAction<number | undefined>>; setFontSize: React.Dispatch<React.SetStateAction<number | undefined>>;
setDyslexic: React.Dispatch<React.SetStateAction<boolean | undefined>>; setDyslexic: React.Dispatch<React.SetStateAction<boolean | undefined>>;
setCurrency: React.Dispatch<React.SetStateAction<string | undefined>>;
} }
const initialState: AppLayoutState = { const initialState: AppLayoutState = {
@ -39,6 +41,7 @@ const initialState: AppLayoutState = {
selectedThemeMode: false, selectedThemeMode: false,
fontSize: 1, fontSize: 1,
dyslexic: false, dyslexic: false,
currency: "USD",
setSubPanelOpen: () => {}, setSubPanelOpen: () => {},
setLanguagePanelOpen: () => {}, setLanguagePanelOpen: () => {},
setMainPanelReduced: () => {}, setMainPanelReduced: () => {},
@ -48,6 +51,7 @@ const initialState: AppLayoutState = {
setConfigPanelOpen: () => {}, setConfigPanelOpen: () => {},
setFontSize: () => {}, setFontSize: () => {},
setDyslexic: () => {}, setDyslexic: () => {},
setCurrency: () => {},
}; };
const AppContext = React.createContext<AppLayoutState>(initialState); const AppContext = React.createContext<AppLayoutState>(initialState);
@ -96,6 +100,11 @@ export const AppContextProvider = (props: Props) => {
initialState.dyslexic initialState.dyslexic
); );
const [currency, setCurrency] = useStateWithLocalStorage<string | undefined>(
"currency",
initialState.currency
);
return ( return (
<AppContext.Provider <AppContext.Provider
value={{ value={{
@ -108,6 +117,7 @@ export const AppContextProvider = (props: Props) => {
selectedThemeMode, selectedThemeMode,
fontSize, fontSize,
dyslexic, dyslexic,
currency,
setSubPanelOpen, setSubPanelOpen,
setLanguagePanelOpen, setLanguagePanelOpen,
setConfigPanelOpen, setConfigPanelOpen,
@ -117,6 +127,7 @@ export const AppContextProvider = (props: Props) => {
setSelectedThemeMode, setSelectedThemeMode,
setFontSize, setFontSize,
setDyslexic, setDyslexic,
setCurrency,
}} }}
> >
{props.children} {props.children}

View File

@ -174,6 +174,7 @@ query getLibraryItemsPreview($language_code: String) {
attributes { attributes {
symbol symbol
code code
rate_to_usd
} }
} }
} }
@ -322,6 +323,7 @@ query getLibraryItem($slug: String, $language_code: String) {
attributes { attributes {
symbol symbol
code code
rate_to_usd
} }
} }
} }
@ -490,6 +492,7 @@ query getLibraryItem($slug: String, $language_code: String) {
attributes { attributes {
symbol symbol
code code
rate_to_usd
} }
} }
} }
@ -1057,3 +1060,17 @@ query getContentText($slug: String, $language_code: String) {
} }
} }
} }
query getCurrencies {
currencies {
data {
id
attributes {
code
symbol
rate_to_usd
display_decimals
}
}
}
}

View File

@ -286,6 +286,7 @@ export type GetLibraryItemsPreviewQuery = {
__typename: "Currency"; __typename: "Currency";
symbol: string; symbol: string;
code: string; code: string;
rate_to_usd: number;
}; };
}; };
}; };
@ -478,6 +479,7 @@ export type GetLibraryItemQuery = {
__typename: "Currency"; __typename: "Currency";
symbol: string; symbol: string;
code: string; code: string;
rate_to_usd: number;
}; };
}; };
}; };
@ -693,6 +695,7 @@ export type GetLibraryItemQuery = {
__typename: "Currency"; __typename: "Currency";
symbol: string; symbol: string;
code: string; code: string;
rate_to_usd: number;
}; };
}; };
}; };
@ -1416,3 +1419,23 @@ export type GetContentTextQuery = {
}>; }>;
}; };
}; };
export type GetCurrenciesQueryVariables = Exact<{ [key: string]: never }>;
export type GetCurrenciesQuery = {
__typename: "Query";
currencies: {
__typename: "CurrencyEntityResponseCollection";
data: Array<{
__typename: "CurrencyEntity";
id: string;
attributes: {
__typename: "Currency";
code: string;
symbol: string;
rate_to_usd: number;
display_decimals: boolean;
};
}>;
};
};

View File

@ -11,6 +11,8 @@ import {
GetContentsSlugsQueryVariables, GetContentsSlugsQueryVariables,
GetContentTextQuery, GetContentTextQuery,
GetContentTextQueryVariables, GetContentTextQueryVariables,
GetCurrenciesQuery,
GetCurrenciesQueryVariables,
GetErasQuery, GetErasQuery,
GetErasQueryVariables, GetErasQueryVariables,
GetLibraryItemQuery, GetLibraryItemQuery,
@ -123,3 +125,10 @@ export async function getContentText(
const query = getQueryFromOperations("getContentText"); const query = getQueryFromOperations("getContentText");
return await graphQL(query, JSON.stringify(variables)); return await graphQL(query, JSON.stringify(variables));
} }
export async function getCurrencies(
variables: GetCurrenciesQueryVariables
): Promise<GetCurrenciesQuery> {
const query = getQueryFromOperations("getCurrencies");
return await graphQL(query, JSON.stringify(variables));
}

View File

@ -1647,6 +1647,7 @@ input CurrencyFiltersInput {
id: IDFilterInput id: IDFilterInput
symbol: StringFilterInput symbol: StringFilterInput
code: StringFilterInput code: StringFilterInput
rate_to_usd: FloatFilterInput
createdAt: DateTimeFilterInput createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput updatedAt: DateTimeFilterInput
and: [CurrencyFiltersInput] and: [CurrencyFiltersInput]
@ -1657,11 +1658,13 @@ input CurrencyFiltersInput {
input CurrencyInput { input CurrencyInput {
symbol: String symbol: String
code: String code: String
rate_to_usd: Float
} }
type Currency { type Currency {
symbol: String! symbol: String!
code: String! code: String!
rate_to_usd: Float
createdAt: DateTime createdAt: DateTime
updatedAt: DateTime updatedAt: DateTime
} }
@ -2099,46 +2102,6 @@ type MetadataTypeEntityResponseCollection {
meta: ResponseCollectionMeta! meta: ResponseCollectionMeta!
} }
input OtherSubtypeFiltersInput {
id: IDFilterInput
slug: StringFilterInput
createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput
and: [OtherSubtypeFiltersInput]
or: [OtherSubtypeFiltersInput]
not: OtherSubtypeFiltersInput
}
input OtherSubtypeInput {
slug: String
titles: [ComponentTranslationsSimpleTitleInput]
}
type OtherSubtype {
slug: String!
titles(
filters: ComponentTranslationsSimpleTitleFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
): [ComponentTranslationsSimpleTitle]
createdAt: DateTime
updatedAt: DateTime
}
type OtherSubtypeEntity {
id: ID
attributes: OtherSubtype
}
type OtherSubtypeEntityResponse {
data: OtherSubtypeEntity
}
type OtherSubtypeEntityResponseCollection {
data: [OtherSubtypeEntity!]!
meta: ResponseCollectionMeta!
}
input PostFiltersInput { input PostFiltersInput {
id: IDFilterInput id: IDFilterInput
authors: RecorderFiltersInput authors: RecorderFiltersInput
@ -2655,6 +2618,7 @@ input WebsiteInterfaceFiltersInput {
order_by: StringFilterInput order_by: StringFilterInput
group_by: StringFilterInput group_by: StringFilterInput
select_option_sidebar: StringFilterInput select_option_sidebar: StringFilterInput
group: StringFilterInput
createdAt: DateTimeFilterInput createdAt: DateTimeFilterInput
updatedAt: DateTimeFilterInput updatedAt: DateTimeFilterInput
and: [WebsiteInterfaceFiltersInput] and: [WebsiteInterfaceFiltersInput]
@ -2742,6 +2706,7 @@ input WebsiteInterfaceInput {
order_by: String order_by: String
group_by: String group_by: String
select_option_sidebar: String select_option_sidebar: String
group: String
} }
type WebsiteInterface { type WebsiteInterface {
@ -2824,6 +2789,7 @@ type WebsiteInterface {
order_by: String order_by: String
group_by: String group_by: String
select_option_sidebar: String select_option_sidebar: String
group: String
createdAt: DateTime createdAt: DateTime
updatedAt: DateTime updatedAt: DateTime
} }
@ -2997,7 +2963,6 @@ union GenericMorph =
| LibraryItem | LibraryItem
| MerchItem | MerchItem
| MetadataType | MetadataType
| OtherSubtype
| Post | Post
| RangedContent | RangedContent
| Recorder | Recorder
@ -3121,12 +3086,6 @@ type Query {
pagination: PaginationArg = {} pagination: PaginationArg = {}
sort: [String] = [] sort: [String] = []
): MetadataTypeEntityResponseCollection ): MetadataTypeEntityResponseCollection
otherSubtype(id: ID): OtherSubtypeEntityResponse
otherSubtypes(
filters: OtherSubtypeFiltersInput
pagination: PaginationArg = {}
sort: [String] = []
): OtherSubtypeEntityResponseCollection
post(id: ID): PostEntityResponse post(id: ID): PostEntityResponse
posts( posts(
filters: PostFiltersInput filters: PostFiltersInput
@ -3277,12 +3236,6 @@ type Mutation {
data: MetadataTypeInput! data: MetadataTypeInput!
): MetadataTypeEntityResponse ): MetadataTypeEntityResponse
deleteMetadataType(id: ID!): MetadataTypeEntityResponse deleteMetadataType(id: ID!): MetadataTypeEntityResponse
createOtherSubtype(data: OtherSubtypeInput!): OtherSubtypeEntityResponse
updateOtherSubtype(
id: ID!
data: OtherSubtypeInput!
): OtherSubtypeEntityResponse
deleteOtherSubtype(id: ID!): OtherSubtypeEntityResponse
createPost(data: PostInput!): PostEntityResponse createPost(data: PostInput!): PostEntityResponse
updatePost(id: ID!, data: PostInput!): PostEntityResponse updatePost(id: ID!, data: PostInput!): PostEntityResponse
deletePost(id: ID!): PostEntityResponse deletePost(id: ID!): PostEntityResponse

View File

@ -3,6 +3,7 @@ import ContentPanel, {
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { GetStaticPaths, GetStaticProps } from "next"; import { GetStaticPaths, GetStaticProps } from "next";
import { import {
getCurrencies,
getLibraryItem, getLibraryItem,
getLibraryItemsSlugs, getLibraryItemsSlugs,
getWebsiteInterface, getWebsiteInterface,
@ -10,6 +11,7 @@ import {
import { import {
Enum_Componentmetadatabooks_Binding_Type, Enum_Componentmetadatabooks_Binding_Type,
Enum_Componentmetadatabooks_Page_Order, Enum_Componentmetadatabooks_Page_Order,
GetCurrenciesQuery,
GetLibraryItemQuery, GetLibraryItemQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
@ -20,7 +22,6 @@ import {
prettyItemType, prettyItemType,
prettyItemSubType, prettyItemSubType,
prettyPrice, prettyPrice,
prettySlug,
prettyTestError, prettyTestError,
prettyTestWarning, prettyTestWarning,
sortContent, sortContent,
@ -32,7 +33,6 @@ import ReturnButton, {
import NavOption from "components/PanelComponents/NavOption"; import NavOption from "components/PanelComponents/NavOption";
import Chip from "components/Chip"; import Chip from "components/Chip";
import Button from "components/Button"; import Button from "components/Button";
import HorizontalLine from "components/HorizontalLine";
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import LibraryItemsPreview from "components/Library/LibraryItemsPreview"; import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
import InsetBox from "components/InsetBox"; import InsetBox from "components/InsetBox";
@ -44,12 +44,14 @@ import ContentTOCLine from "components/Library/ContentTOCLine";
interface LibrarySlugProps { interface LibrarySlugProps {
libraryItem: GetLibraryItemQuery; libraryItem: GetLibraryItemQuery;
langui: GetWebsiteInterfaceQuery; langui: GetWebsiteInterfaceQuery;
currencies: GetCurrenciesQuery;
} }
export default function LibrarySlug(props: LibrarySlugProps): JSX.Element { export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
useTesting(props); useTesting(props);
const item = props.libraryItem.libraryItems.data[0].attributes; const item = props.libraryItem.libraryItems.data[0].attributes;
const langui = props.langui.websiteInterfaces.data[0].attributes; const langui = props.langui.websiteInterfaces.data[0].attributes;
const currencies = props.currencies.currencies.data;
const appLayout = useAppLayout(); const appLayout = useAppLayout();
const isVariantSet = const isVariantSet =
@ -226,7 +228,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
{item.price ? ( {item.price ? (
<div className="grid place-items-center"> <div className="grid place-items-center">
<h3 className="text-xl">{langui.price}</h3> <h3 className="text-xl">{langui.price}</h3>
<p>{prettyPrice(item.price)}</p> <p>
{prettyPrice(item.price, currencies, appLayout.currency)}
</p>
</div> </div>
) : ( ) : (
"" ""
@ -409,6 +413,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
langui: await getWebsiteInterface({ langui: await getWebsiteInterface({
language_code: context.locale, language_code: context.locale,
}), }),
currencies: await getCurrencies({}),
}; };
return { return {
props: props, props: props,

View File

@ -4,10 +4,12 @@ import ContentPanel, {
ContentPanelWidthSizes, ContentPanelWidthSizes,
} from "components/Panels/ContentPanel"; } from "components/Panels/ContentPanel";
import { import {
GetCurrenciesQuery,
GetLibraryItemsPreviewQuery, GetLibraryItemsPreviewQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
} from "graphql/operations-types"; } from "graphql/operations-types";
import { import {
getCurrencies,
getLibraryItemsPreview, getLibraryItemsPreview,
getWebsiteInterface, getWebsiteInterface,
} from "graphql/operations"; } from "graphql/operations";
@ -22,6 +24,7 @@ import Switch from "components/Switch";
type LibraryProps = { type LibraryProps = {
libraryItems: GetLibraryItemsPreviewQuery; libraryItems: GetLibraryItemsPreviewQuery;
langui: GetWebsiteInterfaceQuery; langui: GetWebsiteInterfaceQuery;
currencies: GetCurrenciesQuery;
}; };
type GroupLibraryItems = Map< type GroupLibraryItems = Map<
@ -138,7 +141,11 @@ export default function Library(props: LibraryProps): JSX.Element {
className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0" className="grid gap-8 items-end mobile:grid-cols-2 desktop:grid-cols-[repeat(auto-fill,_minmax(13rem,1fr))] pb-12 border-b-[3px] border-dotted last-of-type:border-0"
> >
{items.map((item) => ( {items.map((item) => (
<LibraryItemsPreview key={item.id} item={item.attributes} /> <LibraryItemsPreview
key={item.id}
item={item.attributes}
currencies={props.currencies.currencies.data}
/>
))} ))}
</div> </div>
</> </>
@ -166,6 +173,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
langui: await getWebsiteInterface({ langui: await getWebsiteInterface({
language_code: context.locale, language_code: context.locale,
}), }),
currencies: await getCurrencies({}),
}; };
return { return {
props: props, props: props,

View File

@ -4,6 +4,7 @@ import {
ImageQuality, ImageQuality,
} from "components/Img"; } from "components/Img";
import { import {
GetCurrenciesQuery,
GetLibraryItemQuery, GetLibraryItemQuery,
GetLibraryItemsPreviewQuery, GetLibraryItemsPreviewQuery,
GetWebsiteInterfaceQuery, GetWebsiteInterfaceQuery,
@ -24,12 +25,27 @@ export function prettyDate(
} }
export function prettyPrice( export function prettyPrice(
pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"] pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"],
currencies: GetCurrenciesQuery["currencies"]["data"],
targetCurrencyCode?: string
): string { ): string {
return ( if (!targetCurrencyCode) return "";
pricePicker.currency.data.attributes.symbol + let result = "";
pricePicker.amount.toLocaleString() currencies.map((currency) => {
); if (currency.attributes.code === targetCurrencyCode) {
let amountInUSD =
pricePicker.amount * pricePicker.currency.data.attributes.rate_to_usd;
let amountInTargetCurrency =
amountInUSD / currency.attributes.rate_to_usd;
result =
currency.attributes.symbol +
amountInTargetCurrency.toLocaleString(undefined, {
minimumFractionDigits: currency.attributes.display_decimals ? 2 : 0,
maximumFractionDigits: currency.attributes.display_decimals ? 2 : 0,
});
}
});
return result;
} }
export function prettySlug(slug?: string, parentSlug?: string): string { export function prettySlug(slug?: string, parentSlug?: string): string {