Added currency selection and auto-convertion
This commit is contained in:
parent
250adfc746
commit
f5c661c623
|
@ -13,7 +13,8 @@ import ReactTooltip from "react-tooltip";
|
|||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
import { ImageQuality } from "./Img";
|
||||
import Popup from "./Popup";
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import Select from "./Select";
|
||||
|
||||
type AppLayoutProps = {
|
||||
subPanel?: React.ReactNode;
|
||||
|
@ -96,7 +97,20 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
document.getElementsByTagName("html")[0].style.fontSize = `${
|
||||
(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 (
|
||||
<div
|
||||
|
@ -268,93 +282,115 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element {
|
|||
>
|
||||
<h2 className="text-2xl">Settings</h2>
|
||||
|
||||
<h3 className="text-xl mt-4">Theme</h3>
|
||||
<div className="flex flex-row">
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setDarkMode(false);
|
||||
appLayout.setSelectedThemeMode(true);
|
||||
}}
|
||||
active={
|
||||
appLayout.selectedThemeMode === true &&
|
||||
appLayout.darkMode === false
|
||||
}
|
||||
className="rounded-r-none"
|
||||
>
|
||||
Light
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setSelectedThemeMode(false);
|
||||
}}
|
||||
active={appLayout.selectedThemeMode === false}
|
||||
className="rounded-l-none rounded-r-none border-x-0"
|
||||
>
|
||||
Auto
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setDarkMode(true);
|
||||
appLayout.setSelectedThemeMode(true);
|
||||
}}
|
||||
active={
|
||||
appLayout.selectedThemeMode === true &&
|
||||
appLayout.darkMode === true
|
||||
}
|
||||
className="rounded-l-none"
|
||||
>
|
||||
Dark
|
||||
</Button>
|
||||
</div>
|
||||
<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">
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setDarkMode(false);
|
||||
appLayout.setSelectedThemeMode(true);
|
||||
}}
|
||||
active={
|
||||
appLayout.selectedThemeMode === true &&
|
||||
appLayout.darkMode === false
|
||||
}
|
||||
className="rounded-r-none"
|
||||
>
|
||||
Light
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setSelectedThemeMode(false);
|
||||
}}
|
||||
active={appLayout.selectedThemeMode === false}
|
||||
className="rounded-l-none rounded-r-none border-x-0"
|
||||
>
|
||||
Auto
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
appLayout.setDarkMode(true);
|
||||
appLayout.setSelectedThemeMode(true);
|
||||
}}
|
||||
active={
|
||||
appLayout.selectedThemeMode === true &&
|
||||
appLayout.darkMode === true
|
||||
}
|
||||
className="rounded-l-none"
|
||||
>
|
||||
Dark
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl mt-4">Font size</h3>
|
||||
<div className="flex flex-row">
|
||||
<Button
|
||||
className="rounded-r-none"
|
||||
onClick={() =>
|
||||
appLayout.setFontSize(
|
||||
appLayout.fontSize ? appLayout.fontSize / 1.05 : 1 / 1.05
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="material-icons">text_decrease</span>
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-l-none rounded-r-none border-x-0"
|
||||
onClick={() => appLayout.setFontSize(1)}
|
||||
>
|
||||
{((appLayout.fontSize || 1) * 100).toLocaleString(undefined, {
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
%
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-l-none"
|
||||
onClick={() =>
|
||||
appLayout.setFontSize(
|
||||
appLayout.fontSize ? appLayout.fontSize * 1.05 : 1 * 1.05
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="material-icons">text_increase</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl">Currency</h3>
|
||||
<div>
|
||||
<Select
|
||||
options={currencyOptions}
|
||||
state={currencySelect}
|
||||
setState={setCurrencySelect}
|
||||
className="w-28"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 className="text-xl mt-4">Font</h3>
|
||||
<Button
|
||||
active={appLayout.dyslexic === false}
|
||||
onClick={() => appLayout.setDyslexic(false)}
|
||||
className="font-zenMaruGothic"
|
||||
>
|
||||
Zen Maru Gothic
|
||||
</Button>
|
||||
<Button
|
||||
active={appLayout.dyslexic === true}
|
||||
onClick={() => appLayout.setDyslexic(true)}
|
||||
className="font-openDyslexic"
|
||||
>
|
||||
OpenDyslexic
|
||||
</Button>
|
||||
<div>
|
||||
<h3 className="text-xl">Font size</h3>
|
||||
<div className="flex flex-row">
|
||||
<Button
|
||||
className="rounded-r-none"
|
||||
onClick={() =>
|
||||
appLayout.setFontSize(
|
||||
appLayout.fontSize ? appLayout.fontSize / 1.05 : 1 / 1.05
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="material-icons">text_decrease</span>
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-l-none rounded-r-none border-x-0"
|
||||
onClick={() => appLayout.setFontSize(1)}
|
||||
>
|
||||
{((appLayout.fontSize || 1) * 100).toLocaleString(undefined, {
|
||||
maximumFractionDigits: 0,
|
||||
})}
|
||||
%
|
||||
</Button>
|
||||
<Button
|
||||
className="rounded-l-none"
|
||||
onClick={() =>
|
||||
appLayout.setFontSize(
|
||||
appLayout.fontSize ? appLayout.fontSize * 1.05 : 1 * 1.05
|
||||
)
|
||||
}
|
||||
>
|
||||
<span className="material-icons">text_increase</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl">Font</h3>
|
||||
<div className="grid gap-2">
|
||||
<Button
|
||||
active={appLayout.dyslexic === false}
|
||||
onClick={() => appLayout.setDyslexic(false)}
|
||||
className="font-zenMaruGothic"
|
||||
>
|
||||
Zen Maru Gothic
|
||||
</Button>
|
||||
<Button
|
||||
active={appLayout.dyslexic === true}
|
||||
onClick={() => appLayout.setDyslexic(true)}
|
||||
className="font-openDyslexic"
|
||||
>
|
||||
OpenDyslexic
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Popup>
|
||||
|
||||
<ReactTooltip
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
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 Chip from "components/Chip";
|
||||
import Img, { ImageQuality } from "components/Img";
|
||||
import { useAppLayout } from "contexts/AppLayoutContext";
|
||||
|
||||
export type LibraryItemsPreviewProps = {
|
||||
className?: string;
|
||||
|
@ -15,12 +19,14 @@ export type LibraryItemsPreviewProps = {
|
|||
release_date?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["release_date"];
|
||||
metadata?: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["metadata"];
|
||||
};
|
||||
currencies?: GetCurrenciesQuery["currencies"]["data"];
|
||||
};
|
||||
|
||||
export default function LibraryItemsPreview(
|
||||
props: LibraryItemsPreviewProps
|
||||
): JSX.Element {
|
||||
const item = props.item;
|
||||
const appLayout = useAppLayout();
|
||||
|
||||
return (
|
||||
<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">
|
||||
<span className="material-icons !text-base translate-y-[.15em] mr-1">
|
||||
shopping_cart
|
||||
</span>
|
||||
{prettyPrice(item.price)}
|
||||
{prettyPrice(
|
||||
item.price,
|
||||
props.currencies,
|
||||
appLayout.currency
|
||||
)}
|
||||
</p>
|
||||
) : (
|
||||
""
|
||||
|
|
|
@ -15,7 +15,7 @@ export default function Select(props: SelectProps): JSX.Element {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`relative transition-[filter] ${
|
||||
className={`relative text-center transition-[filter] ${
|
||||
opened && "drop-shadow-shade-lg z-10"
|
||||
} ${props.className}`}
|
||||
>
|
||||
|
|
|
@ -12,6 +12,7 @@ export interface AppLayoutState {
|
|||
selectedThemeMode: boolean | undefined;
|
||||
fontSize: number | undefined;
|
||||
dyslexic: boolean | undefined;
|
||||
currency: string | undefined;
|
||||
setSubPanelOpen: React.Dispatch<React.SetStateAction<boolean | undefined>>;
|
||||
setLanguagePanelOpen: React.Dispatch<
|
||||
React.SetStateAction<boolean | undefined>
|
||||
|
@ -27,6 +28,7 @@ export interface AppLayoutState {
|
|||
>;
|
||||
setFontSize: React.Dispatch<React.SetStateAction<number | undefined>>;
|
||||
setDyslexic: React.Dispatch<React.SetStateAction<boolean | undefined>>;
|
||||
setCurrency: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
}
|
||||
|
||||
const initialState: AppLayoutState = {
|
||||
|
@ -39,6 +41,7 @@ const initialState: AppLayoutState = {
|
|||
selectedThemeMode: false,
|
||||
fontSize: 1,
|
||||
dyslexic: false,
|
||||
currency: "USD",
|
||||
setSubPanelOpen: () => {},
|
||||
setLanguagePanelOpen: () => {},
|
||||
setMainPanelReduced: () => {},
|
||||
|
@ -48,6 +51,7 @@ const initialState: AppLayoutState = {
|
|||
setConfigPanelOpen: () => {},
|
||||
setFontSize: () => {},
|
||||
setDyslexic: () => {},
|
||||
setCurrency: () => {},
|
||||
};
|
||||
|
||||
const AppContext = React.createContext<AppLayoutState>(initialState);
|
||||
|
@ -96,6 +100,11 @@ export const AppContextProvider = (props: Props) => {
|
|||
initialState.dyslexic
|
||||
);
|
||||
|
||||
const [currency, setCurrency] = useStateWithLocalStorage<string | undefined>(
|
||||
"currency",
|
||||
initialState.currency
|
||||
);
|
||||
|
||||
return (
|
||||
<AppContext.Provider
|
||||
value={{
|
||||
|
@ -108,6 +117,7 @@ export const AppContextProvider = (props: Props) => {
|
|||
selectedThemeMode,
|
||||
fontSize,
|
||||
dyslexic,
|
||||
currency,
|
||||
setSubPanelOpen,
|
||||
setLanguagePanelOpen,
|
||||
setConfigPanelOpen,
|
||||
|
@ -117,6 +127,7 @@ export const AppContextProvider = (props: Props) => {
|
|||
setSelectedThemeMode,
|
||||
setFontSize,
|
||||
setDyslexic,
|
||||
setCurrency,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
|
|
|
@ -174,6 +174,7 @@ query getLibraryItemsPreview($language_code: String) {
|
|||
attributes {
|
||||
symbol
|
||||
code
|
||||
rate_to_usd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -322,6 +323,7 @@ query getLibraryItem($slug: String, $language_code: String) {
|
|||
attributes {
|
||||
symbol
|
||||
code
|
||||
rate_to_usd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -490,6 +492,7 @@ query getLibraryItem($slug: String, $language_code: String) {
|
|||
attributes {
|
||||
symbol
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -286,6 +286,7 @@ export type GetLibraryItemsPreviewQuery = {
|
|||
__typename: "Currency";
|
||||
symbol: string;
|
||||
code: string;
|
||||
rate_to_usd: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -478,6 +479,7 @@ export type GetLibraryItemQuery = {
|
|||
__typename: "Currency";
|
||||
symbol: string;
|
||||
code: string;
|
||||
rate_to_usd: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -693,6 +695,7 @@ export type GetLibraryItemQuery = {
|
|||
__typename: "Currency";
|
||||
symbol: 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;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -11,6 +11,8 @@ import {
|
|||
GetContentsSlugsQueryVariables,
|
||||
GetContentTextQuery,
|
||||
GetContentTextQueryVariables,
|
||||
GetCurrenciesQuery,
|
||||
GetCurrenciesQueryVariables,
|
||||
GetErasQuery,
|
||||
GetErasQueryVariables,
|
||||
GetLibraryItemQuery,
|
||||
|
@ -123,3 +125,10 @@ export async function getContentText(
|
|||
const query = getQueryFromOperations("getContentText");
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -1647,6 +1647,7 @@ input CurrencyFiltersInput {
|
|||
id: IDFilterInput
|
||||
symbol: StringFilterInput
|
||||
code: StringFilterInput
|
||||
rate_to_usd: FloatFilterInput
|
||||
createdAt: DateTimeFilterInput
|
||||
updatedAt: DateTimeFilterInput
|
||||
and: [CurrencyFiltersInput]
|
||||
|
@ -1657,11 +1658,13 @@ input CurrencyFiltersInput {
|
|||
input CurrencyInput {
|
||||
symbol: String
|
||||
code: String
|
||||
rate_to_usd: Float
|
||||
}
|
||||
|
||||
type Currency {
|
||||
symbol: String!
|
||||
code: String!
|
||||
rate_to_usd: Float
|
||||
createdAt: DateTime
|
||||
updatedAt: DateTime
|
||||
}
|
||||
|
@ -2099,46 +2102,6 @@ type MetadataTypeEntityResponseCollection {
|
|||
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 {
|
||||
id: IDFilterInput
|
||||
authors: RecorderFiltersInput
|
||||
|
@ -2655,6 +2618,7 @@ input WebsiteInterfaceFiltersInput {
|
|||
order_by: StringFilterInput
|
||||
group_by: StringFilterInput
|
||||
select_option_sidebar: StringFilterInput
|
||||
group: StringFilterInput
|
||||
createdAt: DateTimeFilterInput
|
||||
updatedAt: DateTimeFilterInput
|
||||
and: [WebsiteInterfaceFiltersInput]
|
||||
|
@ -2742,6 +2706,7 @@ input WebsiteInterfaceInput {
|
|||
order_by: String
|
||||
group_by: String
|
||||
select_option_sidebar: String
|
||||
group: String
|
||||
}
|
||||
|
||||
type WebsiteInterface {
|
||||
|
@ -2824,6 +2789,7 @@ type WebsiteInterface {
|
|||
order_by: String
|
||||
group_by: String
|
||||
select_option_sidebar: String
|
||||
group: String
|
||||
createdAt: DateTime
|
||||
updatedAt: DateTime
|
||||
}
|
||||
|
@ -2997,7 +2963,6 @@ union GenericMorph =
|
|||
| LibraryItem
|
||||
| MerchItem
|
||||
| MetadataType
|
||||
| OtherSubtype
|
||||
| Post
|
||||
| RangedContent
|
||||
| Recorder
|
||||
|
@ -3121,12 +3086,6 @@ type Query {
|
|||
pagination: PaginationArg = {}
|
||||
sort: [String] = []
|
||||
): MetadataTypeEntityResponseCollection
|
||||
otherSubtype(id: ID): OtherSubtypeEntityResponse
|
||||
otherSubtypes(
|
||||
filters: OtherSubtypeFiltersInput
|
||||
pagination: PaginationArg = {}
|
||||
sort: [String] = []
|
||||
): OtherSubtypeEntityResponseCollection
|
||||
post(id: ID): PostEntityResponse
|
||||
posts(
|
||||
filters: PostFiltersInput
|
||||
|
@ -3277,12 +3236,6 @@ type Mutation {
|
|||
data: MetadataTypeInput!
|
||||
): MetadataTypeEntityResponse
|
||||
deleteMetadataType(id: ID!): MetadataTypeEntityResponse
|
||||
createOtherSubtype(data: OtherSubtypeInput!): OtherSubtypeEntityResponse
|
||||
updateOtherSubtype(
|
||||
id: ID!
|
||||
data: OtherSubtypeInput!
|
||||
): OtherSubtypeEntityResponse
|
||||
deleteOtherSubtype(id: ID!): OtherSubtypeEntityResponse
|
||||
createPost(data: PostInput!): PostEntityResponse
|
||||
updatePost(id: ID!, data: PostInput!): PostEntityResponse
|
||||
deletePost(id: ID!): PostEntityResponse
|
||||
|
|
|
@ -3,6 +3,7 @@ import ContentPanel, {
|
|||
} from "components/Panels/ContentPanel";
|
||||
import { GetStaticPaths, GetStaticProps } from "next";
|
||||
import {
|
||||
getCurrencies,
|
||||
getLibraryItem,
|
||||
getLibraryItemsSlugs,
|
||||
getWebsiteInterface,
|
||||
|
@ -10,6 +11,7 @@ import {
|
|||
import {
|
||||
Enum_Componentmetadatabooks_Binding_Type,
|
||||
Enum_Componentmetadatabooks_Page_Order,
|
||||
GetCurrenciesQuery,
|
||||
GetLibraryItemQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
|
@ -20,7 +22,6 @@ import {
|
|||
prettyItemType,
|
||||
prettyItemSubType,
|
||||
prettyPrice,
|
||||
prettySlug,
|
||||
prettyTestError,
|
||||
prettyTestWarning,
|
||||
sortContent,
|
||||
|
@ -32,7 +33,6 @@ import ReturnButton, {
|
|||
import NavOption from "components/PanelComponents/NavOption";
|
||||
import Chip from "components/Chip";
|
||||
import Button from "components/Button";
|
||||
import HorizontalLine from "components/HorizontalLine";
|
||||
import AppLayout from "components/AppLayout";
|
||||
import LibraryItemsPreview from "components/Library/LibraryItemsPreview";
|
||||
import InsetBox from "components/InsetBox";
|
||||
|
@ -44,12 +44,14 @@ import ContentTOCLine from "components/Library/ContentTOCLine";
|
|||
interface LibrarySlugProps {
|
||||
libraryItem: GetLibraryItemQuery;
|
||||
langui: GetWebsiteInterfaceQuery;
|
||||
currencies: GetCurrenciesQuery;
|
||||
}
|
||||
|
||||
export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
||||
useTesting(props);
|
||||
const item = props.libraryItem.libraryItems.data[0].attributes;
|
||||
const langui = props.langui.websiteInterfaces.data[0].attributes;
|
||||
const currencies = props.currencies.currencies.data;
|
||||
const appLayout = useAppLayout();
|
||||
|
||||
const isVariantSet =
|
||||
|
@ -226,7 +228,9 @@ export default function LibrarySlug(props: LibrarySlugProps): JSX.Element {
|
|||
{item.price ? (
|
||||
<div className="grid place-items-center">
|
||||
<h3 className="text-xl">{langui.price}</h3>
|
||||
<p>{prettyPrice(item.price)}</p>
|
||||
<p>
|
||||
{prettyPrice(item.price, currencies, appLayout.currency)}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
|
@ -409,6 +413,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
langui: await getWebsiteInterface({
|
||||
language_code: context.locale,
|
||||
}),
|
||||
currencies: await getCurrencies({}),
|
||||
};
|
||||
return {
|
||||
props: props,
|
||||
|
|
|
@ -4,10 +4,12 @@ import ContentPanel, {
|
|||
ContentPanelWidthSizes,
|
||||
} from "components/Panels/ContentPanel";
|
||||
import {
|
||||
GetCurrenciesQuery,
|
||||
GetLibraryItemsPreviewQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
} from "graphql/operations-types";
|
||||
import {
|
||||
getCurrencies,
|
||||
getLibraryItemsPreview,
|
||||
getWebsiteInterface,
|
||||
} from "graphql/operations";
|
||||
|
@ -22,6 +24,7 @@ import Switch from "components/Switch";
|
|||
type LibraryProps = {
|
||||
libraryItems: GetLibraryItemsPreviewQuery;
|
||||
langui: GetWebsiteInterfaceQuery;
|
||||
currencies: GetCurrenciesQuery;
|
||||
};
|
||||
|
||||
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"
|
||||
>
|
||||
{items.map((item) => (
|
||||
<LibraryItemsPreview key={item.id} item={item.attributes} />
|
||||
<LibraryItemsPreview
|
||||
key={item.id}
|
||||
item={item.attributes}
|
||||
currencies={props.currencies.currencies.data}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
|
@ -166,6 +173,7 @@ export const getStaticProps: GetStaticProps = async (context) => {
|
|||
langui: await getWebsiteInterface({
|
||||
language_code: context.locale,
|
||||
}),
|
||||
currencies: await getCurrencies({}),
|
||||
};
|
||||
return {
|
||||
props: props,
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
ImageQuality,
|
||||
} from "components/Img";
|
||||
import {
|
||||
GetCurrenciesQuery,
|
||||
GetLibraryItemQuery,
|
||||
GetLibraryItemsPreviewQuery,
|
||||
GetWebsiteInterfaceQuery,
|
||||
|
@ -24,12 +25,27 @@ export function prettyDate(
|
|||
}
|
||||
|
||||
export function prettyPrice(
|
||||
pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"]
|
||||
pricePicker: GetLibraryItemsPreviewQuery["libraryItems"]["data"][number]["attributes"]["price"],
|
||||
currencies: GetCurrenciesQuery["currencies"]["data"],
|
||||
targetCurrencyCode?: string
|
||||
): string {
|
||||
return (
|
||||
pricePicker.currency.data.attributes.symbol +
|
||||
pricePicker.amount.toLocaleString()
|
||||
);
|
||||
if (!targetCurrencyCode) return "";
|
||||
let result = "";
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue