diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..6fb85c5 Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/api/banknotes/get-country-banknotes.ts b/src/api/banknotes/get-country-banknotes.ts new file mode 100644 index 0000000..c40f847 --- /dev/null +++ b/src/api/banknotes/get-country-banknotes.ts @@ -0,0 +1,24 @@ +import { CoinProps } from "@/types/coin"; +import { readFile, readdir } from "fs/promises"; +import path from "path"; + +export const getCountryBanknotes = async (country: string) => { + try { + const banknoteIds = await readdir(path.join("./public/banknotes", country)); + + const banknotes: CoinProps[] = []; + + for (const banknoteId of banknoteIds) { + const banknote = await readFile( + path.join("./public/banknotes", country, banknoteId), + { encoding: "utf-8" }, + ); + + banknotes.push(JSON.parse(banknote)); + } + + return banknotes; + } catch { + return []; + } +}; diff --git a/src/api/coins/get-country-coins.ts b/src/api/coins/get-country-coins.ts new file mode 100644 index 0000000..e7f9f62 --- /dev/null +++ b/src/api/coins/get-country-coins.ts @@ -0,0 +1,24 @@ +import { CoinProps } from "@/types/coin"; +import { readFile, readdir } from "fs/promises"; +import path from "path"; + +export const getCountryCoins = async (country: string) => { + try { + const coinIds = await readdir(path.join("./public/coins", country)); + + const coins: CoinProps[] = []; + + for (const coinId of coinIds) { + const coin = await readFile( + path.join("./public/coins", country, coinId), + { encoding: "utf-8" }, + ); + + coins.push(JSON.parse(coin)); + } + + return coins; + } catch { + return []; + } +}; diff --git a/src/components/scene/banknote.tsx b/src/components/banknote/index.tsx similarity index 100% rename from src/components/scene/banknote.tsx rename to src/components/banknote/index.tsx diff --git a/src/components/scene/coin.tsx b/src/components/coin/index.tsx similarity index 100% rename from src/components/scene/coin.tsx rename to src/components/coin/index.tsx diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx new file mode 100644 index 0000000..92b1a52 --- /dev/null +++ b/src/components/header/index.tsx @@ -0,0 +1,70 @@ +type Props = { + route: "pile" | "coins" | "banknotes"; + country: string; + coinCount: number; + banknoteCount: number; +}; + +export const Header = ({ route, country, banknoteCount, coinCount }: Props) => ( +
+ +
+ {route !== "pile" && coinCount > 0 && ( + + )} + {route !== "coins" && coinCount > 0 && ( + + )} + {route !== "banknotes" && banknoteCount > 0 && ( + + )} +
+
+); diff --git a/src/components/scene/coin-instances.tsx b/src/components/pile/coin-instances.tsx similarity index 96% rename from src/components/scene/coin-instances.tsx rename to src/components/pile/coin-instances.tsx index 538137a..2fc7bf8 100644 --- a/src/components/scene/coin-instances.tsx +++ b/src/components/pile/coin-instances.tsx @@ -1,5 +1,5 @@ import { CoinProps } from "@/types/coin"; -import { CoinInstance } from "./coin"; +import { CoinInstance } from "../coin"; import { useEffect, useRef } from "react"; import { InstancedMesh } from "three"; import { useCylinder } from "@react-three/cannon"; diff --git a/src/components/scene/index.tsx b/src/components/pile/index.tsx similarity index 96% rename from src/components/scene/index.tsx rename to src/components/pile/index.tsx index 4ebece0..376f5b3 100644 --- a/src/components/scene/index.tsx +++ b/src/components/pile/index.tsx @@ -20,7 +20,7 @@ const Plane = (props: PlaneProps) => { ); }; -export const Scene = ({ coins }: Props) => ( +export const Pile = ({ coins }: Props) => ( diff --git a/src/components/showcase/index.tsx b/src/components/showcase/index.tsx new file mode 100644 index 0000000..751f5ab --- /dev/null +++ b/src/components/showcase/index.tsx @@ -0,0 +1,118 @@ +import { CoinProps } from "@/types/coin"; +import { Canvas, MeshProps, useFrame } from "@react-three/fiber"; +import { Suspense, useRef, useState } from "react"; +import { CoinInstance } from "@/components/coin"; +import { Mesh } from "three"; +import { OrbitControls } from "@react-three/drei"; +import { BanknoteInstance } from "@/components/banknote"; +import { InfoBox } from "./info-box"; + +type Props = { + category: "coins" | "banknotes"; + types: CoinProps[]; +}; + +const SpinninType = ({ + isSelected, + category, + typeProps, + ...props +}: { typeProps: CoinProps; isSelected?: boolean } & MeshProps & + Pick) => { + const ref = useRef(null!); + const Instance = category === "banknotes" ? BanknoteInstance : CoinInstance; + + useFrame((_state, delta) => { + if (!isSelected) { + return; + } + + if (category === "banknotes") { + ref.current.rotation.y += delta; + return; + } + + switch (typeProps.orientation) { + case "medal": + ref.current.rotation.x += delta; + break; + + default: + ref.current.rotation.z += delta; + break; + } + }); + + return ( + + + + + + ); +}; + +const Row = ({ + category, + types, + selectedIndex, +}: Props & { selectedIndex: number }) => { + const ref = useRef(null!); + const spacing = category === "banknotes" ? 8 : 6; + + useFrame(() => { + const xPosition = Math.round(10 * ref.current.position.x) / 10; + const target = -selectedIndex * spacing; + + if (xPosition > target) { + ref.current.position.x -= Math.abs(xPosition - target) / 16; + } + + if (xPosition < target) { + ref.current.position.x += Math.abs(xPosition - target) / 16; + } + }); + + return ( + + {types.map( + (type, index) => + Math.abs(index - selectedIndex) <= 1 && ( + + + + ), + )} + + ); +}; + +export const Showcase = (props: Props) => { + const [selectedIndex, selectIndex] = useState(0); + + return ( + <> + + + + + + + + + + + ); +}; diff --git a/src/components/showcase/info-box.tsx b/src/components/showcase/info-box.tsx new file mode 100644 index 0000000..b95a225 --- /dev/null +++ b/src/components/showcase/info-box.tsx @@ -0,0 +1,79 @@ +import { CoinProps } from "@/types/coin"; +import { Dispatch, SetStateAction } from "react"; + +export const InfoBox = ({ + category, + type, + maxIndex, + selectIndex, + selectedIndex, +}: { + category: "banknotes" | "coins"; + type: CoinProps; + maxIndex: number; + selectIndex: Dispatch>; + selectedIndex: number; +}) => { + return ( +
+
+ {type.issuer.name} +

{type.title}

+

{type.min_year + " - " + type.max_year}

+ {(type.count ?? 1) + " in collection"} + {category === "coins" && ( + <> +

{type.weight + "g"}

+

{type.size + "mm"}

+

{type.thickness + "mm"}

+ + )} +
+ +
+ + + +
+
+ ); +}; diff --git a/src/pages/api/countries/[country]/[coin].ts b/src/pages/api/countries/[country]/[coin].ts deleted file mode 100644 index 9cd3c8f..0000000 --- a/src/pages/api/countries/[country]/[coin].ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { NextApiHandler } from "next"; -import { readFile } from "fs/promises"; -import path from "path"; - -const handler: NextApiHandler = async ( - req, - res, -) => { - if (typeof req.query.country !== "string") { - res.status(400).json({ - message: `Invalid country "${JSON.stringify(req.query.country)}"`, - }); - return; - } - - if (typeof req.query.coin !== "string") { - res - .status(400) - .json({ message: `Invalid coin "${JSON.stringify(req.query.coin)}"` }); - return; - } - - try { - const coin = await readFile( - path.join("./public/coins", req.query.country, `${req.query.coin}.json`), - { encoding: "utf-8" }, - ); - - res.status(200).json(JSON.parse(coin)); - } catch { - res.status(404).json({ - message: `Coin "${req.query.country}/${req.query.coin}" not found`, - }); - } -}; - -export default handler; diff --git a/src/pages/api/countries/[country]/index.ts b/src/pages/api/countries/[country]/index.ts deleted file mode 100644 index 5c34462..0000000 --- a/src/pages/api/countries/[country]/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { NextApiHandler } from "next"; -import { readdir } from "fs/promises"; -import path from "path"; - -const handler: NextApiHandler = async ( - req, - res, -) => { - if (typeof req.query.country !== "string") { - res.status(400).json({ - message: `Invalid country "${JSON.stringify(req.query.country)}"`, - }); - return; - } - - try { - const countryCoins = await readdir( - path.join("./public/coins", req.query.country), - ); - - res - .status(200) - .json( - countryCoins - .filter((file) => file.endsWith(".json")) - .map((file) => file.replace(/\.json$/, "")), - ); - } catch { - res - .status(404) - .json({ message: `Country "${req.query.country}" not found` }); - } -}; - -export default handler; diff --git a/src/pages/api/countries/index.ts b/src/pages/api/countries/index.ts deleted file mode 100644 index 320a2c2..0000000 --- a/src/pages/api/countries/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { readdir } from "fs/promises"; -import type { NextApiHandler } from "next"; - -const handler: NextApiHandler = async (_req, res) => { - const countries = await readdir("./public/coins"); - - res.status(200).json(countries); -}; - -export default handler; diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts deleted file mode 100644 index ea77e8f..0000000 --- a/src/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from "next"; - -type Data = { - name: string; -}; - -export default function handler( - req: NextApiRequest, - res: NextApiResponse, -) { - res.status(200).json({ name: "John Doe" }); -} diff --git a/src/pages/banknotes/[country].tsx b/src/pages/banknotes/[country].tsx new file mode 100644 index 0000000..720baf1 --- /dev/null +++ b/src/pages/banknotes/[country].tsx @@ -0,0 +1,69 @@ +import Head from "next/head"; +import { GetStaticPaths, GetStaticProps, NextPage } from "next"; +import { CoinProps } from "@/types/coin"; +import { readdir } from "fs/promises"; +import { Showcase } from "@/components/showcase"; +import { Header } from "@/components/header"; +import { getCountryBanknotes } from "@/api/banknotes/get-country-banknotes"; +import { getCountryCoins } from "@/api/coins/get-country-coins"; + +type Props = { + country: string; + coinCount: number; + banknoteCount: number; + banknotes: CoinProps[]; +}; + +const BanknotesPage: NextPage = ({ banknotes, ...props }) => ( + <> + + Banknotes + + + + + +
+ +
+ +
+ +); + +export const getStaticProps: GetStaticProps = async ({ params }) => { + if (typeof params?.country !== "string") { + return { + notFound: true, + }; + } + + const coins = await getCountryCoins(params.country); + const banknotes = await getCountryBanknotes(params.country); + + return { + props: { + country: params.country, + coinCount: coins.reduce((total, coin) => total + (coin.count ?? 1), 0), + banknoteCount: banknotes.reduce( + (total, banknote) => total + (banknote.count ?? 1), + 0, + ), + banknotes: banknotes.sort((a, b) => a.min_year - b.min_year), + }, + }; +}; + +export const getStaticPaths: GetStaticPaths = async () => { + const countries = await readdir("./public/banknotes"); + + return { + fallback: false, + paths: countries.map((country) => ({ params: { country } })), + }; +}; + +export default BanknotesPage; diff --git a/src/pages/coins/[country].tsx b/src/pages/coins/[country].tsx new file mode 100644 index 0000000..e5cdb80 --- /dev/null +++ b/src/pages/coins/[country].tsx @@ -0,0 +1,71 @@ +import Head from "next/head"; +import { GetStaticPaths, GetStaticProps, NextPage } from "next"; +import { CoinProps } from "@/types/coin"; +import { readdir } from "fs/promises"; +import { Showcase } from "@/components/showcase"; +import { Header } from "@/components/header"; +import { getCountryBanknotes } from "@/api/banknotes/get-country-banknotes"; +import { getCountryCoins } from "@/api/coins/get-country-coins"; + +type Props = { + country: string; + coinCount: number; + banknoteCount: number; + coins: CoinProps[]; +}; + +const CoinsPage: NextPage = ({ coins, ...props }) => ( + <> + + Coins + + + + + +
+ +
+ +
+ +); + +export const getStaticProps: GetStaticProps = async ({ params }) => { + if (typeof params?.country !== "string") { + return { + notFound: true, + }; + } + + const coins = await getCountryCoins(params.country); + const banknotes = await getCountryBanknotes(params.country); + + console.log({ coins, banknotes }); + + return { + props: { + country: params.country, + banknoteCount: banknotes.reduce( + (total, banknote) => total + (banknote.count ?? 1), + 0, + ), + coinCount: coins.reduce((total, coin) => total + (coin.count ?? 1), 0), + coins: coins.sort((a, b) => a.min_year - b.min_year), + }, + }; +}; + +export const getStaticPaths: GetStaticPaths = async () => { + const countries = await readdir("./public/coins"); + + return { + fallback: false, + paths: countries.map((country) => ({ params: { country } })), + }; +}; + +export default CoinsPage; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 3393de7..2692df9 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -2,19 +2,23 @@ import Head from "next/head"; import { GetStaticProps, NextPage } from "next"; import { readdir } from "fs/promises"; import { useMemo } from "react"; +import { getCountryCoins } from "@/api/coins/get-country-coins"; +import { getCountryBanknotes } from "@/api/banknotes/get-country-banknotes"; type Props = { - banknoteCountries: string[]; - coinCountries: string[]; + countsByCountry: Record< + string, + { + coinCount: number; + banknoteCount: number; + } + >; }; -const CountriesPage: NextPage = ({ - banknoteCountries, - coinCountries, -}) => { +const CountriesPage: NextPage = ({ countsByCountry }) => { const countries = useMemo( - () => Array.from(new Set([...banknoteCountries, ...coinCountries])).sort(), - [banknoteCountries, coinCountries], + () => Object.keys(countsByCountry).sort(), + [countsByCountry], ); return ( @@ -51,10 +55,14 @@ const CountriesPage: NextPage = ({ width: "min(640px, 95vw)", }} > - {coinCountries.includes(country) ? ( + {countsByCountry[country].coinCount > 0 ? ( <> - {"pile"} - {"coins"} + + {"pile (" + countsByCountry[country].coinCount + ")"} + + + {"coins (" + countsByCountry[country].coinCount + ")"} + ) : ( <> @@ -63,8 +71,10 @@ const CountriesPage: NextPage = ({ )} - {banknoteCountries.includes(country) ? ( - {"banknotes"} + {countsByCountry[country].banknoteCount > 0 ? ( + + {"banknotes (" + countsByCountry[country].banknoteCount + ")"} + ) : (
)} @@ -79,11 +89,24 @@ const CountriesPage: NextPage = ({ export const getStaticProps: GetStaticProps = async () => { const coinCountries = await readdir("./public/coins"); const banknoteCountries = await readdir("./public/banknotes"); + const countsByCountry: Props["countsByCountry"] = {}; + + for (const country of new Set([...coinCountries, ...banknoteCountries])) { + countsByCountry[country] = { + coinCount: (await getCountryCoins(country)).reduce( + (total, coin) => total + (coin.count ?? 1), + 0, + ), + banknoteCount: (await getCountryBanknotes(country)).reduce( + (total, banknote) => total + (banknote.count ?? 1), + 0, + ), + }; + } return { props: { - banknoteCountries, - coinCountries, + countsByCountry, }, }; }; diff --git a/src/pages/pile/[country].tsx b/src/pages/pile/[country].tsx index 78eea12..59a1f07 100644 --- a/src/pages/pile/[country].tsx +++ b/src/pages/pile/[country].tsx @@ -1,75 +1,58 @@ import Head from "next/head"; -import { Scene } from "@/components/scene"; +import { Pile } from "@/components/pile"; import { GetStaticPaths, GetStaticProps, NextPage } from "next"; import { CoinProps } from "@/types/coin"; -import { readFile, readdir } from "fs/promises"; -import path from "path"; +import { readdir } from "fs/promises"; +import { Header } from "@/components/header"; +import { getCountryBanknotes } from "@/api/banknotes/get-country-banknotes"; +import { getCountryCoins } from "@/api/coins/get-country-coins"; type Props = { + country: string; + coinCount: number; + banknoteCount: number; coins: CoinProps[]; }; -const Home: NextPage = ({ coins }) => { - return ( - <> - - Coins - - - - -
- +const PilePage: NextPage = ({ coins, ...props }) => ( + <> + + Coin pile + + + + - -
- - ); -}; +
-export const getStaticProps: GetStaticProps = async (ctx) => { - if (typeof ctx.params?.country !== "string") { +
+ +
+ +); + +export const getStaticProps: GetStaticProps = async ({ params }) => { + if (typeof params?.country !== "string") { return { notFound: true, }; } - const coinIds = await readdir( - path.join("./public/coins", ctx.params.country), - ); - - const coins: CoinProps[] = []; - - for (const coinId of coinIds) { - const coin = await readFile( - path.join("./public/coins", ctx.params.country, coinId), - { encoding: "utf-8" }, - ); - - coins.push(JSON.parse(coin)); - } + const coins = await getCountryCoins(params.country); + const banknotes = await getCountryBanknotes(params.country); return { props: { - coins, + country: params.country, + banknoteCount: banknotes.reduce( + (total, banknote) => total + (banknote.count ?? 1), + 0, + ), + coinCount: coins.reduce((total, coin) => total + (coin.count ?? 1), 0), + coins: coins.sort((a, b) => a.min_year - b.min_year), }, }; }; @@ -83,4 +66,4 @@ export const getStaticPaths: GetStaticPaths = async () => { }; }; -export default Home; +export default PilePage; diff --git a/src/pages/showcase-banknotes/[country].tsx b/src/pages/showcase-banknotes/[country].tsx deleted file mode 100644 index 4f23616..0000000 --- a/src/pages/showcase-banknotes/[country].tsx +++ /dev/null @@ -1,225 +0,0 @@ -import Head from "next/head"; -import { GetStaticPaths, GetStaticProps, NextPage } from "next"; -import { CoinProps } from "@/types/coin"; -import { Canvas, MeshProps, useFrame } from "@react-three/fiber"; -import { Dispatch, SetStateAction, Suspense, useRef, useState } from "react"; -import { Mesh } from "three"; -import { OrbitControls } from "@react-three/drei"; -import path from "path"; -import { readFile, readdir } from "fs/promises"; -import { BanknoteInstance } from "@/components/scene/banknote"; - -type Props = { - banknotes: CoinProps[]; -}; - -const SpinninBanknote = ({ - isSelected, - coinProps, - ...props -}: { coinProps: CoinProps; isSelected?: boolean } & MeshProps) => { - const ref = useRef(null!); - - useFrame((_state, delta) => { - if (isSelected) { - ref.current.rotation.y += delta; - } - }); - - return ( - - - - - - ); -}; - -const Row = ({ - banknotes, - selectedIndex, -}: Props & { selectedIndex: number }) => { - const ref = useRef(null!); - - useFrame(() => { - const xPosition = Math.round(10 * ref.current.position.x) / 10; - const target = -selectedIndex * 8; - - if (xPosition > target) { - ref.current.position.x -= Math.abs(xPosition - target) / 16; - } - - if (xPosition < target) { - ref.current.position.x += Math.abs(xPosition - target) / 16; - } - }); - - return ( - - {banknotes.map((coin, index) => ( - - - - ))} - - ); -}; - -const InfoBox = ({ - coin, - maxIndex, - selectIndex, -}: { - coin: CoinProps; - maxIndex: number; - selectIndex: Dispatch>; -}) => { - return ( -
-
- {coin.issuer.name} -

{coin.title}

-

{coin.min_year + " - " + coin.max_year}

- {(coin.count ?? 1) + " in collection"} -
- -
- - - -
-
- ); -}; - -const CountryPage: NextPage = ({ banknotes }) => { - const [selectedIndex, selectIndex] = useState(0); - - return ( - <> - - Coins - - - - -
- - - - - - - - - - - -
- - ); -}; - -export const getStaticProps: GetStaticProps = async (ctx) => { - console.log(ctx.params?.country); - if (typeof ctx.params?.country !== "string") { - return { - notFound: true, - }; - } - - const coinIds = await readdir( - path.join("./public/banknotes", ctx.params?.country), - ); - const banknotes: CoinProps[] = []; - - for (const coinId of coinIds) { - const coin = await readFile( - path.join("./public/banknotes", ctx.params.country, coinId), - { encoding: "utf-8" }, - ); - - banknotes.push(JSON.parse(coin)); - } - - return { - props: { - banknotes: banknotes.sort((a, b) => a.min_year - b.min_year), - }, - }; -}; - -export const getStaticPaths: GetStaticPaths = async () => { - const countries = await readdir("./public/banknotes"); - - return { - fallback: false, - paths: countries.map((country) => ({ params: { country } })), - }; -}; - -export default CountryPage; diff --git a/src/pages/showcase/[country].tsx b/src/pages/showcase/[country].tsx deleted file mode 100644 index c327d0b..0000000 --- a/src/pages/showcase/[country].tsx +++ /dev/null @@ -1,234 +0,0 @@ -import Head from "next/head"; -import { GetStaticPaths, GetStaticProps, NextPage } from "next"; -import { CoinProps } from "@/types/coin"; -import { Canvas, MeshProps, useFrame } from "@react-three/fiber"; -import { Dispatch, SetStateAction, Suspense, useRef, useState } from "react"; -import { CoinInstance } from "@/components/scene/coin"; -import { Mesh } from "three"; -import { OrbitControls } from "@react-three/drei"; -import path from "path"; -import { readFile, readdir } from "fs/promises"; - -type Props = { - coins: CoinProps[]; -}; - -const SpinninCoin = ({ - isSelected, - coinProps, - ...props -}: { coinProps: CoinProps; isSelected?: boolean } & MeshProps) => { - const ref = useRef(null!); - - useFrame((_state, delta) => { - if (!isSelected) { - return; - } - - switch (coinProps.orientation) { - case "medal": - ref.current.rotation.x += delta; - break; - - default: - ref.current.rotation.z += delta; - break; - } - }); - - return ( - - - - - - ); -}; - -const Row = ({ coins, selectedIndex }: Props & { selectedIndex: number }) => { - const ref = useRef(null!); - - useFrame(() => { - const xPosition = Math.round(10 * ref.current.position.x) / 10; - const target = -selectedIndex * 6; - - if (xPosition > target) { - ref.current.position.x -= Math.abs(xPosition - target) / 16; - } - - if (xPosition < target) { - ref.current.position.x += Math.abs(xPosition - target) / 16; - } - }); - - return ( - - {coins.map((coin, index) => ( - - - - ))} - - ); -}; - -const InfoBox = ({ - coin, - maxIndex, - selectIndex, -}: { - coin: CoinProps; - maxIndex: number; - selectIndex: Dispatch>; -}) => { - return ( -
-
- {coin.issuer.name} -

{coin.title}

-

{coin.min_year + " - " + coin.max_year}

- {(coin.count ?? 1) + " in collection"} -

{coin.weight + "g"}

-

{coin.size + "mm"}

-

{coin.thickness + "mm"}

-
- -
- - - -
-
- ); -}; - -const CountryPage: NextPage = ({ coins }) => { - const [selectedIndex, selectIndex] = useState(0); - - return ( - <> - - Coins - - - - -
- - - - - - - - - - - -
- - ); -}; - -export const getStaticProps: GetStaticProps = async (ctx) => { - if (typeof ctx.params?.country !== "string") { - return { - notFound: true, - }; - } - - const coinIds = await readdir( - path.join("./public/coins", ctx.params?.country), - ); - const coins: CoinProps[] = []; - - for (const coinId of coinIds) { - const coin = await readFile( - path.join("./public/coins", ctx.params.country, coinId), - { encoding: "utf-8" }, - ); - - coins.push(JSON.parse(coin)); - } - - return { - props: { - coins: coins.sort((a, b) => a.min_year - b.min_year), - }, - }; -}; - -export const getStaticPaths: GetStaticPaths = async () => { - const countries = await readdir("./public/coins"); - - return { - fallback: false, - paths: countries.map((country) => ({ params: { country } })), - }; -}; - -export default CountryPage; diff --git a/src/styles/globals.css b/src/styles/globals.css index 72d127f..60a2f2a 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -10,6 +10,10 @@ body { overflow-x: hidden; } +#scene-root { + background-color: #111; +} + #scene-root > div:first-child { height: 100vh !important; } diff --git a/src/types/coin.ts b/src/types/coin.ts index bb1bd63..753f06d 100644 --- a/src/types/coin.ts +++ b/src/types/coin.ts @@ -14,7 +14,7 @@ export type CoinProps = { id: number; url: string; title: string; - category: "coin" | "exonumia"; + category: "banknote" | "coin" | "exonumia"; issuer: { code: string; name: string;