Merge branch 'Create-Dashboard' of https://github.com/nimbus-gui/nimbus-gui into Create-Dashboard

This commit is contained in:
Hristo Nedelkov 2023-09-16 06:09:22 +03:00
commit 8922170358
31 changed files with 604 additions and 409 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -15,3 +15,20 @@ export const BAD_NETWORK_TEXT = 'Network Latency is high.'
export const KEYSTORE_FILES = 'KeystoreFiles'
export const RECOVERY_PHRASE = 'Recovery Phrase'
export const BOTH_KEY_AND_RECOVERY = 'Both KeystoreFiles & Recovery Phrase'
/* Dashboard */
export const years = [
'JAN',
'FEB',
'MAR',
'APR',
'MAY',
'JUN',
'JUL',
'AUG',
'SEPT',
'OCT',
'NOV',
'DEC',
]

View File

@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import BalanceChartCard from './BalanceChartCard'
const meta = {
title: 'Dashboard/BalanceChartCard',
component: BalanceChartCard,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof BalanceChartCard>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {},
}

View File

@ -0,0 +1,105 @@
import { useState } from 'react'
import { Stack, XStack, YStack } from 'tamagui'
import { Calendar } from '@status-im/components'
import { Text } from '@status-im/components'
import { DateRange } from 'react-day-picker'
import DashboardCardWrapper from '../DashboardCardWrapper'
import LineChart from './LineChart'
import Icon from '../../../components/General/Icon'
import { years } from '../../../constants'
import './calendar.css'
const userGains = [
10000, 15000, 17500, 20000, 19000, 23222, 25000, 20000, 20000, 21000, 22300, 21000,
]
const getMonthIndicesFromRange = (range: DateRange) => {
if (!range.from || !range.to) return [0, 11]
return [range.from.getMonth(), range.to.getMonth()]
}
const BalanceChartCard = () => {
const [isCalendarVisible, setIsCalendarVisible] = useState(false)
const [dateRange, setDateRange] = useState<DateRange>({ from: undefined, to: undefined })
const [startMonth, endMonth] = getMonthIndicesFromRange(dateRange)
const filteredYears = years.slice(startMonth, endMonth + 1)
const filteredUserGains = userGains.slice(startMonth, endMonth + 1)
const handleRangeSelect = (
range: DateRange | undefined,
// @NOTE: You can take selectedDay: Date,
) => {
if (!range) {
setDateRange({ from: undefined, to: undefined })
return
}
setDateRange(range)
if (range.from && range.to) {
setIsCalendarVisible(false)
}
}
return (
<DashboardCardWrapper>
<Stack style={{ width: '536px' }}>
<YStack space={'$4'}>
<XStack justifyContent={'space-between'}>
<YStack>
<Text size={15} weight={'semibold'}>
Balance
</Text>
<XStack
style={{ alignItems: 'end' }}
space={'$1'}
onClick={() => setIsCalendarVisible(true)}
>
<Text size={27} weight={'semibold'}>
24,273
</Text>
<Text size={11} color="#23ADA0">
1.56%
</Text>
</XStack>
</YStack>
<XStack
onClick={() => setIsCalendarVisible(prev => !prev)}
style={{
border: '2px solid #09101C14',
height: 'fit-content',
padding: '3px',
borderRadius: '10px',
}}
>
<Text size={13} weight={'semibold'}>
{dateRange?.from ? dateRange.from.toLocaleDateString() + ' ->' : 'Start Date -> '}{' '}
</Text>
<Text size={13} weight={'semibold'}>
{dateRange?.to ? dateRange.to.toLocaleDateString() : ' End Date'}
</Text>
<Icon src="/icons/edit.svg" />
</XStack>
</XStack>
{isCalendarVisible && (
<Calendar
style={{
backgroundColor: 'white',
position: 'absolute',
zIndex: 1000,
top: '100%',
right: '0',
}}
mode="range"
selected={dateRange}
onSelect={handleRangeSelect}
/>
)}
<LineChart years={filteredYears} userGains={filteredUserGains} />
</YStack>
</Stack>
</DashboardCardWrapper>
)
}
export default BalanceChartCard

View File

