From b0ca663c96a2d6e0045c0205d0ff344f40cb7fc0 Mon Sep 17 00:00:00 2001 From: Tomasz Awramski Date: Tue, 20 Feb 2024 14:29:30 +0100 Subject: [PATCH] refactor(gui): gui framework change from solid to react - changed gui framework to react because it is more common and more friendly for newcomers. - routing moved from src/pages/Pages to src/main, beside that only refactoring were made Signed-off-by: Tomasz Awramski --- packages/cacti-ledger-browser-react/README.md | 61 + .../cacti-ledger-browser-react/index.html | 16 + .../cacti-ledger-browser-react/package.json | 84 ++ .../AccountCard/AccountCard.module.css | 19 + .../components/AccountCard/AccountCard.tsx | 17 + .../components/BlockCard/BlockCard.module.css | 33 + .../src/components/BlockCard/BlockCard.tsx | 23 + .../CardWrapper/CardWrapper.module.css | 85 ++ .../components/CardWrapper/CardWrapper.tsx | 150 +++ .../src/components/Chart/Chart.module.css | 29 + .../src/components/Chart/Chart.tsx | 37 + .../src/components/Chart/LineChart.tsx | 79 ++ .../Pagination/Pagination.module.css | 51 + .../src/components/Pagination/Pagination.tsx | 63 + .../components/TokenHeader/TokenAccount.tsx | 18 + .../TokenHeader/TokenHeader.module.css | 57 + .../components/TokenHeader/TokenHeader.tsx | 51 + .../components/UI/Button/Button.module.css | 77 ++ .../src/components/UI/Button/Button.tsx | 22 + .../components/UI/CustomTable/CustomTable.css | 53 + .../UI/CustomTable/CustomTable.module.css | 137 +++ .../components/UI/CustomTable/CustomTable.tsx | 103 ++ .../EmptyTablePlaceholder.module.css | 7 + .../EmptyTablePlaceholder.tsx | 9 + .../src/components/UI/Menu/Menu.module.css | 22 + .../src/components/UI/Menu/Menu.tsx | 72 ++ .../components/UI/Search/Search.module.css | 43 + .../src/components/UI/Search/Search.tsx | 38 + .../components/UI/Select/Select.module.css | 73 ++ .../src/components/UI/Select/Select.tsx | 73 ++ .../cacti-ledger-browser-react/src/main.tsx | 266 +++++ .../pages/eth/Accounts/Accounts.module.css | 6 + .../src/pages/eth/Accounts/Accounts.tsx | 63 + .../src/pages/eth/Blocks/Blocks.module.css | 0 .../src/pages/eth/Blocks/Blocks.tsx | 59 + .../pages/eth/Dashboard/Dashboard.module.css | 10 + .../src/pages/eth/Dashboard/Dashboard.tsx | 98 ++ .../src/pages/eth/Details/BlockDetails.tsx | 67 ++ .../src/pages/eth/Details/Details.module.css | 32 + .../src/pages/eth/Details/TokenDetails.tsx | 65 + .../eth/Details/TokenTransactionDetails.tsx | 66 ++ .../pages/eth/Details/TransactionDetails.tsx | 100 ++ .../src/pages/eth/ERC20/ERC20.module.css | 19 + .../src/pages/eth/ERC20/ERC20.tsx | 73 ++ .../src/pages/eth/ERC721/ERC721.module.css | 18 + .../src/pages/eth/ERC721/ERC721.tsx | 114 ++ .../SingleTokenHistory.module.css | 12 + .../SingleTokenHistory/SingleTokenHistory.tsx | 137 +++ .../eth/Transactions/Transactions.module.css | 12 + .../pages/eth/Transactions/Transactions.tsx | 66 ++ .../BlocksFabric/BlocksFabric.module.css | 0 .../fabric/BlocksFabric/BlocksFabric.tsx | 62 + .../fabric/DashFabric/DashFabric.module.css | 11 + .../pages/fabric/DashFabric/DashFabric.tsx | 103 ++ .../fabric/FabricBlock/FabricBlock.module.css | 8 + .../pages/fabric/FabricBlock/FabricBlock.tsx | 74 ++ .../FabricTransaction.module.css | 22 + .../FabricTransaction/FabricTransaction.tsx | 138 +++ .../TransactionsFabric.module.css | 0 .../TransactionsFabric/TransactionsFabric.tsx | 59 + .../src/pages/shared/Home/Home.module.css | 22 + .../src/pages/shared/Home/Home.tsx | 16 + .../src/routes/Root.module.css | 12 + .../src/routes/Root.tsx | 20 + .../src/schema/supabase-types.ts | 103 ++ .../src/schema/token-standards.ts | 4 + .../src/supabase-client.tsx | 7 + .../src/vite-env.d.ts | 1 + .../cacti-ledger-browser-react/tsconfig.json | 25 + .../tsconfig.node.json | 10 + .../cacti-ledger-browser-react/vite.config.ts | 10 + yarn.lock | 1043 ++++++++++++++++- 72 files changed, 4607 insertions(+), 28 deletions(-) create mode 100644 packages/cacti-ledger-browser-react/README.md create mode 100644 packages/cacti-ledger-browser-react/index.html create mode 100644 packages/cacti-ledger-browser-react/package.json create mode 100644 packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/Chart/Chart.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/Chart/Chart.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/Chart/LineChart.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenAccount.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Button/Button.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Button/Button.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Search/Search.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Search/Search.tsx create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Select/Select.module.css create mode 100644 packages/cacti-ledger-browser-react/src/components/UI/Select/Select.tsx create mode 100644 packages/cacti-ledger-browser-react/src/main.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Details/BlockDetails.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Details/Details.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenDetails.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenTransactionDetails.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Details/TransactionDetails.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.tsx create mode 100644 packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.module.css create mode 100644 packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.tsx create mode 100644 packages/cacti-ledger-browser-react/src/routes/Root.module.css create mode 100644 packages/cacti-ledger-browser-react/src/routes/Root.tsx create mode 100644 packages/cacti-ledger-browser-react/src/schema/supabase-types.ts create mode 100644 packages/cacti-ledger-browser-react/src/schema/token-standards.ts create mode 100644 packages/cacti-ledger-browser-react/src/supabase-client.tsx create mode 100644 packages/cacti-ledger-browser-react/src/vite-env.d.ts create mode 100644 packages/cacti-ledger-browser-react/tsconfig.json create mode 100644 packages/cacti-ledger-browser-react/tsconfig.node.json create mode 100644 packages/cacti-ledger-browser-react/vite.config.ts diff --git a/packages/cacti-ledger-browser-react/README.md b/packages/cacti-ledger-browser-react/README.md new file mode 100644 index 0000000000..92d18af3bf --- /dev/null +++ b/packages/cacti-ledger-browser-react/README.md @@ -0,0 +1,61 @@ +# `@hyperledger/cacti-ledger-browser-react` + +This component allows viewing ledger data in Supabase or other postgreSQL compatible database. The data is fed to supabase by persistence plugins for each ledgers. + +## Summary + +- [`@hyperledger/cacti-ledger-browser`](#hyperledgercacti-gui-tx-viewer) + - [Summary](#summary) + - [Remarks](#remarks) + - [Getting Started](#getting-started) + - [Prerequisites using yarn](#prerequisites-using-yarn) + - [Alternative Prerequisites using npm](#alternative-prerequisites-using-npm) + - [Usage](#usage) + - [Contributing](#contributing) + - [License](#license) + - [Acknowledgments](#acknowledgments) + +## Remarks + +- Plugin requires running Supabase or other database and persistence plugins in order to properly view ledger data. +- Currently, fabric and ethereum based ledgers are supported. + +## Getting Started + +Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes. + +### Prerequisites using yarn + +In the root of the project, execute the command to install and build the dependencies. It will also build this GUI front-end component: + +```sh +yarn run build +``` +### Alternative Prerequisites using npm + +In the root of the project, execute the command to install and build the dependencies. It will also build this GUI front-end component: + +```sh +npm install +``` + +### Usage +- Run Supabase instance (see documentation for detailed instructions). For development purposes, you can use our image located in `tools/docker/supabase-all-in-one`. +- Run one or more persistence plugins: + - [Ethereum](../cacti-plugin-persistence-ethereum) + - [Fabric] (../cacti-plugin-persistence-fabric) +- Edit [Supabase configuration file](./src/supabase-client.tsx), set correct supabase API URL and service_role key. +- Execute `yarn run start` or `npm start` in this package directory. +- The running application address: http://localhost:3001/ (can be changed in [Vite configuration](./vite.config.ts)) + +## Contributing + +We welcome contributions to Hyperledger Cacti in many forms, and there’s always plenty to do! + +Please review [CONTIRBUTING.md](../../CONTRIBUTING.md) to get started. + +## License + +This distribution is published under the Apache License Version 2.0 found in the [LICENSE](../../LICENSE) file. + +## Acknowledgments \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/index.html b/packages/cacti-ledger-browser-react/index.html new file mode 100644 index 0000000000..d847393d78 --- /dev/null +++ b/packages/cacti-ledger-browser-react/index.html @@ -0,0 +1,16 @@ + + + + + + + + Cacti Ledger Browser + + + +
+ + + + \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/package.json b/packages/cacti-ledger-browser-react/package.json new file mode 100644 index 0000000000..fc2647ae88 --- /dev/null +++ b/packages/cacti-ledger-browser-react/package.json @@ -0,0 +1,84 @@ +{ + "name": "@hyperledger/cacti-ledger-browser-react", + "version": "2.0.0-alpha.2", + "description": "Cacti GUI for visualizing ledger data build on react.", + "keywords": [ + "Hyperledger", + "Cacti", + "Integration", + "Blockchain", + "Distributed Ledger Technology" + ], + "homepage": "https://github.com/hyperledger/cacti#readme", + "bugs": { + "url": "https://github.com/hyperledger/cacti/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/cacti.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Hyperledger Cacti Contributors", + "email": "cacti@lists.hyperledger.org", + "url": "https://www.hyperledger.org/use/cacti" + }, + "contributors": [ + { + "name": "Please add yourself to the list of contributors", + "email": "your.name@example.com", + "url": "https://example.com" + }, + { + "name": "Tomasz Awramski", + "email": "tomasz.awramski@fujitsu.com", + "url": "https://www.fujitsu.com/global/" + }, + { + "name": "Eryk Baranowski", + "email": "eryk.baranowski@fujitsu.com", + "url": "https://www.fujitsu.com/global/" + }, + { + "name": "Barnaba Pawelczak", + "email": "barnaba.pawelczak@fujitsu.com", + "url": "https://www.fujitsu.com/global/" + } + ], + "scripts": { + "build": "yarn run build:prod:frontend", + "build:dev:frontend": "vite build --mode=development", + "build:prod:frontend": "vite build", + "serve": "vite preview", + "start": "vite" + }, + "dependencies": { + "@emotion/react": "11.11.3", + "@emotion/styled": "11.11.0", + "@mui/icons-material": "5.15.10", + "@mui/material": "5.15.10", + "@supabase/supabase-js": "1.35.6", + "apexcharts": "3.45.2", + "localforage": "1.10.0", + "match-sorter": "6.3.3", + "moment": "2.30.1", + "react": "18.2.0", + "react-apexcharts": "1.4.1", + "react-dom": "18.2.0", + "react-router-dom": "6.21.3", + "sort-by": "1.2.0" + }, + "devDependencies": { + "@types/react": "18.2.43", + "@types/react-dom": "18.2.17", + "@types/sort-by": "1", + "@typescript-eslint/eslint-plugin": "6.14.0", + "@typescript-eslint/parser": "6.14.0", + "@vitejs/plugin-react": "4.2.1", + "eslint": "8.55.0", + "eslint-plugin-react-hooks": "4.6.0", + "eslint-plugin-react-refresh": "0.4.5", + "typescript": "5.2.2", + "vite": "5.0.8" + } +} diff --git a/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.module.css b/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.module.css new file mode 100644 index 0000000000..45da5dea56 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.module.css @@ -0,0 +1,19 @@ +.card { + display: flex; + justify-content: center; + background-color: rgb(252, 249, 249); + align-items: center; + height: 5rem; + padding: 0 2rem; + margin-top: 5px; + border-radius: 10px; + border: .5px solid rgb(224, 228, 224); + width: 35rem; + font-size: 18px; +} + +.card:hover { + cursor: pointer; + background-color: #ffffff; + border:1px solid rgb(39, 153, 39); +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.tsx b/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.tsx new file mode 100644 index 0000000000..b63876faf1 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/AccountCard/AccountCard.tsx @@ -0,0 +1,17 @@ +import { useNavigate, useParams } from "react-router-dom"; +import styles from "./AccountCard.module.css"; + +function AccountCard(props) { + const params = useParams(); + const navigate = useNavigate(); + const handleClick = () => { + navigate(`/${params.standard}/${props.address}`); + }; + return ( +
+ {props.address} +
+ ); +} + +export default AccountCard; diff --git a/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.module.css b/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.module.css new file mode 100644 index 0000000000..3e90ee76fa --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.module.css @@ -0,0 +1,33 @@ +.block-card { + display: flex; + gap: 1rem; + background-color: rgb(252, 249, 249); + height: 5rem; + align-items: center; + justify-content: space-around; + width: 100%; + padding: 1rem 0rem; + margin-top: 5px; + border-radius: 10px; + border: .5px solid rgb(242, 245, 242); + max-height: 100vh; + font-size: 14px; +} + +.block-card:hover { + cursor: pointer; + background-color: #ffffff; +} + +.block-num { + color: rgb(12, 105, 12); +} + +.block-hash { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: min-content; + max-width: 50%; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.tsx b/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.tsx new file mode 100644 index 0000000000..d21e95d3a1 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/BlockCard/BlockCard.tsx @@ -0,0 +1,23 @@ +import TagIcon from "@mui/icons-material/Tag"; + +import styles from "./BlockCard.module.css"; +import { useNavigate } from "react-router-dom"; + +function BlockCard(props) { + const navigate = useNavigate(); + const handleClick = () => { + navigate(`/blockDetails/${props.number}`); + }; + + return ( +
+

{props.created_at.toLocaleString()}

+

{props.number}

+

+ {props.hash} +

+
+ ); +} + +export default BlockCard; diff --git a/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.module.css b/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.module.css new file mode 100644 index 0000000000..d20ba47158 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.module.css @@ -0,0 +1,85 @@ +.wrapper { + background-color: rgb(253, 253, 253); + padding: 1rem; + border-radius: 10px; + border: 1px solid rgb(233, 236, 233); + height: fit-content; +} + +.wrapper-half-width { + width: 50%; +} + +.wrapper-full-width { + width: 100%; +} + +.wrapper-cards { + width: 100%; + display: flex; + justify-content: center; + padding: 1rem; +} + +.wrapper-title { + margin-top: .5rem; + display: flex; + gap:5px; + align-items: center; + font-weight: 700; + font-size: 1.2rem; + color: rgb(9, 75, 9); +} + +.wrapper-btns { + display: flex; + justify-content: flex-end; + padding-right: 1rem; +} + +.wrapper-header { + width: 100%; + display: flex; + justify-content: space-between; + padding: 0 1rem; +} + +.wrapper-columns { + display: flex; + justify-content: space-around; + background-color: rgb(243, 239, 239); + align-items: center; + border-radius: 10px; + border: 1px solid rgb(233, 236, 233); + height: 50px; +} + +.wrapper-columns span { + display: flex; + width: 150px; +} + +.wrapper-search { + display: flex; + gap: 5px; +} + +@media (max-width: 1699px) { + .wrapper { + width: 100%; + } + + .wrapper-header { + padding-left: 0; + padding-right: 0; + } + + .wrapper-cards { + flex-direction: column; + padding: 1rem 0; + } + + .wrapper-title svg { + margin-bottom: -3px; + } +} diff --git a/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.tsx b/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.tsx new file mode 100644 index 0000000000..d4f714dca6 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/CardWrapper/CardWrapper.tsx @@ -0,0 +1,150 @@ +import Button from "../UI/Button/Button"; +import Search from "../UI/Search/Search"; + +import CustomTable from "../UI/CustomTable/CustomTable"; +import { TableProps } from "../../schema/supabase-types"; +import Pagination from "../Pagination/Pagination"; +import EmptyTablePlaceholder from "../UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder"; +import styles from "./CardWrapper.module.css"; + +import { useLocation, useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; + +const pageSize: number = 6; + +function CardWrapper(props) { + const location = useLocation(); + const path = location.pathname.split("/"); + const navigate = useNavigate(); + const [searchKey, setSearchKey] = useState(""); + let filteredData = props.data; + const [paginatedData, setPaginatedData] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + const [viewport, setViewport] = useState(""); + + const handleGoToPage = (pageNumber: number) => { + if (pageNumber < 1 || pageNumber > totalPages) return; + setCurrentPage(pageNumber); + }; + + const handleNextPage = () => { + if (currentPage === totalPages) return; + setCurrentPage((prev) => prev + 1); + }; + + const handlePrevPage = () => { + if (currentPage === 1) return; + setCurrentPage((prev) => prev - 1); + }; + + const filterData = () => { + const { filters, data } = props; + if (searchKey.length === 0) { + filteredData = data; + return; + } + const newData = data.filter((row) => { + let isMatch: boolean = false; + filters?.forEach((property: string | number) => { + if (row[property]?.toString().toLowerCase().includes(searchKey)) { + isMatch = true; + } + }); + return isMatch; + }); + filteredData = newData; + }; + + const handleSearch = () => { + filterData(); + if (props.getSearchValue) { + props.getSearchValue(searchKey); + } + }; + + useEffect(() => { + const screenResized = () => + setViewport(window.innerWidth <= 1699 ? "small" : "wide"); + screenResized(); + window.addEventListener("resize", screenResized, true); + return () => { + window.removeEventListener("resize", screenResized, true); + }; + }, []); + + useEffect(() => { + if (filteredData.length <= pageSize) { + setPaginatedData(filteredData); + } else { + const firstEl = currentPage * pageSize - pageSize; + setPaginatedData(filteredData.slice(firstEl, firstEl + pageSize)); + } + }, [currentPage, filteredData]); + + useEffect(() => { + const pageNum = Math.ceil(filteredData.length / pageSize); + setTotalPages(pageNum); + }, [filteredData]); + + return ( +
+
+ {props.title} + {props.trimmed && viewport === "small" && ( + + )} + {props.filters && ( +
+ setSearchKey(e)} + type="text" + placeholder="Type to search" + /> + +
+ )} +
+
+ {props?.columns && props.data?.length > 0 && ( + + )} + {props?.data?.length === 0 && } +
+
+ {" "} + {props.trimmed && viewport === "wide" && ( + + )} +
+ + {!props.trimmed && ( + + )} +
+ ); +} + +export default CardWrapper; diff --git a/packages/cacti-ledger-browser-react/src/components/Chart/Chart.module.css b/packages/cacti-ledger-browser-react/src/components/Chart/Chart.module.css new file mode 100644 index 0000000000..be4a07ddb5 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/Chart/Chart.module.css @@ -0,0 +1,29 @@ +.chart-wrapper { + width: 100%; + height:fit-content; + display: flex; + flex-direction: column; + gap: 1rem; + justify-content: center; + align-items: center; + background-color: rgb(253, 253, 253); + border-radius: 10px; + border: 1px solid rgb(238, 238, 238); +} + +.chart-wrapper > span { + margin-top: 1rem; + font-size: 24px; +} + +.chart-wrapper-line{ + padding:1rem; + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: rgb(253, 253, 253); + border-radius: 10px; + border: 1px solid rgb(238, 238, 238); +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/Chart/Chart.tsx b/packages/cacti-ledger-browser-react/src/components/Chart/Chart.tsx new file mode 100644 index 0000000000..d93dad5c1f --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/Chart/Chart.tsx @@ -0,0 +1,37 @@ +import Chart from "react-apexcharts"; +import { ERC20Txn } from "../../schema/supabase-types"; + +import styles from "./Chart.module.css"; + +function ApexChart(props) { + const chartProps = { + options: { + chart: { + id: "chart-example", + }, + xaxis: { + categories: props.chartData?.map((txn: ERC20Txn) => txn.token_address), + }, + }, + series: [ + { + name: "balance", + data: props.chartData?.map((txn: ERC20Txn) => txn.balance), + }, + ], + }; + + console.log(chartProps.options); + return ( +
+ +
+ ); +} + +export default ApexChart; diff --git a/packages/cacti-ledger-browser-react/src/components/Chart/LineChart.tsx b/packages/cacti-ledger-browser-react/src/components/Chart/LineChart.tsx new file mode 100644 index 0000000000..701c1cae76 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/Chart/LineChart.tsx @@ -0,0 +1,79 @@ +import Chart from "react-apexcharts"; +import moment from "moment"; +import { balanceDate } from "../../schema/supabase-types"; +import styles from "./Chart.module.css"; +import { useEffect, useState } from "react"; + +function LineChart(props) { + const [chartProps, setChartProps] = useState({ + series: { + list: [ + { + name: "balance", + data: [], + }, + ], + }, + options: { + chart: { + id: "chart-example", + }, + xaxis: { + categories: [], + }, + }, + }); + + useEffect(() => { + const { chartData } = props; + + setChartProps({ + options: { + chart: { + id: "chart-example", + }, + stroke: { + curve: "stepline", + }, + tooltip: { + x: { + show: true, + format: "dd MM yyyy h:mm", + formatter: undefined, + }, + }, + xaxis: { + type: "datetime", + categories: chartData?.map((txn: balanceDate) => + moment(txn.created_at).format("YYYY-MM-DD h:mm:ss a"), + ), + labels: { + format: "dd MM yyyy h:mm", + }, + }, + }, + series: { + list: [ + { + name: "balance", + data: chartData?.map((txn: balanceDate) => txn.balance), + }, + ], + }, + }); + }); + + return ( +
+ +
+ ); +} + +export default LineChart; diff --git a/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.module.css b/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.module.css new file mode 100644 index 0000000000..0632e5e845 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.module.css @@ -0,0 +1,51 @@ +.pagination { + width: 100%; + padding: 1rem; + justify-content: flex-end; + display: flex; + align-items: center; + gap: 10px; +} + +.pagination-counter { + height: 2.5rem; + display: flex; + align-items: center; + padding: 0 1rem; + border-radius: 10px; + border: 1px solid rgb(204, 206, 205); +} + +.pagination-jump { + display: flex; + gap: 10px; + padding: 9px 1rem; + background-color: rgb(233, 229, 229); + border-radius: 10px; +} + +input { + border-radius: 10px; + border: 1px solid rgb(54, 51, 224); + padding: 0 0.5rem; + width: 7rem; + text-align: center; + font-size: 1rem; +} + +@media (max-width: 1699px) { + .pagination { + padding: 0; + justify-content: center; + position: relative; + } + + .pagination button { + min-width: 85px; + } + + .pagination-jump { + position: absolute; + top: 2.75rem; + } +} diff --git a/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.tsx b/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.tsx new file mode 100644 index 0000000000..b7a742d90c --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/Pagination/Pagination.tsx @@ -0,0 +1,63 @@ +import { useState } from "react"; +import Button from "../UI/Button/Button"; +import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft"; +import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight"; +import KeyboardDoubleArrowLeftIcon from "@mui/icons-material/KeyboardDoubleArrowLeft"; +import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight"; +import styles from "./Pagination.module.css"; + +type pagination = { + current: number; + total: number; + goToPage: (pageNumber: number) => void; + goNextPage: () => void; + goPrevPage: () => void; +}; + +function Pagination(props) { + let inputRef: any; + const getInputValue = () => + inputRef?.value ? inputRef.value : props.current; + const [goToPageVisible, setGoToPageVisible] = useState(false); + + return ( +
+ + + + {goToPageVisible === true && ( +
+ + +
+ )} + + +
+ ); +} + +export default Pagination; diff --git a/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenAccount.tsx b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenAccount.tsx new file mode 100644 index 0000000000..0400b16cfc --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenAccount.tsx @@ -0,0 +1,18 @@ +import styles from "./TokenHeader.module.css"; +import AccountBalanceWalletIcon from "@mui/icons-material/AccountBalanceWallet"; + +function TokenAccount(props) { + return ( +
+ + {" "} + + + {" "} + {props.accountNum} + +
+ ); +} + +export default TokenAccount; diff --git a/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.module.css b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.module.css new file mode 100644 index 0000000000..2d9ef9600c --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.module.css @@ -0,0 +1,57 @@ +.token-header { + display: flex; + flex-direction: column; + width: 100%; + gap: 1rem; +} + +.token-details { + width: 100%; + height: min-content; + border: 1px solid rgb(240, 236, 236); + border-radius: 10px; + gap: 3rem; + padding: 1rem 2rem; + display: flex; + justify-content: flex-start; + align-items: center; + background-color: rgb(247, 245, 245); +} + +.token-details div { + display: flex; + align-items: center; + gap: 1rem; +} + +.token-icon { + height: 100%; + transform: translateY(10%); + color: rgb(34, 70, 70); +} + +.token-account { + font-size: 16px; + width: 100%; + height: min-content; + display: flex; + align-items: center; + justify-content: center; + background-color: rgb(247, 245, 245); + border-radius: 10px; + padding: 1rem; + padding-left: 2rem; +} + +.token-account span { + display: flex; + align-items: center; + gap: .5rem; +} + +.token-account-icon { + color: rgb(22, 92, 65); + font-size: 28px; + height: 30px; + width: 30px; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.tsx b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.tsx new file mode 100644 index 0000000000..d47c124ff8 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/TokenHeader/TokenHeader.tsx @@ -0,0 +1,51 @@ +import TokenAccount from "./TokenAccount"; +import { TokenMetadata20 } from "../../schema/supabase-types"; +import { supabase } from "../../supabase-client"; + +import styles from "./TokenHeader.module.css"; +import { useEffect, useState } from "react"; + +function TokenHeader(props) { + const [tokenData, setTokenData] = useState(); + + const fetchData = async () => { + try { + const { data } = await supabase + .from(`token_metadata_erc20`) + .select("*") + .match({ address: props.token_address }); + console.log(data); + if (data?.[0]) { + setTokenData(data[0]); + } else { + throw new Error("Failed to load token details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchData(); + }, []); + + return ( +
+ +
+

+ Address: {props.token_address} +

+

+ Created at: {tokenData?.created_at} +

+

+ Total supply: + {tokenData?.total_supply} +

+
+
+ ); +} + +export default TokenHeader; diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.module.css b/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.module.css new file mode 100644 index 0000000000..eab9eabd84 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.module.css @@ -0,0 +1,77 @@ +.button { + color: rgb(14, 48, 23); + background-color: rgb(248, 248, 250); + height: 2.5rem; + display: flex; + align-items: center; + justify-content: center; + width: max-content; + min-width: 100px; + padding: 10px; + border: 1px solid rgb(32, 133, 77); + font-family: 'Roboto'; + border-radius: 10px; +} + +.button:hover { + background-color: rgb(219, 219, 224); + transform: scale(1.01); + cursor: pointer; +} + +.button-primary { + background-color: rgb(244, 247, 245); + color:rgb(14, 44, 14); + border-radius: 5px; + width:150px; +} + +.button-primary:hover { background-color: rgb(226, 253, 219);} + +.button-warn { background-color: rgb(155, 22, 13);} + +.button-warn:hover { background-color: rgb(114, 22, 16);} + +.button-menu{ + border:none; + background: transparent; + height: 100%; + transition: background-color 0.5s ease-out; + position:relative; + border-radius: 0; + +} +.button-menu:hover{ +color:rgb(0, 0, 0); +background-color: rgb(243, 242, 242); +} +.button-menu:hover:after { + content: ''; + display: block; + position: absolute; + left: 0; + right: 0; + bottom: 1px; + width: 100%; + height: 1px; + border-bottom: 2px solid green; + +} + +.button-link { + background: transparent; + border:none; + height: min-content; + color:rgb(64, 64, 228); +} + +.button-link:hover{ + background: transparent; + color:rgb(78, 78, 236); +} + +@media (max-width: 1699px) { + .button-primary { + font-size: 1rem; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.tsx b/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.tsx new file mode 100644 index 0000000000..ec1c40d5f0 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Button/Button.tsx @@ -0,0 +1,22 @@ +import styles from "./Button.module.css"; + +function Button(props) { + type ObjectKey = keyof typeof styles; + const buttonTypeStyle = `button-${props.type}` as ObjectKey; + + const handleClick = (e: MouseEvent) => { + e.stopPropagation(); + props.onClick(); + }; + + return ( + + ); +} + +export default Button; diff --git a/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.css b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.css new file mode 100644 index 0000000000..d94c8789f0 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.css @@ -0,0 +1,53 @@ +table { + border-collapse: separate; + border-spacing: 0; + width: 100%; + } + + tbody tr { + background-color: rgb(248, 248, 248); + border: 1px solid rgb(219, 241, 232); + border-radius: 10px; + } + + tbody tr:hover { + cursor: pointer; + background-color: rgb(235, 240, 237); + } + + th { + background-color: rgb(240, 235, 235); + border-style: none; + border-bottom: solid 1px rgb(223, 218, 218); + padding: 10px; + } + + td { + min-height: 2rem; + border-style: none; + border-bottom: solid 4px rgb(255, 255, 255); + padding: 1.5rem .5rem; + text-align: center; + } + + tr { + min-height: 20rem; + background-color: rgb(90, 103, 116); + padding: 1rem; + } + + tr:first-child th:first-child { + border-top-left-radius: 10px; + } + + tr:first-child th:last-child { + border-top-right-radius: 10px; + } + + tr:last-child td:first-child { + border-bottom-left-radius: 10px; + } + + tr:last-child td:last-child { + border-bottom-right-radius: 10px; + } \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.module.css b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.module.css new file mode 100644 index 0000000000..306f13ac57 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.module.css @@ -0,0 +1,137 @@ +table { + border-collapse: separate; + border-spacing: 0; + width: 100%; +} + +tbody tr { + background-color: rgb(248, 248, 248); + border: 1px solid rgb(219, 241, 232); + border-radius: 10px; +} + +tbody tr:hover { + cursor: pointer; + background-color: rgb(235, 240, 237); +} + +th { + background-color: rgb(240, 235, 235); + border-style: none; + border-bottom: solid 1px rgb(155, 153, 153); + padding: 10px; +} + +td { + min-height: 2rem; + border-style: none; + border-bottom: solid 2px rgb(255, 255, 255); + padding: 1.5rem 0.5rem; + text-align: center; +} + +tr { + min-height: 20rem; + background-color: rgb(90, 103, 116); + padding: 1rem; +} + +tr:first-child th:first-child { + border-top-left-radius: 10px; +} + +tr:first-child th:last-child { + border-top-right-radius: 10px; +} + +tr:last-child td:first-child { + border-bottom-left-radius: 10px; +} + +tr:last-child td:last-child { + border-bottom-right-radius: 10px; +} + +@media (max-width: 1699px) { + table { + width: 100%; + margin-bottom: 0.75rem; + table-layout: fixed; + } + + table:hover td:nth-child(even) { + cursor: pointer; + background-color: rgb(235, 240, 237); + } + + td { + position: relative; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + padding: 0.75rem; + } + + .table-rwd { + border: solid 1px rgb(223, 218, 218); + overflow: hidden; + } + + .table-rwd td { + border-bottom: solid 2px rgb(253, 253, 253); + } + + .table-rwd-heading { + background-color: rgb(240, 235, 235); + border-style: none; + padding: 0.5rem; + width: 140px; + font-weight: 700; + font-size: 0.9rem; + border-right: solid 1px rgb(223, 218, 218); + } + + .table-rwd:first-child { + border-top-left-radius: 10px; + } + + .table-rwd:first-child { + border-top-right-radius: 10px; + } + + .table-rwd:last-child { + border-bottom-left-radius: 10px; + } + + .table-rwd:last-child { + border-bottom-right-radius: 10px; + } + + .table-rwd tr:last-child > td:nth-last-of-type(2) { + border-bottom: 0; + } + + .table-rwd tr:last-child > td:last-of-type { + border-bottom: 0; + } + + .table-rwd td:last-child { + text-align: left; + } + + tr:first-child th:first-child { + border-top-left-radius: 0; + } + + tr:first-child th:last-child { + border-top-right-radius: 0; + } + + tr:last-child td:first-child { + border-bottom-left-radius: 0; + } + + tr:last-child td:last-child { + border-bottom-right-radius: 0; + } +} diff --git a/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.tsx b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.tsx new file mode 100644 index 0000000000..d378d87bc1 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/CustomTable.tsx @@ -0,0 +1,103 @@ +import { TableProperty } from "../../../schema/supabase-types"; + +import EmptyTablePlaceholder from "./EmptyTablePlaceholder/EmptyTablePlaceholder"; +import styles from "./CustomTable.module.css"; +import { useEffect, useState } from "react"; + +function CustomTable(props) { + const [viewport, setViewport] = useState(""); + + useEffect(() => { + const screenResized = () => + setViewport(window.innerWidth <= 1699 ? "small" : "wide"); + screenResized(); + window.addEventListener("resize", screenResized, true); + return () => { + window.removeEventListener("resize", screenResized, true); + }; + }, [viewport]); + + const getObjPropVal = (objProp: string[], row: any) => { + if (objProp.length === 1) return row[objProp[0]]; + else { + return objProp.map((prop) => ( + <> + {row[prop]} +

+ + )); + } + }; + + const handleRowClick = (row: any) => { + props.cols.onClick.action(row[props.cols.onClick.prop]); + }; + + return ( + <> + {props.data.length === 0 ? ( + + ) : ( + <> + {viewport === "wide" && ( + + + + {props.cols.schema.map((col) => ( + + ))} + + + + {props.data.map((row) => { + return ( + + {props.cols.schema.map((col: TableProperty) => ( + + ))} + + ); + })} + +
{col.display}
handleRowClick(row)}> + {getObjPropVal(col.objProp, row)} +
+ )} + + {viewport === "small" && ( + <> + {props.data.map((row) => { + return ( + handleRowClick(row)} + > + + {props.cols.schema.map((heading, idx) => { + return ( + + + + + ); + })} + +
+ {heading.display} + + {getObjPropVal( + props.cols.schema[idx].objProp, + row, + )} +
+ ); + })} + + )} + + )} + + ); +} + +export default CustomTable; diff --git a/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.module.css b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.module.css new file mode 100644 index 0000000000..8d9bbfa661 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.module.css @@ -0,0 +1,7 @@ +.placeholder-container { + display: flex; + justify-content: center; + font-size: 2rem; + font-weight: bold; + color: rgb(9, 75, 9); +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.tsx b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.tsx new file mode 100644 index 0000000000..f788bcd3ab --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder.tsx @@ -0,0 +1,9 @@ +import styles from "./EmptyTablePlaceholder.module.css"; + +function EmptyTablePlaceholder() { + return ( +
No data available
+ ); +} + +export default EmptyTablePlaceholder; diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.module.css b/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.module.css new file mode 100644 index 0000000000..ab9a7591e0 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.module.css @@ -0,0 +1,22 @@ +.nav-bar{ + width: 100%; + display: flex; + justify-content: flex-start; + padding-left: 8rem; + height: 4rem; + background-color: rgb(180, 218, 167); + align-items: center; + gap: 2rem; +} + +.navigation { + height: 100%; + display: flex; + gap: 1rem; +} + +@media (max-width: 1699px) { + .nav-bar{ + padding-left: 1rem; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.tsx b/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.tsx new file mode 100644 index 0000000000..a9af5fd10d --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Menu/Menu.tsx @@ -0,0 +1,72 @@ +import { useEffect, useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; +import Select from "../Select/Select"; +import styles from "./Menu.module.css"; +import Button from "../Button/Button"; + +const ledgersPaths = { + eth: [ + { title: "DASHBOARD", path: "/eth/dashboard" }, + { title: "ERC20", path: "/eth/accounts/erc20" }, + { title: "NFT ERC721", path: "/eth/accounts/erc721" }, + ], + fabric: [{ title: "DASHBOARD", path: "/fabric/dashboard", basePath: "/eth" }], +}; + +function Menu() { + const navigate = useNavigate(); + const location = useLocation(); + + const [activeLedger, setActiveLedger] = useState(""); + const handleSelect = (selectedValue: string) => { + setActiveLedger(selectedValue); + + navigate(`/${selectedValue}/dashboard`); + }; + + const updateLedgers = () => { + if (activeLedger.length > 0) return; + const currentPath = location.pathname; + const ledgers = ["eth", "fabric"]; + + ledgers.forEach((ledger) => { + if (currentPath.includes(ledger)) { + setActiveLedger(ledger); + } + }); + }; + + useEffect(() => { + updateLedgers(); + }); + + function activeLedgerItems(ledger: any) { + const items = ledger.map(function (path: any) { + return ( + + ); + }); + return items; + } + + return ( +
+ handleInput(e)} + onPaste={(e) => handleInput(e)} + /> + +
+ ); +} + +export default Search; diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.module.css b/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.module.css new file mode 100644 index 0000000000..19e2f837af --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.module.css @@ -0,0 +1,73 @@ +.select-wrapper { + height: 2.2rem; + width: 13rem; +} + +.select { + width: 100%; + height: 100%; + display: flex; +} + +.select-icon { + position: relative; + right: 30px; + height: 10px; + width: 10px; + transform: translateY(-50%) rotate(45deg); + pointer-events: none; +} + +.select-icon-up { + top: 60%; + border-top: 2px solid rgb(32, 133, 77); + border-left: 2px solid rgb(32, 133, 77); +} + +.select-icon-down { + top: 40%; + border-bottom: 2px solid rgb(32, 133, 77); + border-right: 2px solid rgb(32, 133, 77); +} + +.select-input { + width: 100%; + height: 100%; + font-family: "Roboto"; + font-size: 1rem; + color: rgb(102, 117, 106); + background-color: rgb(248, 248, 250); + border: 1px solid rgb(32, 133, 77); + border-radius: 10px; + cursor: pointer; + text-align: start; +} + +.select-input:hover { + background-color: rgb(235, 240, 237); +} + +.options-container { + z-index: 1000; + width: 100%; + position: relative; + overflow-y: auto; + border: 1px solid rgb(32, 133, 77); + border-radius: 10px; + color: rgb(102, 117, 106); + background: white; + cursor: pointer; +} + +.option { + padding: 5px; +} + +.selected-option { + padding: 5px; + background-color: rgb(235, 240, 237); +} + +.option:hover { + background-color: rgb(235, 240, 237); +} diff --git a/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.tsx b/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.tsx new file mode 100644 index 0000000000..122bc55f81 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/components/UI/Select/Select.tsx @@ -0,0 +1,73 @@ +import { useLocation } from "react-router-dom"; +import styles from "./Select.module.css"; +import { useState } from "react"; + +const options = [ + { value: "", display: "Select the ledger" }, + { value: "eth", display: "Ethereum" }, + { value: "fabric", display: "Fabric" }, +]; + +function Select(props) { + const selectStartLedgerByUrl = (path: string) => + options.find((option) => option.value === path); + + const [dropdownVisible, setDropdownVisible] = useState(false); + const startLocation = useLocation().pathname.split("/")[1]; + const [selectedOption, setSelectedOption] = useState( + selectStartLedgerByUrl(startLocation) || options[0], + ); + + const selectOption = (item: any) => { + setSelectedOption(item); + props.onSelect(item.value); + setDropdownVisible(false); + }; + + return ( +
+
setDropdownVisible(!dropdownVisible)} + > + setDropdownVisible(true)} + onBlur={() => setDropdownVisible(false)} + className={styles["select-input"]} + /> +
+
+ {dropdownVisible ? ( +
+ {options.map(function (item) { + return ( +
selectOption(item)} + > + {item.display} +
+ ); + })} +
+ ) : null} +
+ ); +} + +export default Select; diff --git a/packages/cacti-ledger-browser-react/src/main.tsx b/packages/cacti-ledger-browser-react/src/main.tsx new file mode 100644 index 0000000000..79702c6575 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/main.tsx @@ -0,0 +1,266 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { createBrowserRouter, Outlet, RouterProvider } from "react-router-dom"; +import Root from "./routes/Root.tsx"; +import Dashboard from "./pages/eth/Dashboard/Dashboard.tsx"; + +import Blocks from "./pages/eth/Blocks/Blocks.tsx"; +import Transactions from "./pages/eth/Transactions/Transactions.tsx"; +import Accounts from "./pages/eth/Accounts/Accounts.tsx"; +import BlockDetails from "./pages/eth/Details/BlockDetails.tsx"; +import TokenTransactionDetails from "./pages/eth/Details/TokenTransactionDetails.tsx"; +import TokenDetails from "./pages/eth/Details/TokenDetails.tsx"; +import TransactionDetails from "./pages/eth/Details/TransactionDetails.tsx"; +import ERC20 from "./pages/eth/ERC20/ERC20.tsx"; +import SingleTokenHistory from "./pages/eth/SingleTokenHistory/SingleTokenHistory.tsx"; +import ERC721 from "./pages/eth/ERC721/ERC721.tsx"; +import TransactionsFabric from "./pages/fabric/TransactionsFabric/TransactionsFabric.tsx"; +import DashFabric from "./pages/fabric/DashFabric/DashFabric.tsx"; +import BlocksFabric from "./pages/fabric/BlocksFabric/BlocksFabric.tsx"; +import FabricTransaction from "./pages/fabric/FabricTransaction/FabricTransaction.tsx"; +import FabricBlock from "./pages/fabric/FabricBlock/FabricBlock.tsx"; + +const router = createBrowserRouter([ + { + path: "/", + element: , + children: [ + { + path: "eth", + element: ( +
+ +
+ ), + children: [ + // MAIN + { path: "dashboard", element: }, + { + path: "blocks", + element: ( +
+ blocks + +
+ ), + }, + { + path: "transactions", + element: ( +
+ transactions + +
+ ), + }, + // ACCOUNTS + { + path: "accounts", + element: , + children: [ + { + path: ":standard", + element: ( +
+ +
+ ), + }, + ], + }, + //BLOCK + { + path: "block-details", + element: , + children: [ + { + path: ":number", + element: ( +
+ +
+ ), + }, + ], + }, + // TOKEN TRANSACTION DETAILS + { + path: "token-txn-details", + element: ( +
+ +
+ ), + children: [ + { + path: ":standard/:address", + element: ( +
+ +
+ ), + }, + ], + }, + // TOKEN DETAILS + { + path: "token-detail", + element: ( +
+ +
+ ), + children: [ + { + path: ":standard/:address", + element: ( +
+ +
+ ), + }, + ], + }, + // TRANSACTION DETAILS + { + path: "txn-details", + element: ( +
+ +
+ ), + children: [ + { + path: ":id", + element: ( +
+ +
+ ), + }, + ], + }, + // ERC tokens + { + path: "erc20", + element: ( +
+ +
+ ), + children: [ + { + path: ":account", + element: ( +
+ +
+ ), + }, + { + path: "trend/:account/:address", + element: ( +
+ +
+ ), + }, + ], + }, + { + path: "erc721", + element: ( +
+ +
+ ), + children: [ + { + path: ":account", + element: ( +
+ +
+ ), + }, + ], + }, + ], + }, + // FABRIC ROUTES + { + path: "fabric", + element: , + children: [ + { + path: "dashboard", + element: ( +
+ +
+ ), + }, + { + path: "transactions", + element: ( +
+ +
+ ), + }, + { + path: "blocks", + element: ( +
+ +
+ ), + }, + { + path: "txn-details", + element: ( +
+ +
+ ), + children: [ + { + path: ":id", + element: ( +
+ +
+ ), + }, + ], + }, + { + path: "block-details", + element: ( +
+ +
+ ), + children: [ + { + path: ":id", + element: ( +
+ block-details/:id + +
+ ), + }, + ], + }, + ], + }, + ], + }, +]); + +ReactDOM.createRoot(document.getElementById("root")!).render( + // + , + // , +); diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.module.css new file mode 100644 index 0000000000..43c52de4a5 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.module.css @@ -0,0 +1,6 @@ +.accounts-wrapper{ + width:100%; + display:grid; + grid-template-columns: repeat(auto-fit, 35rem); + gap: 1rem; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.tsx new file mode 100644 index 0000000000..96f748056b --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Accounts/Accounts.tsx @@ -0,0 +1,63 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { useNavigate, useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; + +function Accounts() { + const params = useParams(); + const navigate = useNavigate(); + const [accounts, setAccounts] = useState<{ address: string }[]>([]); + const [searchKey, setSearchKey] = useState(""); + + const tableProps = { + onClick: { + action: (param: string) => navigate(`/eth/${params.standard}/${param}`), + prop: "address", + }, + schema: [ + { + display: "Account address", + objProp: ["address"], + }, + ], + }; + + const fetchAccounts = async () => { + try { + const { data, error } = await supabase + .from(`token_${params.standard?.toLowerCase()}`) + .select("account_address"); + if (data) { + const objData = [...new Set(data.map((el) => el.account_address))].map( + (el) => ({ address: el }), + ); + setAccounts(objData); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchAccounts(); + }, []); + + return ( +
+ setSearchKey(e)} + > +
+ ); +} + +export default Accounts; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.tsx new file mode 100644 index 0000000000..6ee261ee45 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Blocks/Blocks.tsx @@ -0,0 +1,59 @@ +import { supabase } from "../../../supabase-client"; +import { useNavigate } from "react-router-dom"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Block } from "../../../schema/supabase-types"; +import styles from "./Blocks.module.css"; +import { useEffect, useState } from "react"; + +type ObjectKey = keyof typeof styles; + +function Blocks() { + const navigate = useNavigate(); + const [block, setBlock] = useState([]); + + const blocksTableProps = { + onClick: { + action: (param: string) => navigate(`/eth/block-details/${param}`), + prop: "number", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "block number", objProp: ["number"] }, + { display: "hash", objProp: ["hash"] }, + ], + }; + + const fetchBlock = async () => { + try { + const { data, error } = await supabase.from("block").select("*"); + if (data) { + console.log(JSON.stringify(data)); + setBlock(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchBlock(); + }, []); + + return ( +
+ +
+ ); +} + +export default Blocks; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.module.css new file mode 100644 index 0000000000..f2443fc562 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.module.css @@ -0,0 +1,10 @@ +.dashboard-wrapper { + display: flex; + gap: 1rem; +} + +@media (max-width: 1699px) { + .dashboard-wrapper { + flex-direction: column; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.tsx new file mode 100644 index 0000000000..834e1ee03c --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Dashboard/Dashboard.tsx @@ -0,0 +1,98 @@ +import { useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Transaction } from "../../../schema/supabase-types"; +import { Block } from "../../../schema/supabase-types"; + +import styles from "./Dashboard.module.css"; +import { supabase } from "../../../supabase-client"; + +function Dashboard() { + const navigate = useNavigate(); + const [transaction, setTransaction] = useState([]); + const [block, setBlock] = useState([]); + + const txnTableProps = { + onClick: { + action: (param: string) => { + navigate(`/eth/txn-details/${param}`); + }, + prop: "id", + }, + schema: [ + { display: "transaction id", objProp: ["id"] }, + { display: "sender/recipient", objProp: ["from", "to"] }, + { display: "token value", objProp: ["eth_value"] }, + ], + }; + + const blocksTableProps = { + onClick: { + action: (param: string) => { + navigate(`/eth/block-details/${param}`); + }, + prop: "number", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "block number", objProp: ["number"] }, + { display: "hash", objProp: ["hash"] }, + ], + }; + const fetchTransactions = async () => { + try { + const { data, error } = await supabase.from("transaction").select("*"); + if (data) { + setTransaction(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + const fetchBlock = async () => { + try { + const { data, error } = await supabase.from("block").select("*"); + if (data) { + setBlock(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchTransactions(); + fetchBlock(); + }, []); + + return ( +
+

Dashboard

+
+ + +
+
+ ); +} + +export default Dashboard; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Details/BlockDetails.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Details/BlockDetails.tsx new file mode 100644 index 0000000000..c101421d1d --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Details/BlockDetails.tsx @@ -0,0 +1,67 @@ +import { supabase } from "../../../supabase-client"; +import { Block } from "../../../schema/supabase-types"; + +import styles from "./Details.module.css"; +import { useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; + +function BlockDetails() { + const [details, setDetails] = useState(); + const params = useParams(); + + const fethcData = async () => { + try { + const { data } = await supabase + .from("block") + .select("*") + .match({ number: params.number }); + if (data?.[0]) { + setDetails(data[0]); + } else { + throw new Error("Failed to load block details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fethcData(); + }, []); + + return ( +
+
+ {details ? ( + <> +

Block Details

+

+ Address: {details.number}{" "} +

+

+ {" "} + Created at: + {details.created_at} +

+

+ Hash: + {details.hash} +

+

+ Number of transaction: + {details.number_of_tx} +

+

+ Sync at: + {details.sync_at} +

+ + ) : ( +
Failed to load details
+ )} +
+
+ ); +} + +export default BlockDetails; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Details/Details.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/Details/Details.module.css new file mode 100644 index 0000000000..899ff99432 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Details/Details.module.css @@ -0,0 +1,32 @@ +h1{ + padding: 0; + margin: 0; + margin-bottom: .5rem; +} +.details { + display: flex; + gap: .75rem; +} +.details-card{ + display: flex; + flex-direction: column; + gap: 15px; + border: 1px solid rgb(230, 224, 224); + border-radius: 10px; + padding: 1.5rem 2rem; + width:45%; +} +span { + display: inline-block; + font-size: 1.1rem; +} + +@media (max-width: 1699px) { + .details{ + flex-direction: column; + } + + .details-card { + width: 100%; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenDetails.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenDetails.tsx new file mode 100644 index 0000000000..e979c0eb91 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenDetails.tsx @@ -0,0 +1,65 @@ +import { supabase } from "../../../supabase-client"; +import { STANDARDS } from "../../../schema/token-standards"; +import { + TokenMetadata20, + TokenMetadata721, +} from "../../../schema/supabase-types"; +import styles from "./Details.module.css"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; + +const TokenDetails = () => { + const [tokenData, setTokenData] = useState< + TokenMetadata20 | TokenMetadata721 | any + >(); + + const params = useParams(); + + const fethcData = async () => { + try { + const { data } = await supabase + .from(`token_metadata_${params.standard?.toLowerCase()}`) + .select("*") + .match({ address: params.address }); + if (data?.[0]) { + setTokenData(data[0]); + } else { + throw new Error("Failed to load token details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fethcData(); + }, []); + + return ( +
+
+

Token Details

+

+ Adress: {tokenData?.address}{" "} +

+

+ Created at: + {tokenData?.created_at} +

+

+ Name: + {tokenData?.name} +

+

+ Symbol: + {tokenData?.symbol} +

+ {params.standard === STANDARDS.erc20 && ( +

total_supply : {tokenData?.total_supply}

+ )} +
+
+ ); +}; + +export default TokenDetails; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenTransactionDetails.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenTransactionDetails.tsx new file mode 100644 index 0000000000..a6fa6b20cd --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TokenTransactionDetails.tsx @@ -0,0 +1,66 @@ +import { supabase } from "../../../supabase-client"; +import { STANDARDS } from "../../../schema/token-standards"; +import { ERC20Txn, ERC721Txn } from "../../../schema/supabase-types"; + +import styles from "./Details.module.css"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; + +const TokenTransactionDetails = () => { + const [txnData, setTxnData] = useState({}); + const params = useParams(); + + const fethcData = async () => { + try { + const { data } = await supabase + .from(`token_${params.standard?.toLowerCase()}`) + .select("*") + .match({ account_address: params.address }); + if (data?.[0]) { + setTxnData(data[0]); + } else { + throw new Error("Failed to load transaction details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fethcData(); + }, []); + + return ( +
+
+

Details of Transaction

+

+ {" "} + Address: + {txnData?.account_address}{" "} +

+

+ {" "} + Created_at: + {txnData?.token_address} +

+ {params.standard === STANDARDS.erc20 && ( +

+ {" "} + Balance: + {txnData()?.balance} +

+ )} + {params.standard === STANDARDS.erc721 && ( +

+ {" "} + Uri: + {txnData()?.uri} +

+ )} +
+
+ ); +}; + +export default TokenTransactionDetails; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Details/TransactionDetails.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TransactionDetails.tsx new file mode 100644 index 0000000000..04101f56f4 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Details/TransactionDetails.tsx @@ -0,0 +1,100 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Transaction, TokenTransfer } from "../../../schema/supabase-types"; + +import styles from "./Details.module.css"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; + +const TransactionsDetails = () => { + const [details, setDetails] = useState({}); + const [transfers, setTransfers] = useState([]); + const params = useParams(); + + const detailsTableProps = { + onClick: { + action: () => {}, + prop: "id", + }, + schema: [ + { display: "transfer id", objProp: ["id"] }, + { display: "sender/recipient", objProp: ["sender", "recipient"] }, + { display: "value", objProp: ["value"] }, + ], + }; + + const fetchDetails = async () => { + try { + const { data } = await supabase + .from("transaction") + .select("*") + .match({ id: params.id }); + if (data?.[0]) { + setDetails(data[0]); + } else { + throw new Error("Failed to load transaction details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + const fetchTransfers = async () => { + try { + const { data } = await supabase + .from("token_transfer") + .select("*") + .match({ transaction_id: params.id }); + if (data) { + setTransfers(data); + } else { + throw new Error("Failed to load transfers"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchDetails(); + fetchTransfers(); + }, []); + + return ( +
+
+

Details of Transaction

+

+ {" "} + Hash: {details.hash}{" "} +

+

+ Block: + {details.block_number} +

+

+ From: + {details.from} +

+

+ To: + {details.to}{" "} +

+

+ {" "} + Value:   {details.eth_value} +

+
+ +
+ ); +}; + +export default TransactionsDetails; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.module.css new file mode 100644 index 0000000000..92eaa56f56 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.module.css @@ -0,0 +1,19 @@ +.erc-content { + display: flex; + gap:2rem; +} + +.erc-wrap{ + width:100%; + display: flex; + gap:1rem; + flex-direction: column; + +} + + +@media (max-width: 1699px) { + .erc-content{ + flex-direction: column; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.tsx new file mode 100644 index 0000000000..e8c9a4f53f --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/ERC20/ERC20.tsx @@ -0,0 +1,73 @@ +import TokenAccount from "../../../components/TokenHeader/TokenAccount"; +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import Chart from "../../../components/Chart/Chart"; +import { ERC20Txn } from "../../../schema/supabase-types"; +import styles from "./ERC20.module.css"; +import { useNavigate, useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; + +const ERC20 = () => { + const params = useParams(); + const navigate = useNavigate(); + const [token_erc20, setToken_erc20] = useState([]); + + const ercTableProps = { + onClick: { + action: (token_address: string) => + navigate(`/eth/erc20/trend/${params.account}/${token_address}`), + prop: "token_address", + }, + schema: [ + { + display: "token address", + objProp: ["token_address"], + }, + { + display: "balance", + objProp: ["balance"], + }, + ], + }; + + const fetchERC20 = async () => { + try { + const { data, error } = await supabase + .from("token_erc20") + .select() + .eq("account_address", params.account); + if (data) { + setToken_erc20(data); + } + if (error) { + throw new Error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchERC20(); + }, []); + + return ( +
+
+ + +
+
+ +
+
+ ); +}; + +export default ERC20; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.module.css new file mode 100644 index 0000000000..fb8d75ce96 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.module.css @@ -0,0 +1,18 @@ +.erc-content { + display: flex; + gap:2rem; +} + +.erc-wrap{ + display: flex; + gap:1rem; + flex-direction: column; + align-items: center; +} + +@media (max-width: 1699px) { + + .erc-content{ + flex-direction: column; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.tsx new file mode 100644 index 0000000000..6585226ef5 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/ERC721/ERC721.tsx @@ -0,0 +1,114 @@ +import TokenAccount from "../../../components/TokenHeader/TokenAccount"; +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { ERC721Txn } from "../../../schema/supabase-types"; +import { TokenMetadata721 } from "../../../schema/supabase-types"; +import styles from "./ERC721.module.css"; +import { useNavigate, useParams } from "react-router-dom"; +import { useEffect, useState } from "react"; + +function ERC721() { + const params = useParams(); + const navigate = useNavigate(); + const [token_erc721, setToken_erc721] = useState([]); + const [tokenMetadata, setTokenMetadata] = useState([]); + + const ercTableProps = { + onClick: { + action: (param: string) => navigate(`/eth/token-details/erc721/${param}`), + prop: "token_address", + }, + schema: [ + { + display: "symbol", + objProp: ["symbol"], + }, + { + display: "URI", + objProp: ["uri"], + }, + ], + }; + const metaProps = { + onClick: { + action: () => {}, + prop: "", + }, + schema: [ + { + display: "created at", + objProp: ["created_at"], + }, + { + display: "sender/recipient", + objProp: ["sender", "recipient"], + }, + { + display: "token address", + objProp: ["token_address"], + }, + ], + }; + + const fetchERC721 = async () => { + try { + const { data, error } = await supabase + .from("erc721_txn_meta_view") + .select() + .eq("account_address", params.account); + if (data) { + setToken_erc721(data); + } + if (error) { + throw new Error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + const fetchMetadata = async () => { + try { + const { data, error } = await supabase + .from(`erc721_token_history_view`) + .select("*"); + if (data) { + setTokenMetadata(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchERC721(); + fetchMetadata(); + }, []); + + return ( +
+ +
+ + +
+
+ ); +} + +export default ERC721; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.module.css new file mode 100644 index 0000000000..aa59d7de7e --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.module.css @@ -0,0 +1,12 @@ +.token-history { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.transactions { + display: flex; + flex-direction: column; + gap: 2rem; + margin-top: 2rem; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.tsx new file mode 100644 index 0000000000..59298a47a4 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/SingleTokenHistory/SingleTokenHistory.tsx @@ -0,0 +1,137 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import LineChart from "../../../components/Chart/LineChart"; +import TokenHeader from "../../../components/TokenHeader/TokenHeader"; +import { TokenHistoryItem20 } from "../../../schema/supabase-types"; +import { balanceDate } from "../../../schema/supabase-types"; +import styles from "./SingleTokenHistory.module.css"; +import EmptyTablePlaceholder from "../../../components/UI/CustomTable/EmptyTablePlaceholder/EmptyTablePlaceholder"; +import { useEffect, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; + +const SingleTokenHistory = () => { + type ObjectKey = keyof typeof styles; + const [transactions, setTransactions] = useState([]); + const [balanceHistory, setBalanceHistory] = useState([]); + const navigate = useNavigate(); + const params = useParams(); + + const tokenTableProps = { + onClick: { + action: (param: string) => navigate(`/view/${param}`), + prop: "id", + }, + schema: [ + { + display: "created at", + objProp: ["created_at"], + }, + { + display: "transaction hash", + objProp: ["transaction_hash"], + }, + { + display: "sender/recipient", + objProp: ["sender", "recipient"], + }, + { + display: "token address", + objProp: ["token_address"], + }, + { + display: "token value", + objProp: ["value"], + }, + ], + }; + + const calcTokenBalance = (txnData: TokenHistoryItem20[]) => { + let balance = 0; + const balances = txnData.map((txn) => { + let txn_value = txn.value || 0; + let account = params.account; + if (txn.recipient !== account) { + txn_value *= -1; + } + balance += txn_value; + return { + created_at: txn.created_at + "Z", + balance: balance, + }; + }); + return balances; + }; + + const fetchTransactions = async () => { + try { + const { data, error } = await supabase + .from("erc20_token_history_view") + .select("*") + .match({ token_address: params.address }) + .or(`sender.eq.${params.account}, recipient.eq.${params.account}`); + if (data) { + setTransactions(data); + setBalanceHistory(calcTokenBalance(data)); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchTransactions(); + }, []); + + return ( +
+ +
+ {transactions.length > 0 ? ( + <> + + + + ) : ( + + )} + + {/* 0} + fallback={} + > + + + */} +
+
+ ); +}; + +export default SingleTokenHistory; diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.module.css b/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.module.css new file mode 100644 index 0000000000..7ff183b0da --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.module.css @@ -0,0 +1,12 @@ +.transactions{ + display: flex; + flex-direction: column; + +}.transactions-search { + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 2rem; + + +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.tsx b/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.tsx new file mode 100644 index 0000000000..7f36f27298 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/eth/Transactions/Transactions.tsx @@ -0,0 +1,66 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Transaction } from "../../../schema/supabase-types"; + +import styles from "./Transactions.module.css"; +import { useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; + +function Transactions() { + const navigate = useNavigate(); + const [transactions, setTransactions] = useState([]); + + const txnTableProps = { + onClick: { + action: (param: string) => navigate(`/eth/txn-details/${param}`), + prop: "id", + }, + schema: [ + { + display: "transaction id", + objProp: ["id"], + }, + { + display: "sender/recipient", + objProp: ["from", "to"], + }, + { + display: "token value", + objProp: ["eth_value"], + }, + ], + }; + + const fetchTransactions = async () => { + try { + const { data } = await supabase.from("transaction").select("*"); + if (data) { + console.log(JSON.stringify(data)); + setTransactions(data); + } else { + throw new Error("Failed to load transactions"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchTransactions(); + }, []); + + return ( +
+ +
+ ); +} + +export default Transactions; diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.module.css b/packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.tsx b/packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.tsx new file mode 100644 index 0000000000..b78d3b1c71 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/BlocksFabric/BlocksFabric.tsx @@ -0,0 +1,62 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Block } from "../../../schema/supabase-types"; +import styles from "./BlocksFabric.module.css"; +import { useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; + +type ObjectKey = keyof typeof styles; + +const BlocksFabric = () => { + const navigate = useNavigate(); + const [block, setBlock] = useState([]); + + const blocksTableProps = { + onClick: { + action: (param: string) => { + navigate(`/fabric/block-details/${param}`); + }, + prop: "id", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "block number", objProp: ["block_number"] }, + { display: "channel name", objProp: ["channel_id"] }, + { display: "hash", objProp: ["data_hash"] }, + { display: "transactions count", objProp: ["tx_count"] }, + ], + }; + + const fetchBlock = async () => { + try { + const { data, error } = await supabase.from("fabric_blocks").select("*"); + if (data) { + setBlock(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchBlock(); + }, []); + + return ( +
+ +
+ ); +}; + +export default BlocksFabric; diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.module.css b/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.module.css new file mode 100644 index 0000000000..f75a30b767 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.module.css @@ -0,0 +1,11 @@ +.dashboard-wrapper { + display: flex; + gap: 1rem; + flex-direction: column; +} + +@media (max-width: 1699px) { + .dashboard-wrapper { + flex-direction: column; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.tsx b/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.tsx new file mode 100644 index 0000000000..2eb86d638e --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/DashFabric/DashFabric.tsx @@ -0,0 +1,103 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Transaction } from "../../../schema/supabase-types"; +import { Block } from "../../../schema/supabase-types"; +import styles from "./DashFabric.module.css"; +import { useNavigate } from "react-router-dom"; +import { useEffect, useState } from "react"; + +function DashFabric() { + const navigate = useNavigate(); + const [transaction, setTransaction] = useState([]); + const [block, setBlock] = useState([]); + + const txnTableProps = { + onClick: { + action: (param: string) => { + navigate(`/fabric/txn-details/${param}`); + }, + prop: "id", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "transaction id", objProp: ["transaction_id"] }, + { display: "channel name", objProp: ["channel_id"] }, + { display: "block id", objProp: ["block_id"] }, + { display: "status", objProp: ["status"] }, + ], + }; + + const blocksTableProps = { + onClick: { + action: (param: string) => { + navigate(`/fabric/block-details/${param}`); + }, + prop: "id", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "block number", objProp: ["block_number"] }, + { display: "channel name", objProp: ["channel_id"] }, + { display: "hash", objProp: ["data_hash"] }, + { display: "transactions count", objProp: ["tx_count"] }, + ], + }; + + const fetchTransactions = async () => { + try { + const { data, error } = await supabase + .from("fabric_transactions") + .select("*"); + if (data) { + setTransaction(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + const fetchBlock = async () => { + try { + const { data, error } = await supabase.from("fabric_blocks").select("*"); + if (data) { + setBlock(data); + } + if (error) { + console.error(error.message); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchBlock(); + fetchTransactions(); + }, []); + + return ( +
+
+ + +
+
+ ); +} + +export default DashFabric; diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.module.css b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.module.css new file mode 100644 index 0000000000..5bfa3e269e --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.module.css @@ -0,0 +1,8 @@ +.details-card { + display: flex; + flex-direction: column; + gap: 15px; + border: 1px solid rgb(230, 224, 224); + border-radius: 10px; + padding: 1.5rem 2rem; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.tsx b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.tsx new file mode 100644 index 0000000000..d4fa0f6cb8 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricBlock/FabricBlock.tsx @@ -0,0 +1,74 @@ +import styles from "./FabricBlock.module.css"; + +import { supabase } from "../../../supabase-client"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; + +const FabricBlock = () => { + const [details, setDetails] = useState({}); + const params = useParams(); + + const fetchData = async () => { + try { + const { data, error } = await supabase + .from("fabric_blocks") + .select("*") + .match({ id: params.id }); + if (data?.[0]) { + setDetails(data[0]); + } else { + throw new Error("Failed to load block details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + useEffect(() => { + fetchData(); + }, []); + + return ( +
+
+ {details ? ( + <> +

Block Details

+

+ ID: {details.id}{" "} +

+

+ {" "} + Block Number: + {details.block_number} +

+

+ Hash: + {details.data_hash} +

+

+ Tx Count: + {details.tx_count} +

+

+ Created at: + {details.created_at} +

+

+ {" "} + Previous Blockhash: + {details.prev_blockhash} +

+

+ {" "} + Channel name: + {details.channel_id} +

+ + ) : ( +
Failed to load details
+ )} +
+
+ ); +}; +export default FabricBlock; diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.module.css b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.module.css new file mode 100644 index 0000000000..15fab73ab7 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.module.css @@ -0,0 +1,22 @@ +.details-card { + display: flex; + flex-direction: column; + gap: 15px; + border: 1px solid rgb(230, 224, 224); + border-radius: 10px; + padding: 1.5rem 2rem; +} + +.details-bytes-wrap { + display: flex; + align-items: center; + gap: 1rem; +} +.details-bytes { + width: 30vw; + font-size: 14px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + resize: horizontal; +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.tsx b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.tsx new file mode 100644 index 0000000000..5bd071bb04 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/FabricTransaction/FabricTransaction.tsx @@ -0,0 +1,138 @@ +import styles from "./FabricTransaction.module.css"; +import { supabase } from "../../../supabase-client"; +import Button from "../../../components/UI/Button/Button"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import ContentCopyIcon from "@mui/icons-material/ContentCopy"; + +const notify = () => + alert("Success! Creator ID Bytes was successfully copied to the clipboard."); +// toast("Success! Creator ID Bytes was successfully copied to the clipboard."); + +function FabricTransaction() { + const [details, setDetails] = useState({}); + const params = useParams(); + + const fetchData = async () => { + try { + const { data, error } = await supabase + .from("fabric_transactions") + .select("*") + .match({ id: params.id }); + if (data?.[0]) { + console.log(data); + setDetails(data[0]); + } else { + throw new Error("Failed to load block details"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchData(); + }, []); + + const copyIdToClipboard = () => { + navigator.clipboard.writeText(details.creator_id_bytes); + notify(); + }; + + return ( +
+
+ {details ? ( + <> + <> +

Transaction Details

+

+ Created at: + {details.created_at} +

+

+ Block ID: {details.block_id}{" "} +

+

+ {" "} + Transaction ID: + {details.transaction_id} +

+

+ {" "} + Channel name: + {details.channel_id} +

+

+ {" "} + Status + {details.status} +

+

+ {" "} + Type + {details.type} +

+ +

+ {" "} + Chaincode Name: + {details.chaincode_name} +

+

+ {" "} + Creator ID Bytes: + + {" "} + {details.creator_id_bytes} + + +

+

+ {" "} + Creator nonce: + {details.creator_nonce} +

+

+ {" "} + Creator MSP ID: + {details.creator_msp_id} +

+

+ {" "} + Endorser MSP ID: + {details.endorser_msp_id} +

+

+ {" "} + Payload Proposal Hash: + {details.payload_proposal_hash} +

+ + ) : ( +
Failed to load details
+ )} +
+ {/* */} +
+ ); +} +export default FabricTransaction; + +{ + /* +

+ {" "} + Validation Code + {details.validation_code} +

+

+ {" "} + Network name: + {details.network_name} +

+ */ +} diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.module.css b/packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.module.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.tsx b/packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.tsx new file mode 100644 index 0000000000..782e8daf6f --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/fabric/TransactionsFabric/TransactionsFabric.tsx @@ -0,0 +1,59 @@ +import { supabase } from "../../../supabase-client"; +import CardWrapper from "../../../components/CardWrapper/CardWrapper"; +import { Transaction } from "../../../schema/supabase-types"; +import styles from "./TransactionsFabric.module.css"; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; + +function TransactionsFabric() { + const navigate = useNavigate(); + const [transactions, setTransactions] = useState([]); + + const txnTableProps = { + onClick: { + action: (param: string) => { + navigate(`/fabric/txn-details/${param}`); + }, + prop: "id", + }, + schema: [ + { display: "created at", objProp: ["created_at"] }, + { display: "transaction id", objProp: ["transaction_id"] }, + { display: "channel name", objProp: ["channel_id"] }, + { display: "block id", objProp: ["block_id"] }, + { display: "status", objProp: ["status"] }, + ], + }; + + const fetchTransactions = async () => { + try { + const { data } = await supabase.from("fabric_transactions").select("*"); + if (data) { + setTransactions(data); + } else { + throw new Error("Failed to load transactions"); + } + } catch (error: any) { + console.error(error.message); + } + }; + + useEffect(() => { + fetchTransactions(); + }, []); + + return ( +
+ +
+ ); +} + +export default TransactionsFabric; diff --git a/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.module.css b/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.module.css new file mode 100644 index 0000000000..d6bd86d00d --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.module.css @@ -0,0 +1,22 @@ +.home { + font-weight: 700; + margin: 5rem; + font-size: 3rem; + color: rgb(14, 87, 32); + display: flex; + justify-content: center; + flex-direction: column; + align-items: center; + gap: 2rem; +} + +.home-icon { + object-fit: cover; + width: auto; + overflow: hidden; +} + +.home-scale { + font-size: 2rem; + width: 80%; +} diff --git a/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.tsx b/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.tsx new file mode 100644 index 0000000000..c50ba071b0 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/pages/shared/Home/Home.tsx @@ -0,0 +1,16 @@ +import styles from "./Home.module.css"; +import logo from "../../../../../../images/HL_Cacti_Logo_Color.png"; +const Home = () => { + return ( +
+

+ Select ledger from the dropdown menu +

+ + Logo + +
+ ); +}; + +export default Home; diff --git a/packages/cacti-ledger-browser-react/src/routes/Root.module.css b/packages/cacti-ledger-browser-react/src/routes/Root.module.css new file mode 100644 index 0000000000..cba488b71c --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/routes/Root.module.css @@ -0,0 +1,12 @@ +.main { + width: 100%; +} +.content { + margin: 1rem 2rem; +} + +@media (max-width: 1699px) { + .content { + margin: 1rem; + } +} \ No newline at end of file diff --git a/packages/cacti-ledger-browser-react/src/routes/Root.tsx b/packages/cacti-ledger-browser-react/src/routes/Root.tsx new file mode 100644 index 0000000000..29fdf77b4a --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/routes/Root.tsx @@ -0,0 +1,20 @@ +import { Outlet, useLocation } from "react-router-dom"; +import styles from "./Root.module.css"; +import Menu from "../components/UI/Menu/Menu"; +import Home from "../pages/shared/Home/Home"; + +function Root() { + const location = useLocation(); + console.log(location); + return ( +
+ + {location.pathname === "/" ? : null} +
+ +
+
+ ); +} + +export default Root; diff --git a/packages/cacti-ledger-browser-react/src/schema/supabase-types.ts b/packages/cacti-ledger-browser-react/src/schema/supabase-types.ts new file mode 100644 index 0000000000..45b608e68e --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/schema/supabase-types.ts @@ -0,0 +1,103 @@ +export interface ERC20Txn { + account_address: string; + token_address: string; + uri: string; + token_id: number; + id: string; + balance: number; + last_owner_change: string; +} + +export interface ERC721Txn { + account_address: string; + token_address: string; + uri: string; + token_id: number; + id: string; + last_owner_change: string; +} + +export interface TokenMetadata20 { + address: string; + name: string; + symbol: string; + total_supply: number; + created_at: string; +} + +export interface TokenMetadata721 { + address: string; + name: string; + symbol: string; + created_at: string; +} + +export interface Block { + number: number; + created_at: string; + hash: string; + number_of_tx: number; + sync_at: string; +} + +export interface TokenTransfer { + transaction_id: string; + sender: string; + recipient: string; + value: number; + id: string; +} + +export interface Transaction { + index: number; + hash: string; + block_number: number; + from: string; + to: string; + eth_value: number; + method_signature: string; + method_name: string; + id: string; +} + +export interface TokenHistoryItem { + transaction_hash: string | null; + token_address: string | null; + created_at: string | null; + sender: string | null; + recipient: string | null; +} + +export interface TokenHistoryItem721 extends TokenHistoryItem { + token_id: number | null; +} + +export interface TokenHistoryItem20 extends TokenHistoryItem { + value: number | null; +} + +export interface TokenTransactionMetadata721 { + account_address: string; + token_address: string; + uri: string; + symbol: string; +} + +export interface TableProperty { + display: string; + objProp: string[]; +} + +export interface TableRowClick { + action: (param: string) => void; + prop: string; +} +export interface TableProps { + onClick: TableRowClick; + schema: TableProperty[]; +} + +export interface balanceDate { + created_at: string; + balance: number; +} diff --git a/packages/cacti-ledger-browser-react/src/schema/token-standards.ts b/packages/cacti-ledger-browser-react/src/schema/token-standards.ts new file mode 100644 index 0000000000..65ad5a514c --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/schema/token-standards.ts @@ -0,0 +1,4 @@ +export const STANDARDS = { + erc20: "ERC20", + erc721: "ERC721", +}; diff --git a/packages/cacti-ledger-browser-react/src/supabase-client.tsx b/packages/cacti-ledger-browser-react/src/supabase-client.tsx new file mode 100644 index 0000000000..f0efcb4688 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/supabase-client.tsx @@ -0,0 +1,7 @@ +import { createClient } from "@supabase/supabase-js"; + +const supabaseUrl = "http://localhost:8000"; +const supabaseKey = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE"; + +export const supabase = createClient(supabaseUrl, supabaseKey); diff --git a/packages/cacti-ledger-browser-react/src/vite-env.d.ts b/packages/cacti-ledger-browser-react/src/vite-env.d.ts new file mode 100644 index 0000000000..11f02fe2a0 --- /dev/null +++ b/packages/cacti-ledger-browser-react/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/cacti-ledger-browser-react/tsconfig.json b/packages/cacti-ledger-browser-react/tsconfig.json new file mode 100644 index 0000000000..a7fc6fbf23 --- /dev/null +++ b/packages/cacti-ledger-browser-react/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/packages/cacti-ledger-browser-react/tsconfig.node.json b/packages/cacti-ledger-browser-react/tsconfig.node.json new file mode 100644 index 0000000000..42872c59f5 --- /dev/null +++ b/packages/cacti-ledger-browser-react/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/packages/cacti-ledger-browser-react/vite.config.ts b/packages/cacti-ledger-browser-react/vite.config.ts new file mode 100644 index 0000000000..27d39b69df --- /dev/null +++ b/packages/cacti-ledger-browser-react/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +// https://vitejs.dev/config/ +export default defineConfig({ + server: { + port: 3001, + }, + plugins: [react()], +}); diff --git a/yarn.lock b/yarn.lock index 278ac25918..95bc903f1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1331,6 +1331,29 @@ __metadata: languageName: node linkType: hard +"@babel/core@npm:^7.23.5": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" + dependencies: + "@ampproject/remapping": ^2.2.0 + "@babel/code-frame": ^7.23.5 + "@babel/generator": ^7.23.6 + "@babel/helper-compilation-targets": ^7.23.6 + "@babel/helper-module-transforms": ^7.23.3 + "@babel/helpers": ^7.23.9 + "@babel/parser": ^7.23.9 + "@babel/template": ^7.23.9 + "@babel/traverse": ^7.23.9 + "@babel/types": ^7.23.9 + convert-source-map: ^2.0.0 + debug: ^4.1.0 + gensync: ^1.0.0-beta.2 + json5: ^2.2.3 + semver: ^6.3.1 + checksum: 634a511f74db52a5f5a283c1121f25e2227b006c095b84a02a40a9213842489cd82dc7d61cdc74e10b5bcd9bb0a4e28bab47635b54c7e2256d47ab57356e2a76 + languageName: node + linkType: hard + "@babel/eslint-parser@npm:^7.16.3": version: 7.22.15 resolution: "@babel/eslint-parser@npm:7.22.15" @@ -2282,6 +2305,17 @@ __metadata: languageName: node linkType: hard +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" + dependencies: + "@babel/template": ^7.23.9 + "@babel/traverse": ^7.23.9 + "@babel/types": ^7.23.9 + checksum: 2678231192c0471dbc2fc403fb19456cc46b1afefcfebf6bc0f48b2e938fdb0fef2e0fe90c8c8ae1f021dae5012b700372e4b5d15867f1d7764616532e4a6324 + languageName: node + linkType: hard + "@babel/highlight@npm:7.0.0-beta.51": version: 7.0.0-beta.51 resolution: "@babel/highlight@npm:7.0.0-beta.51" @@ -2431,6 +2465,15 @@ __metadata: languageName: node linkType: hard +"@babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" + bin: + parser: ./bin/babel-parser.js + checksum: e7cd4960ac8671774e13803349da88d512f9292d7baa952173260d3e8f15620a28a3701f14f709d769209022f9e7b79965256b8be204fc550cfe783cdcabe7c7 + languageName: node + linkType: hard + "@babel/parser@npm:^7.4.3": version: 7.22.10 resolution: "@babel/parser@npm:7.22.10" @@ -3521,6 +3564,28 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-jsx-self@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 882bf56bc932d015c2d83214133939ddcf342e5bcafa21f1a93b19f2e052145115e1e0351730897fd66e5f67cad7875b8a8d81ceb12b6e2a886ad0102cb4eb1f + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-source@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": ^7.22.5 + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 92287fb797e522d99bdc77eaa573ce79ff0ad9f1cf4e7df374645e28e51dce0adad129f6f075430b129b5bac8dad843f65021970e12e992d6d6671f0d65bb1e0 + languageName: node + linkType: hard + "@babel/plugin-transform-react-jsx@npm:^7.22.5": version: 7.22.5 resolution: "@babel/plugin-transform-react-jsx@npm:7.22.5" @@ -4056,6 +4121,15 @@ __metadata: languageName: node linkType: hard +"@babel/runtime@npm:^7.23.8, @babel/runtime@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/runtime@npm:7.23.9" + dependencies: + regenerator-runtime: ^0.14.0 + checksum: 6bbebe8d27c0c2dd275d1ac197fc1a6c00e18dab68cc7aaff0adc3195b45862bae9c4cc58975629004b0213955b2ed91e99eccb3d9b39cabea246c657323d667 + languageName: node + linkType: hard + "@babel/runtime@npm:^7.4.4": version: 7.22.10 resolution: "@babel/runtime@npm:7.22.10" @@ -4130,6 +4204,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" + dependencies: + "@babel/code-frame": ^7.23.5 + "@babel/parser": ^7.23.9 + "@babel/types": ^7.23.9 + checksum: 6e67414c0f7125d7ecaf20c11fab88085fa98a96c3ef10da0a61e962e04fdf3a18a496a66047005ddd1bb682a7cc7842d556d1db2f3f3f6ccfca97d5e445d342 + languageName: node + linkType: hard + "@babel/traverse@npm:>=7.23.2": version: 7.23.2 resolution: "@babel/traverse@npm:7.23.2" @@ -4245,6 +4330,17 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" + dependencies: + "@babel/helper-string-parser": ^7.23.4 + "@babel/helper-validator-identifier": ^7.22.20 + to-fast-properties: ^2.0.0 + checksum: 0a9b008e9bfc89beb8c185e620fa0f8ed6c771f1e1b2e01e1596870969096fec7793898a1d64a035176abf1dd13e2668ee30bf699f2d92c210a8128f4b151e65 + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^0.2.3": version: 0.2.3 resolution: "@bcoe/v8-coverage@npm:0.2.3" @@ -5213,6 +5309,27 @@ __metadata: languageName: node linkType: hard +"@emotion/react@npm:11.11.3": + version: 11.11.3 + resolution: "@emotion/react@npm:11.11.3" + dependencies: + "@babel/runtime": ^7.18.3 + "@emotion/babel-plugin": ^11.11.0 + "@emotion/cache": ^11.11.0 + "@emotion/serialize": ^1.1.3 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 + "@emotion/utils": ^1.2.1 + "@emotion/weak-memoize": ^0.3.1 + hoist-non-react-statics: ^3.3.1 + peerDependencies: + react: ">=16.8.0" + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 2e4b223591569f0a41686d5bd72dc8778629b7be33267e4a09582979e6faee4d7218de84e76294ed827058d4384d75557b5d71724756539c1f235e9a69e62b2e + languageName: node + linkType: hard + "@emotion/react@npm:^11.11.1": version: 11.11.1 resolution: "@emotion/react@npm:11.11.1" @@ -5247,6 +5364,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.1.3": + version: 1.1.3 + resolution: "@emotion/serialize@npm:1.1.3" + dependencies: + "@emotion/hash": ^0.9.1 + "@emotion/memoize": ^0.8.1 + "@emotion/unitless": ^0.8.1 + "@emotion/utils": ^1.2.1 + csstype: ^3.0.2 + checksum: 5a756ce7e2692322683978d8ed2e84eadd60bd6f629618a82c5018c84d98684b117e57fad0174f68ec2ec0ac089bb2e0bcc8ea8c2798eb904b6d3236aa046063 + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -5254,7 +5384,7 @@ __metadata: languageName: node linkType: hard -"@emotion/styled@npm:^11.11.0": +"@emotion/styled@npm:11.11.0, @emotion/styled@npm:^11.11.0": version: 11.11.0 resolution: "@emotion/styled@npm:11.11.0" dependencies: @@ -5883,6 +6013,23 @@ __metadata: languageName: node linkType: hard +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" + dependencies: + ajv: ^6.12.4 + debug: ^4.3.2 + espree: ^9.6.0 + globals: ^13.19.0 + ignore: ^5.2.0 + import-fresh: ^3.2.1 + js-yaml: ^4.1.0 + minimatch: ^3.1.2 + strip-json-comments: ^3.1.1 + checksum: 10957c7592b20ca0089262d8c2a8accbad14b4f6507e35416c32ee6b4dbf9cad67dfb77096bbd405405e9ada2b107f3797fe94362e1c55e0b09d6e90dd149127 + languageName: node + linkType: hard + "@eslint/js@npm:8.48.0": version: 8.48.0 resolution: "@eslint/js@npm:8.48.0" @@ -5890,6 +6037,13 @@ __metadata: languageName: node linkType: hard +"@eslint/js@npm:8.55.0": + version: 8.55.0 + resolution: "@eslint/js@npm:8.55.0" + checksum: fa33ef619f0646ed15649b0c2e313e4d9ccee8425884bdbfc78020d6b6b64c0c42fa9d83061d0e6158e1d4274f03f0f9008786540e2efab8fcdc48082259908c + languageName: node + linkType: hard + "@ethereumjs/common@npm:2.5.0": version: 2.5.0 resolution: "@ethereumjs/common@npm:2.5.0" @@ -6676,6 +6830,15 @@ __metadata: languageName: node linkType: hard +"@floating-ui/core@npm:^1.0.0": + version: 1.6.0 + resolution: "@floating-ui/core@npm:1.6.0" + dependencies: + "@floating-ui/utils": ^0.2.1 + checksum: 2e25c53b0c124c5c9577972f8ae21d081f2f7895e6695836a53074463e8c65b47722744d6d2b5a993164936da006a268bcfe87fe68fd24dc235b1cb86bed3127 + languageName: node + linkType: hard + "@floating-ui/core@npm:^1.4.1": version: 1.4.1 resolution: "@floating-ui/core@npm:1.4.1" @@ -6695,6 +6858,16 @@ __metadata: languageName: node linkType: hard +"@floating-ui/dom@npm:^1.6.1": + version: 1.6.3 + resolution: "@floating-ui/dom@npm:1.6.3" + dependencies: + "@floating-ui/core": ^1.0.0 + "@floating-ui/utils": ^0.2.0 + checksum: 81cbb18ece3afc37992f436e469e7fabab2e433248e46fff4302d12493a175b0c64310f8a971e6e1eda7218df28ace6b70237b0f3c22fe12a21bba05b5579555 + languageName: node + linkType: hard + "@floating-ui/react-dom@npm:^2.0.4": version: 2.0.4 resolution: "@floating-ui/react-dom@npm:2.0.4" @@ -6707,6 +6880,18 @@ __metadata: languageName: node linkType: hard +"@floating-ui/react-dom@npm:^2.0.8": + version: 2.0.8 + resolution: "@floating-ui/react-dom@npm:2.0.8" + dependencies: + "@floating-ui/dom": ^1.6.1 + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 5da7f13a69281e38859a3203a608fe9de1d850b332b355c10c0c2427c7b7209a0374c10f6295b6577c1a70237af8b678340bd4cc0a4b1c66436a94755d81e526 + languageName: node + linkType: hard + "@floating-ui/utils@npm:^0.1.1": version: 0.1.1 resolution: "@floating-ui/utils@npm:0.1.1" @@ -6714,6 +6899,13 @@ __metadata: languageName: node linkType: hard +"@floating-ui/utils@npm:^0.2.0, @floating-ui/utils@npm:^0.2.1": + version: 0.2.1 + resolution: "@floating-ui/utils@npm:0.2.1" + checksum: 9ed4380653c7c217cd6f66ae51f20fdce433730dbc77f95b5abfb5a808f5fdb029c6ae249b4e0490a816f2453aa6e586d9a873cd157fdba4690f65628efc6e06 + languageName: node + linkType: hard + "@gar/promisify@npm:^1.0.1, @gar/promisify@npm:^1.1.3": version: 1.1.3 resolution: "@gar/promisify@npm:1.1.3" @@ -6969,6 +7161,17 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/config-array@npm:^0.11.13": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": ^2.0.2 + debug: ^4.3.1 + minimatch: ^3.0.5 + checksum: 861ccce9eaea5de19546653bccf75bf09fe878bc39c3aab00aeee2d2a0e654516adad38dd1098aab5e3af0145bbcbf3f309bdf4d964f8dab9dcd5834ae4c02f2 + languageName: node + linkType: hard + "@humanwhocodes/config-array@npm:^0.5.0": version: 0.5.0 resolution: "@humanwhocodes/config-array@npm:0.5.0" @@ -6994,6 +7197,13 @@ __metadata: languageName: node linkType: hard +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 2fc11503361b5fb4f14714c700c02a3f4c7c93e9acd6b87a29f62c522d90470f364d6161b03d1cc618b979f2ae02aed1106fd29d302695d8927e2fc8165ba8ee + languageName: node + linkType: hard + "@hutson/parse-repository-url@npm:^5.0.0": version: 5.0.0 resolution: "@hutson/parse-repository-url@npm:5.0.0" @@ -7072,6 +7282,38 @@ __metadata: languageName: unknown linkType: soft +"@hyperledger/cacti-ledger-browser-react@workspace:packages/cacti-ledger-browser-react": + version: 0.0.0-use.local + resolution: "@hyperledger/cacti-ledger-browser-react@workspace:packages/cacti-ledger-browser-react" + dependencies: + "@emotion/react": 11.11.3 + "@emotion/styled": 11.11.0 + "@mui/icons-material": 5.15.10 + "@mui/material": 5.15.10 + "@supabase/supabase-js": 1.35.6 + "@types/react": 18.2.43 + "@types/react-dom": 18.2.17 + "@types/sort-by": 1 + "@typescript-eslint/eslint-plugin": 6.14.0 + "@typescript-eslint/parser": 6.14.0 + "@vitejs/plugin-react": 4.2.1 + apexcharts: 3.45.2 + eslint: 8.55.0 + eslint-plugin-react-hooks: 4.6.0 + eslint-plugin-react-refresh: 0.4.5 + localforage: 1.10.0 + match-sorter: 6.3.3 + moment: 2.30.1 + react: 18.2.0 + react-apexcharts: 1.4.1 + react-dom: 18.2.0 + react-router-dom: 6.21.3 + sort-by: 1.2.0 + typescript: 5.2.2 + vite: 5.0.8 + languageName: unknown + linkType: soft + "@hyperledger/cacti-ledger-browser@workspace:packages/cacti-ledger-browser": version: 0.0.0-use.local resolution: "@hyperledger/cacti-ledger-browser@workspace:packages/cacti-ledger-browser" @@ -10627,6 +10869,28 @@ __metadata: languageName: node linkType: hard +"@mui/base@npm:5.0.0-beta.36": + version: 5.0.0-beta.36 + resolution: "@mui/base@npm:5.0.0-beta.36" + dependencies: + "@babel/runtime": ^7.23.9 + "@floating-ui/react-dom": ^2.0.8 + "@mui/types": ^7.2.13 + "@mui/utils": ^5.15.9 + "@popperjs/core": ^2.11.8 + clsx: ^2.1.0 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 25fda38025f2299908739b2d591c58884ee05a9af099f19124d12b16098fd245fed6716891288b1998c12477cc36d7e14f07c4d9eb5eb3a9e75b0400970cd7c9 + languageName: node + linkType: hard + "@mui/core-downloads-tracker@npm:^5.14.19": version: 5.14.19 resolution: "@mui/core-downloads-tracker@npm:5.14.19" @@ -10634,6 +10898,29 @@ __metadata: languageName: node linkType: hard +"@mui/core-downloads-tracker@npm:^5.15.10": + version: 5.15.10 + resolution: "@mui/core-downloads-tracker@npm:5.15.10" + checksum: aeb16b31f60c08cc03585fedadceadd54aa48dda394fb945ab885f884c1b1692efb72309465641b6ca2367bd53d5fdce15f189d4691f42b59206622ffb2d6f0f + languageName: node + linkType: hard + +"@mui/icons-material@npm:5.15.10": + version: 5.15.10 + resolution: "@mui/icons-material@npm:5.15.10" + dependencies: + "@babel/runtime": ^7.23.9 + peerDependencies: + "@mui/material": ^5.0.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 33be07435d511542516965b428044f6f823d001d9fbdc97d957172c310fe4292815842bd82a73a20b6f3a8f2feaa231c39f73e687b7bb36b63e33b531c134532 + languageName: node + linkType: hard + "@mui/icons-material@npm:^5.14.19": version: 5.14.19 resolution: "@mui/icons-material@npm:5.14.19" @@ -10650,6 +10937,39 @@ __metadata: languageName: node linkType: hard +"@mui/material@npm:5.15.10": + version: 5.15.10 + resolution: "@mui/material@npm:5.15.10" + dependencies: + "@babel/runtime": ^7.23.9 + "@mui/base": 5.0.0-beta.36 + "@mui/core-downloads-tracker": ^5.15.10 + "@mui/system": ^5.15.9 + "@mui/types": ^7.2.13 + "@mui/utils": ^5.15.9 + "@types/react-transition-group": ^4.4.10 + clsx: ^2.1.0 + csstype: ^3.1.3 + prop-types: ^15.8.1 + react-is: ^18.2.0 + react-transition-group: ^4.4.5 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: 2c453877d8784ba6330c236888cac86f793ee914d27ccac426ec241c448b836a190017cb6402e9931d7a9d566f02ea2f317a14332e70c87ba136436d45ae18f2 + languageName: node + linkType: hard + "@mui/material@npm:^5.14.19": version: 5.14.19 resolution: "@mui/material@npm:5.14.19" @@ -10700,6 +11020,23 @@ __metadata: languageName: node linkType: hard +"@mui/private-theming@npm:^5.15.9": + version: 5.15.9 + resolution: "@mui/private-theming@npm:5.15.9" + dependencies: + "@babel/runtime": ^7.23.9 + "@mui/utils": ^5.15.9 + prop-types: ^15.8.1 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 15cd0a7d8ba05452ef5f7a6a8856d333f6e6bfc3fe4ca0e242a4e37053856872603e374593f42a297d26353cdc0a8567d8424f8e7912b8bbd7f4507f9f9f2a74 + languageName: node + linkType: hard + "@mui/styled-engine@npm:^5.14.19": version: 5.14.19 resolution: "@mui/styled-engine@npm:5.14.19" @@ -10721,6 +11058,27 @@ __metadata: languageName: node linkType: hard +"@mui/styled-engine@npm:^5.15.9": + version: 5.15.9 + resolution: "@mui/styled-engine@npm:5.15.9" + dependencies: + "@babel/runtime": ^7.23.9 + "@emotion/cache": ^11.11.0 + csstype: ^3.1.3 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.4.1 + "@emotion/styled": ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + checksum: 0a02a3b83d47277fa38421a6cfe0e8c6451e7d5a4d5b5d389ba970ebc55172040f0f2bd628f0211b659b922965ead416da0453e4bc15e7e83942f03ffa57621d + languageName: node + linkType: hard + "@mui/system@npm:^5.14.19": version: 5.14.19 resolution: "@mui/system@npm:5.14.19" @@ -10749,6 +11107,34 @@ __metadata: languageName: node linkType: hard +"@mui/system@npm:^5.15.9": + version: 5.15.9 + resolution: "@mui/system@npm:5.15.9" + dependencies: + "@babel/runtime": ^7.23.9 + "@mui/private-theming": ^5.15.9 + "@mui/styled-engine": ^5.15.9 + "@mui/types": ^7.2.13 + "@mui/utils": ^5.15.9 + clsx: ^2.1.0 + csstype: ^3.1.3 + prop-types: ^15.8.1 + peerDependencies: + "@emotion/react": ^11.5.0 + "@emotion/styled": ^11.3.0 + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@emotion/react": + optional: true + "@emotion/styled": + optional: true + "@types/react": + optional: true + checksum: a5bda6f9c2b8e1241ed0f6865539fea65cdac31b61383c0f35bd1eedc838f67c68cce9609af5563aae6f45bec0c8242283fa408a2b989e23bdc9caeba9939950 + languageName: node + linkType: hard + "@mui/types@npm:^7.2.10": version: 7.2.10 resolution: "@mui/types@npm:7.2.10" @@ -10761,6 +11147,18 @@ __metadata: languageName: node linkType: hard +"@mui/types@npm:^7.2.13": + version: 7.2.13 + resolution: "@mui/types@npm:7.2.13" + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 58dfc96f9654288519ff01d6b54e6a242f05cadad51210deb85710a81be4fa1501a116c8968e2614b16c748fc1f407dc23beeeeae70fa37fceb6c6de876ff70d + languageName: node + linkType: hard + "@mui/utils@npm:^5.14.19": version: 5.14.19 resolution: "@mui/utils@npm:5.14.19" @@ -10779,6 +11177,24 @@ __metadata: languageName: node linkType: hard +"@mui/utils@npm:^5.15.9": + version: 5.15.9 + resolution: "@mui/utils@npm:5.15.9" + dependencies: + "@babel/runtime": ^7.23.9 + "@types/prop-types": ^15.7.11 + prop-types: ^15.8.1 + react-is: ^18.2.0 + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 61e520c0a50cbf463d893b011eaea844dcf028e12387eec12378aa870d4342c688bfe5f48de1f4896dc1a0cc9d4224f90470d238105ee45c178cd8b4bbef7cf5 + languageName: node + linkType: hard + "@multiformats/base-x@npm:^4.0.1": version: 4.0.1 resolution: "@multiformats/base-x@npm:4.0.1" @@ -11958,6 +12374,13 @@ __metadata: languageName: node linkType: hard +"@remix-run/router@npm:1.14.2": + version: 1.14.2 + resolution: "@remix-run/router@npm:1.14.2" + checksum: 8be55596f64563de95dea04c147ab67c4e6c9b72277c92d4de257dbb326e2aa16ad2adbdec32eb2c985808c642933ac895220654b8c899e4f4bd38f9fd97ff6e + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -12016,6 +12439,97 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.9.6" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-android-arm64@npm:4.9.6" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-darwin-arm64@npm:4.9.6" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-darwin-x64@npm:4.9.6" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.9.6" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.9.6" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.9.6" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.9.6" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.9.6" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.9.6" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.9.6" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.9.6" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.9.6": + version: 4.9.6 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.9.6" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rushstack/eslint-patch@npm:^1.1.0": version: 1.3.3 resolution: "@rushstack/eslint-patch@npm:1.3.3" @@ -13302,7 +13816,7 @@ __metadata: languageName: node linkType: hard -"@types/babel__core@npm:^7.20.4": +"@types/babel__core@npm:^7.20.4, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -13692,6 +14206,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: dd8b5bed28e6213b7acd0fb665a84e693554d850b0df423ac8076cc3ad5823a6bc26b0251d080bdc545af83179ede51dd3f6fa78cad2c46ed1f29624ddf3e41a + languageName: node + linkType: hard + "@types/estree@npm:^1.0.0": version: 1.0.1 resolution: "@types/estree@npm:1.0.1" @@ -14534,7 +15055,7 @@ __metadata: languageName: node linkType: hard -"@types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.17": +"@types/react-dom@npm:18.2.17, @types/react-dom@npm:^18.0.0, @types/react-dom@npm:^18.2.17": version: 18.2.17 resolution: "@types/react-dom@npm:18.2.17" dependencies: @@ -14543,6 +15064,15 @@ __metadata: languageName: node linkType: hard +"@types/react-transition-group@npm:^4.4.10": + version: 4.4.10 + resolution: "@types/react-transition-group@npm:4.4.10" + dependencies: + "@types/react": "*" + checksum: fe2ea11f70251e9f79f368e198c18fd469b1d4f1e1d44e4365845b44e15974b0ec925100036f449b023b0ca3480a82725c5f0a73040e282ad32ec7b0def9b57c + languageName: node + linkType: hard + "@types/react-transition-group@npm:^4.4.9": version: 4.4.9 resolution: "@types/react-transition-group@npm:4.4.9" @@ -14563,6 +15093,17 @@ __metadata: languageName: node linkType: hard +"@types/react@npm:18.2.43": + version: 18.2.43 + resolution: "@types/react@npm:18.2.43" + dependencies: + "@types/prop-types": "*" + "@types/scheduler": "*" + csstype: ^3.0.2 + checksum: e7e4da18c7b14e4b8b1ea630d1d8224835698f2bb2485766455bfb9dea93b8ee6cc549a9fe1cb10c984e62685db44fcfb61e8fac913b008cd30a92087f25b9df + languageName: node + linkType: hard + "@types/react@npm:^17.0.52": version: 17.0.62 resolution: "@types/react@npm:17.0.62" @@ -14765,6 +15306,13 @@ __metadata: languageName: node linkType: hard +"@types/sort-by@npm:1": + version: 1.2.3 + resolution: "@types/sort-by@npm:1.2.3" + checksum: edf61bad1538c5861e8187f45ea86476420cfd2e51e5d089e42eb21cf231afa91973e77e956069d85b4d67b21df4932ecd994062ca2155560db20b6a5ecea793 + languageName: node + linkType: hard + "@types/ssh2-streams@npm:*, @types/ssh2-streams@npm:0.1.9": version: 0.1.9 resolution: "@types/ssh2-streams@npm:0.1.9" @@ -15077,6 +15625,31 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.14.0" + dependencies: + "@eslint-community/regexpp": ^4.5.1 + "@typescript-eslint/scope-manager": 6.14.0 + "@typescript-eslint/type-utils": 6.14.0 + "@typescript-eslint/utils": 6.14.0 + "@typescript-eslint/visitor-keys": 6.14.0 + debug: ^4.3.4 + graphemer: ^1.4.0 + ignore: ^5.2.4 + natural-compare: ^1.4.0 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependencies: + "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: ec688fd71b21576bfe0e4176889fddf3c13d8b07792461b84017d689ed11a9bffbf4d2ab61e9bdb254e43d2c1e159d5c2fc21bdfa6a6c2d64f9e1956a668fbe8 + languageName: node + linkType: hard + "@typescript-eslint/eslint-plugin@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/eslint-plugin@npm:6.4.0" @@ -15196,6 +15769,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/parser@npm:6.14.0" + dependencies: + "@typescript-eslint/scope-manager": 6.14.0 + "@typescript-eslint/types": 6.14.0 + "@typescript-eslint/typescript-estree": 6.14.0 + "@typescript-eslint/visitor-keys": 6.14.0 + debug: ^4.3.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 5fbe8d7431654c14ba6c9782d3728026ad5c90e02c9c4319f45df972e653cf5c15ba320dce70cdffa9fb7ce4c4263c37585e7bc1c909d1252d0a599880963063 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/parser@npm:6.4.0" @@ -15234,6 +15825,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/scope-manager@npm:6.14.0" + dependencies: + "@typescript-eslint/types": 6.14.0 + "@typescript-eslint/visitor-keys": 6.14.0 + checksum: 0b577d42db925426a9838fe61703c226e18b697374fbe20cf9b93ba30fe58bf4a7f7f42491a4d24b7f3cc12d9a189fe3524c0e9b7708727e710d95b908250a14 + languageName: node + linkType: hard + "@typescript-eslint/scope-manager@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/scope-manager@npm:6.4.0" @@ -15261,6 +15862,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/type-utils@npm:6.14.0" + dependencies: + "@typescript-eslint/typescript-estree": 6.14.0 + "@typescript-eslint/utils": 6.14.0 + debug: ^4.3.4 + ts-api-utils: ^1.0.1 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 09988f25279598840673c41ba44b03756f2dfb31284ab72af97c170711a0f31e5c53d6b120aa83f31438565e82aae1a1ca4d1ed0de4890654dd6a6a33d88202c + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/type-utils@npm:6.4.0" @@ -15299,6 +15917,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/types@npm:6.14.0" + checksum: 624e6c5227f596dcc9757348d09c5a09b846a62938b8b4409614cf8108013b64ed8b270c32e87ea8890dd09ed896b82e92872c3574dbf07dcda11a168d69dd1f + languageName: node + linkType: hard + "@typescript-eslint/types@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/types@npm:6.4.0" @@ -15361,6 +15986,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.14.0" + dependencies: + "@typescript-eslint/types": 6.14.0 + "@typescript-eslint/visitor-keys": 6.14.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: 495d7616463685bfd8138ffa9fbc0a7f9130ff8a3f6f85775960b4f0a3fdc259ae53b104cdfe562b60310860b5a6c8387307790734555084aa087e3bb9c28a69 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/typescript-estree@npm:6.4.0" @@ -15397,6 +16040,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/utils@npm:6.14.0" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.14.0 + "@typescript-eslint/types": 6.14.0 + "@typescript-eslint/typescript-estree": 6.14.0 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: 36e8501cb85647947189f31017c36d6f6ac7ef0399fa0e18eb64f1b83e00f1e8ace1d9ac5015ef4d9c1b820179f1def8d61d7ea9e5d61433eb848cf5c49dc8b0 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/utils@npm:6.4.0" @@ -15443,6 +16103,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:6.14.0": + version: 6.14.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.14.0" + dependencies: + "@typescript-eslint/types": 6.14.0 + eslint-visitor-keys: ^3.4.1 + checksum: fc593c4e94d5739be7bd88e42313a301bc9806fad758b6a0a1bafd296ff41522be602caf4976beec84e363b0f56585bb98df3c157f70de984de721798501fd8a + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:6.4.0": version: 6.4.0 resolution: "@typescript-eslint/visitor-keys@npm:6.4.0" @@ -15453,6 +16123,13 @@ __metadata: languageName: node linkType: hard +"@ungap/structured-clone@npm:^1.2.0": + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524 + languageName: node + linkType: hard + "@unimodules/core@npm:*": version: 7.2.0 resolution: "@unimodules/core@npm:7.2.0" @@ -15481,6 +16158,21 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-react@npm:4.2.1": + version: 4.2.1 + resolution: "@vitejs/plugin-react@npm:4.2.1" + dependencies: + "@babel/core": ^7.23.5 + "@babel/plugin-transform-react-jsx-self": ^7.23.3 + "@babel/plugin-transform-react-jsx-source": ^7.23.3 + "@types/babel__core": ^7.20.5 + react-refresh: ^0.14.0 + peerDependencies: + vite: ^4.2.0 || ^5.0.0 + checksum: 08d227d27ff2304e395e746bd2d4b5fee40587f69d7e2fcd6beb7d91163c1f1dc26d843bc48e2ffb8f38c6b8a1b9445fb07840e3dcc841f97b56bbb8205346aa + languageName: node + linkType: hard + "@vue/compiler-core@npm:3.3.7": version: 3.3.7 resolution: "@vue/compiler-core@npm:3.3.7" @@ -15770,6 +16462,13 @@ __metadata: languageName: node linkType: hard +"@yr/monotone-cubic-spline@npm:^1.0.3": + version: 1.0.3 + resolution: "@yr/monotone-cubic-spline@npm:1.0.3" + checksum: ebc75e4d84d5b97d1d715452088ffe3cf6b3d71943433118116a2e90f17aed654b6f726868e913a49aef28645bb8afcc28580349de1ac77ad0c7dab3d991843e + languageName: node + linkType: hard + "JSONStream@npm:^1.3.5": version: 1.3.5 resolution: "JSONStream@npm:1.3.5" @@ -16495,6 +17194,21 @@ __metadata: languageName: node linkType: hard +"apexcharts@npm:3.45.2": + version: 3.45.2 + resolution: "apexcharts@npm:3.45.2" + dependencies: + "@yr/monotone-cubic-spline": ^1.0.3 + svg.draggable.js: ^2.2.2 + svg.easing.js: ^2.0.0 + svg.filter.js: ^2.0.2 + svg.pathmorphing.js: ^0.1.3 + svg.resize.js: ^1.4.3 + svg.select.js: ^3.0.1 + checksum: a7250e5c9a5d0104bbcdc0716d71a781c27c0d20f2381f0f3838d0ac152cd461f3f94c7ade92eedd56a924096d2a628c66d2f111d4ca493851b72b60ee28d836 + languageName: node + linkType: hard + "apexcharts@npm:^3.33.1": version: 3.41.0 resolution: "apexcharts@npm:3.41.0" @@ -20224,6 +20938,13 @@ __metadata: languageName: node linkType: hard +"clsx@npm:^2.1.0": + version: 2.1.0 + resolution: "clsx@npm:2.1.0" + checksum: 43fefc29b6b49c9476fbce4f8b1cc75c27b67747738e598e6651dd40d63692135dc60b18fa1c5b78a2a9ba8ae6fd2055a068924b94e20b42039bd53b78b98e1d + languageName: node + linkType: hard + "cmd-shim@npm:^6.0.0": version: 6.0.1 resolution: "cmd-shim@npm:6.0.1" @@ -21914,6 +22635,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.1.3": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 8db785cc92d259102725b3c694ec0c823f5619a84741b5c7991b8ad135dfaa66093038a1cc63e03361a6cd28d122be48f2106ae72334e067dd619a51f49eddf7 + languageName: node + linkType: hard + "cucumber-expressions@npm:^6.0.0": version: 6.6.2 resolution: "cucumber-expressions@npm:6.6.2" @@ -24249,7 +24977,7 @@ __metadata: languageName: node linkType: hard -"esbuild@npm:~0.19.10": +"esbuild@npm:^0.19.3, esbuild@npm:~0.19.10": version: 0.19.12 resolution: "esbuild@npm:0.19.12" dependencies: @@ -24751,7 +25479,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:^4.3.0": +"eslint-plugin-react-hooks@npm:4.6.0, eslint-plugin-react-hooks@npm:^4.3.0": version: 4.6.0 resolution: "eslint-plugin-react-hooks@npm:4.6.0" peerDependencies: @@ -24760,6 +25488,15 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-react-refresh@npm:0.4.5": + version: 0.4.5 + resolution: "eslint-plugin-react-refresh@npm:0.4.5" + peerDependencies: + eslint: ">=7" + checksum: 953e665f6aaf097291a2bb07fde05466338aecd169bcd6faa708b50166912e3a757f45a45252cf7738b5e0d986224d363cc227864e98c979fe9978770b2b9f42 + languageName: node + linkType: hard + "eslint-plugin-react@npm:^7.27.1": version: 7.33.2 resolution: "eslint-plugin-react@npm:7.33.2" @@ -24983,6 +25720,54 @@ __metadata: languageName: node linkType: hard +"eslint@npm:8.55.0": + version: 8.55.0 + resolution: "eslint@npm:8.55.0" + dependencies: + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.6.1 + "@eslint/eslintrc": ^2.1.4 + "@eslint/js": 8.55.0 + "@humanwhocodes/config-array": ^0.11.13 + "@humanwhocodes/module-importer": ^1.0.1 + "@nodelib/fs.walk": ^1.2.8 + "@ungap/structured-clone": ^1.2.0 + ajv: ^6.12.4 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.3.2 + doctrine: ^3.0.0 + escape-string-regexp: ^4.0.0 + eslint-scope: ^7.2.2 + eslint-visitor-keys: ^3.4.3 + espree: ^9.6.1 + esquery: ^1.4.2 + esutils: ^2.0.2 + fast-deep-equal: ^3.1.3 + file-entry-cache: ^6.0.1 + find-up: ^5.0.0 + glob-parent: ^6.0.2 + globals: ^13.19.0 + graphemer: ^1.4.0 + ignore: ^5.2.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + is-path-inside: ^3.0.3 + js-yaml: ^4.1.0 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash.merge: ^4.6.2 + minimatch: ^3.1.2 + natural-compare: ^1.4.0 + optionator: ^0.9.3 + strip-ansi: ^6.0.1 + text-table: ^0.2.0 + bin: + eslint: bin/eslint.js + checksum: 83f82a604559dc1faae79d28fdf3dfc9e592ca221052e2ea516e1b379b37e77e4597705a16880e2f5ece4f79087c1dd13fd7f6e9746f794a401175519db18b41 + languageName: node + linkType: hard + "eslint@npm:^4.19.1": version: 4.19.1 resolution: "eslint@npm:4.19.1" @@ -29744,6 +30529,13 @@ __metadata: languageName: node linkType: hard +"immediate@npm:~3.0.5": + version: 3.0.6 + resolution: "immediate@npm:3.0.6" + checksum: f9b3486477555997657f70318cc8d3416159f208bec4cca3ff3442fd266bc23f50f0c9bd8547e1371a6b5e82b821ec9a7044a4f7b944798b25aa3cc6d5e63e62 + languageName: node + linkType: hard + "immediate@npm:~3.2.3": version: 3.2.3 resolution: "immediate@npm:3.2.3" @@ -34422,6 +35214,15 @@ __metadata: languageName: node linkType: hard +"lie@npm:3.1.1": + version: 3.1.1 + resolution: "lie@npm:3.1.1" + dependencies: + immediate: ~3.0.5 + checksum: 6da9f2121d2dbd15f1eca44c0c7e211e66a99c7b326ec8312645f3648935bc3a658cf0e9fa7b5f10144d9e2641500b4f55bd32754607c3de945b5f443e50ddd1 + languageName: node + linkType: hard + "lilconfig@npm:^2.0.3, lilconfig@npm:^2.0.5, lilconfig@npm:^2.1.0": version: 2.1.0 resolution: "lilconfig@npm:2.1.0" @@ -34556,6 +35357,15 @@ __metadata: languageName: node linkType: hard +"localforage@npm:1.10.0": + version: 1.10.0 + resolution: "localforage@npm:1.10.0" + dependencies: + lie: 3.1.1 + checksum: f2978b434dafff9bcb0d9498de57d97eba165402419939c944412e179cab1854782830b5ec196212560b22712d1dd03918939f59cf1d4fc1d756fca7950086cf + languageName: node + linkType: hard + "locate-path@npm:^2.0.0": version: 2.0.0 resolution: "locate-path@npm:2.0.0" @@ -35439,6 +36249,16 @@ __metadata: languageName: node linkType: hard +"match-sorter@npm:6.3.3": + version: 6.3.3 + resolution: "match-sorter@npm:6.3.3" + dependencies: + "@babel/runtime": ^7.23.8 + remove-accents: 0.5.0 + checksum: 8191bc5a39a33ec62571a171dff24ce3f604f4fcb0667c4bd512ec39834f4af6db759f91abdba3f91cf3e0ee9229f6e3d8953ec6093efb05b5f718509c9c3618 + languageName: node + linkType: hard + "math-random@npm:^1.0.1": version: 1.0.4 resolution: "math-random@npm:1.0.4" @@ -36355,6 +37175,13 @@ __metadata: languageName: node linkType: hard +"moment@npm:2.30.1": + version: 2.30.1 + resolution: "moment@npm:2.30.1" + checksum: 859236bab1e88c3e5802afcf797fc801acdbd0ee509d34ea3df6eea21eb6bcc2abd4ae4e4e64aa7c986aa6cba563c6e62806218e6412a765010712e5fa121ba6 + languageName: node + linkType: hard + "morgan@npm:1.10.0": version: 1.10.0 resolution: "morgan@npm:1.10.0" @@ -38047,6 +38874,13 @@ __metadata: languageName: node linkType: hard +"object-path@npm:0.6.0": + version: 0.6.0 + resolution: "object-path@npm:0.6.0" + checksum: e9d7a901bcfcfe39b195cdac5bb2b8c1f030abdf86f45ed6d0385c5d0c38a8c5e4b4a30c88bf483d6b3b37b5a8d620d004dbfc6db6be8565f88e9cf0b078e945 + languageName: node + linkType: hard + "object-path@npm:^0.11.5": version: 0.11.8 resolution: "object-path@npm:0.11.8" @@ -41772,6 +42606,18 @@ __metadata: languageName: node linkType: hard +"react-apexcharts@npm:1.4.1": + version: 1.4.1 + resolution: "react-apexcharts@npm:1.4.1" + dependencies: + prop-types: ^15.8.1 + peerDependencies: + apexcharts: ^3.41.0 + react: ">=0.13" + checksum: 32d1a946ad40493ecd82f7ba68c8657424a8cf0d08e0cd813752211175d6b23dd3ae9f0f7edbac9dd2bbc050a7f3531ca6e5d7ea0158f1c276c49c4f397f347f + languageName: node + linkType: hard + "react-app-polyfill@npm:^3.0.0": version: 3.0.0 resolution: "react-app-polyfill@npm:3.0.0" @@ -41828,7 +42674,7 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^18.2.0": +"react-dom@npm:18.2.0, react-dom@npm:^18.2.0": version: 18.2.0 resolution: "react-dom@npm:18.2.0" dependencies: @@ -41915,6 +42761,37 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.14.0": + version: 0.14.0 + resolution: "react-refresh@npm:0.14.0" + checksum: dc69fa8c993df512f42dd0f1b604978ae89bd747c0ed5ec595c0cc50d535fb2696619ccd98ae28775cc01d0a7c146a532f0f7fb81dc22e1977c242a4912312f4 + languageName: node + linkType: hard + +"react-router-dom@npm:6.21.3": + version: 6.21.3 + resolution: "react-router-dom@npm:6.21.3" + dependencies: + "@remix-run/router": 1.14.2 + react-router: 6.21.3 + peerDependencies: + react: ">=16.8" + react-dom: ">=16.8" + checksum: bcf668aa1428ca3048d7675f1ae3fe983c8792357a0ed59a1414cb1d682227727aad7c44c4222c6774b8d01bf352478845f7f3f668ebfcaa177208ef64e10bdc + languageName: node + linkType: hard + +"react-router@npm:6.21.3": + version: 6.21.3 + resolution: "react-router@npm:6.21.3" + dependencies: + "@remix-run/router": 1.14.2 + peerDependencies: + react: ">=16.8" + checksum: 7e6297d5b67ae07d2e8564e036dbb15ebd706b41c22238940f47eee9b21ffb76d41336803c3b33435f1ebe210226577e32df3838bcbf2cd7c813fa357c0a4fac + languageName: node + linkType: hard + "react-scripts@npm:5.0.1": version: 5.0.1 resolution: "react-scripts@npm:5.0.1" @@ -41997,22 +42874,22 @@ __metadata: languageName: node linkType: hard -"react@npm:^17.0.2": - version: 17.0.2 - resolution: "react@npm:17.0.2" +"react@npm:18.2.0, react@npm:^18.2.0": + version: 18.2.0 + resolution: "react@npm:18.2.0" dependencies: loose-envify: ^1.1.0 - object-assign: ^4.1.1 - checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b + checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b languageName: node linkType: hard -"react@npm:^18.2.0": - version: 18.2.0 - resolution: "react@npm:18.2.0" +"react@npm:^17.0.2": + version: 17.0.2 + resolution: "react@npm:17.0.2" dependencies: loose-envify: ^1.1.0 - checksum: 88e38092da8839b830cda6feef2e8505dec8ace60579e46aa5490fc3dc9bba0bd50336507dc166f43e3afc1c42939c09fe33b25fae889d6f402721dcd78fca1b + object-assign: ^4.1.1 + checksum: b254cc17ce3011788330f7bbf383ab653c6848902d7936a87b09d835d091e3f295f7e9dd1597c6daac5dc80f90e778c8230218ba8ad599f74adcc11e33b9d61b languageName: node linkType: hard @@ -42723,6 +43600,13 @@ __metadata: languageName: node linkType: hard +"remove-accents@npm:0.5.0": + version: 0.5.0 + resolution: "remove-accents@npm:0.5.0" + checksum: 7045b37015acb03df406d21f9cbe93c3fcf2034189f5d2e33b1dace9c7d6bdcd839929905ced21a5d76c58553557e1a42651930728702312a5774179d5b9147b + languageName: node + linkType: hard + "remove-trailing-separator@npm:^1.0.1": version: 1.1.0 resolution: "remove-trailing-separator@npm:1.1.0" @@ -43502,6 +44386,60 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.2.0": + version: 4.9.6 + resolution: "rollup@npm:4.9.6" + dependencies: + "@rollup/rollup-android-arm-eabi": 4.9.6 + "@rollup/rollup-android-arm64": 4.9.6 + "@rollup/rollup-darwin-arm64": 4.9.6 + "@rollup/rollup-darwin-x64": 4.9.6 + "@rollup/rollup-linux-arm-gnueabihf": 4.9.6 + "@rollup/rollup-linux-arm64-gnu": 4.9.6 + "@rollup/rollup-linux-arm64-musl": 4.9.6 + "@rollup/rollup-linux-riscv64-gnu": 4.9.6 + "@rollup/rollup-linux-x64-gnu": 4.9.6 + "@rollup/rollup-linux-x64-musl": 4.9.6 + "@rollup/rollup-win32-arm64-msvc": 4.9.6 + "@rollup/rollup-win32-ia32-msvc": 4.9.6 + "@rollup/rollup-win32-x64-msvc": 4.9.6 + "@types/estree": 1.0.5 + fsevents: ~2.3.2 + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: cdc0bdd41ee2d3fe7f01df26f5a85921caf46ffe0ae118b2f3deebdf569e8b1c1800b8eee04960425e67aecbd9ccdd37bcdb92595866adb3968d223a07e9b7e6 + languageName: node + linkType: hard + "run-applescript@npm:^5.0.0": version: 5.0.0 resolution: "run-applescript@npm:5.0.0" @@ -45054,6 +45992,15 @@ __metadata: languageName: node linkType: hard +"sort-by@npm:1.2.0": + version: 1.2.0 + resolution: "sort-by@npm:1.2.0" + dependencies: + object-path: 0.6.0 + checksum: 82c9812aa318eff68669fe25cc0168d172ccbff9d34d52449c345631118b5e29608e3524e9028b23dc4959c8a7601b19a40ddbe3eb05234c0a54792912c5ad2f + languageName: node + linkType: hard + "sort-keys@npm:^5.0.0": version: 5.0.0 resolution: "sort-keys@npm:5.0.0" @@ -48283,6 +49230,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:5.2.2, typescript@npm:^4.6.4 || ^5.0.0": + version: 5.2.2 + resolution: "typescript@npm:5.2.2" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + languageName: node + linkType: hard + "typescript@npm:5.3.3": version: 5.3.3 resolution: "typescript@npm:5.3.3" @@ -48303,13 +49260,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.6.4 || ^5.0.0": +"typescript@patch:typescript@5.2.2#~builtin, typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin": version: 5.2.2 - resolution: "typescript@npm:5.2.2" + resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=5da071" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 7912821dac4d962d315c36800fe387cdc0a6298dba7ec171b350b4a6e988b51d7b8f051317786db1094bd7431d526b648aba7da8236607febb26cf5b871d2d3c + checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 languageName: node linkType: hard @@ -48333,16 +49290,6 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@^4.6.4 || ^5.0.0#~builtin": - version: 5.2.2 - resolution: "typescript@patch:typescript@npm%3A5.2.2#~builtin::version=5.2.2&hash=5da071" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 07106822b4305de3f22835cbba949a2b35451cad50888759b6818421290ff95d522b38ef7919e70fb381c5fe9c1c643d7dea22c8b31652a717ddbd57b7f4d554 - languageName: node - linkType: hard - "ubiquity-ts-client-renovated@npm:1.0.0": version: 1.0.0 resolution: "ubiquity-ts-client-renovated@npm:1.0.0" @@ -49303,6 +50250,46 @@ __metadata: languageName: node linkType: hard +"vite@npm:5.0.8": + version: 5.0.8 + resolution: "vite@npm:5.0.8" + dependencies: + esbuild: ^0.19.3 + fsevents: ~2.3.3 + postcss: ^8.4.32 + rollup: ^4.2.0 + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 884dc2f17aa2c41786c5acd4ff420d1f291fef7653786ed7bd59d4275e18483c94eabe44dd3a9741798ef65270dcbb6edfa280b60004314db50ac43476ff3d81 + languageName: node + linkType: hard + "vitefu@npm:^0.2.5": version: 0.2.5 resolution: "vitefu@npm:0.2.5"