Compare commits

...

5 Commits

9 changed files with 210 additions and 54 deletions
+10 -20
View File
@@ -4,11 +4,11 @@ import Grid from "@mui/material/Grid2";
import BlogArticlesCards from "../components/blogs/BlogArticleCards";
import { ContentLayout } from "../components/contentLayout/ContentLayout";
import SectionHeading from "../components/headings/SectionHeading";
import { CurrentEpochCard } from "../components/landingPageComponents/CurrentEpochCard";
import { NetworkStakeCard } from "../components/landingPageComponents/NetworkStakeCard";
import { NoiseCard } from "../components/landingPageComponents/NoiseCard";
import { StakersNumberCard } from "../components/landingPageComponents/StakersNumberCard";
import { TokenomicsCard } from "../components/landingPageComponents/TokenomicsCard";
import { CurrentEpochCardWrapper } from "../components/landingPageComponents/CurrentEpochCardWrapper";
import { NetworkStakeCardWrapper } from "../components/landingPageComponents/NetworkStakeCardWrapper";
import { NoiseCardWrapper } from "../components/landingPageComponents/NoiseCardWrapper";
import { StakersNumberCardWrapper } from "../components/landingPageComponents/StakersNumberCardWrapper";
import { TokenomicsCardWrapper } from "../components/landingPageComponents/TokenomicsCardWrapper";
import NodeTable from "../components/nodeTable/NodeTableWithAction";
import NodeAndAddressSearch from "../components/search/NodeAndAddressSearch";
@@ -23,29 +23,19 @@ export default async function Home() {
<Grid size={12}>
<SectionHeading title="Network Overview" />
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<NoiseCard />
</Grid>
<NoiseCardWrapper />
<Grid
container
columnSpacing={5}
rowSpacing={5}
size={{ xs: 12, sm: 6, lg: 3 }}
>
<Grid size={12}>
<StakersNumberCard />
</Grid>
<Grid size={12}>
<CurrentEpochCard />
</Grid>
<StakersNumberCardWrapper />
<CurrentEpochCardWrapper />
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<NetworkStakeCard />
</Grid>
<Grid size={{ xs: 12, sm: 6, lg: 3 }}>
<TokenomicsCard />
</Grid>
<NetworkStakeCardWrapper />
<TokenomicsCardWrapper />
</Grid>
<Grid container rowSpacing={5}>
<Grid size={12}>
@@ -0,0 +1,23 @@
"use client";
import Grid from "@mui/material/Grid2";
import { ReactNode } from "react";
interface ConditionalCardWrapperProps {
children: ReactNode;
size?:
| number
| { xs?: number; sm?: number; md?: number; lg?: number; xl?: number };
visible?: boolean;
}
export const ConditionalCardWrapper = ({
children,
size,
visible = true,
}: ConditionalCardWrapperProps) => {
if (!visible) {
return null;
}
return <Grid size={size}>{children}</Grid>;
};
@@ -0,0 +1,19 @@
"use client";
import { useEpochContext } from "@/providers/EpochProvider";
import { CurrentEpochCard } from "./CurrentEpochCard";
import { ConditionalCardWrapper } from "./ConditionalCardWrapper";
export const CurrentEpochCardWrapper = () => {
const { data, isError, isLoading, epochStatus } = useEpochContext();
// Determine if the card should be visible
// Show the card if we have data and it's not in a pending state, or if we're still loading
const isVisible =
!isError && (data || isLoading) && epochStatus !== "pending";
return (
<ConditionalCardWrapper size={12} visible={isVisible}>
<CurrentEpochCard />
</ConditionalCardWrapper>
);
};
@@ -33,21 +33,14 @@ export const NetworkStakeCard = () => {
);
}
if (isStakingError || !packetsAndStaking) {
return (
<ExplorerCard label="Current network stake">
<Typography
variant="h5"
sx={{
color: isDarkMode ? "base.white" : "pine.950",
letterSpacing: 0.7,
}}
>
Failed to load data
</Typography>
<Skeleton variant="text" height={238} />
</ExplorerCard>
);
// Don't display the card if there's an error or insufficient data
if (
isStakingError ||
!packetsAndStaking ||
!Array.isArray(packetsAndStaking) ||
packetsAndStaking.length < 10
) {
return null;
}
const packetsAndStakingData: ExplorerData["packetsAndStakingData"] =
@@ -0,0 +1,25 @@
"use client";
import { fetchNoise } from "@/app/api";
import { useQuery } from "@tanstack/react-query";
import { NetworkStakeCard } from "./NetworkStakeCard";
import { ConditionalCardWrapper } from "./ConditionalCardWrapper";
export const NetworkStakeCardWrapper = () => {
const { data, isLoading, isError } = useQuery({
queryKey: ["noise"],
queryFn: fetchNoise,
staleTime: 10 * 60 * 1000, // 10 minutes
refetchOnWindowFocus: false,
refetchOnReconnect: false,
});
// Determine if the card should be visible
const isVisible =
!isLoading && !isError && data && Array.isArray(data) && data.length >= 10;
return (
<ConditionalCardWrapper size={{ xs: 12, sm: 6, lg: 3 }} visible={isVisible}>
<NetworkStakeCard />
</ConditionalCardWrapper>
);
};
@@ -41,31 +41,21 @@ export const NoiseCard = () => {
);
}
if (isError || !data) {
return (
<ExplorerCard label="Mixnet traffic">
<Typography
variant="h5"
sx={{
color: isDarkMode ? "base.white" : "pine.950",
letterSpacing: 0.7,
}}
>
Failed to load data
</Typography>
<Skeleton variant="text" height={238} />
</ExplorerCard>
);
// Don't display the card if there's an error or insufficient data
if (isError || !data || !Array.isArray(data) || data.length < 10) {
return null;
}
const todaysData = data[data.length - 2];
const yesterdaysData = data[data.length - 3];
const noiseLast24H =
todaysData.total_packets_sent + todaysData.total_packets_received;
(todaysData?.total_packets_sent || 0) +
(todaysData?.total_packets_received || 0);
const noisePrevious24H =
yesterdaysData.total_packets_sent + yesterdaysData.total_packets_received;
(yesterdaysData?.total_packets_sent || 0) +
(yesterdaysData?.total_packets_received || 0);
const formatNoiseVolume = (packets: number): string => {
if (packets < 0) {
@@ -107,8 +97,9 @@ export const NoiseCard = () => {
.slice(0, -1)
.map((item: IPacketsAndStakingData) => {
return {
date_utc: item.date_utc,
numericData: item.total_packets_sent + item.total_packets_received,
date_utc: item?.date_utc,
numericData:
(item?.total_packets_sent || 0) + (item?.total_packets_received || 0),
};
})
.filter((item) => item.numericData >= 2_500_000_000);
@@ -0,0 +1,25 @@
"use client";
import { fetchNoise } from "@/app/api";
import { useQuery } from "@tanstack/react-query";
import { NoiseCard } from "./NoiseCard";
import { ConditionalCardWrapper } from "./ConditionalCardWrapper";
export const NoiseCardWrapper = () => {
const { data, isLoading, isError } = useQuery({
queryKey: ["noise"],
queryFn: fetchNoise,
staleTime: 10 * 60 * 1000, // 10 minutes
refetchOnWindowFocus: false,
refetchOnReconnect: false,
});
// Determine if the card should be visible
const isVisible =
!isLoading && !isError && data && Array.isArray(data) && data.length >= 10;
return (
<ConditionalCardWrapper size={{ xs: 12, sm: 6, lg: 3 }} visible={isVisible}>
<NoiseCard />
</ConditionalCardWrapper>
);
};
@@ -0,0 +1,26 @@
"use client";
import { fetchNSApiNodes } from "@/app/api";
import { useQuery } from "@tanstack/react-query";
import { StakersNumberCard } from "./StakersNumberCard";
import { ConditionalCardWrapper } from "./ConditionalCardWrapper";
export const StakersNumberCardWrapper = () => {
const { data, isLoading, isError } = useQuery({
queryKey: ["nsApiNodes"],
queryFn: fetchNSApiNodes,
staleTime: 10 * 60 * 1000, // 10 minutes
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
// Determine if the card should be visible
const isVisible =
!isLoading && !isError && data && Array.isArray(data) && data.length > 0;
return (
<ConditionalCardWrapper size={12} visible={isVisible}>
<StakersNumberCard />
</ConditionalCardWrapper>
);
};
@@ -0,0 +1,64 @@
"use client";
import { fetchEpochRewards, fetchNoise, fetchNymPrice } from "@/app/api";
import { useQuery } from "@tanstack/react-query";
import { TokenomicsCard } from "./TokenomicsCard";
import { ConditionalCardWrapper } from "./ConditionalCardWrapper";
export const TokenomicsCardWrapper = () => {
const {
data: nymPrice,
isLoading: isPriceLoading,
isError: isPriceError,
} = useQuery({
queryKey: ["nymPrice"],
queryFn: fetchNymPrice,
staleTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
const {
data: epochRewards,
isLoading: isEpochLoading,
isError: isEpochError,
} = useQuery({
queryKey: ["epochRewards"],
queryFn: fetchEpochRewards,
staleTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
const {
data: packetsAndStaking,
isLoading: isStakingLoading,
isError: isStakingError,
} = useQuery({
queryKey: ["noise"],
queryFn: fetchNoise,
staleTime: 10 * 60 * 1000,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
refetchOnMount: false,
});
// Determine if the card should be visible
const isLoading = isPriceLoading || isEpochLoading || isStakingLoading;
const hasError = isPriceError || isEpochError || isStakingError;
const hasData =
nymPrice &&
epochRewards &&
packetsAndStaking &&
Array.isArray(packetsAndStaking) &&
packetsAndStaking.length >= 2;
const isVisible = !hasError && (hasData || isLoading);
return (
<ConditionalCardWrapper size={{ xs: 12, sm: 6, lg: 3 }} visible={isVisible}>
<TokenomicsCard />
</ConditionalCardWrapper>
);
};