From 2169d0899279415244509266aa7e55c05dc4d095 Mon Sep 17 00:00:00 2001 From: rare-magma Date: Sat, 2 Sep 2023 19:53:25 +0200 Subject: [PATCH] refactor: use react context for config Signed-off-by: rare-magma --- src/App.test.tsx | 2 +- src/App.tsx | 5 +- src/components/Budget/BudgetPage.test.tsx | 3 +- src/components/Budget/BudgetPage.tsx | 33 ++--------- .../CalculateButton/CalculateButton.test.tsx | 3 +- .../CalculateButton/CalculateButton.tsx | 6 +- .../CalculateButton.test.tsx.snap | 6 -- src/components/Chart/Chart.test.tsx | 3 +- src/components/Chart/Chart.tsx | 15 ++--- src/components/Chart/ChartTooltip.tsx | 6 +- .../Chart/__snapshots__/Chart.test.tsx.snap | 6 -- src/components/ChartsPage/ChartsPage.tsx | 9 +-- .../ItemForm/ItemFormGroup.test.tsx | 13 ++-- src/components/ItemForm/ItemFormGroup.tsx | 7 +-- .../__snapshots__/ItemFormGroup.test.tsx.snap | 6 -- src/components/NavBar/NavBar.test.tsx | 15 +---- src/components/NavBar/NavBar.tsx | 16 +---- .../NavBar/__snapshots__/NavBar.test.tsx.snap | 2 - src/components/StatCard/StatCard.test.tsx | 3 +- src/components/StatCard/StatCard.tsx | 6 +- .../__snapshots__/StatCard.test.tsx.snap | 6 -- src/components/TableCard/TableCard.test.tsx | 4 +- src/components/TableCard/TableCard.tsx | 6 +- .../__snapshots__/TableCard.test.tsx.snap | 6 -- src/context/ConfigContext.test.tsx | 26 ++++++++ src/context/ConfigContext.tsx | 59 +++++++++++++++++++ src/{ => context}/db.ts | 0 src/index.tsx | 1 + src/setupTests.ts | 26 ++++++++ 29 files changed, 157 insertions(+), 142 deletions(-) create mode 100644 src/context/ConfigContext.test.tsx create mode 100644 src/context/ConfigContext.tsx rename src/{ => context}/db.ts (100%) diff --git a/src/App.test.tsx b/src/App.test.tsx index 60df8df..1fe72b3 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import App from "./App"; import userEvent from "@testing-library/user-event"; -import { budgetsDB, optionsDB } from "./db"; +import { budgetsDB, optionsDB } from "./context/db"; describe("App", () => { const comp = ; diff --git a/src/App.tsx b/src/App.tsx index 1e35795..a50b6b3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,16 +2,17 @@ import "bootstrap/dist/css/bootstrap.min.css"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import "./App.css"; import BudgetPage from "./components/Budget/BudgetPage"; +import { ConfigProvider } from "./context/ConfigContext"; export default function App() { return ( - <> + } /> } /> - + ); } diff --git a/src/components/Budget/BudgetPage.test.tsx b/src/components/Budget/BudgetPage.test.tsx index 36933bb..a28025e 100644 --- a/src/components/Budget/BudgetPage.test.tsx +++ b/src/components/Budget/BudgetPage.test.tsx @@ -95,6 +95,7 @@ describe("BudgetPage", () => { // currency change await userEvent.type(screen.getByPlaceholderText("USD"), "CAD"); await userEvent.click(screen.getByText("CAD")); - expect(screen.getByDisplayValue("CA$200")).toBeInTheDocument(); + + expect(screen.getByDisplayValue("CAD")).toBeInTheDocument(); }); }); diff --git a/src/components/Budget/BudgetPage.tsx b/src/components/Budget/BudgetPage.tsx index b2ee303..965d277 100644 --- a/src/components/Budget/BudgetPage.tsx +++ b/src/components/Budget/BudgetPage.tsx @@ -12,14 +12,12 @@ import { convertCsvToBudget, createBudgetNameList, createNewBudget, - initialCurrencyCode, roundBig, userLang, } from "../../utils"; import Papa from "papaparse"; import { Option } from "react-bootstrap-typeahead/types/types"; import { useHotkeys } from "react-hotkeys-hook"; -import { CurrencyInputProps } from "react-currency-input-field"; import ErrorModal, { CsvError, JsonError } from "../ErrorModal/ErrorModal"; import LandingPage from "../LandingPage/LandingPage"; import NavBar from "../NavBar/NavBar"; @@ -29,7 +27,8 @@ import { Expense } from "../TableCard/Expense"; import { Income } from "../TableCard/Income"; import TableCard from "../TableCard/TableCard"; import ChartsPage from "../ChartsPage/ChartsPage"; -import { budgetsDB, optionsDB } from "../../db"; +import { budgetsDB, optionsDB } from "../../context/db"; +import { useConfig } from "../../context/ConfigContext"; // import { useWhatChanged } from "@simbathesailor/use-what-changed"; function BudgetPage() { @@ -42,14 +41,6 @@ function BudgetPage() { const [jsonError, setJsonError] = useState([]); const [show, setShow] = useState(false); - const [currency, setCurrency] = useState(initialCurrencyCode); - const [intlConfig, setIntlConfig] = useState< - CurrencyInputProps["intlConfig"] - >({ - locale: userLang, - currency: currency, - }); - const [budget, setBudget] = useState(null); const [budgetList, setBudgetList] = useState([]); const [budgetNameList, setBudgetNameList] = useState< @@ -63,6 +54,8 @@ function BudgetPage() { budget?.incomes.total ?? 0, ); + const { setIntlConfig, handleCurrency } = useConfig(); + useHotkeys("s", () => handleExportJSON(), { preventDefault: true, }); @@ -286,14 +279,6 @@ function BudgetPage() { handleGo(1, budgetList.length - 1); } - function handleSetCurrency(c: string) { - optionsDB.setItem("currencyCode", c).catch((e) => { - handleError(e); - }); - setCurrency(c); - setIntlConfig({ locale: userLang, currency: c }); - } - function handleImportCsv(fileReader: FileReader, file: File) { const newBudgetList: Budget[] = []; const csvObject = Papa.parse(fileReader.result as string, { @@ -461,7 +446,7 @@ function BudgetPage() { .getItem("currencyCode") .then((c) => { if (c) { - setCurrency(c as string); + handleCurrency(c as string); setIntlConfig({ locale: userLang, currency: c as string }); } }) @@ -506,7 +491,6 @@ function BudgetPage() { selected={budget?.name ?? undefined} id={budget?.id ?? undefined} budgetNameList={budgetNameList} - currency={currency || initialCurrencyCode} onRename={(e) => { handleRename(e); }} @@ -537,9 +521,6 @@ function BudgetPage() { onSelect={(e) => { handleSelect(e); }} - onSetCurrency={(e) => { - handleSetCurrency(e); - }} /> )} @@ -569,7 +550,6 @@ function BudgetPage() { {showGraphs && ( a.name.localeCompare(b.name))} - intlConfig={intlConfig} onShowGraphs={() => setShowGraphs(false)} /> )} @@ -584,7 +564,6 @@ function BudgetPage() { key={"stats-" + budget.expenses.total + budget.incomes.total} stat={budget.stats} revenuePercentage={revenuePercentage} - intlConfig={intlConfig} onChange={handleStatChange} onAutoGoal={handleAutoGoal} onShowGraphs={() => setShowGraphs(true)} @@ -594,7 +573,6 @@ function BudgetPage() { { const onCalculate = vi.fn(); const comp = ( diff --git a/src/components/CalculateButton/CalculateButton.tsx b/src/components/CalculateButton/CalculateButton.tsx index c58b8d5..10462db 100644 --- a/src/components/CalculateButton/CalculateButton.tsx +++ b/src/components/CalculateButton/CalculateButton.tsx @@ -5,22 +5,21 @@ import { OverlayTrigger, Popover, } from "react-bootstrap"; -import CurrencyInput, { CurrencyInputProps } from "react-currency-input-field"; +import CurrencyInput from "react-currency-input-field"; import { BsDashLg, BsXLg, BsCheckLg, BsPlusSlashMinus } from "react-icons/bs"; import { CgMathPlus, CgMathDivide } from "react-icons/cg"; import { ItemForm } from "../ItemForm/ItemForm"; import { useRef, useState } from "react"; +import { useConfig } from "../../context/ConfigContext"; interface CalculateButtonProps { itemForm: ItemForm; label: string; - intlConfig: CurrencyInputProps["intlConfig"]; onCalculate: (changeValue: number, operation: string) => void; } function CalculateButton({ itemForm, - intlConfig, label, onCalculate, }: CalculateButtonProps) { @@ -28,6 +27,7 @@ function CalculateButton({ const [changeValue, setChangeValue] = useState(0); const opButtonRef = useRef(null); const inputRef = useRef(null); + const { intlConfig } = useConfig(); function handleKeyPress(e: { key: string }) { if (e.key === "Enter") { diff --git a/src/components/CalculateButton/__snapshots__/CalculateButton.test.tsx.snap b/src/components/CalculateButton/__snapshots__/CalculateButton.test.tsx.snap index 37e9095..6306301 100644 --- a/src/components/CalculateButton/__snapshots__/CalculateButton.test.tsx.snap +++ b/src/components/CalculateButton/__snapshots__/CalculateButton.test.tsx.snap @@ -2,12 +2,6 @@ exports[`CalculateButton > matches snapshot 1`] = ` { x + 10, }); + const { intlConfig } = useConfig(); + function tickFormatter(value: number) { return ( (intlConfig?.currency && intlFormat(value, intlConfig.currency)) ?? "" @@ -99,13 +100,7 @@ function Chart({ /> )} - } + content={} contentStyle={{ backgroundColor: "var(--bgcolor)" }} itemStyle={{ color: "var(--textcolor)" }} /> diff --git a/src/components/Chart/ChartTooltip.tsx b/src/components/Chart/ChartTooltip.tsx index c642257..b2eda87 100644 --- a/src/components/Chart/ChartTooltip.tsx +++ b/src/components/Chart/ChartTooltip.tsx @@ -1,13 +1,12 @@ import Big from "big.js"; import { Container, Row, Col } from "react-bootstrap"; import { intlFormat, roundBig } from "../../utils"; -import { CurrencyInputProps } from "react-currency-input-field"; +import { useConfig } from "../../context/ConfigContext"; interface ChartTooltipProps { active?: boolean; payload?: { name: string; value: number; unit: string }[]; label?: string; - intlConfig: CurrencyInputProps["intlConfig"]; key1?: string; key2?: string; } @@ -16,10 +15,11 @@ function ChartTooltip({ active, payload, label, - intlConfig, key1, key2, }: ChartTooltipProps) { + const { intlConfig } = useConfig(); + if (active && payload?.length && intlConfig?.currency) { return ( diff --git a/src/components/Chart/__snapshots__/Chart.test.tsx.snap b/src/components/Chart/__snapshots__/Chart.test.tsx.snap index 01e20df..081c546 100644 --- a/src/components/Chart/__snapshots__/Chart.test.tsx.snap +++ b/src/components/Chart/__snapshots__/Chart.test.tsx.snap @@ -113,12 +113,6 @@ exports[`Chart > matches snapshot 1`] = ` ] } header="chart header" - intlConfig={ - { - "currency": "USD", - "locale": "en-US", - } - } legend1="median revenue" legendValues1={ [ diff --git a/src/components/ChartsPage/ChartsPage.tsx b/src/components/ChartsPage/ChartsPage.tsx index eba19f8..ff3d355 100644 --- a/src/components/ChartsPage/ChartsPage.tsx +++ b/src/components/ChartsPage/ChartsPage.tsx @@ -7,18 +7,16 @@ import { Row, Tooltip, } from "react-bootstrap"; -import { CurrencyInputProps } from "react-currency-input-field"; import { BsArrowLeft } from "react-icons/bs"; import { useHotkeys } from "react-hotkeys-hook"; import Chart from "../Chart/Chart"; interface GraphProps { budgetList: Budget[]; - intlConfig: CurrencyInputProps["intlConfig"]; onShowGraphs: () => void; } -function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { +function ChartsPage({ budgetList, onShowGraphs }: GraphProps) { useHotkeys("i", () => onShowGraphs(), { preventDefault: true, }); @@ -51,7 +49,6 @@ function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { { @@ -75,7 +72,6 @@ function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { { return b.stats.saved; @@ -91,7 +87,6 @@ function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { { return b.stats.reserves; @@ -108,7 +103,6 @@ function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { { @@ -132,7 +126,6 @@ function ChartsPage({ budgetList, intlConfig, onShowGraphs }: GraphProps) { { return b.stats.goal; diff --git a/src/components/ItemForm/ItemFormGroup.test.tsx b/src/components/ItemForm/ItemFormGroup.test.tsx index c88d0cb..0e39765 100644 --- a/src/components/ItemForm/ItemFormGroup.test.tsx +++ b/src/components/ItemForm/ItemFormGroup.test.tsx @@ -2,12 +2,9 @@ import { cleanup, fireEvent, render, screen } from "@testing-library/react"; import ItemFormGroup from "./ItemFormGroup"; import userEvent from "@testing-library/user-event"; import { vi } from "vitest"; -import { - testIntlConfig, - itemForm1, - testSpanishIntlConfig, -} from "../../setupTests"; +import { itemForm1, testSpanishContext } from "../../setupTests"; import React from "react"; +import * as AppContext from "../../context/ConfigContext"; describe("ItemFormGroup", () => { const onRemove = vi.fn(); @@ -18,7 +15,6 @@ describe("ItemFormGroup", () => { itemForm={itemForm1} label="Expenses" inputRef={ref} - intlConfig={testIntlConfig} costPercentage={1} onRemove={onRemove} onChange={onChange} @@ -93,12 +89,15 @@ describe("ItemFormGroup", () => { it("transforms decimal separator based on locale", async () => { cleanup(); + vi.spyOn(AppContext, "useConfig").mockImplementation( + () => testSpanishContext, + ); + render( ; onChange: (itemForm: ItemForm) => void; onRemove: (itemForm: ItemForm) => void; @@ -26,7 +26,6 @@ interface ItemFormProps { function ItemFormGroup({ itemForm: initialItemForm, costPercentage, - intlConfig, inputRef, label, onRemove, @@ -36,6 +35,7 @@ function ItemFormGroup({ const [changed, setChanged] = useState(false); const deleteButtonRef = useRef(null); const valueRef = useRef(null); + const { intlConfig } = useConfig(); function handleRemove(item: ItemForm) { onRemove(item); @@ -141,7 +141,6 @@ function ItemFormGroup({ handleChange(operation, "", undefined, changeValue) } diff --git a/src/components/ItemForm/__snapshots__/ItemFormGroup.test.tsx.snap b/src/components/ItemForm/__snapshots__/ItemFormGroup.test.tsx.snap index e6beeca..0ec5c22 100644 --- a/src/components/ItemForm/__snapshots__/ItemFormGroup.test.tsx.snap +++ b/src/components/ItemForm/__snapshots__/ItemFormGroup.test.tsx.snap @@ -15,12 +15,6 @@ exports[`ItemFormGroup > matches snapshot 1`] = ` />, } } - intlConfig={ - { - "currency": "USD", - "locale": "en-US", - } - } itemForm={ ItemForm { "id": 1, diff --git a/src/components/NavBar/NavBar.test.tsx b/src/components/NavBar/NavBar.test.tsx index eb0aff2..d99a94b 100644 --- a/src/components/NavBar/NavBar.test.tsx +++ b/src/components/NavBar/NavBar.test.tsx @@ -2,7 +2,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { vi } from "vitest"; import NavBar from "./NavBar"; -import { budgetNameList, testIntlConfig, testBudget } from "../../setupTests"; +import { budgetNameList, testBudget } from "../../setupTests"; describe("NavBar", () => { const onClone = vi.fn(); @@ -15,11 +15,9 @@ describe("NavBar", () => { const onRemove = vi.fn(); const onRename = vi.fn(); const onSelect = vi.fn(); - const onSetCurrency = vi.fn(); const comp = ( { onRemove={onRemove} onRename={onRename} onSelect={onSelect} - onSetCurrency={onSetCurrency} /> ); @@ -140,14 +137,6 @@ describe("NavBar", () => { ]); }); - it("triggers onSetCurrency when currency is selected from dropdown", async () => { - const newButton = screen.getAllByRole("button", { name: "new budget" }); - await userEvent.click(newButton[0]); - await userEvent.type(screen.getByPlaceholderText("USD"), "CAD"); - await userEvent.click(screen.getByText("CAD")); - expect(onSetCurrency).toBeCalledWith("CAD"); - }); - it("opens instructions in new tab", async () => { const instructionsButton = screen.getByLabelText( "open instructions in new tab", @@ -163,7 +152,6 @@ describe("NavBar", () => { render( { onRemove={onRemove} onRename={onRename} onSelect={onSelect} - onSetCurrency={onSetCurrency} />, ); const guitosButton = screen.getByLabelText("open guitos repository"); diff --git a/src/components/NavBar/NavBar.tsx b/src/components/NavBar/NavBar.tsx index 6455e5e..401e1b5 100644 --- a/src/components/NavBar/NavBar.tsx +++ b/src/components/NavBar/NavBar.tsx @@ -23,12 +23,12 @@ import TypeaheadRef from "react-bootstrap-typeahead/types/core/Typeahead"; import { NavBarItem } from "./NavBarItem"; import { NavBarDelete } from "./NavBarDelete"; import { NavBarExport } from "./NavBarExport"; +import { useConfig } from "../../context/ConfigContext"; interface NavBarProps { budgetNameList: { id: string; name: string }[]; id?: string | null; selected?: string | null; - currency: string; onClone: () => void; onExport: (t: string) => void; onGoBack: () => void; @@ -39,14 +39,12 @@ interface NavBarProps { onRemove: (name: string) => void; onRename: (name?: string | null) => void; onSelect: (budget: Option[]) => void; - onSetCurrency: (currency: string) => void; } function NavBar({ budgetNameList: initialBudgetNameList, id: initialId, selected: initialSelectedName, - currency, onClone, onExport, onGoBack, @@ -57,7 +55,6 @@ function NavBar({ onRemove, onRename, onSelect, - onSetCurrency, }: NavBarProps) { const importRef = useRef() as React.MutableRefObject; @@ -71,6 +68,7 @@ function NavBar({ const [expanded, setExpanded] = useState(false); const [theme, setTheme] = useState("light"); + const { currency, handleCurrency } = useConfig(); useHotkeys("pageup", () => handleGoForward(), { preventDefault: true }); useHotkeys("pagedown", () => handleGoBack(), { preventDefault: true }); @@ -154,14 +152,6 @@ function NavBar({ onGoForward(); } - function handleSetCurrency(c: string) { - setExpanded(false); - onSetCurrency(c); - if (currencyRef.current) { - currencyRef.current.clear(); - } - } - function editName(event: React.ChangeEvent) { const newName = event.target.value; if (newName) { @@ -387,7 +377,7 @@ function NavBar({ paginate={false} onChange={(c: Option[]) => { if (currenciesList.includes(c[0] as string)) { - handleSetCurrency(c[0] as string); + handleCurrency(c[0] as string); } }} className="w-100 fixed-width-font" diff --git a/src/components/NavBar/__snapshots__/NavBar.test.tsx.snap b/src/components/NavBar/__snapshots__/NavBar.test.tsx.snap index cabe01a..8c97f3f 100644 --- a/src/components/NavBar/__snapshots__/NavBar.test.tsx.snap +++ b/src/components/NavBar/__snapshots__/NavBar.test.tsx.snap @@ -18,7 +18,6 @@ exports[`NavBar > matches snapshot 1`] = ` }, ] } - currency="USD" id="035c2de4-00a4-403c-8f0e-f81339be9a4e" onClone={[MockFunction spy]} onExport={[MockFunction spy]} @@ -30,7 +29,6 @@ exports[`NavBar > matches snapshot 1`] = ` onRemove={[MockFunction spy]} onRename={[MockFunction spy]} onSelect={[MockFunction spy]} - onSetCurrency={[MockFunction spy]} selected="2023-04" /> `; diff --git a/src/components/StatCard/StatCard.test.tsx b/src/components/StatCard/StatCard.test.tsx index c2d5e60..f65902f 100644 --- a/src/components/StatCard/StatCard.test.tsx +++ b/src/components/StatCard/StatCard.test.tsx @@ -1,7 +1,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { vi } from "vitest"; -import { testIntlConfig, testBudget } from "../../setupTests"; +import { testBudget } from "../../setupTests"; import StatCard from "./StatCard"; describe("StatCard", () => { @@ -10,7 +10,6 @@ describe("StatCard", () => { const onShowGraphs = vi.fn(); const comp = ( void; onAutoGoal: (stat: Stat) => void; onShowGraphs: () => void; @@ -28,13 +28,13 @@ interface StatCardProps { function StatCard({ stat: initialStat, revenuePercentage, - intlConfig, onChange, onAutoGoal, onShowGraphs, }: StatCardProps) { const [stat, setStat] = useState(initialStat); const [autoGoal, setAutoGoal] = useState(false); + const { intlConfig } = useConfig(); const goalRef = useRef() as React.MutableRefObject; diff --git a/src/components/StatCard/__snapshots__/StatCard.test.tsx.snap b/src/components/StatCard/__snapshots__/StatCard.test.tsx.snap index d446da8..3df612e 100644 --- a/src/components/StatCard/__snapshots__/StatCard.test.tsx.snap +++ b/src/components/StatCard/__snapshots__/StatCard.test.tsx.snap @@ -2,12 +2,6 @@ exports[`StatCard > matches snapshot 1`] = ` { const onChange = vi.fn(); const comp = ( { render( void; } @@ -28,13 +27,13 @@ function TableCard({ items: initialItems, revenueTotal, header: label, - intlConfig, onChange, }: TableCardProps) { const [table, setTable] = useState(initialItems); const [total, setTotal] = useState(roundBig(calcTotal(table.items), 2)); const revenuePercentage = calcPercentage(total, revenueTotal); const inputRef = useRef(null); + const { intlConfig } = useConfig(); function addTable(tableBeingEdited: Income | Expense) { let newTable; @@ -151,7 +150,6 @@ function TableCard({ matches snapshot 1`] = ` +

{intlConfig?.currency}

+

{intlConfig?.locale}

+

{currency}

+ + ); +} + +describe("ConfigProvider", () => { + it("provides expected ConfigContext obj to child elements", () => { + const { getByLabelText } = render( + + + , + ); + expect(getByLabelText("currency").textContent).toEqual("USD"); + expect(getByLabelText("locale").textContent).toEqual("en-US"); + expect(getByLabelText("c").textContent).toEqual("USD"); + }); +}); diff --git a/src/context/ConfigContext.tsx b/src/context/ConfigContext.tsx new file mode 100644 index 0000000..ee7b5e7 --- /dev/null +++ b/src/context/ConfigContext.tsx @@ -0,0 +1,59 @@ +import { PropsWithChildren, createContext, useContext, useState } from "react"; +import { CurrencyInputProps } from "react-currency-input-field"; +import { initialCurrencyCode, userLang } from "../utils"; +import { IntlConfig } from "react-currency-input-field/dist/components/CurrencyInputProps"; +import { optionsDB } from "./db"; + +interface ConfigContextInterface { + intlConfig: IntlConfig | undefined; + setIntlConfig: (value: IntlConfig) => void; + currency: string; + setCurrency: (value: string) => void; +} + +const ConfigContext = createContext({ + intlConfig: { locale: userLang, currency: initialCurrencyCode }, + setIntlConfig: (value: IntlConfig) => { + value; + }, + currency: initialCurrencyCode, + setCurrency: (value: string) => { + value; + }, +}); + +function useConfig() { + const { intlConfig, setIntlConfig } = useContext(ConfigContext); + const { currency, setCurrency } = useContext(ConfigContext); + + function handleCurrency(c: string) { + optionsDB.setItem("currencyCode", c).catch((e) => { + throw new Error(e as string); + }); + setCurrency(c); + setIntlConfig({ locale: userLang, currency: c }); + } + + return { intlConfig, setIntlConfig, currency, handleCurrency }; +} + +function ConfigProvider({ children }: PropsWithChildren) { + const [currency, setCurrency] = useState(initialCurrencyCode); + const [intlConfig, setIntlConfig] = useState< + CurrencyInputProps["intlConfig"] + >({ + locale: userLang, + currency: currency, + }); + + return ( + + {children} + + ); +} + +// eslint-disable-next-line react-refresh/only-export-components +export { ConfigProvider, useConfig }; diff --git a/src/db.ts b/src/context/db.ts similarity index 100% rename from src/db.ts rename to src/context/db.ts diff --git a/src/index.tsx b/src/index.tsx index 5c04320..1e32aee 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -15,6 +15,7 @@ const updateSW = registerSW({ }); const root = ReactDOM.createRoot(document.getElementById("root")!); + root.render( diff --git a/src/setupTests.ts b/src/setupTests.ts index 4d36478..57b7f29 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -9,6 +9,8 @@ import * as matchers from "@testing-library/jest-dom/matchers"; import { randomUUID } from "node:crypto"; import { ItemForm } from "./components/ItemForm/ItemForm"; import { Budget } from "./components/Budget/Budget"; +import { IntlConfig } from "react-currency-input-field/dist/components/CurrencyInputProps"; +import * as AppContext from "./context/ConfigContext"; window.crypto.randomUUID = randomUUID; // global.URL.createObjectURL = vi.fn(); @@ -197,3 +199,27 @@ export const testIntlConfig = { locale: "en-US", currency: "USD" }; export const testSpanishIntlConfig = { locale: "es-ES", currency: "EUR" }; export const testBudgetList = [testBudget, testBudget2, testBigBudget]; + +export const testContext = { + intlConfig: testIntlConfig || undefined, + setIntlConfig: (value: IntlConfig) => { + value; + }, + currency: "USD", + handleCurrency: (value: string) => { + value; + }, +}; + +export const testSpanishContext = { + intlConfig: testSpanishIntlConfig, + setIntlConfig: (value: IntlConfig) => { + value; + }, + currency: "EUR", + handleCurrency: (value: string) => { + value; + }, +}; + +vi.spyOn(AppContext, "useConfig").mockImplementation(() => testContext);