feat: add conditional card wrappers to prevent empty grid spaces

This commit is contained in:
Yana
2025-07-12 11:49:30 +03:00
parent 1847a84372
commit fb689a35e6
9 changed files with 201 additions and 62 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,21 @@
"use client";
import Grid from "@mui/material/Grid2";
import { ReactNode } from "react";
interface ConditionalCardWrapperProps {
children: ReactNode;
size?: any;
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,33 +41,9 @@ export const NoiseCard = () => {
);
}
if (isError || !data || !Array.isArray(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>
);
}
// If we don't have enough data, show loading
if (data.length < 3) {
return (
<ExplorerCard label="Mixnet traffic">
<Stack gap={1}>
<Skeleton variant="text" />
<Skeleton variant="text" height={238} />
</Stack>
</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];
@@ -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>
);
};