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

74 total number of nodes changes when searching #80

Merged
merged 5 commits into from
Feb 25, 2025
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
32 changes: 18 additions & 14 deletions src/components/Card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
Area,
ResponsiveContainer,
XAxis,
Tooltip
Tooltip,
CartesianGrid
} from 'recharts'

interface CardProps {
Expand Down Expand Up @@ -132,16 +133,16 @@ const Card: React.FC<CardProps> = ({
</ResponsiveContainer>
)}
{chartType === 'line' && chartData && chartData.length > 0 && (
<ResponsiveContainer
width="100%"
height={200}
style={{ paddingTop: '50px' }}
>
<LineChart data={chartData}>
<ResponsiveContainer width="100%" height={170}>
<LineChart
data={chartData}
margin={{ top: 10, right: 0, bottom: 10, left: 0 }}
>
<defs>
<linearGradient id="lineWave" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#CF1FB1" stopOpacity={1} />
<stop offset="100%" stopColor="#CF1FB1" stopOpacity={0.2} />
<linearGradient id="lineWave" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stopColor="#7b1173" stopOpacity={0.8} />
<stop offset="30%" stopColor="#bd2881" stopOpacity={0.6} />
<stop offset="60%" stopColor="#CF1FB1" stopOpacity={1} />
</linearGradient>
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" />
Expand All @@ -155,6 +156,8 @@ const Card: React.FC<CardProps> = ({
</feMerge>
</filter>
</defs>
<CartesianGrid opacity={0} />
<XAxis hide />
<Line
type="basis"
dataKey="foreground.value"
Expand All @@ -169,7 +172,6 @@ const Card: React.FC<CardProps> = ({
stroke: '#ffffff',
strokeWidth: 2
}}
filter="url(#shadow)"
/>
<Area
type="basis"
Expand All @@ -181,17 +183,19 @@ const Card: React.FC<CardProps> = ({
<Tooltip
contentStyle={{
background: '#1A0820',
border: '1px solid #CF1FB1',
border: '1px solid rgba(207, 31, 177, 0.3)',
borderRadius: '8px',
boxShadow: '0 4px 20px rgba(207, 31, 177, 0.3)'
boxShadow: '0 4px 20px rgba(207, 31, 177, 0.3)',
cursor: 'none'
}}
cursor={false}
formatter={(value) => [
<span key="value" style={{ color: '#CF1FB1' }}>
{Number(value).toLocaleString()} ROSE
</span>
]}
labelFormatter={(label) => (
<span style={{ color: '#CF1FB1' }}>{label}</span>
<span style={{ color: '#CF1FB1' }}>Week {label}</span>
)}
/>
</LineChart>
Expand Down
55 changes: 42 additions & 13 deletions src/components/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React from 'react'
import React, { useEffect, useState } from 'react'
import Card from '../Card/Card'
import styles from './Dashboard.module.css'
import { useDataContext } from '@/context/DataContext'
import { useMapContext } from '../../context/MapContext'
import { CircularProgress, Alert, Box } from '@mui/material'
import { Alert, Box } from '@mui/material'
import { usePathname } from 'next/navigation'

const formatNumber = (num: number | string | undefined): string => {
if (num === undefined) return '0'
const formatNumber = (num: number | string | null | undefined): string => {
if (num === null || num === undefined) return '-'
const numStr = typeof num === 'string' ? num : num.toString()
return numStr.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

const formatRewardsNumber = (num: number | string | undefined): string => {
if (num === undefined) return '0'
const formatRewardsNumber = (num: number | string | null | undefined): string => {
if (num === null || num === undefined) return '-'
const number = typeof num === 'string' ? parseFloat(num) : num

if (number >= 1000000) {
Expand All @@ -29,11 +29,39 @@ const formatRewardsNumber = (num: number | string | undefined): string => {
}

const Dashboard = () => {
const { loading, error, totalNodes, totalEligibleNodes, totalRewards, rewardsHistory } =
useDataContext()
const {
loadingTotalNodes,
loadingTotalEligible,
loadingTotalRewards,
loadingRewardsHistory,
error,
totalNodes,
totalEligibleNodes,
totalRewards,
rewardsHistory
} = useDataContext()
const { totalCountries, loading: mapLoading } = useMapContext()
const pathname = usePathname()

const combinedLoading =
loadingTotalNodes ||
loadingTotalEligible ||
loadingTotalRewards ||
loadingRewardsHistory

const [overallDashboardLoading, setOverallDashboardLoading] = useState(combinedLoading)

useEffect(() => {
if (combinedLoading) {
setOverallDashboardLoading(true)
} else {
const timer = setTimeout(() => {
setOverallDashboardLoading(false)
}, 300)
return () => clearTimeout(timer)
}
}, [combinedLoading])

if (error) {
return (
<Box display="flex" justifyContent="center" alignItems="center" minHeight="400px">
Expand All @@ -58,27 +86,28 @@ const Dashboard = () => {
<Card
title="Total Eligible Nodes"
bigNumber={formatNumber(totalEligibleNodes)}
isLoading={loading}
isLoading={overallDashboardLoading}
/>

<Card
title="Total Nodes"
bigNumber={formatNumber(totalNodes)}
isLoading={loading}
isLoading={overallDashboardLoading}
/>

{pathname === '/nodes' ? (
<Card
title="Rewards History"
chartType="line"
chartData={rewardsHistory}
isLoading={loading || !rewardsHistory}
isLoading={overallDashboardLoading}
dataLoading={overallDashboardLoading}
/>
) : (
<Card
title="Total Countries"
bigNumber={formatNumber(totalCountries)}
isLoading={loading}
isLoading={overallDashboardLoading || mapLoading}
dataLoading={mapLoading}
/>
)}
Expand All @@ -93,7 +122,7 @@ const Dashboard = () => {
<span className={styles.oceanText}>ROSE</span>
</div>
}
isLoading={loading}
isLoading={overallDashboardLoading}
/>
</div>
)
Expand Down
87 changes: 64 additions & 23 deletions src/components/PieChart/PieChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface PieChartCardProps {

const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
const [activeIndex, setActiveIndex] = useState<number | undefined>(undefined)
const [lockedIndex, setLockedIndex] = useState<number | undefined>(undefined)
const [hoverText, setHoverText] = useState('Hover to see details')

const totalValue = useMemo(
Expand All @@ -22,14 +23,31 @@ const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
)

const onPieEnter = (_: any, index: number) => {
setActiveIndex(index)
const percentage = ((data[index].value / totalValue) * 100).toFixed(2)
setHoverText(`${data[index].name}: ${percentage}%`)
if (lockedIndex === undefined) {
setActiveIndex(index)
const percentage = ((data[index].value / totalValue) * 100).toFixed(2)
setHoverText(`${data[index].name}: ${percentage}%`)
}
}

const onPieLeave = () => {
setActiveIndex(undefined)
setHoverText('Hover to see details')
if (lockedIndex === undefined) {
setActiveIndex(undefined)
setHoverText('Hover to see details')
}
}

const onPieClick = (_: any, index: number) => {
if (lockedIndex === index) {
setLockedIndex(undefined)
setActiveIndex(undefined)
setHoverText('Hover to see details')
} else {
setLockedIndex(index)
setActiveIndex(index)
const percentage = ((data[index].value / totalValue) * 100).toFixed(2)
setHoverText(`${data[index].name}: ${percentage}%`)
}
}

const renderActiveShape = (props: any) => {
Expand Down Expand Up @@ -60,10 +78,15 @@ const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
}

const CustomTooltip = ({ active, payload }: any) => {
if (active && payload && payload.length) {
const { name, value, details } = payload[0].payload
const percentage = ((value / totalValue) * 100).toFixed(1)

const isActive = active || lockedIndex !== undefined
let item
if (lockedIndex !== undefined) {
item = data[lockedIndex]
} else if (payload && payload.length > 0) {
item = payload[0].payload
}
if (isActive && item) {
const percentage = ((item.value / totalValue) * 100).toFixed(1)
return (
<div
style={{
Expand All @@ -73,25 +96,26 @@ const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
color: '#000'
}}
>
<p style={{ margin: '0 0 8px 0', fontWeight: 'bold' }}>{name}</p>
<p style={{ margin: '0 0 8px 0', fontWeight: 'bold' }}>{item.name}</p>
<p style={{ margin: '0 0 8px 0' }}>
Total: {value} nodes ({percentage}%)
Total: {item.value} nodes ({percentage}%)
</p>
{details && (
{item.details && (
<div
style={{
fontSize: '12px',
maxHeight: '150px',
height: '150px',
overflowY: 'auto',
borderTop: '1px solid #eee',
paddingTop: '8px'
paddingTop: '8px',
pointerEvents: 'auto'
}}
>
{Array.isArray(details) &&
details.map((detail: string, index: number) => (
<p key={index} style={{ margin: '2px 0' }}>
{detail}
</p>
{Array.isArray(item.details) &&
item.details.map((detail: string, index: number) => (
<div key={index}>
<p style={{ margin: '2px 0' }}>{detail}</p>
</div>
))}
</div>
)}
Expand All @@ -118,6 +142,7 @@ const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
dataKey="value"
onMouseEnter={onPieEnter}
onMouseLeave={onPieLeave}
onClick={onPieClick}
className={styles.pieHover}
>
{data.map((entry, index) => (
Expand All @@ -126,16 +151,32 @@ const PieChartCard: React.FC<PieChartCardProps> = ({ data, title }) => {
fill={entry.color}
stroke="none"
style={{
transition: 'all 0.3s ease-in-out',
filter: activeIndex === index ? 'url(#glow)' : 'none'
transition: 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)',
filter:
activeIndex === index || lockedIndex === index
? 'url(#glow)'
: 'none',
transform:
activeIndex === index || lockedIndex === index
? 'scale(1.05)'
: 'scale(1)'
}}
/>
))}
</Pie>
<Tooltip content={<CustomTooltip />} />
<Tooltip
active={lockedIndex !== undefined ? true : undefined}
content={<CustomTooltip />}
position={{ y: 250 }}
wrapperStyle={{
transition: 'opacity 0.3s ease-in-out',
opacity: activeIndex !== undefined || lockedIndex !== undefined ? 1 : 0,
zIndex: 1000
}}
/>
</PieChart>
</ResponsiveContainer>
<p className={styles.tapToSee}>{hoverText}</p>
<div style={{ textAlign: 'center', marginTop: '8px' }}>{hoverText}</div>
</div>
)
}
Expand Down
13 changes: 10 additions & 3 deletions src/components/Table/CustomPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ const NavButton = styled(Button)(({ theme }) => ({
padding: '6px',
'&.Mui-disabled': {
opacity: 0.5
},
'& .MuiTypography-root': {
fontFamily: "'Sharp Sans', sans-serif",
fontSize: '16px',
fontWeight: 400,
lineHeight: '24px'
}
}))

Expand Down Expand Up @@ -100,7 +106,8 @@ const StyledTextField = styled(TextField)(({ theme }) => ({
fontSize: '16px',
fontWeight: 400,
lineHeight: '24px',
color: '#000000'
color: '#000000',
minWidth: '42px'
},
'& .MuiInputBase-input::placeholder': {
color: '#A0AEC0',
Expand Down Expand Up @@ -219,7 +226,7 @@ const CustomPagination = React.memo(function CustomPagination({
</MenuItem>
))}
</StyledSelect>
<div className={styles.pageJumpContainer}>
<div>
<StyledTextField
size="small"
value={pageInput}
Expand Down Expand Up @@ -320,7 +327,7 @@ const CustomPagination = React.memo(function CustomPagination({
</MenuItem>
))}
</StyledSelect>
<div className={styles.pageJumpContainer}>
<div>
<StyledTextField
size="small"
value={pageInput}
Expand Down
10 changes: 8 additions & 2 deletions src/components/TopCountriesChart/TopCountriesChart .tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ const TopCountriesChart: React.FC = () => {
nodes: stat.totalNodes
}))

const maxNodes = Math.max(...topCountries.map((country) => country.nodes))

const tickInterval = maxNodes > 50000 ? 5000 : 1000
const roundedMax = Math.ceil(maxNodes / tickInterval) * tickInterval
const tickValues = Array.from({ length: 6 }, (_, i) => Math.round((roundedMax / 5) * i))

return (
<div className={styles.root}>
<h2 className={styles.title}>Top 5 countries by Ocean Nodes</h2>
Expand All @@ -30,8 +36,8 @@ const TopCountriesChart: React.FC = () => {
axisLine={false}
tickLine={false}
tick={<CustomXAxisTick />}
domain={[0, 10000]}
ticks={[0, 2000, 4000, 6000, 8000, 10000]}
domain={[0, roundedMax]}
ticks={tickValues}
/>
<YAxis
dataKey="country"
Expand Down
Loading
Loading