Skip to content

Commit

Permalink
Network selector functional
Browse files Browse the repository at this point in the history
  • Loading branch information
quietbits committed Feb 22, 2024
1 parent f59f62c commit e900f87
Show file tree
Hide file tree
Showing 14 changed files with 738 additions and 60 deletions.
20 changes: 20 additions & 0 deletions src/components/NetworkIndicator/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import "./styles.scss";

export const NetworkIndicator = ({
networkId,
networkLabel,
}: {
networkId: string;
networkLabel: string;
}) => {
return (
<div className="NetworkIndicator">
<span
className="NetworkIndicator__dot"
aria-hidden="true"
data-network={networkId}
></span>
{networkLabel}
</div>
);
};
30 changes: 30 additions & 0 deletions src/components/NetworkIndicator/styles.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
@use "../../styles/utils.scss" as *;

.NetworkIndicator {
--NetworkSelector-dot-color: var(--sds-clr-gray-09);

display: flex;
align-items: center;
gap: pxToRem(4px);

font-size: pxToRem(14px);
line-height: pxToRem(20px);
font-weight: var(--sds-fw-medium);
color: var(--sds-clr-gray-12);

&__dot {
display: block;
width: pxToRem(6px);
height: pxToRem(6px);
border-radius: pxToRem(3px);
background-color: var(--NetworkSelector-dot-color);

&[data-network="futurenet"] {
--NetworkSelector-dot-color: var(--sds-clr-lilac-09);
}

&[data-network="mainnet"] {
--NetworkSelector-dot-color: var(--sds-clr-green-09);
}
}
}
52 changes: 0 additions & 52 deletions src/components/NetworkSelector.tsx

This file was deleted.

210 changes: 210 additions & 0 deletions src/components/NetworkSelector/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { useCallback, useEffect, useState } from "react";
import { Button, Icon, Input } from "@stellar/design-system";

import { NetworkIndicator } from "@/components/NetworkIndicator";
import { localStorageSavedNetwork } from "@/helpers/localStorageSavedNetwork";
import { useStore } from "@/store/useStore";
import { Network, NetworkType } from "@/types/types";

import "./styles.scss";

// TODO: update dropdown open and close actions
// TODO: update input

const NetworkOptions: Network[] = [
{
id: "futurenet",
label: "Futurenet",
url: "https://horizon-futurenet.stellar.org",
passphrase: "Test SDF Future Network ; October 2022",
},
{
id: "mainnet",
label: "Mainnet",
url: "https://horizon.stellar.org",
passphrase: "Public Global Stellar Network ; September 2015",
},
{
id: "testnet",
label: "Testnet",
url: "https://horizon-testnet.stellar.org",
passphrase: "Test SDF Network ; September 2015",
},
{
id: "custom",
label: "Custom",
url: "",
passphrase: "",
},
];

export const NetworkSelector = () => {
const { network, selectNetwork } = useStore();

const [activeNetworkId, setActiveNetworkId] = useState(network.id);
const [isVisible, setIsVisible] = useState(false);

const isCustomNetwork = activeNetworkId === "custom";

const initialCustomState = {
url: isCustomNetwork ? network.url : "",
passphrase: isCustomNetwork ? network.passphrase : "",
};

const [customNetwork, setCustomNetwork] = useState(initialCustomState);

const setNetwork = useCallback(() => {
if (!network?.id) {
const defaultNetwork =
localStorageSavedNetwork.get() || getNetworkById("testnet");

if (defaultNetwork) {
selectNetwork(defaultNetwork);
setActiveNetworkId(defaultNetwork.id);
}
}
}, [network?.id, selectNetwork]);

// Set default network on launch
useEffect(() => {
setNetwork();
}, [setNetwork]);

const handleSelectNetwork = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

const networkData = getNetworkById(activeNetworkId);

if (networkData) {
const data =
networkData.id === "custom"
? { ...networkData, ...customNetwork }
: networkData;

selectNetwork(data);
setCustomNetwork(initialCustomState);
localStorageSavedNetwork.set(data);
}
};

const handleSelectActive = (networkId: NetworkType) => {
setActiveNetworkId(networkId);
setCustomNetwork(initialCustomState);
};

const getNetworkById = (networkId: NetworkType) => {
return NetworkOptions.find((op) => op.id === networkId);
};

const isSameNetwork = () => {
if (activeNetworkId === "custom") {
return (
network.url &&
network.passphrase &&
customNetwork.url === network.url &&
customNetwork.passphrase === network.passphrase
);
}

return activeNetworkId === network.id;
};

const isNetworkUrlInvalid = () => {
if (activeNetworkId !== "custom" || !customNetwork.url) {
return "";
}

try {
new URL(customNetwork.url);
return "";
} catch (e) {
return "Value is not a valid URL";
}
};

return (
<div className="NetworkSelector">
<button
className="NetworkSelector__button"
onClick={() => setIsVisible(!isVisible)}
>
<NetworkIndicator networkId={network.id} networkLabel={network.label} />
<Icon.ChevronDown />
</button>
<div
className="NetworkSelector__floater Floater__content Floater__content--light"
data-is-visible={isVisible}
>
<div className="NetworkSelector__body">
<div className="NetworkSelector__body__links">
{NetworkOptions.map((op) => (
<div
key={op.id}
className="NetworkSelector__body__link"
data-is-active={op.id === activeNetworkId}
role="button"
onClick={() => handleSelectActive(op.id)}
>
<NetworkIndicator networkId={op.id} networkLabel={op.label} />
<div className="NetworkSelector__body__link__url">{op.url}</div>
</div>
))}
</div>

<div
className="NetworkSelector__body__inputs"
data-is-active={activeNetworkId === "custom"}
>
<form onSubmit={handleSelectNetwork}>
<Input
id="network-url"
fieldSize="sm"
label="Horizon URL"
value={
isCustomNetwork
? customNetwork.url
: getNetworkById(activeNetworkId)?.url
}
disabled={!isCustomNetwork}
onChange={(e) =>
setCustomNetwork({ ...customNetwork, url: e.target.value })
}
error={isNetworkUrlInvalid()}
/>
<Input
id="network-passphrase"
fieldSize="sm"
label="Network Passphrase"
value={
isCustomNetwork
? customNetwork.passphrase
: getNetworkById(activeNetworkId)?.passphrase
}
disabled={!isCustomNetwork}
onChange={(e) =>
setCustomNetwork({
...customNetwork,
passphrase: e.target.value,
})
}
/>
<Button
size="sm"
variant="secondary"
type="submit"
disabled={
isSameNetwork() ||
(activeNetworkId === "custom" &&
!(customNetwork.url && customNetwork.passphrase)) ||
Boolean(customNetwork.url && isNetworkUrlInvalid())
}
>
{`Use ${getNetworkById(activeNetworkId)?.label} Network`}
</Button>
</form>
</div>
</div>
</div>
</div>
);
};
Loading

0 comments on commit e900f87

Please sign in to comment.