@ -0,0 +1,32 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Stack } from 'tamagui'
import LineChart from './LineChart'
import { years } from '../../../constants'
const userGains = [
10000, 15000, 17500, 20000, 19000, 23222, 25000, 20000, 20000, 21000, 22300, 21000,
]
const meta = {
title: 'Dashboard/LineChart',
component: LineChart,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [
StoryObj => (
<Stack width={'536px'}>
<StoryObj />,
</Stack>
),
],
} satisfies Meta<typeof LineChart>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: { userGains, years },
}

View File

@ -0,0 +1,41 @@
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Filler,
} from 'chart.js'
import { Line } from 'react-chartjs-2'
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, Filler)
type LineChartProps = {
years: string[]
userGains: number[]
}
const LineChart = ({ years, userGains }: LineChartProps) => {
const data = {
type: 'line',
labels: years,
datasets: [
{
data: userGains,
borderColor: '#1992D7',
backgroundColor: '#f6fbfd',
fill: true,
tension: 0.4,
pointRadius: 0,
},
],
options: {
responsive: true,
maintainAspectRatio: true,
},
}
return <Line options={data.options} data={data} />
}
export default LineChart

View File

@ -1,73 +0,0 @@
import './calendar.css'
import { Stack, XStack, YStack } from "tamagui";
import DashboardCardWrapper from "../DashboardCardWrapper";
import { Text } from "@status-im/components";
import LineChart from "./LineChart";
import Icon from "../../../components/General/Icon";
import { DateRange } from 'react-day-picker';
import { Calendar } from '@status-im/components'
import { useState } from "react";
const years = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEPT', 'OCT', 'NOV', 'DEC']
const userGains = [10000, 15000, 17500, 20000, 19000, 23222, 25000, 20000, 20000, 21000, 22300, 21000]
const getMonthIndicesFromRange = (range: DateRange) => {
if (!range.from || !range.to) return [0, 11];
return [range.from.getMonth(), range.to.getMonth()];
};
const BalanceChardCard = () => {
const [isCalendarVisible, setIsCalendarVisible] = useState(false)
const [dateRange, setDateRange] = useState<DateRange>({ from: undefined, to: undefined });
const [startMonth, endMonth] = getMonthIndicesFromRange(dateRange);
const filteredYears = years.slice(startMonth, endMonth + 1);
const filteredUserGains = userGains.slice(startMonth, endMonth + 1);
const handleRangeSelect = (
range: DateRange | undefined,
// @NOTE: You can take selectedDay: Date,
) => {
if (!range) {
setDateRange({ from: undefined, to: undefined });
return;
}
setDateRange(range);
if (range.from && range.to) {
setIsCalendarVisible(false)
}
};
return (
<DashboardCardWrapper >
<Stack style={{ width: '536px' }}>
<YStack space={'$4'}>
<XStack justifyContent={'space-between'}>
<YStack>
<Text size={15} weight={'semibold'}> Balance</Text>
<XStack style={{ alignItems: 'end', }} space={'$1'} onClick={() => setIsCalendarVisible(true)}>
<Text size={27} weight={'semibold'}>24,273</Text>
<Text size={11} color="#23ADA0" >1.56%</Text>
</XStack>
</YStack>
<XStack onClick={() => setIsCalendarVisible((prev) => !prev)} style={{ border: '2px solid #09101C14', height: 'fit-content', padding: '3px', borderRadius: '10px' }}>
<Text size={13} weight={'semibold'}>{dateRange?.from ? dateRange.from.toLocaleDateString() + ' ->' : 'Start Date -> '} </Text>
<Text size={13} weight={'semibold'}>{dateRange?.to ? dateRange.to.toLocaleDateString() : ' End Date'}</Text>
<Icon src="/icons/edit.svg" />
</XStack>
</XStack>
{isCalendarVisible && (
<Calendar
style={{ backgroundColor: 'white', position: 'absolute', zIndex: 1000, top: '100%', right: '0' }}
mode="range"
selected={dateRange}
onSelect={handleRangeSelect}
/>
)}
<LineChart years={filteredYears} userGains={filteredUserGains} />
</YStack>
</Stack>
</DashboardCardWrapper>
)
}
export default BalanceChardCard;

View File

