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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint