Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: chain selector initial state #161

Merged
merged 9 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/Molecules/AddressDetails/AddressDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ export const AddressDetails: React.FC<AddressDetailsProps> = ({
</DropdownMenuTrigger>

<DropdownMenuContent
className="z-10 mx-auto w-72 rounded border border-secondary-light bg-white dark:border-secondary-dark dark:bg-background-dark dark:text-white"
className="z-10 mx-auto max-h-96 w-72 overflow-y-scroll rounded border border-secondary-light bg-white dark:border-secondary-dark dark:bg-background-dark dark:text-white"
align="start"
>
{holdings.map(
Expand Down
8 changes: 2 additions & 6 deletions src/components/Molecules/BlockDetails/BlockDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,12 @@ export const BlockDetails: React.FC<BlockDetailsProps> = ({
return (
<Card className="flex w-full flex-col items-start gap-x-4 rounded border border-secondary-light p-2 dark:border-secondary-dark dark:bg-background-dark dark:text-white">
{maybeResult.match({
None: () => (
<div className="mt-4">
<Skeleton size={GRK_SIZES.LARGE} />
</div>
),
None: () => <Skeleton size={GRK_SIZES.LARGE} />,
Some: (block) =>
errorMessage ? (
<p className="mt-4">{errorMessage}</p>
) : (
<div className="mt-2 grid w-full grid-cols-3 gap-16 gap-y-4">
<div className="grid w-full grid-cols-3 gap-16 gap-y-4">
<div>
<CardDescription>HEIGHT</CardDescription>

Expand Down
2 changes: 1 addition & 1 deletion src/components/Molecules/ChainSelector/ChainSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const ChainSelector: React.FC<ChainSelectorProps> = ({
onChangeChain,
}) => {
const { chains, selectedChain, setSelectedChain } = useGoldRush();
const [open, setOpen] = useState<boolean>(!false);
const [open, setOpen] = useState<boolean>(false);

const dropdownChains = useMemo<ChainItem[] | null>(() => {
if (!chains) {
Expand Down
241 changes: 112 additions & 129 deletions src/components/Molecules/GasCard/GasCard.tsx
Original file line number Diff line number Diff line change
@@ -1,155 +1,138 @@
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { type GasCardProps } from "@/utils/types/molecules.types";
import { useGoldRush } from "@/utils/store";
import type { Option } from "@/utils/option";
import { None, Some } from "@/utils/option";
import { type GasPricesResponse, type PriceItem } from "@covalenthq/client-sdk";
import { type GasPricesResponse } from "@covalenthq/client-sdk";
import { Skeleton } from "@/components/ui/skeleton";
import { GRK_SIZES } from "@/utils/constants/shared.constants";

export const GasCard: React.FC<GasCardProps> = ({ chain_name, event_type }) => {
const [maybeResult, setResult] = useState<Option<GasPricesResponse>>(None);
const [error, setError] = useState({ error: false, error_message: "" });
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const { covalentClient } = useGoldRush();

const handleGas = async () => {
setResult(None);
let response;
try {
response = await covalentClient.BaseService.getGasPrices(
chain_name,
event_type
);
if (response.error) {
setError({
error: response ? response.error : false,
error_message: response ? response.error_message : "",
});
setResult(new Some(response.data));
return;
}
console.log(response);
setResult(new Some(response.data));
setError({ error: false, error_message: "" });
} catch (error) {
setError({
error: response ? response.error : false,
error_message: response ? response.error_message : "",
});
console.error(`Error fetching Gas for ${chain_name}:`, error);
}
};

useEffect(() => {
handleGas();
(async () => {
setResult(None);
setErrorMessage(null);
try {
const { data, ...error } =
await covalentClient.BaseService.getGasPrices(
chain_name,
event_type
);
if (error.error) {
setErrorMessage(error.error_message);
throw error;
}
setResult(new Some(data));
} catch (error) {
console.error(error);
}
})();
}, [chain_name, event_type]);

const copy = useMemo<
{
logo: string;
content: string;
}[]
>(
() => [
{
logo: "🚴",
content: "Low",
},
{
logo: "🚗",
content: "Normal",
},
{
logo: "🚄",
content: "High",
},
],
[]
);

return (
<>
<div className="flex w-full flex-col gap-4 rounded border border-secondary-light dark:border-secondary-dark">
<div className="bg-accent-light h-12 rounded-t" />
<div className="flex flex-col items-center justify-center gap-2 p-4">
<span className="text-7xl">⛽</span>
<h2 className="text-xl">Current Network Fee</h2>
<label className="flex items-center gap-x-2 text-base text-secondary-light dark:text-secondary-dark">
Base Fee:{" "}
{maybeResult.match({
None: () => <Skeleton size={GRK_SIZES.MEDIUM} />,
Some: (result) => {
const baseFeeGwei = Math.round(
(parseInt(String(result?.base_fee)) ?? 0) /
Math.pow(10, 9)
);
return <span> {baseFeeGwei}</span>;
},
})}
</label>
</div>
<div className="flex w-full flex-col gap-6 p-6">
{maybeResult.match({
None: () => {
return (
<div className="flex flex-col gap-3">
{[1, 2, 3].map((o, i) => {
return (
<div
className="flex justify-between"
key={i}
>
<Skeleton
size={GRK_SIZES.LARGE}
/>
<Skeleton
size={GRK_SIZES.LARGE}
/>
</div>
);
})}
<div className="flex w-full flex-col gap-4 rounded border border-secondary-light p-2 dark:border-secondary-dark">
<div className="flex flex-col items-center justify-center gap-2">
{maybeResult.match({
None: () => <Skeleton size={GRK_SIZES.LARGE} />,
Some: ({ base_fee }) => (
<p className="text-xl">
⛽ Base Fee:{" "}
{Math.round(
(Number(base_fee) ?? 0) / Math.pow(10, 9)
)}{" "}
Gwei
</p>
),
})}
</div>

<div className="grid grid-cols-3 items-center">
{maybeResult.match({
None: () =>
Array(3)
.fill(null)
.map(() => (
<div key={Math.random()} className="mx-auto">
<Skeleton size={GRK_SIZES.LARGE} />
</div>
);
},
Some: (result) => {
if (error.error) {
return (
<div className="flex items-center justify-center">
{error.error_message}
</div>
);
}
return result.items
)),
Some: ({ items }) =>
errorMessage ? (
<p className="mt-4">{errorMessage}</p>
) : (
items
.sort(
(
a: { gas_price: string },
b: { gas_price: string }
) =>
(a, b) =>
parseInt(a.gas_price) -
parseInt(b.gas_price)
)
.map((o: PriceItem, i: number) => {
const gwei = Math.round(
parseInt(o.gas_price) / Math.pow(10, 9)
);
return (
.map(
(
{
interval,
gas_price,
pretty_total_gas_quote,
},
i
) => (
<div
className="flex justify-between"
key={i}
key={Math.random()}
className="text-center"
>
<div className="flex items-center gap-4">
<div className="text-3xl">
{i === 0
? "🚴"
: i === 1
? "🚗"
: "🚄"}
</div>
<div className="flex flex-col">
<label>
{i === 0
? "Low"
: i === 1
? "Normal"
: "High"}
</label>
<label className="text-sm text-secondary-light dark:text-secondary-dark">
{o.interval}
</label>
</div>
</div>
<div className="flex flex-col">
<label>
{gwei.toFixed(0)} Gwei
</label>
<label className="text-sm text-secondary-light dark:text-secondary-dark">
{o.pretty_total_gas_quote}
</label>
</div>
<p className="text-3xl">
{copy[i].logo}
</p>
<p className="mt-2">
{copy[i].content}
</p>

<p>
{Math.round(
parseInt(gas_price) /
Math.pow(10, 9)
).toFixed(0)}{" "}
Gwei
<span className="ml-1 text-sm text-secondary-light dark:text-secondary-dark">
({pretty_total_gas_quote})
</span>
</p>

<p className="text-sm text-secondary-light dark:text-secondary-dark">
{interval}
</p>
</div>
);
});
},
})}
</div>
)
)
),
})}
</div>
</>
</div>
);
};
17 changes: 17 additions & 0 deletions src/components/Molecules/LatestPrice/LatestPrice.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { type Meta, type StoryObj } from "@storybook/react";
import { LatestPrice as LatestPriceComponent } from "./LatestPrice";

type Story = StoryObj<typeof LatestPriceComponent>;

const meta: Meta<typeof LatestPriceComponent> = {
title: "Molecules/Latest Price",
component: LatestPriceComponent,
};

export default meta;

export const LatestPrice: Story = {
args: {
chain_name: "eth-mainnet",
},
};
63 changes: 63 additions & 0 deletions src/components/Molecules/LatestPrice/LatestPrice.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Card, CardDescription } from "@/components/ui/card";
import { Skeleton } from "@/components/ui/skeleton";
import { GRK_SIZES } from "@/utils/constants/shared.constants";
import { None, Some, type Option } from "@/utils/option";
import { useGoldRush } from "@/utils/store";
import { type LatestPriceProps } from "@/utils/types/molecules.types";
import { type Price } from "@covalenthq/client-sdk";
import { useEffect, useState } from "react";

export const LatestPrice: React.FC<LatestPriceProps> = ({ chain_name }) => {
const { covalentClient } = useGoldRush();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [maybeResult, setResult] = useState<Option<Price>>(None);

useEffect(() => {
(async () => {
setResult(None);
setErrorMessage(null);
try {
const { data, ...error } =
await covalentClient.PricingService.getTokenPrices(
chain_name,
"USD",
"0x0000000000000000000000000000000000000000"
);
if (error.error) {
setErrorMessage(error.error_message);
throw error;
}
setResult(new Some(data[0].items[0]));
} catch (error) {
console.error(error);
}
})();
}, [chain_name]);

return (
<Card className="flex w-full flex-col items-start gap-x-4 rounded border border-secondary-light p-2 dark:border-secondary-dark dark:bg-background-dark dark:text-white">
{maybeResult.match({
None: () => <Skeleton size={GRK_SIZES.LARGE} />,
Some: ({
pretty_price,
contract_metadata: { contract_ticker_symbol },
}) =>
errorMessage ? (
<p className="mt-4">{errorMessage}</p>
) : (
<div className="w-full">
<div>
<CardDescription>
{contract_ticker_symbol} PRICE
</CardDescription>

<p className="mt-1 flex items-center gap-x-1.5">
{pretty_price}
</p>
</div>
</div>
),
})}
</Card>
);
};
Loading
Loading