@ -1,29 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react'
import LineChart from './LineChart'
import { Stack } from 'tamagui'
const years = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEPT', 'OCT', 'NOV', 'DEC']
const userGains = [10000, 15000, 17500, 20000, 19000, 23222, 25000, 20000, 20000, 21000, 22300, 21000]
const meta = {
title: 'Dashboard/LineChart',
component: LineChart,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
decorators: [StoryObj =>
(
<Stack width={'536px'}>
<StoryObj />,
</Stack>
)
]
} satisfies Meta<typeof LineChart>
export default meta
type Story = StoryObj<typeof meta>
export const Page: Story = {
args: { userGains, years },
}

View File

@ -1,48 +0,0 @@
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Filler,
} from 'chart.js';
import { Line } from 'react-chartjs-2';
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Filler,
);
type LineChartProps = {
years: string[];
userGains: number[];
};
const LineChart = ({ years, userGains }: LineChartProps) => {
const data = {
type: 'line',
labels: years,
datasets: [
{
data: userGains,
borderColor: '#1992D7',
backgroundColor: '#f6fbfd',
fill: true,
tension: 0.4,
pointRadius: 0,
}
],
options: {
responsive: true,
maintainAspectRatio: true,
}
};
return <Line options={data.options} data={data} />;
}
export default LineChart;

View File

@ -14,6 +14,6 @@ const meta = {
export default meta
type Story = StoryObj<typeof meta>
export const Page: Story = {
args: {load:[32,12,45,10]},
export const Default: Story = {
args: { load: [32, 12, 45, 10] },
}

View File

@ -1,88 +1,96 @@
import StandartLineChart from '../../../components/Charts/StandardLineChart'
import IconText from '../../../components/General/IconText'
import { Paragraph, Separator, XStack, YStack } from 'tamagui'
import { Shadow, Text } from '@status-im/components'
import { IncorrectIcon } from '@status-im/icons'
import StandartLineChart from '../../../components/Charts/StandardLineChart'
import IconText from '../../../components/General/IconText'
import Icon from '../../../components/General/Icon'
type DataPoint = {
x: number
y: number
x: number
y: number
}
type ChartData = {
id: string
color: string
data: DataPoint[]
id: string
color: string
data: DataPoint[]
}
type CPUCardProps = {
load: number[]
load: number[]
}
const CPUCard = ({ load }: CPUCardProps) => {
const chartData: ChartData[] = [
{
id: 'cpu',
color: '#8DC6BC',
data: load.map((yValue, index: number) => ({
x: index + 1,
y: yValue,
})),
},
]
const currentLoad =
chartData[0].data.length > 0 ? chartData[0].data[chartData[0].data.length - 1].y : 0
const chartData: ChartData[] = [
{
id: 'cpu',
color: '#8DC6BC',
data: load.map((yValue, index: number) => ({
x: index + 1,
y: yValue,
})),
},
]
const currentLoad =
chartData[0].data.length > 0 ? chartData[0].data[chartData[0].data.length - 1].y : 0
const message = currentLoad < 80 ? 'Good' : 'Poor'
const message = currentLoad < 80 ? 'Good' : 'Poor'
return (
<Shadow
variant="$2"
style={{
width: '284px',
height: '136px',
borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
}}
return (
<Shadow
variant="$2"
style={{
width: '284px',
height: '136px',
borderRadius: '16px',
border: message === 'Poor' ? '1px solid #D92344' : 'none',
backgroundColor: message === 'Poor' ? '#fefafa' : '#fff',
}}
>
<YStack>
<XStack
justifyContent="space-between"
style={{
padding: '8px 16px',
position: 'relative',
}}
>
<YStack>
<XStack
justifyContent="space-between"
style={{
padding: '8px 16px',
position: 'relative',
}}
>
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
<StandartLineChart data={chartData} />
</div>
<YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}>
CPU
</Paragraph>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}>
{currentLoad} GB
</Paragraph>
</YStack>
</XStack>
<Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}>
<IconText
icon={message === 'Good' ? <Icon src='icons/active.svg' width={16} /> : <IncorrectIcon size={16} />}
weight={'semibold'}
>
{message}
</IconText>
{message === 'Poor' && (
<Text size={13} color="#E95460">
{((currentLoad / 80) * 100).toFixed(0)}% Utilization
</Text>
)}
</XStack>
</YStack>
</Shadow >
)
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
<StandartLineChart data={chartData} />
</div>
<YStack space={'$3'}>
<Paragraph color={'#09101C'} size={'$6'} fontWeight={'600'}>
CPU
</Paragraph>
<Paragraph color={'#09101C'} size={'$8'} fontWeight={'700'}>
{currentLoad} GB
</Paragraph>
</YStack>
</XStack>
<Separator borderColor={'#e3e3e3'} />
<XStack space={'$4'} style={{ padding: '10px 16px 10px 16px' }}>
<IconText
icon={
message === 'Good' ? (
<Icon src="icons/active.svg" width={16} />
) : (
<IncorrectIcon size={16} />
)
}
weight={'semibold'}
>
{message}
</IconText>
{message === 'Poor' && (
<Text size={13} color="#E95460">
{((currentLoad / 80) * 100).toFixed(0)}% Utilization
</Text>
)}
</XStack>
</YStack>
</Shadow>
)
}
export default CPUCard

