From 8e75a0cce8d88fec0fef04b77e43afe2f966b39e Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 13 Jul 2023 12:25:22 +0700 Subject: [PATCH 01/19] feat: implement merge navigation --- src/lib/components/icon/CustomIcon.tsx | 9 + src/lib/hooks/index.ts | 1 + src/lib/hooks/useLocalStorage.ts | 1 + src/lib/hooks/useReadLocalStorage.ts | 34 ++++ src/lib/layout/SubHeader.tsx | 60 +++---- src/lib/layout/index.tsx | 48 +----- src/lib/layout/navbar/Collapse.tsx | 143 +++++++++------- src/lib/layout/navbar/Expand.tsx | 127 +++++++------- src/lib/layout/navbar/index.tsx | 225 +++++++++++++------------ src/lib/layout/navbar/type.ts | 2 + 10 files changed, 346 insertions(+), 304 deletions(-) create mode 100644 src/lib/hooks/useReadLocalStorage.ts diff --git a/src/lib/components/icon/CustomIcon.tsx b/src/lib/components/icon/CustomIcon.tsx index 8407221da..20ff1fa0b 100644 --- a/src/lib/components/icon/CustomIcon.tsx +++ b/src/lib/components/icon/CustomIcon.tsx @@ -1424,6 +1424,15 @@ export const ICONS = { ), viewBox: "0 0 24 24", }, + list: { + svg: ( + + ), + viewBox: "0 5 15 15", + }, }; export type IconKeys = keyof typeof ICONS; diff --git a/src/lib/hooks/index.ts b/src/lib/hooks/index.ts index cd025d8c0..ceb9e3dda 100644 --- a/src/lib/hooks/index.ts +++ b/src/lib/hooks/index.ts @@ -9,3 +9,4 @@ export * from "./useUserKey"; export * from "./useOpenTab"; export * from "./useIsCurrentPage"; export * from "./useGetMaxLengthError"; +export * from "./useReadLocalStorage"; diff --git a/src/lib/hooks/useLocalStorage.ts b/src/lib/hooks/useLocalStorage.ts index 59fa3fab5..aa086fb86 100644 --- a/src/lib/hooks/useLocalStorage.ts +++ b/src/lib/hooks/useLocalStorage.ts @@ -60,6 +60,7 @@ export const useLocalStorage = ( // Save state setStoredValue(newValue); + window.dispatchEvent(new Event("local-storage")); } catch (error) { console.warn(`Error setting localStorage key “${key}”:`, error); } diff --git a/src/lib/hooks/useReadLocalStorage.ts b/src/lib/hooks/useReadLocalStorage.ts new file mode 100644 index 000000000..ca7719e53 --- /dev/null +++ b/src/lib/hooks/useReadLocalStorage.ts @@ -0,0 +1,34 @@ +import { useCallback, useState } from "react"; + +// Reference: https://usehooks-ts.com/react-hook/use-read-local-storage + +type Value = T | null; + +export const useReadLocalStorage = (key: string): Value => { + // Get from local storage then + // parse stored json or return initialValue + const readValue = useCallback((): Value => { + // Prevent build error "window is undefined" but keep keep working + if (typeof window === "undefined") { + return null; + } + + try { + const item = window.localStorage.getItem(key); + return item ? (JSON.parse(item) as T) : null; + } catch (error) { + return null; + } + }, [key]); + + // State to store our value + // Pass initial state function to useState so logic is only executed once + const [storedValue, setStoredValue] = useState>(readValue); + + const handleStorageChange = useCallback(() => { + setStoredValue(readValue()); + }, [readValue]); + + window.addEventListener("local-storage", handleStorageChange); + return storedValue; +}; diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index 82756934b..69197699a 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -1,10 +1,11 @@ -import { Flex, Text } from "@chakra-ui/react"; +import { Flex, Text, Switch, FormControl, FormLabel } from "@chakra-ui/react"; -import { useCurrentChain } from "lib/app-provider"; +import { usePoolConfig, useWasmConfig } from "lib/app-provider"; import { AppLink } from "lib/components/AppLink"; import type { IconKeys } from "lib/components/icon"; import { CustomIcon } from "lib/components/icon"; import { useIsCurrentPage } from "lib/hooks"; +import { useLocalStorage } from "lib/hooks/useLocalStorage"; interface SubHeaderMenuInfo { name: string; @@ -12,20 +13,30 @@ interface SubHeaderMenuInfo { icon: IconKeys; } const SubHeader = () => { + const [isDevMode, setIsDevMode] = useLocalStorage("devMode", false); + + const wasmConfig = useWasmConfig({ shouldRedirect: false }); + const poolConfig = usePoolConfig({ shouldRedirect: false }); + const subHeaderMenu: SubHeaderMenuInfo[] = [ { name: "Overview", slug: "/", icon: "home" }, { name: "Transactions", slug: "/txs", icon: "file" }, { name: "Blocks", slug: "/blocks", icon: "block" }, + ...(wasmConfig.enabled + ? ([ + { name: "Codes", slug: "/codes", icon: "code" }, + { name: "Contracts", slug: "/contracts", icon: "website" }, + ] as const) + : []), { name: "Proposals", slug: "/proposals", icon: "proposal" }, - // { name: "Validators", slug: "/validators", icon: "admin" }, + ...(poolConfig.enabled + ? ([{ name: "Osmosis Pools", slug: "/pools", icon: "pool" }] as const) + : []), ]; - const { address } = useCurrentChain(); const isCurrentPage = useIsCurrentPage(); const activeColor = "primary.light"; - const myPageSlug = `/accounts/${address}`; - return ( @@ -69,29 +80,20 @@ const SubHeader = () => { ))} - {address && ( - - - - - - My Page - - - - - )} + + + + Dev Mode + + + { + setIsDevMode(e.target.checked); + }} + /> + ); }; diff --git a/src/lib/layout/index.tsx b/src/lib/layout/index.tsx index 6f1f1b0de..238e48a64 100644 --- a/src/lib/layout/index.tsx +++ b/src/lib/layout/index.tsx @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; import type { ReactNode } from "react"; import { useEffect, useMemo } from "react"; -import { useCelatoneApp, useMobile, useWasmConfig } from "lib/app-provider"; +import { useCelatoneApp, useMobile } from "lib/app-provider"; import { useLocalStorage } from "lib/hooks/useLocalStorage"; import { scrollToTop } from "lib/utils"; @@ -23,38 +23,10 @@ const Layout = ({ children }: LayoutProps) => { } = useCelatoneApp(); const router = useRouter(); const isMobile = useMobile(); - const wasm = useWasmConfig({ shouldRedirect: false }); const [isExpand, setIsExpand] = useLocalStorage("navbar", !isMobile); const defaultRow = "70px 48px 1fr"; const mode = useMemo(() => { - if (hasSubHeader) { - if (isMobile) - return { - templateAreas: `"header""main"`, - templateRows: "60px 1fr", - templateCols: "1fr", - header: , - subHeader: undefined, - }; - - if (wasm.enabled) - return { - templateAreas: `"header header""subheader subheader""nav main"`, - templateRows: defaultRow, - templateCols: isExpand ? "224px 1fr" : "48px 1fr", - header:
, - subHeader: , - }; - - return { - templateAreas: `"header""nav""main"`, - templateRows: defaultRow, - templateCols: "1fr", - navBar: , - }; - } - if (isMobile) return { templateAreas: `"header""main"`, @@ -64,22 +36,14 @@ const Layout = ({ children }: LayoutProps) => { subHeader: undefined, }; - if (wasm.enabled) - return { - templateAreas: `"header header""nav main"`, - templateRows: "70px 1fr", - templateCols: isExpand ? "224px 1fr" : "48px 1fr", - header:
, - subHeader: undefined, - }; - return { - templateAreas: `"header""nav""main"`, + templateAreas: `"header header""subheader subheader""nav main"`, templateRows: defaultRow, - templateCols: "1fr", - navBar: , + templateCols: isExpand ? "250px 1fr" : "48px 1fr", + header:
, + subHeader: , }; - }, [isMobile, wasm.enabled, isExpand, hasSubHeader]); + }, [isMobile, isExpand]); useEffect(() => { scrollToTop(); diff --git a/src/lib/layout/navbar/Collapse.tsx b/src/lib/layout/navbar/Collapse.tsx index 692d12e86..6a0befc9f 100644 --- a/src/lib/layout/navbar/Collapse.tsx +++ b/src/lib/layout/navbar/Collapse.tsx @@ -6,7 +6,52 @@ import { CustomIcon } from "lib/components/icon"; import { Tooltip } from "lib/components/Tooltip"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; -import type { NavMenuProps } from "./type"; +import type { NavMenuProps, SubmenuInfo } from "./type"; + +interface CollapseNavInfoProps { + submenu: SubmenuInfo; + isCurrentPage: (slug: string) => boolean; +} +const CollapseNavInfo = ({ submenu, isCurrentPage }: CollapseNavInfoProps) => ( + + + + {submenu.icon && } + {submenu.logo && ( + {submenu.slug} + )} + + +); export const CollapseNavMenu = ({ navMenu, @@ -32,70 +77,42 @@ export const CollapseNavMenu = ({ }} > - {!isMobile && - (item.category === "Your Account" || - item.category === "Overview") && ( - - } - onClick={() => setIsExpand(true)} - /> - - )} - - {item.submenu.map((submenu) => ( - AmpTrack(AmpEvent.USE_SIDEBAR)} - > - - + - - {submenu.icon && ( - - )} - {submenu.logo && ( - {submenu.slug} - )} - + mt={2} + mx={2} + icon={} + onClick={() => setIsExpand(true)} + /> - - ))} + )} + + {item.submenu.map((submenu) => + submenu.isDisable ? ( + + ) : ( + AmpTrack(AmpEvent.USE_SIDEBAR)} + > + + + ) + )} ))} diff --git a/src/lib/layout/navbar/Expand.tsx b/src/lib/layout/navbar/Expand.tsx index ea8bc2385..71b65990a 100644 --- a/src/lib/layout/navbar/Expand.tsx +++ b/src/lib/layout/navbar/Expand.tsx @@ -2,10 +2,58 @@ import { Box, Button, Flex, Image, Text } from "@chakra-ui/react"; import { AppLink } from "lib/components/AppLink"; import { CustomIcon } from "lib/components/icon"; -import { CreateNewListModal } from "lib/components/modal"; +import { Tooltip } from "lib/components/Tooltip"; import { AmpEvent, AmpTrack } from "lib/services/amplitude"; -import type { NavMenuProps } from "./type"; +import type { NavMenuProps, SubmenuInfo } from "./type"; + +interface NavInfoProps { + submenu: SubmenuInfo; + isCurrentPage: (slug: string) => boolean; +} +const NavInfo = ({ submenu, isCurrentPage }: NavInfoProps) => ( + + + {submenu.icon && } + {submenu.logo && ( + {submenu.slug} + )} + + {submenu.name} + + +); export const ExpandNavMenu = ({ navMenu, @@ -32,8 +80,7 @@ export const ExpandNavMenu = ({ {item.category} - {(item.category === "Your Account" || - item.category === "Overview") && ( + {item.category === "Your Account" && ( + + + +); + +const SubHeader = () => { + const [isDevMode, setIsDevMode] = useLocalStorage>( + "devMode", + undefined + ); const wasmConfig = useWasmConfig({ shouldRedirect: false }); const poolConfig = usePoolConfig({ shouldRedirect: false }); - const subHeaderMenu: SubHeaderMenuInfo[] = [ { name: "Overview", slug: "/", icon: "home" }, { name: "Transactions", slug: "/txs", icon: "file" }, @@ -38,63 +89,68 @@ const SubHeader = () => { const activeColor = "primary.light"; return ( - - - {subHeaderMenu.map((item) => ( - - svg, > p": { - color: activeColor, - transition: "all .25s ease-in-out", + <> + + + {subHeaderMenu.map((item) => ( + + svg, > p": { + color: activeColor, + transition: "all .25s ease-in-out", + }, + borderBottomWidth: 2, + borderColor: activeColor, }, - borderBottomWidth: 2, - borderColor: activeColor, - }, - }} - > - - - {item.name} - - - - ))} + + + {item.name} + + + + ))} + + + + + Dev Mode + + + { + setIsDevMode(e.target.checked); + }} + /> + - - - - Dev Mode - - - { - setIsDevMode(e.target.checked); - }} - /> - - + {isDevMode === undefined && ( + + )} + ); }; From 0630606c9c8bc5e95dbdc19156584d3527bffee0 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Thu, 13 Jul 2023 18:37:53 +0700 Subject: [PATCH 08/19] fix: comment --- src/lib/layout/navbar/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/layout/navbar/index.tsx b/src/lib/layout/navbar/index.tsx index 7a094de5b..90ec3f216 100644 --- a/src/lib/layout/navbar/index.tsx +++ b/src/lib/layout/navbar/index.tsx @@ -150,10 +150,10 @@ const Navbar = observer(({ isExpand, setIsExpand }: NavbarProps) => { ]; useEffect(() => { - // Currently in dev mode and want to change to basic and nav is collapse -> should expand + // Currently in basic mode and want to change from dev and nav is open -> should close if (isDevMode && !prevIsDevModeRef.current && !isExpand) { setIsExpand(true); - // Currently in basic mode and want to change from dev and nav is open -> should close + // Currently in dev mode and want to change to basic and nav is collapse -> should expand } else if (!isDevMode && prevIsDevModeRef.current && isExpand) { setIsExpand(false); } From 28abde799dbad62eacabac905426667ed490d8da Mon Sep 17 00:00:00 2001 From: poomthiti Date: Thu, 13 Jul 2023 19:59:03 +0700 Subject: [PATCH 09/19] fix: set initial value to false for mobile --- src/lib/layout/SubHeader.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index c2aeaddd8..8e3fa8f19 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -8,7 +8,7 @@ import { } from "@chakra-ui/react"; import type { Dispatch, SetStateAction } from "react"; -import { usePoolConfig, useWasmConfig } from "lib/app-provider"; +import { useMobile, usePoolConfig, useWasmConfig } from "lib/app-provider"; import { AppLink } from "lib/components/AppLink"; import type { IconKeys } from "lib/components/icon"; import { CustomIcon } from "lib/components/icon"; @@ -63,9 +63,10 @@ const FirstLandPrompt = ({ ); const SubHeader = () => { + const isMobile = useMobile(); const [isDevMode, setIsDevMode] = useLocalStorage>( "devMode", - undefined + isMobile ? false : undefined ); const wasmConfig = useWasmConfig({ shouldRedirect: false }); const poolConfig = usePoolConfig({ shouldRedirect: false }); From 11f8eb467afea1c8a32c4f6a79cd7fc5539dca77 Mon Sep 17 00:00:00 2001 From: bkioshn Date: Fri, 14 Jul 2023 09:54:41 +0700 Subject: [PATCH 10/19] chore: fix comment and remove unnecessary style --- src/lib/layout/SubHeader.tsx | 2 +- src/lib/layout/navbar/index.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index 69197699a..ff101eab4 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -81,7 +81,7 @@ const SubHeader = () => { ))} - + Dev Mode diff --git a/src/lib/layout/navbar/index.tsx b/src/lib/layout/navbar/index.tsx index 90ec3f216..0863cfff3 100644 --- a/src/lib/layout/navbar/index.tsx +++ b/src/lib/layout/navbar/index.tsx @@ -150,10 +150,10 @@ const Navbar = observer(({ isExpand, setIsExpand }: NavbarProps) => { ]; useEffect(() => { - // Currently in basic mode and want to change from dev and nav is open -> should close + // Basic to dev and nav is collapse -> should exapnd if (isDevMode && !prevIsDevModeRef.current && !isExpand) { setIsExpand(true); - // Currently in dev mode and want to change to basic and nav is collapse -> should expand + // Dev to basic and nav is exapnd -> should collapse } else if (!isDevMode && prevIsDevModeRef.current && isExpand) { setIsExpand(false); } From c9c46d2d46b2e35408756b1f555b1f013980c8dd Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 14 Jul 2023 11:51:25 +0700 Subject: [PATCH 11/19] feat: add new home page --- CHANGELOG.md | 1 + .../pages/dev-home/components/QuickMenu.tsx | 174 ----------- .../dev-home/components/RecentActivities.tsx | 119 -------- src/lib/pages/dev-home/index.tsx | 25 -- src/lib/pages/home/components/DevShortcut.tsx | 114 ++++++++ .../pages/home/components/TopDecorations.tsx | 32 +++ src/lib/pages/home/components/index.ts | 2 + src/lib/pages/home/index.tsx | 270 +++++++++++++++++- src/lib/pages/network-overview/index.tsx | 237 --------------- src/pages/[network]/dev-home.tsx | 3 - src/pages/[network]/network-overview.tsx | 3 - src/pages/dev-home.tsx | 3 - src/pages/network-overview.tsx | 3 - 13 files changed, 417 insertions(+), 569 deletions(-) delete mode 100644 src/lib/pages/dev-home/components/QuickMenu.tsx delete mode 100644 src/lib/pages/dev-home/components/RecentActivities.tsx delete mode 100644 src/lib/pages/dev-home/index.tsx create mode 100644 src/lib/pages/home/components/DevShortcut.tsx create mode 100644 src/lib/pages/home/components/TopDecorations.tsx create mode 100644 src/lib/pages/home/components/index.ts delete mode 100644 src/lib/pages/network-overview/index.tsx delete mode 100644 src/pages/[network]/dev-home.tsx delete mode 100644 src/pages/[network]/network-overview.tsx delete mode 100644 src/pages/dev-home.tsx delete mode 100644 src/pages/network-overview.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 4200a9555..c4708d15f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Features +- [#438](https://github.com/alleslabs/celatone-frontend/pull/438) Add new home page - [#436](https://github.com/alleslabs/celatone-frontend/pull/436) Implement merge navigation ### Improvements diff --git a/src/lib/pages/dev-home/components/QuickMenu.tsx b/src/lib/pages/dev-home/components/QuickMenu.tsx deleted file mode 100644 index fa946b0be..000000000 --- a/src/lib/pages/dev-home/components/QuickMenu.tsx +++ /dev/null @@ -1,174 +0,0 @@ -import { Flex, Heading, Box, Text, SimpleGrid } from "@chakra-ui/react"; - -import { CURR_THEME } from "env"; -import { useMobile } from "lib/app-provider"; -import { AppLink } from "lib/components/AppLink"; -import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; -import { CustomIcon } from "lib/components/icon"; -import type { IconKeys } from "lib/components/icon"; - -const cardProps = { - width: "100%", - padding: "16px", - borderRadius: "8px", - justifyContent: "space-between", - height: "100%", -}; - -interface SecondaryMenuType { - title: string; - subtitle: string; - slug: string; - icon: IconKeys; -} - -const secondaryMenu: SecondaryMenuType[] = [ - { - title: "Query", - subtitle: "Query and get contract state data", - slug: "query", - icon: "query", - }, - { - title: "Execute", - subtitle: "Send transactions to contracts", - slug: "execute", - icon: "execute", - }, - { - title: "Migrate", - subtitle: "Migrate contract to new code ID", - slug: "migrate", - icon: "migrate", - }, - { - title: "Update Admin", - subtitle: "Change contract admin", - slug: "admin", - icon: "admin", - }, -]; - -export const QuickMenu = () => { - const isMobile = useMobile(); - return ( - - - Start using {CURR_THEME.branding.seo.appName} - - {!isMobile && ( - - )} - - {!isMobile && ( - - - - - - Deploy a new contract - - - Upload a new wasm code or instantiate a new contract - - - - - - - )} - - {secondaryMenu.map((item) => ( - <> - {!isMobile || item.slug === "query" ? ( - - - - - - - {item.title} - - - {item.subtitle} - - - - - - - ) : ( - - - - - - {item.title} - - - {item.subtitle} - - - - {/* - On Mobile Soon - */} - - )} - - ))} - - - {isMobile && ( - - Some features will available on mobile soon - - )} - - ); -}; diff --git a/src/lib/pages/dev-home/components/RecentActivities.tsx b/src/lib/pages/dev-home/components/RecentActivities.tsx deleted file mode 100644 index bc30d0c87..000000000 --- a/src/lib/pages/dev-home/components/RecentActivities.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Flex, Heading, Box, Text } from "@chakra-ui/react"; -import { observer } from "mobx-react-lite"; -import { useMemo } from "react"; - -import { useInternalNavigate } from "lib/app-provider"; -import { ExplorerLink } from "lib/components/ExplorerLink"; -import { CustomIcon } from "lib/components/icon"; -import { useUserKey } from "lib/hooks"; -import { useContractStore } from "lib/providers/store"; -import { dateFromNow } from "lib/utils"; - -export const RecentActivities = observer(() => { - const userKey = useUserKey(); - const { getRecentActivities, isHydrated } = useContractStore(); - const navigate = useInternalNavigate(); - - const activities = useMemo(() => { - return getRecentActivities(userKey); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [getRecentActivities, userKey, isHydrated]); - - return ( - - - Recent Queries and Executes on this device - - {activities.length ? ( - - {activities.map((item) => ( - - navigate({ - pathname: `/${item.type}`, - query: { contract: item.contractAddress, msg: item.msg }, - }) - } - > - - - - {item.type === "query" ? "Query" : "Execute"} - - - - - {item.action} - - - on - - - - - {dateFromNow(item.timestamp)} - {/* TODO - check address as me */} - {item.sender && ( - <> - by - - - )} - - - ))} - - ) : ( - - - Your recent interactions will display here. - - - )} - - ); -}); diff --git a/src/lib/pages/dev-home/index.tsx b/src/lib/pages/dev-home/index.tsx deleted file mode 100644 index 6f8a0d4fd..000000000 --- a/src/lib/pages/dev-home/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Box } from "@chakra-ui/react"; -import { useRouter } from "next/router"; -import { useEffect } from "react"; - -import { AmpEvent, AmpTrack } from "lib/services/amplitude"; - -import { QuickMenu } from "./components/QuickMenu"; -import { RecentActivities } from "./components/RecentActivities"; - -const DevHome = () => { - const router = useRouter(); - - useEffect(() => { - if (router.isReady) AmpTrack(AmpEvent.TO_OVERVIEW); - }, [router.isReady]); - - return ( - - - - - ); -}; - -export default DevHome; diff --git a/src/lib/pages/home/components/DevShortcut.tsx b/src/lib/pages/home/components/DevShortcut.tsx new file mode 100644 index 000000000..d0e66e36c --- /dev/null +++ b/src/lib/pages/home/components/DevShortcut.tsx @@ -0,0 +1,114 @@ +import type { SystemStyleObject } from "@chakra-ui/react"; +import { Flex, Box, Text, SimpleGrid } from "@chakra-ui/react"; + +import { useMobile } from "lib/app-provider"; +import { AppLink } from "lib/components/AppLink"; +import { CustomIcon } from "lib/components/icon"; +import type { IconKeys } from "lib/components/icon"; + +const cardProps: SystemStyleObject = { + width: "full", + height: "full", + padding: "16px", + borderRadius: "8px", + justifyContent: "space-between", + bg: "transparent", + alignItems: "center", + border: "2px solid", + borderColor: "gray.700", +}; + +interface ShortcutMetadata { + title: string; + subtitle: string; + slug: string; + icon: IconKeys; +} + +const shortcutList: ShortcutMetadata[] = [ + { + title: "Deploy", + subtitle: "Upload code or instantiate contract", + slug: "/deploy", + icon: "add-new", + }, + { + title: "Query", + subtitle: "Query and get contract state data", + slug: "query", + icon: "query", + }, + { + title: "Execute", + subtitle: "Send transactions to contracts", + slug: "execute", + icon: "execute", + }, +]; + +export const DevShortcut = () => { + const isMobile = useMobile(); + return ( + + {shortcutList.map((item) => ( + <> + {!isMobile || item.slug === "query" ? ( + + + + + + + {item.title} + + + {item.subtitle} + + + + + + + ) : ( + + + + + + {item.title} + + + {item.subtitle} + + + + {/* + On Mobile Soon + */} + + )} + + ))} + + ); +}; diff --git a/src/lib/pages/home/components/TopDecorations.tsx b/src/lib/pages/home/components/TopDecorations.tsx new file mode 100644 index 000000000..3df20078b --- /dev/null +++ b/src/lib/pages/home/components/TopDecorations.tsx @@ -0,0 +1,32 @@ +import { Image } from "@chakra-ui/react"; + +export const TopDecorations = ({ chain }: { chain: string }) => { + // Handle dedicated decorations for each chain + switch (chain) { + case "osmosis": + case "sei": + default: + return ( + <> + + + + ); + } +}; diff --git a/src/lib/pages/home/components/index.ts b/src/lib/pages/home/components/index.ts new file mode 100644 index 000000000..04a782376 --- /dev/null +++ b/src/lib/pages/home/components/index.ts @@ -0,0 +1,2 @@ +export * from "./DevShortcut"; +export * from "./TopDecorations"; diff --git a/src/lib/pages/home/index.tsx b/src/lib/pages/home/index.tsx index c622bab05..8f5ac6853 100644 --- a/src/lib/pages/home/index.tsx +++ b/src/lib/pages/home/index.tsx @@ -1,5 +1,271 @@ -import DevHome from "../dev-home"; +import type { SystemStyleObject } from "@chakra-ui/react"; +import { Box, Flex, Heading, Spinner, Text } from "@chakra-ui/react"; +import { useRouter } from "next/router"; +import { useEffect } from "react"; -const Home = () => ; +import { CURR_THEME } from "env"; +import { useCelatoneApp, useInternalNavigate } from "lib/app-provider"; +import { ConnectWalletAlert } from "lib/components/ConnectWalletAlert"; +import { CustomIcon } from "lib/components/icon"; +import PageContainer from "lib/components/PageContainer"; +import { ViewMore } from "lib/components/table"; +import { Tooltip } from "lib/components/Tooltip"; +import { useLocalStorage } from "lib/hooks/useLocalStorage"; +import { BlocksTable } from "lib/pages/blocks/components/BlocksTable"; +import { TxsTable } from "lib/pages/txs/components/TxsTable"; +import { AmpEvent, AmpTrack } from "lib/services/amplitude"; +import { + useAverageBlockTime, + useLatestBlockInfo, +} from "lib/services/blockService"; +import { useTxsCount } from "lib/services/txService"; +import type { Option } from "lib/types"; +import { dateFromNow, formatUTC } from "lib/utils"; + +import { DevShortcut, TopDecorations } from "./components"; + +const cardProps: SystemStyleObject = { + width: "100%", + padding: "16px", + borderRadius: "8px", + justifyContent: "space-between", + alignItems: "center", + height: "100%", + cursor: "pointer", + boxShadow: "0px 4px 1px 0px var(--chakra-colors-gray-700)", +}; + +const txInfo = { + title: "Total Transactions", + tooltip: + "Verified transactions track network activity and growth, indicating ecosystem health.", +}; + +const blockTimeInfo = { + title: "Average Block Time", + tooltip: "Average time to finality between the last 100 indexed blocks.", +}; + +const blockInfo = { + title: "Latest Block Height", + tooltip: + "Latest Block Height tracks transactions and network growth for a healthy blockchain ecosystem.", +}; + +const indexedBlockInfo = { + title: "Latest Indexed Block Height", + tooltip: "The latest block height indexed by the indexer.", +}; + +const getBlockInfo = (chain: string) => + chain === "sei" ? indexedBlockInfo : blockInfo; + +interface CardInfoProps { + title: string; + tooltip: string; + value: string; + isLoading: boolean; + navigate: () => void; +} +const CardInfo = ({ + title, + tooltip, + value, + isLoading, + navigate, +}: CardInfoProps) => ( + + + + + {title} + + + + + + + + {isLoading ? ( + + ) : ( + + {value} + + )} + + + +); + +const calculateAverageBlockTime = ( + latest: Option, + hundred: Option +) => { + if (!latest || !hundred) return "N/A"; + return `${((latest.getTime() - hundred.getTime()) / 100 / 1000) + .toFixed(3) + .toString()}s`; +}; + +const Home = () => { + const router = useRouter(); + const navigate = useInternalNavigate(); + const [isDevMode] = useLocalStorage("devMode", undefined); + + const { + chainConfig: { chain, prettyName }, + } = useCelatoneApp(); + const { + data: latestBlockInfo, + isLoading: isLoadingLatestBlockInfo, + error: latestBlockInfoError, + } = useLatestBlockInfo(); + const { data } = useAverageBlockTime(); + const averageBlockTime = calculateAverageBlockTime( + data?.latest, + data?.hundred + ); + const { data: txsCount, isLoading: isLoadingTxsCount } = useTxsCount(); + + const chainBlockInfo = getBlockInfo(chain); + + const toTxs = () => + navigate({ + pathname: "/txs", + }); + + const toBlocks = () => + navigate({ + pathname: "/blocks", + }); + + useEffect(() => { + if (router.isReady) AmpTrack(AmpEvent.TO_NETWORK_OVERVIEW); + }, [router.isReady]); + + return ( + + div": { zIndex: 1 } }} + > + + + + + {prettyName} + {" "} + Overview + + {isLoadingLatestBlockInfo ? ( + + + + Loading latest data for you ... + + + ) : ( + + {latestBlockInfoError + ? "Error updating ..." + : latestBlockInfo?.timestamp && + `Updated ${dateFromNow(latestBlockInfo.timestamp)} \n + ${formatUTC(latestBlockInfo.timestamp)}`} + + )} + + + + + + + + + {isDevMode && ( +
+ + + Dev Shortcuts + + + + +
+ )} + +
+ + Recent Transactions + + + {txsCount && txsCount > 5 && } +
+ +
+ + Recent Blocks + + + {latestBlockInfo?.height && latestBlockInfo.height > 5 && ( + + )} +
+
+ ); +}; export default Home; diff --git a/src/lib/pages/network-overview/index.tsx b/src/lib/pages/network-overview/index.tsx deleted file mode 100644 index 7da8671fe..000000000 --- a/src/lib/pages/network-overview/index.tsx +++ /dev/null @@ -1,237 +0,0 @@ -import { Box, Flex, Heading, Spinner, Text } from "@chakra-ui/react"; -import { useRouter } from "next/router"; -import { useEffect } from "react"; - -import { useCelatoneApp, useInternalNavigate } from "lib/app-provider"; -import { CustomIcon } from "lib/components/icon"; -import PageContainer from "lib/components/PageContainer"; -import { ViewMore } from "lib/components/table"; -import { Tooltip } from "lib/components/Tooltip"; -import { BlocksTable } from "lib/pages/blocks/components/BlocksTable"; -import { TxsTable } from "lib/pages/txs/components/TxsTable"; -import { AmpEvent, AmpTrack } from "lib/services/amplitude"; -import { - useAverageBlockTime, - useLatestBlockInfo, -} from "lib/services/blockService"; -import { useTxsCount } from "lib/services/txService"; -import type { Option } from "lib/types"; -import { dateFromNow, formatUTC } from "lib/utils"; - -const cardProps = { - width: "100%", - padding: "16px", - borderRadius: "8px", - justifyContent: "space-between", - alignItems: "center", - height: "100%", - cursor: "pointer", -}; - -const txInfo = { - title: "Total Transactions", - tooltip: - "Verified transactions track network activity and growth, indicating ecosystem health.", -}; - -const blockTimeInfo = { - title: "Average Block Time", - tooltip: "Average time to finality between the last 100 indexed blocks.", -}; - -const blockInfo = { - title: "Latest Block Height", - tooltip: - "Latest Block Height tracks transactions and network growth for a healthy blockchain ecosystem.", -}; - -const indexedBlockInfo = { - title: "Latest Indexed Block Height", - tooltip: "The latest block height indexed by the indexer.", -}; - -interface CardInfoProps { - title: string; - tooltip: string; - value: string; - isLoading: boolean; - navigate: () => void; -} -const CardInfo = ({ - title, - tooltip, - value, - isLoading, - navigate, -}: CardInfoProps) => ( - - - - - {title} - - - - - - - - {isLoading ? ( - - ) : ( - - {value} - - )} - - - -); - -const calculateAverageBlockTime = ( - latest: Option, - hundred: Option -) => { - if (!latest || !hundred) return "N/A"; - return `${((latest.getTime() - hundred.getTime()) / 100 / 1000) - .toFixed(3) - .toString()}s`; -}; - -const NetworkOverview = () => { - const router = useRouter(); - - const navigate = useInternalNavigate(); - - useEffect(() => { - if (router.isReady) AmpTrack(AmpEvent.TO_NETWORK_OVERVIEW); - }, [router.isReady]); - - const { - chainConfig: { chain }, - } = useCelatoneApp(); - const { - data: latestBlockInfo, - isLoading: isLoadingLatestBlockInfo, - error: latestBlockInfoError, - } = useLatestBlockInfo(); - const { data } = useAverageBlockTime(); - const averageBlockTime = calculateAverageBlockTime( - data?.latest, - data?.hundred - ); - const { data: txsCount, isLoading: isLoadingTxsCount } = useTxsCount(); - - const toTxs = () => - navigate({ - pathname: "/txs", - }); - - const toBlocks = () => - navigate({ - pathname: "/blocks", - }); - - return ( - - - - Network Overview - - {isLoadingLatestBlockInfo ? ( - - - - Loading latest data for you ... - - - ) : ( - - {latestBlockInfoError - ? "Error updating ..." - : latestBlockInfo?.timestamp && - `Updated ${dateFromNow(latestBlockInfo.timestamp)} \n - ${formatUTC(latestBlockInfo.timestamp)}`} - - )} - - - {chain === "sei" ? ( - - ) : ( - - )} - {chain === "sei" ? ( - - ) : ( - - )} - - - - Recent Transactions - - - {txsCount && txsCount > 5 && } - - - - - Recent Blocks - - - {latestBlockInfo?.height && latestBlockInfo.height > 5 && ( - - )} - - - ); -}; - -export default NetworkOverview; diff --git a/src/pages/[network]/dev-home.tsx b/src/pages/[network]/dev-home.tsx deleted file mode 100644 index 470983d5e..000000000 --- a/src/pages/[network]/dev-home.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import DevHome from "lib/pages/dev-home"; - -export default DevHome; diff --git a/src/pages/[network]/network-overview.tsx b/src/pages/[network]/network-overview.tsx deleted file mode 100644 index 5418255e4..000000000 --- a/src/pages/[network]/network-overview.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import NetworkOverview from "lib/pages/network-overview"; - -export default NetworkOverview; diff --git a/src/pages/dev-home.tsx b/src/pages/dev-home.tsx deleted file mode 100644 index 470983d5e..000000000 --- a/src/pages/dev-home.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import DevHome from "lib/pages/dev-home"; - -export default DevHome; diff --git a/src/pages/network-overview.tsx b/src/pages/network-overview.tsx deleted file mode 100644 index 5418255e4..000000000 --- a/src/pages/network-overview.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import NetworkOverview from "lib/pages/network-overview"; - -export default NetworkOverview; From b40aa24c67abd130935f6e2b603b08d63970fbad Mon Sep 17 00:00:00 2001 From: poomthiti Date: Fri, 14 Jul 2023 15:56:57 +0700 Subject: [PATCH 12/19] refactor: move illustration src to theme config --- src/config/theme/default.ts | 4 ++ src/config/theme/osmosis.ts | 4 ++ src/config/theme/sei.ts | 4 ++ src/config/theme/types.ts | 4 ++ src/lib/pages/home/components/DevShortcut.tsx | 3 - .../pages/home/components/TopDecorations.tsx | 55 +++++++++---------- src/lib/pages/home/index.tsx | 4 +- 7 files changed, 43 insertions(+), 35 deletions(-) diff --git a/src/config/theme/default.ts b/src/config/theme/default.ts index 0712e2671..f9fc1f074 100644 --- a/src/config/theme/default.ts +++ b/src/config/theme/default.ts @@ -117,6 +117,10 @@ export const DEFAULT_THEME: ThemeConfig = { "https://assets.alleslabs.dev/illustration/search-not-found.svg", searchEmpty: "https://assets.alleslabs.dev/illustration/search-empty.svg", disconnected: "https://assets.alleslabs.dev/illustration/disconnected.svg", + overview: { + main: "https://assets.alleslabs.dev/illustration/bg-left.svg", + secondary: "https://assets.alleslabs.dev/illustration/bg-right.svg", + }, }, socialMedia: { website: "https://celat.one/", diff --git a/src/config/theme/osmosis.ts b/src/config/theme/osmosis.ts index f10afd502..67de537ae 100644 --- a/src/config/theme/osmosis.ts +++ b/src/config/theme/osmosis.ts @@ -122,6 +122,10 @@ export const OSMOSIS_THEME: ThemeConfig = { "https://assets.alleslabs.dev/integrations/osmosis/illustration/search-empty.svg", disconnected: "https://assets.alleslabs.dev/integrations/osmosis/illustration/disconnected.svg", + overview: { + // Fill image url + main: "", + }, }, footer: { logo: "https://assets.alleslabs.dev/integrations/osmosis/logo.png", diff --git a/src/config/theme/sei.ts b/src/config/theme/sei.ts index 901dc85eb..b299570ae 100644 --- a/src/config/theme/sei.ts +++ b/src/config/theme/sei.ts @@ -134,6 +134,10 @@ export const SEI_THEME: ThemeConfig = { "https://assets.alleslabs.dev/integrations/sei/illustration/search-empty.svg", disconnected: "https://assets.alleslabs.dev/integrations/sei/illustration/disconnected.svg", + overview: { + // Fill image url + main: "", + }, }, footer: { logo: "https://www.sei.io/_next/static/media/logo-light.1249fa55.svg", diff --git a/src/config/theme/types.ts b/src/config/theme/types.ts index f09d4403f..c5c4682cc 100644 --- a/src/config/theme/types.ts +++ b/src/config/theme/types.ts @@ -127,6 +127,10 @@ export type ThemeConfig = { searchNotFound: string; searchEmpty: string; disconnected: string; + overview: { + main: string; + secondary?: string; + }; }; jsonTheme: "monokai" | "one_dark" | "pastel_on_dark"; footer?: { diff --git a/src/lib/pages/home/components/DevShortcut.tsx b/src/lib/pages/home/components/DevShortcut.tsx index d0e66e36c..b580cc2b0 100644 --- a/src/lib/pages/home/components/DevShortcut.tsx +++ b/src/lib/pages/home/components/DevShortcut.tsx @@ -102,9 +102,6 @@ export const DevShortcut = () => { - {/* - On Mobile Soon - */} )} diff --git a/src/lib/pages/home/components/TopDecorations.tsx b/src/lib/pages/home/components/TopDecorations.tsx index 3df20078b..46812cbe4 100644 --- a/src/lib/pages/home/components/TopDecorations.tsx +++ b/src/lib/pages/home/components/TopDecorations.tsx @@ -1,32 +1,27 @@ import { Image } from "@chakra-ui/react"; -export const TopDecorations = ({ chain }: { chain: string }) => { - // Handle dedicated decorations for each chain - switch (chain) { - case "osmosis": - case "sei": - default: - return ( - <> - - - - ); - } -}; +import { CURR_THEME } from "env"; + +// TODO: Handle different chains decoration rendering +export const TopDecorations = () => ( + <> + + + +); diff --git a/src/lib/pages/home/index.tsx b/src/lib/pages/home/index.tsx index 8f5ac6853..7324a9fd9 100644 --- a/src/lib/pages/home/index.tsx +++ b/src/lib/pages/home/index.tsx @@ -166,7 +166,7 @@ const Home = () => { overflow="hidden" sx={{ "& > div": { zIndex: 1 } }} > - + { {isDevMode && (
- + Dev Shortcuts Date: Fri, 14 Jul 2023 16:01:11 +0700 Subject: [PATCH 13/19] refactor: change prompt wording --- src/lib/layout/SubHeader.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/layout/SubHeader.tsx b/src/lib/layout/SubHeader.tsx index 8e3fa8f19..0a7550b3e 100644 --- a/src/lib/layout/SubHeader.tsx +++ b/src/lib/layout/SubHeader.tsx @@ -48,10 +48,10 @@ const FirstLandPrompt = ({ }, }} > -
Are you developers?
+
Looking for developer features?
- Try query, execute, or deploy contracts with our Dev Mode. You can change - it later anytime. + For quick access to our deploy, query, and other developer features, try + our Dev Mode. You can change it back at any time