feat: introduce lumeDashboard

This commit is contained in:
Juan Di Toro 2023-09-28 23:00:26 +02:00
parent f0104c5b61
commit 23387f74ac
3 changed files with 175 additions and 0 deletions

View File

@ -0,0 +1,17 @@
import { StoryFn, Meta } from '@storybook/react';
import LumeDashboard from './LumeDashboard';
import LumeProvider from '../LumeProvider';
export default {
title: 'LumeDashboard',
component: LumeDashboard,
} as Meta<typeof LumeDashboard>;
const Template: StoryFn<typeof LumeDashboard> = (args) => <LumeProvider>
<LumeDashboard {...args} />
</LumeProvider>;
export const Primary = Template.bind({});
Primary.args = {
// Add initial props here
};

View File

@ -0,0 +1,87 @@
import * as Dialog from "@radix-ui/react-dialog"
import { Chain, useLume } from "@/components/lume/LumeProvider"
const LumeDashboard = () => {
const { chains } = useLume()
return (
<Dialog.Root>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="fixed z-40 inset-0 bg-black bg-opacity-50 backdrop-blur-sm" />
<Dialog.Content className="fixed p-5 z-50 right-0 bottom-0 top-0 w-[300px] bg-neutral-800 text-white border-black border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500">
<Dialog.Title>Syncing State: Connected</Dialog.Title>
<Dialog.Description>Network Log:</Dialog.Description>
{chains.map((chain) => (
<div key={chain.chainId}>
<CircularProgress chain={chain} />
</div>
))}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
)
}
const CircularProgress = ({
chain,
className
}: {
chain: Chain
className?: string
}) => {
const progressOffset = ((100 - chain.progress) / 100) * 565.48
const textOffset = (chain.progress / 100) * (30 - 44) + 44
return (
<svg
className={`${className} ${
chain.syncState === "done"
? "text-primary"
: chain.syncState === "error"
? "text-red-600"
: "text-orange-500"
}`}
width="100"
height="100"
viewBox="-25 -25 250 250"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
style={{ transform: "rotate(-90deg)" }}
>
<circle
r="45"
cx="50"
cy="50"
fill="transparent"
stroke="#e0e0e0"
stroke-width="8px"
stroke-dasharray="282.74px"
stroke-dashoffset="0"
></circle>
<circle
r="45"
cx="50"
cy="50"
stroke="currentColor"
stroke-width="8px"
stroke-linecap="round"
stroke-dashoffset={`${progressOffset}px`}
fill="transparent"
stroke-dasharray="282.74px"
></circle>
<text
x={textOffset}
y="57.5px"
fill="currentColor"
font-size="26px"
font-weight="bold"
style={{ transform: "rotate(90deg) translate(0px, -98px)" }}
>
{chain.progress}
</text>
</svg>
)
}
export default LumeDashboard

View File

@ -0,0 +1,71 @@
import React, { useContext } from 'react';
type LumeSyncState = 'syncing' | 'done' | 'error'
export type Chain = {
syncState: LumeSyncState,
chainId: string,
active: boolean,
progress: number, // in porcentage
logs: string[],
type: 'blockchain' | 'content',
peerCount?: number
}
type LumeObject = {
chains: Chain[],
activeResolver: 'local' | 'rpc'
}
type LumeContext = {
lume: LumeObject
}
const LumeContext = React.createContext<LumeContext | undefined>(undefined);
const LumeProvider = ({ children }: { children: React.ReactNode }) => {
const [lume, setLume] = React.useState<LumeObject>({
chains: [
{
syncState: 'done',
chainId: '1',
active: true,
progress: 100,
logs: [],
type: 'blockchain',
peerCount: 5
},
{
syncState: 'syncing',
chainId: '2',
active: false,
progress: 50,
logs: [],
type: 'content',
peerCount: 3
}
],
activeResolver: 'local',
});
// Here you can add the logic to update the lume state
return (
<LumeContext.Provider value={{ lume }}>
{children}
</LumeContext.Provider>
);
};
export default LumeProvider;
export function useLume() {
const ctx = useContext(LumeContext);
if(!ctx) {
throw new Error('useLume must be used within a LumeProvider');
}
const { lume } = ctx;
return lume
}