View File

@ -14,6 +14,6 @@ const meta = {
export default meta
type Story = StoryObj<typeof meta>
export const Page: Story = {
export const Default: Story = {
args: {},
}

View File

@ -1,75 +1,86 @@
import { Shadow, Text } from '@status-im/components';
import { Stack, XStack, YStack } from 'tamagui';
import UptimeChart from '../UptimeChart/UptimeChart';
import Icon from '../../../components/General/Icon';
const data: DataItem[] = [
{
// @NOTE: if you want to add name in the XAxis. You need to set the names here
// name: 'Jan',
pv: 1,
pa: 1,
},
{
// name: 'Feb',
pv: 0,
pa: 0
},
{
//name: 'Feb',
pv: 1,
pa: 0
},
{
//name: 'Feb',
pv: 0,
pa: 0
},
{
//name: 'Feb',
pv: 0,
pa: 0
},
{
//name: 'Feb',
pv: 1,
pa: 1
},
{
//name: 'Feb',
pv: 1,
pa: 1
},
];
interface DataItem {
name?: string;
pa: number;
pv: number;
}
const ConsensusUptimeCard = () => {
return (
<Shadow
variant="$2"
style={{
borderRadius: '16px',
}}
>
<YStack space={'$3'} width={'260px'} height={'156px'} padding={'$3'}>
<YStack>
<Text size={15} weight={'semibold'}> Consensus Uptime</Text>
<XStack style={{ alignItems: 'end', }} space={'$2'} >
<Text size={27} weight={'semibold'}>98%</Text>
<Icon src='/icons/positive.svg' width={13}></Icon>
<Text size={13} color="#E95460" >1.56%</Text>
</XStack>
</YStack>
<XStack height={'50%'} justifyContent="center" alignItems="center">
<Stack style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', width: '228px', height: '100%' }}>
<UptimeChart data={data} />
</Stack>
</XStack>
</YStack>
import { Shadow, Text } from '@status-im/components'
import { Stack, XStack, YStack } from 'tamagui'
</Shadow >
);
import UptimeChart from '../UptimeChart/UptimeChart'
import Icon from '../../../components/General/Icon'
const data: DataItem[] = [
{
// @NOTE: if you want to add name in the XAxis. You need to set the names here
// name: 'Jan',
pv: 1,
pa: 1,
},
{
pv: 0,
pa: 0,
},
{
pv: 1,
pa: 0,
},
{
pv: 0,
pa: 0,
},
{
pv: 0,
pa: 0,
},
{
pv: 1,
pa: 1,
},
{
pv: 1,
pa: 1,
},
]
type DataItem = {
name?: string
pa: number
pv: number
}
export default ConsensusUptimeCard;
const ConsensusUptimeCard = () => {
return (
<Shadow
variant="$2"
style={{
borderRadius: '16px',
}}
>
<YStack space={'$3'} width={'260px'} height={'156px'} padding={'$3'}>
<YStack>
<Text size={15} weight={'semibold'}>
Consensus Uptime
</Text>
<XStack style={{ alignItems: 'end' }} space={'$2'}>
<Text size={27} weight={'semibold'}>
98%
</Text>
<Icon src="/icons/positive.svg" width={13}></Icon>
<Text size={13} color="#E95460">
1.56%
</Text>
</XStack>
</YStack>
<XStack height={'50%'} justifyContent="center" alignItems="center">
<Stack
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '228px',
height: '100%',
}}
>
<UptimeChart data={data} />
</Stack>
</XStack>
</YStack>
</Shadow>
)
}
export default ConsensusUptimeCard

View File

@ -3,22 +3,24 @@ import { XStack, YStack } from 'tamagui'
import BasicInfoCards from './BasicInfoCards/BasicInfoCards'
import AddCardsContainer from '../../components/General/AddCards/AddCardsContainer'
import SyncStatusCard from './SyncStatusCard/SyncStatusCard'
import BalanceChardCard from './BalanceLineChart/BalanceChardCard'
import BalanceChartCard from './BalanceChartCard/BalanceChartCard'
import CPUCard from './CPULoad/CPUCard'
import ConsensusUptimeCard from './ConsensusUptime/ConsensusUptimeCard'
import ExecutionUptime from './ExecutionUptime/ExecutionUptime'
import DeviceUptime from './DeviceUptime/DeviceUptime'
import TitleLogo from './TitleLogo'
const Dashboard = () => {
return (
<YStack space={'$4'} alignItems="start">
<TitleLogo />
<XStack space={'$4'} style={{ width: '100%' }}>
<XStack space={'$4'}>
<AddCardsContainer />
<SyncStatusCard />
</XStack>
<BalanceChardCard />
<CPUCard load={[12, 31, 3, 2, 24,]} />
<BalanceChartCard />
<CPUCard load={[12, 31, 3, 2, 24]} />
</XStack>
<BasicInfoCards />
<XStack space="$3">

View File

@ -14,6 +14,6 @@ const meta = {
export default meta
type Story = StoryObj<typeof meta>
export const Page: Story = {
export const Default: Story = {
args: {},
}

View File

@ -1,70 +1,85 @@
import { Shadow, Text } from '@status-im/components';
import { Stack, XStack, YStack } from 'tamagui';
import Icon from '../../../components/General/Icon';
import UptimeChart from '../UptimeChart/UptimeChart';
import { Shadow, Text } from '@status-im/components'
import { Stack, XStack, YStack } from 'tamagui'
import Icon from '../../../components/General/Icon'
import UptimeChart from '../UptimeChart/UptimeChart'
const data: DataItem[] = [
{
// @NOTE: if you want to add name in the XAxis. You need to set the names here
pv: 1,
pa: 1,
},
{
pv: 0,
pa: 0
},
{
pv: 0,
pa: 0
},
{
pv: 0,
pa: 1
},
{
pv: 0,
pa: 0
},
{
pv: 1,
pa: 0
},
{
pv: 0,
pa: 1
},
];
{
// @NOTE: if you want to add name in the XAxis. You need to set the names here
pv: 1,
pa: 1,
},
{
pv: 0,
pa: 0,
},
{
pv: 0,
pa: 0,
},
{
pv: 0,
pa: 1,
},
{
pv: 0,
pa: 0,
},
{
pv: 1,
pa: 0,
},
{
pv: 0,
pa: 1,
},
]
interface DataItem {
name?: string;
pa: number;
pv: number;
type DataItem = {
name?: string
pa: number
pv: number
}
const ExecutionUptime = () => {
return (
<Shadow
variant="$2"
return (
<Shadow
variant="$2"
style={{
borderRadius: '16px',
}}
>
<YStack space={'$3'} width={'260px'} height={'156px'} padding={'$3'}>
<YStack>
<Text size={15} weight={'semibold'}>
Execution Uptime
</Text>
<XStack style={{ alignItems: 'end' }} space={'$2'}>
<Text size={27} weight={'semibold'}>
99%
</Text>
<Icon src="/icons/positive.svg" width={13}></Icon>
<Text size={13} color="#E95460">
2%
</Text>
</XStack>
</YStack>
<XStack height={'50%'} justifyContent="center" alignItems="center">
<Stack
style={{
borderRadius: '16px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '228px',
height: '100%',
}}
>
<YStack space={'$3'} width={'260px'} height={'156px'} padding={'$3'}>
<YStack>
<Text size={15} weight={'semibold'}> Execution Uptime</Text>
<XStack style={{ alignItems: 'end', }} space={'$2'} >
<Text size={27} weight={'semibold'}>99%</Text>
<Icon src='/icons/positive.svg' width={13}></Icon>
<Text size={13} color="#E95460" >2%</Text>
</XStack>
</YStack>
<XStack height={'50%'} justifyContent="center" alignItems="center">
<Stack style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', width: '228px', height: '100%' }}>
<UptimeChart data={data} />
</Stack>
</XStack>
</YStack>
</Shadow >
);
>
<UptimeChart data={data} />
</Stack>
</XStack>
</YStack>
</Shadow>
)
}
export default ExecutionUptime;
export default ExecutionUptime

View File

@ -14,6 +14,38 @@ const meta = {
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: { title: 'Sync Status', total: 113220, value: 50000 },
export const ExecutionClient: Story = {
args: { title: 'Execution Client', value: 123.424, total: 170, isTop: true },
}
export const ConsensusClient: Story = {
args: { title: 'Consensus Client', value: 123.424, total: 170, isTop: false },
}
export const WithoutTitle: Story = {
args: { title: '', value: 123.424, total: 170 },
}
export const WithZeroValue: Story = {
args: { title: 'Consensus Client', value: 0, total: 170 },
}
export const WithZeroTotal: Story = {
args: { title: 'Consensus Client', value: 123.424, total: 0 },
}
export const WithZeroValueAndTotal: Story = {
args: { title: 'Consensus Client', value: 0, total: 0 },
}
export const WithoutValues: Story = {
args: { title: '', value: 0, total: 0 },
}
export const WithTopBorders: Story = {
args: { title: '', value: 0, total: 0, isTop: true },
}
export const WithBottomBorders: Story = {
args: { title: '', value: 0, total: 0, isTop: false },
}

View File

@ -1,27 +1,46 @@
import { Separator, XStack, YStack } from 'tamagui'
import { formatNumberForGauge } from '../../../utilities'
import { Text } from '@status-im/components'
import { Separator, Stack, XStack, YStack } from 'tamagui'
import { Shadow, Text } from '@status-im/components'
import { SwapIcon } from '@status-im/icons'
import { CSSProperties } from 'react'
import { formatNumberWithComa } from '../../../utilities'
import IconText from '../../../components/General/IconText'
type SyncCardContentProps = {
title: string
value: number
total: number
isTop?: boolean
}
const SyncCardContent = ({ title, value, total }: SyncCardContentProps) => {
const SyncCardContent = ({ title, value, total, isTop }: SyncCardContentProps) => {
const style: CSSProperties = {}
if (isTop === true) {
style.borderTopLeftRadius = '16px'
style.borderTopRightRadius = '16px'
} else if (isTop === false) {
style.borderBottomLeftRadius = '16px'
style.borderBottomRightRadius = '16px'
}
return (
<YStack>
<Text size={15} weight={'semibold'}>
{title}
</Text>
<Separator borderColor={'#e3e3e3'} />
<XStack space={'$2'} style={{ padding: '10px 16px 10px 16px' }}>
{/* <IconText icon={<TokenIcon size={16} />}>Syncing</IconText> */}
<Text size={13}>
{formatNumberForGauge(value)} / {formatNumberForGauge(total)}
</Text>
</XStack>
</YStack>
<Shadow variant="$1" style={style}>
<YStack>
<Stack style={{ width: '260px', height: '84px', paddingTop: '12px', paddingLeft: '16px' }}>
<Text size={15} weight={'semibold'} color="#647084">
{title}
</Text>
</Stack>
<Separator borderColor={'#e3e3e3'} />
<XStack space={'$3'} style={{ padding: '12px 16px' }}>
<IconText icon={<SwapIcon size={16} />}>Syncing</IconText>
<Text size={13} weight={'semibold'}>
{formatNumberWithComa(value)} / {formatNumberWithComa(total)}
</Text>
</XStack>
</YStack>
</Shadow>
)
}

View File

@ -1,20 +1,22 @@
import { Separator, YStack } from 'tamagui'
import { Separator, Stack, YStack } from 'tamagui'
import { Text } from '@status-im/components'
import SyncCardContent from './SyncCardContent'
import DashboardCardWrapper from '../DashboardCardWrapper'
import { Text } from '@status-im/components'
const SyncStatusCard = () => {
return (
<DashboardCardWrapper padding="0">
<YStack space={'$2'}>
<Text size={15} weight={'semibold'}>
Sync Status
</Text>
<Stack style={{ paddingTop: '12px', paddingLeft: '16px' }}>
<Text size={15} weight={'semibold'}>
Sync Status
</Text>
</Stack>
<YStack>
<SyncCardContent title={'Execution Client'} value={123.424} total={170.0} />
<SyncCardContent title={'Execution Client'} value={123.424} total={170} isTop={true} />
<Separator borderColor={'#e3e3e3'} />
<SyncCardContent title={'Consensus Client'} value={123.424} total={170.0} />
<SyncCardContent title={'Consensus Client'} value={123.424} total={170} isTop={false} />
</YStack>
</YStack>
</DashboardCardWrapper>

View File

@ -1,19 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react'
import BalanceChardCard from './BalanceChardCard'
import TitleLogo from './TitleLogo'
const meta = {
title: 'Dashboard/BalanceChardCard',
component: BalanceChardCard,
title: 'Dashboard/TitleLogo',
component: TitleLogo,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof BalanceChardCard>
} satisfies Meta<typeof TitleLogo>
export default meta
type Story = StoryObj<typeof meta>
export const Page: Story = {
export const Default: Story = {
args: {},
}

View File

@ -0,0 +1,20 @@
import { Text } from '@status-im/components'
import { XStack, YStack } from 'tamagui'
const TitleLogo = () => {
return (
<XStack>
{/* <Avatar type="icon" size={80} icon={<img src={'/icons/dashboard-logo.png'} />} /> */}
<YStack>
<Text size={27} color="#09101C" weight={'semibold'}>
Nimbus
</Text>
<Text size={19} color="#647084">
Node Management Dashboard
</Text>
</YStack>
</XStack>
)
}
export default TitleLogo

View File

@ -0,0 +1,21 @@
import type { Meta, StoryObj } from '@storybook/react'
import UptimeChart from './UptimeChart'
const meta = {
title: 'Dashboard/UptimeChart',
component: UptimeChart,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof UptimeChart>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
data: [],
},
}

View File

@ -1,13 +1,13 @@
import { BarChart, Bar, ResponsiveContainer, XAxis } from 'recharts';
interface DataItem {
name?: string;
pa: number;
pv: number;
type DataItem = {
name?: string
pa: number
pv: number
}
type UptimeChartProps = {
data: DataItem[];
data: DataItem[]
}
const UptimeChart = ({ data }: UptimeChartProps) => {
@ -27,4 +27,5 @@ const UptimeChart = ({ data }: UptimeChartProps) => {
</ResponsiveContainer>
);
}
export default UptimeChart;
export default UptimeChart

View File

@ -40,8 +40,8 @@ const DeviceSyncStatus = () => {
subtitle="Monitor your Validator Client and Beacon Node syncing progression."
/>
<YStack style={{ width: '100%' }}>
<SyncStatusCardExecution synced={132.432} total={200.0} />
<SyncStatusCardConsensus synced={149.5} total={160.0} />
<SyncStatusCardExecution synced={132.432} total={200} />
<SyncStatusCardConsensus synced={149.5} total={160} />
</YStack>
<Stack style={{ marginTop: '1rem' }}>
<Button>Continue</Button>

View File

@ -5,7 +5,7 @@ import Icon from '../../components/General/Icon'
import StandardGauge from '../../components/Charts/StandardGauge'
import IconText from '../../components/General/IconText'
import { TokenIcon } from '@status-im/icons'
import { formatNumberForGauge } from '../../utilities'
import { formatNumberWithComa } from '../../utilities'
interface DeviceStorageHealthProps {
synced: number
@ -72,7 +72,7 @@ const SyncStatusCardConsensus: React.FC<DeviceStorageHealthProps> = ({ synced, t
<XStack space={'$2'} style={{ padding: '10px 16px 10px 16px' }}>
<IconText icon={<TokenIcon size={16} />}>{message}</IconText>
<Text size={13}>
{formatNumberForGauge(synced)} / {formatNumberForGauge(total)}
{formatNumberWithComa(synced)} / {formatNumberWithComa(total)}
</Text>
</XStack>
</YStack>

View File

@ -3,7 +3,7 @@ import { Shadow, Text } from '@status-im/components'
import StandardGauge from '../../components/Charts/StandardGauge'
import IconText from '../../components/General/IconText'
import { TokenIcon } from '@status-im/icons'
import { formatNumberForGauge } from '../../utilities'
import { formatNumberWithComa } from '../../utilities'
interface DeviceStorageHealthProps {
synced: number
@ -73,7 +73,7 @@ const SyncStatusCardExecution: React.FC<DeviceStorageHealthProps> = ({ synced, t
<XStack space={'$2'} style={{ padding: '10px 16px 10px 16px' }}>
<IconText icon={<TokenIcon size={16} />}>{message}</IconText>
<Text size={13}>
{formatNumberForGauge(synced)} / {formatNumberForGauge(total)}
{formatNumberWithComa(synced)} / {formatNumberWithComa(total)}
</Text>
</XStack>
</YStack>

View File

@ -1,7 +1,7 @@
import { Stack, XStack, YStack } from 'tamagui'
import StandardGauge from '../../../components/Charts/StandardGauge'
import { Text } from '@status-im/components'
import { formatNumberForGauge } from '../../../utilities'
import { formatNumberWithComa } from '../../../utilities'
type ActivationSyncCardProps = {
gaugeColor: string
@ -37,7 +37,7 @@ const ActivationSyncCard = ({ gaugeColor, gaugeSynced, gaugeTotal }: ActivationS
</Stack>
<YStack>
<Text size={15} weight={'semibold'}>
{formatNumberForGauge(gaugeSynced)} / {formatNumberForGauge(gaugeTotal)}
{formatNumberWithComa(gaugeSynced)} / {formatNumberWithComa(gaugeTotal)}
</Text>
</YStack>
</XStack>

View File

@ -4,7 +4,7 @@ import { Text } from '@status-im/components'
import StandardGauge from '../../../../components/Charts/StandardGauge'
import BorderBox from '../../../../components/General/BorderBox'
import { formatNumberForGauge } from '../../../../utilities'
import { formatNumberWithComa } from '../../../../utilities'
type KeyGenerationSyncCardProps = {
synced: number
@ -45,7 +45,7 @@ const KeyGenerationSyncCard = ({ synced, total, title, color }: KeyGenerationSyn
{title}
</Text>
<Text size={15} weight={'semibold'}>
{formatNumberForGauge(synced)} / {formatNumberForGauge(total)}
{formatNumberWithComa(synced)} / {formatNumberWithComa(total)}
</Text>
</YStack>
<ClearIcon size={20} color="#A1ABBD" />

View File

@ -4,7 +4,7 @@ import { Text } from '@status-im/components'
import StandardGauge from '../../../../components/Charts/StandardGauge'
import BorderBox from '../../../../components/General/BorderBox'
import { formatNumberForGauge } from '../../../../utilities'
import { formatNumberWithComa } from '../../../../utilities'
type ConsensusGaugeCardProps = {
synced: number
@ -45,7 +45,7 @@ const ConsensusGaugeCard = ({ synced, total, title, color }: ConsensusGaugeCardP
{title}
</Text>
<Text size={15} weight={'semibold'}>
{formatNumberForGauge(synced)} / {formatNumberForGauge(total)}
{formatNumberWithComa(synced)} / {formatNumberWithComa(total)}
</Text>
</YStack>
<ClearIcon size={20} color="#A1ABBD" />

View File

@ -23,6 +23,6 @@ export const convertSecondsToTimerFormat = (seconds: number) => {
return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`
}
export const formatNumberForGauge = (n: number): string => {
return n.toString().replace(/\./g, ',')
export const formatNumberWithComa = (n: number): string => {
return n.toFixed(3).replace(/\./g, ',')
}