Skip to content

Commit

Permalink
Merge pull request #794 from anoma/feat/namadillo-settings
Browse files Browse the repository at this point in the history
Creating Settings Page
  • Loading branch information
pedrorezende authored May 30, 2024
2 parents 8213ce8 + b75d8f3 commit b16abb3
Show file tree
Hide file tree
Showing 11 changed files with 367 additions and 44 deletions.
78 changes: 49 additions & 29 deletions apps/namadillo/src/App/AppRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,68 @@
import { Router } from "@remix-run/router";
import {
Route,
Routes,
createBrowserRouter,
createRoutesFromElements,
useLocation,
} from "react-router-dom";
import { AccountOverview } from "./AccountOverview";
import { App } from "./App";
import { AnimatedTransition } from "./Common/AnimatedTransition";
import { Governance } from "./Governance";
import { SettingsPanel } from "./Settings/SettingsPanel";
import { Staking } from "./Staking";

import GovernanceRoutes from "./Governance/routes";
import SettingsRoutes from "./Settings/routes";
import StakingRoutes from "./Staking/routes";

export const getRouter = (): Router => {
return createBrowserRouter(
createRoutesFromElements(
<Route path="/" element={<App />}>
<Route
index
element={
// eslint-disable-next-line react/jsx-no-undef
<AnimatedTransition elementKey={"/"}>
<AccountOverview />
</AnimatedTransition>
}
/>
<Route
path={`${StakingRoutes.index()}/*`}
element={
<AnimatedTransition elementKey={StakingRoutes.index()}>
<Staking />
</AnimatedTransition>
}
/>
export const MainRoutes = (): JSX.Element => {
const location = useLocation();
const state = location.state as { backgroundLocation?: Location };

return (
<>
<Routes location={state?.backgroundLocation || location}>
<Route path="/" element={<App />}>
<Route
index
element={
<AnimatedTransition elementKey="/">
<AccountOverview />
</AnimatedTransition>
}
/>
<Route
path={`${StakingRoutes.index()}/*`}
element={
<AnimatedTransition elementKey={StakingRoutes.index()}>
<Staking />
</AnimatedTransition>
}
/>
<Route
path={`${GovernanceRoutes.index()}/*`}
element={
<AnimatedTransition elementKey={GovernanceRoutes.index()}>
<Governance />
</AnimatedTransition>
}
/>
</Route>
</Routes>
<Routes>
<Route
path={`${GovernanceRoutes.index()}/*`}
element={
<AnimatedTransition elementKey={GovernanceRoutes.index()}>
<Governance />
</AnimatedTransition>
}
path={`${SettingsRoutes.index()}/*`}
element={<SettingsPanel />}
/>
</Route>
)
</Routes>
</>
);
};

export const getRouter = (): Router => {
return createBrowserRouter(
createRoutesFromElements(<Route path="/*" element={<MainRoutes />} />)
);
};
16 changes: 13 additions & 3 deletions apps/namadillo/src/App/Common/TopNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { ToggleButton } from "@namada/components";
import { Chain } from "@namada/types";
import { ActiveAccount } from "App/Common/ActiveAccount";
import { ConnectExtensionButton } from "App/Common/ConnectExtensionButton";
import SettingsRoutes from "App/Settings/routes";
import { ConnectStatus, useExtensionConnect } from "hooks/useExtensionConnect";
import { useAtom } from "jotai";
import { IoSettingsOutline } from "react-icons/io5";
import { Link } from "react-router-dom";
import { useLocation, useNavigate } from "react-router-dom";
import { hideBalancesAtom } from "slices/settings";

type Props = {
Expand All @@ -15,6 +16,8 @@ type Props = {
export const TopNavigation = ({ chain }: Props): JSX.Element => {
const { connectionStatus } = useExtensionConnect(chain);
const [hideBalances, setHideBalances] = useAtom(hideBalancesAtom);
const location = useLocation();
const navigate = useNavigate();

return (
<>
Expand All @@ -32,9 +35,16 @@ export const TopNavigation = ({ chain }: Props): JSX.Element => {
onChange={() => setHideBalances(!hideBalances)}
containerProps={{ className: "hidden text-white md:flex" }}
/>
<Link className="text-2xl text-yellow hover:text-cyan" to="/">
<button
className="text-2xl text-yellow hover:text-cyan"
onClick={() =>
navigate(SettingsRoutes.index(), {
state: { backgroundLocation: location },
})
}
>
<IoSettingsOutline />
</Link>
</button>
<ActiveAccount />
</div>
)}
Expand Down
39 changes: 39 additions & 0 deletions apps/namadillo/src/App/Settings/Advanced.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ActionButton, Input, Stack } from "@namada/components";
import SettingsRoute from "App/Settings/routes";
import { useAtom } from "jotai";
import { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";
import { rpcUrlAtom } from "slices/settings";

export const Advanced = (): JSX.Element => {
const navigate = useNavigate();
const location = useLocation();
const [currentRpc, setCurrentRpc] = useAtom(rpcUrlAtom);
const [rpc, setRpc] = useState(currentRpc);

const onSubmit = (e: React.FormEvent): void => {
e.preventDefault();
setCurrentRpc(rpc);
navigate(SettingsRoute.index(), { replace: true, state: location.state });
};

return (
<form
className="flex flex-col flex-1 justify-between text-base"
onSubmit={onSubmit}
>
<Stack gap={6}>
<Input
type="text"
value={rpc}
label="RPC Url"
onChange={(e) => setRpc(e.currentTarget.value)}
required
/>
</Stack>
<ActionButton size="lg" borderRadius="sm">
Confirm
</ActionButton>
</form>
);
};
21 changes: 21 additions & 0 deletions apps/namadillo/src/App/Settings/CurrencySelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Stack } from "@namada/components";
import { FiatCurrencyList } from "@namada/utils";
import { useAtom } from "jotai";
import { selectedCurrencyAtom } from "slices/settings";
import { CurrencySelectorEntry } from "./CurrencySelectorEntry";

export const CurrencySelector = (): JSX.Element => {
const [selectedCurrency, setSelectedCurrency] = useAtom(selectedCurrencyAtom);
return (
<Stack as="ul" gap={2}>
{FiatCurrencyList.map((currency) => (
<CurrencySelectorEntry
key={`currency-selector-${currency.id}`}
selected={currency.id === selectedCurrency}
currency={currency}
onClick={() => setSelectedCurrency(currency.id)}
/>
))}
</Stack>
);
};
35 changes: 35 additions & 0 deletions apps/namadillo/src/App/Settings/CurrencySelectorEntry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CurrencyInfoListItem } from "@namada/utils";
import clsx from "clsx";
import { twMerge } from "tailwind-merge";

type CurrencySelectorEntryType = {
currency: CurrencyInfoListItem;
selected: boolean;
onClick: () => void;
};

export const CurrencySelectorEntry = ({
currency,
selected,
onClick,
}: CurrencySelectorEntryType): JSX.Element => {
return (
<li>
<button
onClick={onClick}
className={twMerge(
clsx(
"w-full rounded-lg border-transparent border text-white",
"px-6 py-6 text-base uppercase text-left bg-black cursor-pointer",
{
"border-yellow": selected,
}
)
)}
>
<span className="sr-only">{currency.plural}</span>
{currency.id} ({currency.sign})
</button>
</li>
);
};
56 changes: 56 additions & 0 deletions apps/namadillo/src/App/Settings/SettingsMain.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { Alert, Stack, ToggleButton } from "@namada/components";
import { useAtom } from "jotai";
import { IoWarning } from "react-icons/io5";
import { signArbitraryEnabledAtom } from "slices/settings";
import { SettingsPanelMenuItem } from "./SettingsPanelMenuItem";
import SettingsRoutes from "./routes";

export const SettingsMain = (): JSX.Element => {
const [signArbitraryEnabled, setSignArbitraryEnabled] = useAtom(
signArbitraryEnabledAtom
);

return (
<div className="flex flex-1 justify-between flex-col pb-4">
<ul className="flex flex-col gap-2">
<SettingsPanelMenuItem
url={`${SettingsRoutes.currencySelection().url}`}
text="Currency"
/>
<SettingsPanelMenuItem
url={`${SettingsRoutes.advanced().url}`}
text="Advanced"
/>
</ul>

<Stack as="footer" className="px-5" gap={3}>
<h2 className="text-base">Sign Arbitrary Message</h2>
<p className="text-sm">
Enabling this setting puts you at risk of phishing attacks. Please
check what you are signing very carefully when using this feature. We
recommend keeping this setting turned off unless absolutely necessary
</p>
{signArbitraryEnabled && (
<Alert type="warning" className="text-xs rounded-sm py-3">
<div className="flex items-center gap-3">
<i className="text-4xl">
<IoWarning />
</i>
You are at risk of phishing attacks. Please review carefully what
you sign
</div>
</Alert>
)}
<ToggleButton
label={
signArbitraryEnabled ? "On (Not Recommended)" : "Off (Recommended)"
}
color="white"
activeColor="yellow"
checked={signArbitraryEnabled}
onChange={() => setSignArbitraryEnabled(!signArbitraryEnabled)}
/>
</Stack>
</div>
);
};
69 changes: 69 additions & 0 deletions apps/namadillo/src/App/Settings/SettingsPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Modal } from "@namada/components";
import clsx from "clsx";
import { FaChevronLeft } from "react-icons/fa6";
import { IoClose } from "react-icons/io5";
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
import { Advanced } from "./Advanced";
import { CurrencySelector } from "./CurrencySelector";
import { SettingsMain } from "./SettingsMain";
import SettingsRoutes from "./routes";

export const SettingsPanel = (): JSX.Element => {
const location = useLocation();
const navigate = useNavigate();

const onClose = (): void => {
if (location.state?.backgroundLocation) {
navigate((location.state.backgroundLocation as Location).pathname, {
replace: true,
});
} else {
navigate("/", { replace: true });
}
};

const onClickBack = (): void => {
navigate(SettingsRoutes.index(), { state: location.state });
};

return (
<Modal
onClose={onClose}
className="left-auto right-4 top-2 translate-x-0 translate-y-0 p-5"
>
<main
className={clsx(
"flex flex-col gap-8",
"w-[400px] min-h-[700px] max-h-[80vh] rounded-md text-white",
"bg-rblack border border-neutral-700 p-5"
)}
>
<header className="relative">
<h1 className="text-center text-md">Settings</h1>
<button
onClick={onClose}
className="absolute right-0 top-0 flex items-center h-full text-2xl hover:text-yellow"
>
<IoClose />
</button>
{location.pathname !== SettingsRoutes.index() && (
<button
className="absolute left-0 top-0 flex items-center h-full text-lg hover:text-yellow"
onClick={onClickBack}
>
<FaChevronLeft />
</button>
)}
</header>
<Routes>
<Route index element={<SettingsMain />} />
<Route
path={`${SettingsRoutes.currencySelection()}`}
element={<CurrencySelector />}
/>
<Route path={`${SettingsRoutes.advanced()}`} element={<Advanced />} />
</Routes>
</main>
</Modal>
);
};
31 changes: 31 additions & 0 deletions apps/namadillo/src/App/Settings/SettingsPanelMenuItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import clsx from "clsx";
import { FaChevronRight } from "react-icons/fa6";
import { Link, useLocation } from "react-router-dom";

type SettingsPanelMenuItemProps = {
text: string;
url: string;
};

export const SettingsPanelMenuItem = ({
url,
text,
}: SettingsPanelMenuItemProps): JSX.Element => {
const location = useLocation();
return (
<li>
<Link
to={url}
state={location.state}
className={clsx(
"text-white text-lg bg-black py-8 px-6",
"flex justify-between items-center rounded-sm",
"transition-colors duration-150 ease-out-quad hover:text-yellow"
)}
>
{text}
<FaChevronRight />
</Link>
</li>
);
};
Loading

0 comments on commit b16abb3

Please sign in to comment.