diff --git a/packages/frontend/.env b/packages/frontend/.env index bd557b412..6f3af3265 100644 --- a/packages/frontend/.env +++ b/packages/frontend/.env @@ -1 +1,2 @@ -REACT_APP_API_BASE_URL=http://127.0.0.1:3005 \ No newline at end of file +REACT_APP_API_BASE_URL=https://platform-explorer.pshenmic.dev +NEXT_PUBLIC_API_BASE_URL=https://platform-explorer.pshenmic.dev \ No newline at end of file diff --git a/packages/frontend/.eslintrc.json b/packages/frontend/.eslintrc.json new file mode 100644 index 000000000..bffb357a7 --- /dev/null +++ b/packages/frontend/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/packages/frontend/.gitignore b/packages/frontend/.gitignore index 4d29575de..fd3dbb571 100644 --- a/packages/frontend/.gitignore +++ b/packages/frontend/.gitignore @@ -4,20 +4,33 @@ /node_modules /.pnp .pnp.js +.yarn/install-state.gz # testing /coverage +# next.js +/.next/ +/out/ + # production /build # misc .DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local +*.pem +# debug npm-debug.log* yarn-debug.log* yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/packages/frontend/README.md b/packages/frontend/README.md index 1d803e4a9..4e0d41712 100644 --- a/packages/frontend/README.md +++ b/packages/frontend/README.md @@ -3,8 +3,34 @@ This packages handles frontend of the applicaiton. -## Build, Run -Just: +## Install dependencies: -`$ yarn start` +```bash +npm install +``` + +Verify your packages/frontend/.env is matching your backend API URL + +## Run the app + +Development server: + +```bash +npm run dev +``` + +Build: + +```bash +npm run build +``` + +Start: + +```bash +npm run start +``` + + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. diff --git a/packages/frontend/next.config.mjs b/packages/frontend/next.config.mjs new file mode 100644 index 000000000..4678774e6 --- /dev/null +++ b/packages/frontend/next.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = {}; + +export default nextConfig; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 9df77f787..f5d5a129c 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@chakra-ui/icons": "^2.1.1", + "@chakra-ui/next-js": "^2.2.0", "@chakra-ui/react": "^2.8.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", @@ -11,7 +12,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "express": "^4.18.2", - "framer-motion": "^10.16.4", + "next": "14.1.0", "node-fetch": "^3.3.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -22,29 +23,10 @@ "web-vitals": "^2.1.4" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - }, - "main": "index.js", "license": "MIT" } diff --git a/packages/frontend/src/routes/block/block.route.js b/packages/frontend/src/app/block/[hash]/Block.js similarity index 80% rename from packages/frontend/src/routes/block/block.route.js rename to packages/frontend/src/app/block/[hash]/Block.js index b036d3e05..fbd1d22a6 100644 --- a/packages/frontend/src/routes/block/block.route.js +++ b/packages/frontend/src/app/block/[hash]/Block.js @@ -1,7 +1,8 @@ -import React from 'react' -import { useLoaderData} from 'react-router-dom' -import * as Api from '../../util/Api' -import TransactionsList from '../../components/transactions/TransactionsList' +'use client' + +import { useState, useEffect } from 'react' +import * as Api from '../../../util/Api' +import TransactionsList from '../../../components/transactions/TransactionsList' import { Container, @@ -10,18 +11,24 @@ import { } from '@chakra-ui/react' -export async function loader({params}) { - const {hash} = params - const block = await Api.getBlockByHash(hash); - return {block}; -} +function Block({ hash }) { + const [block, setBlock] = useState({}) + const [loading, setLoading] = useState(true) + + const fetchData = () => { + setLoading(true) + + Api.getBlockByHash(hash) + .then(setBlock) + .catch(console.log) + .finally(() => setLoading(false)) + } -function BlockRoute() { - const {block} = useLoaderData(); + useEffect(fetchData, [hash]) - const txHashes = block?.txs || []; + const txHashes = block?.txs || [] - return ( + if (!loading) return ( - - {txHashes.length ? : null} - - ); + ) } -export default BlockRoute; +export default Block diff --git a/packages/frontend/src/app/block/[hash]/page.js b/packages/frontend/src/app/block/[hash]/page.js new file mode 100644 index 000000000..1078285fc --- /dev/null +++ b/packages/frontend/src/app/block/[hash]/page.js @@ -0,0 +1,17 @@ +import Block from './Block' + + +export async function generateMetadata({ params }) { + return { + title: 'Block #' + params.hash + ' — Dash Platform Explorer', + description: 'Dash Platform Block Hash ' + params.hash + '. The Timestamp, Transactions count, Block Version.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'block', 'Timestamp', 'Transactions', 'Block'], + applicationName: 'Dash Platform Explorer' + } +} + +async function BlockRoute({ params }) { + return +} + +export default BlockRoute diff --git a/packages/frontend/src/routes/blocks/blocks.route.js b/packages/frontend/src/app/blocks/Blocks.js similarity index 52% rename from packages/frontend/src/routes/blocks/blocks.route.js rename to packages/frontend/src/app/blocks/Blocks.js index 8c5b0babc..4cc79a449 100644 --- a/packages/frontend/src/routes/blocks/blocks.route.js +++ b/packages/frontend/src/app/blocks/Blocks.js @@ -1,19 +1,20 @@ -import React, {useState, useEffect} from 'react' -import {Link, useLoaderData} from 'react-router-dom' +'use client' + +import { useState, useEffect } from 'react' import * as Api from '../../util/Api' -import ReactPaginate from 'react-paginate' -import GoToHeightForm from './../../components/goToHeightForm/GoToHeightForm' -import PageSizeSelector from './../../components/pageSizeSelector/PageSizeSelector' +import Pagination from '../../components/pagination' +import GoToHeightForm from '../../components/goToHeightForm/GoToHeightForm' +import PageSizeSelector from '../../components/pageSizeSelector/PageSizeSelector' import BlocksList from '../../components/blocks/BlocksList' import './Blocks.scss' -import { +import { Container, Heading, } from '@chakra-ui/react' -const paginateConfig = { +const paginateConfig = { pageSize: { default: 25, values: [10, 25, 50, 75, 100], @@ -22,46 +23,51 @@ const paginateConfig = { } -export async function loader() { - const paginatedBlocks = await Api.getBlocks(paginateConfig.defaultPage, paginateConfig.pageSize.default, 'desc') - const {resultSet, pagination} = paginatedBlocks - - return {blocks: resultSet, total: pagination.total}; -} - -function BlocksRoute() { - const {blocks: defaultBlocks, total} = useLoaderData() - const [blocks, setBlocks] = useState(defaultBlocks) +function Blocks() { + const [loading, setLoading] = useState(true) + const [blocks, setBlocks] = useState([]) + const [total, setTotal] = useState(1) const [pageSize, setPageSize] = useState(paginateConfig.pageSize.default) const [currentPage, setCurrentPage] = useState(0) const [blockHeightToSearch, setBlockHeightToSearch] = useState(0) const pageCount = Math.ceil(total / pageSize) - - const handlePageClick = async ({selected}) => { - const {resultSet} = await Api.getBlocks(selected+1, pageSize, 'desc') - - setCurrentPage(selected) - - setBlocks(resultSet) + + const fetchData = () => { + setLoading(true) + + Api.getBlocks(paginateConfig.defaultPage, paginateConfig.pageSize.default, 'desc') + .then((res) => { + setBlocks(res.resultSet) + setTotal(res.pagination.total) + }) + .catch(console.log) + .finally(() => setLoading(false)) } - const goToHeight = async (e) => { - e.preventDefault(); + useEffect(fetchData, []) - const page = Math.ceil((total - blockHeightToSearch + 2) / pageSize) - 1; + const handlePageClick = ({selected}) => { + Api.getBlocks(selected+1, pageSize, 'desc') + .then((res) => { + setCurrentPage(selected) + setBlocks(res.resultSet) + }) + } - setCurrentPage(page); + const goToHeight = (e) => { + e.preventDefault() - handlePageClick({selected: page}); + const page = Math.ceil((total - blockHeightToSearch + 2) / pageSize) - 1 + setCurrentPage(page) + handlePageClick({selected: page}) } useEffect(() => { - setCurrentPage(0); + setCurrentPage(0) + handlePageClick({selected: 0}) + }, [pageSize]) - handlePageClick({selected: 0}); - }, [pageSize]); - - return ( + if (!loading) return ( Blocks -
- @@ -122,7 +112,7 @@ function BlocksRoute() { - ); + ) } -export default BlocksRoute; +export default Blocks diff --git a/packages/frontend/src/routes/blocks/Blocks.scss b/packages/frontend/src/app/blocks/Blocks.scss similarity index 97% rename from packages/frontend/src/routes/blocks/Blocks.scss rename to packages/frontend/src/app/blocks/Blocks.scss index e8661ec16..74450627a 100644 --- a/packages/frontend/src/routes/blocks/Blocks.scss +++ b/packages/frontend/src/app/blocks/Blocks.scss @@ -2,7 +2,7 @@ .ListNavigation { display: flex; justify-content: space-between; - align-items: end; + align-items: flex-end; margin-top: 10px; flex-wrap: wrap; } diff --git a/packages/frontend/src/app/blocks/page.js b/packages/frontend/src/app/blocks/page.js new file mode 100644 index 000000000..ed19c941b --- /dev/null +++ b/packages/frontend/src/app/blocks/page.js @@ -0,0 +1,15 @@ +import Blocks from './Blocks' + + +export const metadata = { + title: 'Blocks — Dash Platform Explorer', + description: 'Blocks that are included in the Dash Platform blockchain. The Timestamp, Hash, Transactions count.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'blocks', 'Timestamp', 'Hash', 'Transactions'], + applicationName: 'Dash Platform Explorer' +} + +async function BlocksRoute() { + return +} + +export default BlocksRoute; diff --git a/packages/frontend/src/routes/dataContract/data.contract.route.js b/packages/frontend/src/app/dataContract/[identifier]/DataContract.js similarity index 54% rename from packages/frontend/src/routes/dataContract/data.contract.route.js rename to packages/frontend/src/app/dataContract/[identifier]/DataContract.js index efa781f70..69553961e 100644 --- a/packages/frontend/src/routes/dataContract/data.contract.route.js +++ b/packages/frontend/src/app/dataContract/[identifier]/DataContract.js @@ -1,18 +1,19 @@ -import React, {useState} from 'react' -import {Link} from 'react-router-dom' -import {useLoaderData} from 'react-router-dom' -import * as Api from '../../util/Api' -import ReactPaginate from 'react-paginate' -import DocumentsList from '../../components/documents/DocumentsList' +'use client' + +import { useState, useEffect } from 'react' +import Link from 'next/link' +import * as Api from '../../../util/Api' +import Pagination from '../../../components/pagination' +import DocumentsList from '../../../components/documents/DocumentsList' import './DataContract.scss' -import { +import { Box, Container, TableContainer, Table, Thead, Tbody, Tfoot, Tr, Th, Td, Tabs, TabList, TabPanels, Tab, TabPanel, Code -} from '@chakra-ui/react'; +} from '@chakra-ui/react' const pagintationConfig = { @@ -23,35 +24,48 @@ const pagintationConfig = { defaultPage: 1 } -export async function loader({params}) { - const {identifier} = params - const [dataContract, documents] = await Promise.all([ - Api.getDataContractByIdentifier(identifier), - Api.getDocumentsByDataContract(identifier, - pagintationConfig.defaultPage, - pagintationConfig.itemsOnPage.default + 1) - ]) +function DataContract({identifier}) { + const [dataContract, setDataContract] = useState({}) + const [documents, setDocuments] = useState([]) + const pageSize = pagintationConfig.itemsOnPage.default + const [total, setTotal] = useState(1) + const [currentPage, setCurrentPage] = useState(0) + const pageCount = Math.ceil(total / pageSize) + const [loading, setLoading] = useState(true) + + const fetchData = () => { + setLoading(true) + + Promise.all([ + Api.getDataContractByIdentifier(identifier), + Api.getDocumentsByDataContract(identifier, + pagintationConfig.defaultPage, + pagintationConfig.itemsOnPage.default + 1) + ]) + .then(([defaultDataContract, defaultDocuments]) => { + setDataContract(defaultDataContract) + setDocuments(defaultDocuments.resultSet) + setTotal(defaultDocuments.pagination.total) + }) + .catch(console.log) + .finally(() => { + setLoading(false) + }) + } - return { - dataContract, - documents - }; -} + useEffect(fetchData, [identifier]) -function DataContractRoute() { - const {dataContract, documents: defaultDocuments} = useLoaderData(); - const [documents, setDocuments] = useState(defaultDocuments.resultSet) - const pageCount = Math.ceil(defaultDocuments.pagination.total / pagintationConfig.itemsOnPage.default); + const handlePageClick = ({selected}) => { + Api.getDocumentsByDataContract(dataContract.identifier, + selected + 1, + pagintationConfig.itemsOnPage.default + 1) + .then((res) => setDocuments(res.resultSet)) - const handlePageClick = async ({selected}) => { - const {resultSet} = await Api.getDocumentsByDataContract(dataContract.identifier, - selected + 1, - pagintationConfig.itemsOnPage.default + 1) - setDocuments(resultSet); + setCurrentPage(selected) } - return ( + if (!loading) return ( Transaction - {dataContract.txHash} + {dataContract.txHash} @@ -115,25 +129,14 @@ function DataContractRoute() { columnsCount={2} /> - + + {pageCount > 1 && + + } @@ -146,7 +149,7 @@ function DataContractRoute() { p={4} w='100%' > - {JSON.stringify(dataContract.schema, null, 2)} + {JSON.stringify(JSON.parse(dataContract.schema), null, 2)}
@@ -154,11 +157,8 @@ function DataContractRoute() {
- - - - ); + ) } -export default DataContractRoute; +export default DataContract; diff --git a/packages/frontend/src/routes/dataContract/DataContract.scss b/packages/frontend/src/app/dataContract/[identifier]/DataContract.scss similarity index 100% rename from packages/frontend/src/routes/dataContract/DataContract.scss rename to packages/frontend/src/app/dataContract/[identifier]/DataContract.scss diff --git a/packages/frontend/src/app/dataContract/[identifier]/page.js b/packages/frontend/src/app/dataContract/[identifier]/page.js new file mode 100644 index 000000000..8d7ed096d --- /dev/null +++ b/packages/frontend/src/app/dataContract/[identifier]/page.js @@ -0,0 +1,17 @@ +import DataContract from './DataContract' + + +export async function generateMetadata({ params }) { + return { + title: 'Data Contract #' + params.identifier + ' — Dash Platform Explorer', + description: 'Data Contract ' + params.identifier + 'on Dash Platform. The Schema, Documents, Date of Creation, Revision, Transaction.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'data contract', 'datacontract', 'Schema', 'Documents', 'Date of Creation', 'Revision', 'Transaction'], + applicationName: 'Dash Platform Explorer' + } +} + +function DataContractRoute({params}) { + return +} + +export default DataContractRoute diff --git a/packages/frontend/src/app/dataContracts/DataContracts.js b/packages/frontend/src/app/dataContracts/DataContracts.js new file mode 100644 index 000000000..e9d57b30a --- /dev/null +++ b/packages/frontend/src/app/dataContracts/DataContracts.js @@ -0,0 +1,80 @@ +'use client' + +import { useEffect, useState } from 'react' +import * as Api from '../../util/Api' +import DataContractsList from '../../components/dataContracts/DataContractsList' +import Pagination from '../../components/pagination' + +import { + Container, + Heading, +} from '@chakra-ui/react' + + +function DataContractsLayout() { + const [loading, setLoading] = useState(true) + const [dataContracts, setDataContracts] = useState(null) + const [total, setTotal] = useState(1) + const pageSize = 25 + const [currentPage, setCurrentPage] = useState(0) + const pageCount = Math.ceil(total / pageSize) + + const fetchData = () => { + setLoading(true) + + Api.getDataContracts(1, pageSize) + .then((res) => { + setDataContracts(res.resultSet) + setTotal(res.pagination.total) + }) + .catch(console.log) + .finally(() => { + setLoading(false) + }) + } + + useEffect(fetchData, []) + + const handlePageClick = ({selected}) => { + Api.getDataContracts(selected+1, pageSize, 'desc') + .then((res) => { + setCurrentPage(selected) + setDataContracts(res.resultSet) + }) + } + + if (!loading) return ( +
+ {dataContracts && + + + Data contracts + + + + {pageCount > 1 && +
+ +
+ } + + +
+ } + +
+ ) +} + +export default DataContractsLayout \ No newline at end of file diff --git a/packages/frontend/src/app/dataContracts/page.js b/packages/frontend/src/app/dataContracts/page.js new file mode 100644 index 000000000..dc61837c4 --- /dev/null +++ b/packages/frontend/src/app/dataContracts/page.js @@ -0,0 +1,15 @@ +import DataContracts from './DataContracts' + + +export const metadata = { + title: 'Data Contracts — Dash Platform Explorer', + description: 'Data Contracts on Dash Platform. The Identifier, Date of Creation.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'data contrancts', 'Datacontract', 'Identifier', 'Date of Creation'], + applicationName: 'Dash Platform Explorer' +} + +function DataContractsRoute() { + return +} + +export default DataContractsRoute; diff --git a/packages/frontend/src/routes/document/document.route.js b/packages/frontend/src/app/document/[identifier]/Document.js similarity index 75% rename from packages/frontend/src/routes/document/document.route.js rename to packages/frontend/src/app/document/[identifier]/Document.js index 00f4ebf51..e0c510f25 100644 --- a/packages/frontend/src/routes/document/document.route.js +++ b/packages/frontend/src/app/document/[identifier]/Document.js @@ -1,7 +1,8 @@ -import React from 'react'; -import {useLoaderData} from "react-router-dom"; -import * as Api from "../../util/Api"; -import './document.scss' +'use client' + +import { useState, useEffect } from 'react' +import * as Api from "../../../util/Api" +import './Document.scss' import { Box, @@ -10,18 +11,27 @@ import { Heading, Flex, Code -} from "@chakra-ui/react"; +} from "@chakra-ui/react" -export async function loader({params}) { - const {identifier} = params - return await Api.getDocumentByIdentifier(identifier); -} +function Document({identifier}) { + const [document, setDocument] = useState({}) + const [loading, setLoading] = useState(true) + + const fetchData = () => { + setLoading(true) + + Api.getDocumentByIdentifier(identifier) + .then(setDocument) + .catch(console.log) + .finally(() => { + setLoading(false) + }) + } -function DocumentRoute() { - const document = useLoaderData() + useEffect(fetchData, [identifier]) - return ( + if (!loading) return ( - {JSON.stringify(document.data, null, 2)} + {JSON.stringify(JSON.parse(document.data), null, 2)} - ); + ) } -export default DocumentRoute; +export default Document diff --git a/packages/frontend/src/routes/document/document.scss b/packages/frontend/src/app/document/[identifier]/Document.scss similarity index 100% rename from packages/frontend/src/routes/document/document.scss rename to packages/frontend/src/app/document/[identifier]/Document.scss diff --git a/packages/frontend/src/app/document/[identifier]/page.js b/packages/frontend/src/app/document/[identifier]/page.js new file mode 100644 index 000000000..a17178fd0 --- /dev/null +++ b/packages/frontend/src/app/document/[identifier]/page.js @@ -0,0 +1,17 @@ +import Document from './Document' + + +export async function generateMetadata({ params }) { + return { + title: 'Document #' + params.identifier + ' — Dash Platform Explorer', + description: 'Document ' + params.identifier + ' on Dash Platform. The Data, Identifier, Revision.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'document', 'Data', 'Identifier', 'Revision'], + applicationName: 'Dash Platform Explorer' + } +} + +function DocumentRoute({ params }) { + return +} + +export default DocumentRoute diff --git a/packages/frontend/src/routes/enums/state.transition.type.js b/packages/frontend/src/app/enums/state.transition.type.js similarity index 100% rename from packages/frontend/src/routes/enums/state.transition.type.js rename to packages/frontend/src/app/enums/state.transition.type.js diff --git a/packages/frontend/src/routes/error/error.route.js b/packages/frontend/src/app/error/error.route.js similarity index 100% rename from packages/frontend/src/routes/error/error.route.js rename to packages/frontend/src/app/error/error.route.js diff --git a/packages/frontend/src/app/home/Home.js b/packages/frontend/src/app/home/Home.js new file mode 100644 index 000000000..e8a40896c --- /dev/null +++ b/packages/frontend/src/app/home/Home.js @@ -0,0 +1,139 @@ +'use client' + +import { useState, useEffect } from 'react' +import * as Api from '../../util/Api' +import TransactionsList from '../../components/transactions/TransactionsList' + +import { + Box, + Text, + Container, + Heading, + Flex, + Stack, + StackDivider +} from '@chakra-ui/react' + + +function Home() { + const [loading, setLoading] = useState(true) + const [status, setStatus] = useState(true) + const [transactions, setTransactions] = useState([]) + + const fetchData = () => { + setLoading(true) + + Promise.all([ + Api.getStatus(), + Api.getTransactions(1, 25, 'desc') + ]) + .then(([status, paginatedTransactions]) => { + setStatus(status) + setTransactions(paginatedTransactions.resultSet) + }) + .catch(console.log) + .finally(() => setLoading(false)) + } + + useEffect(fetchData, []) + + if (!loading) return ( + + + } + > + + + + Network: + {status.network} + + + + Tenderdash Version: + {status.tenderdashVersion} + + + + App Version: + {status.appVersion} + + + + + + + + Average block time: + {Math.ceil(status.blockTimeAverage)} sec. + + + + Blocks: + {status.blocksCount} + + + + Transactions: + {status.txCount} + + + + + + + + Data contracts: + {status.dataContractsCount} + + + + Documents: + {status.documentsCount} + + + + Transfers: + {status.transfersCount} + + + + + + + + + Last transaction + + + + + + + + ); +} + +export default Home; diff --git a/packages/frontend/src/app/identities/Identities.js b/packages/frontend/src/app/identities/Identities.js new file mode 100644 index 000000000..0c16194a9 --- /dev/null +++ b/packages/frontend/src/app/identities/Identities.js @@ -0,0 +1,76 @@ +'use client' + +import {useEffect, useState} from 'react' +import * as Api from '../../util/Api' +import IdentitiesList from '../../components/identities/IdentitiesList' +import Pagination from '../../components/pagination' + +import { + Container, + Heading, +} from '@chakra-ui/react' + + +function Identities() { + const [loading, setLoading] = useState(true) + const [identities, setIdentities] = useState([]) + const [total, setTotal] = useState(1) + const pageSize = 25 + const [currentPage, setCurrentPage] = useState(0) + const pageCount = Math.ceil(total / pageSize) + + const fetchData = () => { + setLoading(true) + + Api.getIdentities(1, pageSize) + .then((identities) => { + setIdentities(identities.resultSet) + setTotal(identities.pagination.total) + }) + .catch(console.log) + .finally(() => setLoading(false)) + } + + useEffect(fetchData, []) + + const handlePageClick = ({selected}) => { + Api.getDataContracts(selected+1, pageSize, 'desc') + .then((res) => { + setCurrentPage(selected) + setIdentities(res.resultSet) + }) + } + + return ( + + + Identities + + {!loading && <> + + + {pageCount > 1 && +
+ +
+ } + } + +
+
+ ) +} + +export default Identities diff --git a/packages/frontend/src/app/identities/page.js b/packages/frontend/src/app/identities/page.js new file mode 100644 index 000000000..61c407130 --- /dev/null +++ b/packages/frontend/src/app/identities/page.js @@ -0,0 +1,15 @@ +import Identities from './Identities' + + +export const metadata = { + title: 'Identities — Dash Platform Explorer', + description: 'Identities on Dash Platform. The Identifier, Date of Creation', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'Identities'], + applicationName: 'Dash Platform Explorer' +} + +function IdentitiesRoute() { + return +} + +export default IdentitiesRoute; diff --git a/packages/frontend/src/routes/identity/identity.route.js b/packages/frontend/src/app/identity/[identifier]/Identity.js similarity index 74% rename from packages/frontend/src/routes/identity/identity.route.js rename to packages/frontend/src/app/identity/[identifier]/Identity.js index 26f17c265..19741bfee 100644 --- a/packages/frontend/src/routes/identity/identity.route.js +++ b/packages/frontend/src/app/identity/[identifier]/Identity.js @@ -1,11 +1,13 @@ -import {useLoaderData} from "react-router-dom"; -import * as Api from "../../util/Api"; -import {Link} from "react-router-dom"; -import TransactionsList from "../../components/transactions/TransactionsList"; -import DocumentsList from "../../components/documents/DocumentsList"; -import DataContractsList from "../../components/dataContracts/DataContractsList"; -import TransfersList from "../../components/transfers/TransfersList"; -import './identity.scss' +'use client' + +import { useState, useEffect } from 'react' +import * as Api from "../../../util/Api"; +import Link from 'next/link' +import TransactionsList from "../../../components/transactions/TransactionsList"; +import DocumentsList from "../../../components/documents/DocumentsList"; +import DataContractsList from "../../../components/dataContracts/DataContractsList"; +import TransfersList from "../../../components/transfers/TransfersList"; +import './Identity.scss' import { Box, @@ -16,36 +18,44 @@ import { } from "@chakra-ui/react" -export async function loader({params}) { - const {identifier} = params - - const [identity, dataContracts, documents, transactions, transfers] = await Promise.all([ - Api.getIdentity(identifier), - Api.getDataContractsByIdentity(identifier), - Api.getDocumentsByIdentity(identifier), - Api.getTransactionsByIdentity(identifier), - Api.getTransfersByIdentity(identifier), - ]) - - return { - identity, - dataContracts, - documents, - transactions, - transfers - }; -} - -function IdentityRoute() { - const { - identity, - dataContracts, - documents, - transactions, - transfers - } = useLoaderData(); - - return ( +function Identity({identifier}) { + const [identity, setIdentity] = useState({}) + const [dataContracts, setDataContracts] = useState([]) + const [documents, setDocuments] = useState([]) + const [transactions, setTransactions] = useState([]) + const [transfers, setTransfers] = useState([]) + const [loading, setLoading] = useState(true) + + const fetchData = () => { + setLoading(true) + + Promise.all([ + Api.getIdentity(identifier), + Api.getDataContractsByIdentity(identifier), + Api.getDocumentsByIdentity(identifier), + Api.getTransactionsByIdentity(identifier), + Api.getTransfersByIdentity(identifier), + ]) + .then(([ + defaultIdentity, + defaultDataContracts, + defaultDocuments, + defaultTransactions, + defaultTransfers + ]) => { + setIdentity(defaultIdentity) + setDataContracts(defaultDataContracts) + setDocuments(defaultDocuments) + setTransactions(defaultTransactions) + setTransfers(defaultTransfers) + }) + .catch(console.log) + .finally(() => setLoading(false)) + } + + useEffect(fetchData, [identifier]) + + if (!loading) return (
Created - + {new Date(identity.timestamp).toLocaleString()} @@ -161,7 +171,7 @@ function IdentityRoute() {
- ); + ) } -export default IdentityRoute; +export default Identity diff --git a/packages/frontend/src/routes/identity/identity.scss b/packages/frontend/src/app/identity/[identifier]/Identity.scss similarity index 100% rename from packages/frontend/src/routes/identity/identity.scss rename to packages/frontend/src/app/identity/[identifier]/Identity.scss diff --git a/packages/frontend/src/app/identity/[identifier]/page.js b/packages/frontend/src/app/identity/[identifier]/page.js new file mode 100644 index 000000000..fa7eca7a7 --- /dev/null +++ b/packages/frontend/src/app/identity/[identifier]/page.js @@ -0,0 +1,17 @@ +import Identity from "./Identity" + + +export async function generateMetadata({ params }) { + return { + title: 'Identity #' + params.identifier + ' — Dash Platform Explorer', + description: 'Identity #' + params.identifier + ' on Dash Platform. The Identifier, Balance, Transactions, Transfers, Documents, Data contracts', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'Identity', 'Identifier', 'Balance', 'Transactions', 'Transfers', 'Documents', 'Data contracts'], + applicationName: 'Dash Platform Explorer' + } +} + +function IdentityRoute({ params }) { + return +} + +export default IdentityRoute; diff --git a/packages/frontend/src/app/layout.js b/packages/frontend/src/app/layout.js new file mode 100644 index 000000000..48ec47bc1 --- /dev/null +++ b/packages/frontend/src/app/layout.js @@ -0,0 +1,16 @@ +import RootComponent from '../components/RootComponent' + + +export default function RootLayout({ children }) { + return ( + + + + + { children } + + + + + ) +} \ No newline at end of file diff --git a/packages/frontend/src/app/page.js b/packages/frontend/src/app/page.js new file mode 100644 index 000000000..481a81690 --- /dev/null +++ b/packages/frontend/src/app/page.js @@ -0,0 +1,15 @@ +import Home from './home/Home' + + +export const metadata = { + title: 'Dashboard — Dash Platform Explorer', + description: 'Dashboard of Dash Platform. The Last Transactions, Blocks, Data contracts, Documents, Transfers, Average block time.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'Transactions', 'Blocks', ' Data contracts', 'Documents', 'Transfers', 'platform dash money'], + applicationName: 'Dash Platform Explorer' +} + +async function HomeRoute() { + return +} + +export default HomeRoute diff --git a/packages/frontend/src/routes/transaction/transaction.route.js b/packages/frontend/src/app/transaction/[hash]/Transaction.js similarity index 75% rename from packages/frontend/src/routes/transaction/transaction.route.js rename to packages/frontend/src/app/transaction/[hash]/Transaction.js index 60aef6a45..d3e25475b 100644 --- a/packages/frontend/src/routes/transaction/transaction.route.js +++ b/packages/frontend/src/app/transaction/[hash]/Transaction.js @@ -1,9 +1,11 @@ -import * as Api from '../../util/Api' -import {Link, useLoaderData} from 'react-router-dom' +'use client' + +import * as Api from '../../../util/Api' +import Link from 'next/link' import {useState, useEffect} from 'react' -import {getTransitionTypeString} from '../../util' -import {StateTransitionEnum} from "../enums/state.transition.type" -import './transaction.scss' +import {getTransitionTypeString} from '../../../util' +import {StateTransitionEnum} from "../../enums/state.transition.type" +import './Transaction.scss' import { Container, @@ -12,14 +14,6 @@ import { } from '@chakra-ui/react' -export async function loader({params}) { - const { txHash } = params - - const transaction = await Api.getTransaction(txHash) - - return { transaction } -} - function TransactionData({data}) { if (data === null) return <> @@ -35,11 +29,11 @@ function TransactionData({data}) { Data contract - {data.dataContractId} + {data.dataContractId} Owner - {data.identityId} + {data.identityId} ) @@ -58,11 +52,11 @@ function TransactionData({data}) { Data contract - {transition.dataContractId} + {transition.dataContractId} Document - {transition.id} + {transition.id} )} @@ -81,7 +75,7 @@ function TransactionData({data}) { Identity - {data.identityId} + {data.identityId} ) @@ -121,11 +115,11 @@ function TransactionData({data}) { Data contract - {data.dataContractId} + {data.dataContractId} Owner - {data.identityId} + {data.identityId} Version @@ -147,7 +141,7 @@ function TransactionData({data}) { Identity - {data.identityId} + {data.identityId} Revision @@ -173,7 +167,7 @@ function TransactionData({data}) { Identity - {data.identityId} + {data.identityId} ) @@ -195,21 +189,23 @@ function TransactionData({data}) { Sender - {data.senderId} + {data.senderId} Recipient - {data.recipientId} + {data.recipientId} ) } } -function TransactionRoute() { - const { transaction } = useLoaderData() - - const { hash, blockHeight, index, type, timestamp, data } = transaction +function Transaction({hash}) { + const [transaction, setTransaction] = useState({}) + const [loading, setLoading] = useState(true) + const [decoding, setDecoding] = useState(false) + const [decodingError, setDecodingError] = useState(null) + const [decodedST, setDecodedST] = useState(null) const decodeTx = (tx) => { if (decodedST || decoding) { @@ -231,15 +227,21 @@ function TransactionRoute() { .finally(() => setDecoding(false)) } - const [decoding, setDecoding] = useState(false) - const [decodingError, setDecodingError] = useState(null) - const [decodedST, setDecodedST] = useState(null) + const fetchData = () => { + setLoading(true) + + Api.getTransaction(hash) + .then((res) => { + setTransaction(res) + decodeTx(res.data) + }) + .catch(console.log) + .finally(() => setLoading(false)) + } - useEffect(() => { - decodeTx(data) - }, []) + useEffect(fetchData, [hash]) - return ( + if (!loading) return ( Hash - {hash} + {transaction.hash} Height - {blockHeight} + {transaction.blockHeight} Index - {index} + {transaction.index} Type - {getTransitionTypeString(type)} + {getTransitionTypeString(transaction.type)} Timestamp - {new Date(timestamp).toLocaleString()} + {new Date(transaction.timestamp).toLocaleString()} @@ -301,4 +303,4 @@ function TransactionRoute() { ) } -export default TransactionRoute +export default Transaction diff --git a/packages/frontend/src/routes/transaction/transaction.scss b/packages/frontend/src/app/transaction/[hash]/Transaction.scss similarity index 100% rename from packages/frontend/src/routes/transaction/transaction.scss rename to packages/frontend/src/app/transaction/[hash]/Transaction.scss diff --git a/packages/frontend/src/app/transaction/[hash]/page.js b/packages/frontend/src/app/transaction/[hash]/page.js new file mode 100644 index 000000000..2ac83923c --- /dev/null +++ b/packages/frontend/src/app/transaction/[hash]/page.js @@ -0,0 +1,17 @@ +import Transaction from'./Transaction' + + +export function generateMetadata({ params }) { + return { + title: 'Transaction #' + params.hash + ' — Dash Platform Explorer', + description: 'Transaction #' + params.hash + ' on dash platform. The Hash, Height, Type, Timestamp, Transaction data.', + keywords: ['Dash', 'platform', 'explorer', 'blockchain', 'Transaction', 'Hash', 'Height', 'Type', 'Timestamp', 'Data'], + applicationName: 'Dash Platform Explorer' + } +} + +function TransactionRoute({params}) { + return +} + +export default TransactionRoute diff --git a/packages/frontend/src/components/RootComponent.js b/packages/frontend/src/components/RootComponent.js index 42cdccd2f..842b90f1d 100644 --- a/packages/frontend/src/components/RootComponent.js +++ b/packages/frontend/src/components/RootComponent.js @@ -1,21 +1,25 @@ -import {Outlet, Link} from "react-router-dom"; -import "./root.css"; -import React, {useState} from 'react'; -import Navbar from "../components/navbar/Navbar"; -import theme from "../styles/theme"; -import "../styles/theme.scss"; -import { ChakraProvider} from '@chakra-ui/react' +'use client' +import Navbar from '../components/navbar/Navbar' +import { ChakraProvider, localStorageManager } from '@chakra-ui/react' +import { useEffect } from "react"; +import theme from '../styles/theme' +import '../styles/theme.scss' -export default function RootComponent() { + + +export default function RootComponent({ children }) { + useEffect(() => { + localStorage.setItem('chakra-ui-color-mode', theme.initialColorMode) + }, []) return ( - + - + { children } - ); -} + ) +} \ No newline at end of file diff --git a/packages/frontend/src/components/blocks/BlocksList.js b/packages/frontend/src/components/blocks/BlocksList.js index 0e3eb2ebb..9e8b1d70b 100644 --- a/packages/frontend/src/components/blocks/BlocksList.js +++ b/packages/frontend/src/components/blocks/BlocksList.js @@ -1,4 +1,3 @@ -import {Link} from "react-router-dom"; import BlocksListItem from './BlocksListItem' import './BlocksList.scss' diff --git a/packages/frontend/src/components/blocks/BlocksListItem.js b/packages/frontend/src/components/blocks/BlocksListItem.js index d17b887c0..1759e29b3 100644 --- a/packages/frontend/src/components/blocks/BlocksListItem.js +++ b/packages/frontend/src/components/blocks/BlocksListItem.js @@ -1,4 +1,4 @@ -import {Link} from 'react-router-dom' +import Link from 'next/link' import './BlocksListItem.scss' @@ -8,7 +8,7 @@ function BlocksListItem ({ block }) { return( {(typeof height === 'number' && diff --git a/packages/frontend/src/components/blocks/BlocksListItem.scss b/packages/frontend/src/components/blocks/BlocksListItem.scss index 740908073..7f047946d 100644 --- a/packages/frontend/src/components/blocks/BlocksListItem.scss +++ b/packages/frontend/src/components/blocks/BlocksListItem.scss @@ -3,10 +3,6 @@ .BlocksListItem { @include mixins.def_list_item; - &:last-child { - border-bottom: none; - } - &__Hash { color: var(--chakra-colors-gray-200); flex-grow: 1; diff --git a/packages/frontend/src/components/dataContracts/DataContractsListItem.js b/packages/frontend/src/components/dataContracts/DataContractsListItem.js index b90c8d333..25a2df0cf 100644 --- a/packages/frontend/src/components/dataContracts/DataContractsListItem.js +++ b/packages/frontend/src/components/dataContracts/DataContractsListItem.js @@ -1,4 +1,4 @@ -import {Link} from 'react-router-dom'; +import Link from 'next/link' import './DataContractsListItem.scss' @@ -7,7 +7,7 @@ function DataContractsListItem ({ dataContract }) { return (
diff --git a/packages/frontend/src/components/documents/DocumentsListItem.js b/packages/frontend/src/components/documents/DocumentsListItem.js index caa673e47..fa9cacc57 100644 --- a/packages/frontend/src/components/documents/DocumentsListItem.js +++ b/packages/frontend/src/components/documents/DocumentsListItem.js @@ -1,4 +1,4 @@ -import {Link} from 'react-router-dom'; +import Link from 'next/link' import './DocumentsListItem.scss' @@ -7,7 +7,7 @@ export default function DocumentsListItem({document}) { return ( diff --git a/packages/frontend/src/components/identities/IdentitiesListItem.js b/packages/frontend/src/components/identities/IdentitiesListItem.js index 806b7c6ff..c711bc456 100644 --- a/packages/frontend/src/components/identities/IdentitiesListItem.js +++ b/packages/frontend/src/components/identities/IdentitiesListItem.js @@ -1,4 +1,4 @@ -import {Link} from "react-router-dom"; +import Link from 'next/link' import './IdentitiesListItem.scss' @@ -7,7 +7,7 @@ function IdentitiesListItem ({identity}) { return (
diff --git a/packages/frontend/src/components/modalWindow/ModalWindow.scss b/packages/frontend/src/components/modalWindow/ModalWindow.scss new file mode 100644 index 000000000..57f6790e7 --- /dev/null +++ b/packages/frontend/src/components/modalWindow/ModalWindow.scss @@ -0,0 +1,39 @@ +.modal { + position: fixed; + bottom: 0; + right: 0; + top: 0; + left: 0; + z-index: 9999; + } + + .modal_container { + display: flex; + justify-content: center; + align-items:center; + height: 100%; + background-color: rgba(0, 0, 0, 0.8); + } + + .modal_message { + display: flex; + position: relative; + justify-content: center; + align-items: center; + height: 30%; + min-width: 300px; + color: black; + background-color: rgb(101, 80, 11); + } + + .modal_close { + position: absolute; + top: 0; + right: 0; + font-size: 20pt; + padding: 10px; + } + + .modal_close:hover { + cursor: pointer; + } \ No newline at end of file diff --git a/packages/frontend/src/components/ModalWindow.js b/packages/frontend/src/components/modalWindow/index.js similarity index 88% rename from packages/frontend/src/components/ModalWindow.js rename to packages/frontend/src/components/modalWindow/index.js index 51e378259..adf527929 100644 --- a/packages/frontend/src/components/ModalWindow.js +++ b/packages/frontend/src/components/modalWindow/index.js @@ -1,5 +1,4 @@ -import "./root.css"; -import React, {useState} from 'react'; +import "./ModalWindow.scss" export default function ModalWindow({open, text, setShowModal}) { diff --git a/packages/frontend/src/components/navbar/Navbar.js b/packages/frontend/src/components/navbar/Navbar.js index 9d968b3b2..90df30d6f 100644 --- a/packages/frontend/src/components/navbar/Navbar.js +++ b/packages/frontend/src/components/navbar/Navbar.js @@ -35,6 +35,7 @@ const NavLink = (props) => { textDecoration: 'none', bg: useColorModeValue('brand.deep', 'brand.deep'), }} + color={'white'} href={to}> {children} diff --git a/packages/frontend/src/components/pagination/index.js b/packages/frontend/src/components/pagination/index.js new file mode 100644 index 000000000..ca20c2125 --- /dev/null +++ b/packages/frontend/src/components/pagination/index.js @@ -0,0 +1,32 @@ +import './pagination.scss' + +import ReactPaginate from 'react-paginate' + +function Pagination ({onPageChange, pageCount, forcePage}) { + const forcePageProp = forcePage ? { forcePage: forcePage } : {} + + return ( + + ) +} + +export default Pagination \ No newline at end of file diff --git a/packages/frontend/src/components/pagination/pagination.scss b/packages/frontend/src/components/pagination/pagination.scss new file mode 100644 index 000000000..04e7b1778 --- /dev/null +++ b/packages/frontend/src/components/pagination/pagination.scss @@ -0,0 +1,65 @@ +.pagination { + display: flex; + justify-content: center; + list-style: none; + padding: 0; +} + +.page-item { + padding: 1px 4px 2px; + margin: 0 2px; + cursor: pointer; + font-size: 14pt; + -webkit-user-select: none; + -ms-user-select: none; + text-align: center; + border-radius: 5px; +} + +.page-item:hover:not(.disabled) { + background-color: #ffffff10; +} + +.page-item--next, +.page-item--previous { + display: inline-block; + width: 22px; + padding: 0px 2px 2px; + border: 1px solid #ffffff75; + border-radius: 5px; + user-select: none; +} + +.page-item--next:hover:not(.disabled), +.page-item--previous:hover:not(.disabled) { + border: 1px solid #ffffff; + background-color: #ffffff15; +} + +.page-link { + position: relative; +} + +.page-item.disabled { + cursor: default; + opacity: .3; +} + +.active, .active:hover { + background-color: var(--chakra-colors-gray-800); +} + +.page-item.active:hover { + cursor: default; +} + +.page-item--break-link { + padding: 1px 2px 2px; + margin: 0; +} + +@media screen and (max-width: 440px) { + .page-item:not(.active):not(.page-item--previous):not(.page-item--next) { + display: none; + } +} \ No newline at end of file diff --git a/packages/frontend/src/components/root.css b/packages/frontend/src/components/root.css deleted file mode 100644 index 5a841f420..000000000 --- a/packages/frontend/src/components/root.css +++ /dev/null @@ -1,68 +0,0 @@ -/* Add a black background color to the top navigation bar */ -.topnav { - overflow: hidden; - background-color: black; -} - -/* Style the links inside the navigation bar */ -.topnav a { - float: left; - display: block; - color: white; - text-align: center; - padding: 14px 16px; - text-decoration: none; - font-size: 17px; -} - -/* Change the color of links on hover */ -.topnav a:hover { - background-color: #1a491c; - color: black; -} - -/* Style the "active" element to highlight the current page */ -.topnav a.active { - background-color: #2196F3; - color: white; -} - -/* Style the search box inside the navigation bar */ -.topnav input[type=text] { - float: right; - padding: 6px; - border: none; - min-width: 400px; - border-radius: 5px; - margin-top: 8px; - margin-right: 16px; - font-size: 20px; - background-color: #1a491c; - color: black; -} - -.topnav input[type=text]:focus { - outline: none; -} - -::placeholder { - color: black; - opacity: 0.5 -} - -/* When the screen is less than 600px wide, stack the links and the search field vertically instead of horizontally */ -@media screen and (max-width: 600px) { - .topnav a, .topnav input[type=text] { - float: none; - display: block; - text-align: left; - width: 100%; - margin: 0; - padding: 14px; - min-width: auto; - box-sizing: border-box; - } - .topnav input[type=text] { - border: 1px solid #ccc; - } -} diff --git a/packages/frontend/src/components/search/GlobalSearchInput.js b/packages/frontend/src/components/search/GlobalSearchInput.js index efe35d765..8493eca88 100644 --- a/packages/frontend/src/components/search/GlobalSearchInput.js +++ b/packages/frontend/src/components/search/GlobalSearchInput.js @@ -1,14 +1,11 @@ -import React, {useState} from 'react'; -import {useNavigate} from "react-router-dom"; -import ModalWindow from "../ModalWindow"; +import { useState } from 'react' +import ModalWindow from "../modalWindow" import * as Api from '../../util/Api' import { Input, InputGroup, InputRightElement, Button } from '@chakra-ui/react' import { SearchIcon } from '@chakra-ui/icons' - +import { redirect } from 'next/navigation' function GlobalSearchInput () { - let navigate = useNavigate(); - const [showModal, setShowModal] = useState(false) const [modalText, setModalText] = useState("false") @@ -33,22 +30,22 @@ function GlobalSearchInput () { if (searchResult?.block) { // redirect to blocks setSearchQuery("") - return navigate(`/block/${searchResult?.block.header.hash}`) + redirect(`/block/${searchResult?.block.header.hash}`) } if (searchResult?.transaction) { setSearchQuery("") - return navigate(`/transaction/${searchResult?.transaction.hash}`) + redirect(`/transaction/${searchResult?.transaction.hash}`) } if (searchResult?.dataContract) { setSearchQuery("") - return navigate(`/dataContract/${searchResult?.dataContract.identifier}`) + redirect(`/dataContract/${searchResult?.dataContract.identifier}`) } if (searchResult?.document) { setSearchQuery("") - return navigate(`/document/${searchResult?.document.identifier}`) + redirect(`/document/${searchResult?.document.identifier}`) } showModalWindow('Not found', 6000) @@ -81,8 +78,14 @@ function GlobalSearchInput () { bg='gray.900' /> - diff --git a/packages/frontend/src/components/transactions/TransactionsList.js b/packages/frontend/src/components/transactions/TransactionsList.js index b0590211b..a14f18066 100644 --- a/packages/frontend/src/components/transactions/TransactionsList.js +++ b/packages/frontend/src/components/transactions/TransactionsList.js @@ -1,7 +1,8 @@ +'use client' + import TransactionsListItem from './TransactionsListItem' import './TransactionsList.scss' - export default function TransactionsList({transactions = [], size='l'}) { return ( @@ -22,5 +23,5 @@ export default function TransactionsList({transactions = [], size='l'}) {
- ); + ) } diff --git a/packages/frontend/src/components/transactions/TransactionsListItem.js b/packages/frontend/src/components/transactions/TransactionsListItem.js index 0025bfb59..868d37b1b 100644 --- a/packages/frontend/src/components/transactions/TransactionsListItem.js +++ b/packages/frontend/src/components/transactions/TransactionsListItem.js @@ -1,15 +1,17 @@ -import {Link} from 'react-router-dom' +'use client' + +import Link from 'next/link' import {getTransitionTypeString} from '../../util/index' import './TransactionsListItem.scss' function TransactionsListItem({ transaction }) { - const hash = typeof transaction === 'object' ? transaction.hash : transaction; + const hash = typeof transaction === 'object' ? transaction.hash : transaction const {timestamp, type} = transaction return ( @@ -35,4 +37,4 @@ function TransactionsListItem({ transaction }) { ) } -export default TransactionsListItem; \ No newline at end of file +export default TransactionsListItem \ No newline at end of file diff --git a/packages/frontend/src/components/transfers/TransfersListItem.js b/packages/frontend/src/components/transfers/TransfersListItem.js index 5e3756f67..f07181578 100644 --- a/packages/frontend/src/components/transfers/TransfersListItem.js +++ b/packages/frontend/src/components/transfers/TransfersListItem.js @@ -1,4 +1,3 @@ -import {Link} from 'react-router-dom' import { Box, Tag } from '@chakra-ui/react' import { ArrowForwardIcon, ArrowBackIcon } from '@chakra-ui/icons' import './TransfersListItem.scss' diff --git a/packages/frontend/src/index.css b/packages/frontend/src/index.css deleted file mode 100644 index 5221317ce..000000000 --- a/packages/frontend/src/index.css +++ /dev/null @@ -1,146 +0,0 @@ -body { - margin: 0; - background-color: black; - color: white; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} - -.container { - display: flex; - justify-content: center; - align-content: center; - height: 100%; - margin: 0; - align-items: center; - flex-flow: column; - padding: 10px; -} - -.modal { - position: fixed; - bottom: 0; - right: 0; - top: 0; - left: 0; - z-index: 9999; -} - -.modal_container { - display: flex; - justify-content: center; - align-items:center; - height: 100%; - background-color: rgba(0, 0, 0, 0.8); -} - -.modal_message { - display: flex; - position: relative; - justify-content: center; - align-items: center; - height: 30%; - min-width: 300px; - color: black; - background-color: rgb(101, 80, 11); -} - -.modal_close { - position: absolute; - top: 0; - right: 0; - font-size: 20pt; - padding: 10px; -} - -.modal_close:hover { - cursor: pointer; -} - -.pagination { - display: flex; - justify-content: center; - list-style: none; - padding: 0; -} - -.page-item { - padding: 1px 4px 2px; - margin: 0 2px; - cursor: pointer; - font-size: 14pt; - -webkit-user-select: none; - -ms-user-select: none; - text-align: center; - border-radius: 5px; -} - -.page-item:hover:not(.disabled) { - background-color: #ffffff10; -} - -.page-item--next, -.page-item--previous { - display: inline-block; - width: 22px; - padding: 0px 2px 2px; - border: 1px solid #ffffff75; - border-radius: 5px; - user-select: none; -} - -.page-item--next:hover:not(.disabled), -.page-item--previous:hover:not(.disabled) { - border: 1px solid #ffffff; - background-color: #ffffff15; -} - -.page-link { - position: relative; -} - -.page-item.disabled { - cursor: default; - opacity: .3; -} - -.active, .active:hover { - background-color: var(--chakra-colors-gray-800); -} - -.page-item.active:hover { - cursor: default; -} - -.page-item--break-link { - padding: 1px 2px 2px; - margin: 0; -} - -.disabled { - display: none; -} - -.noselect { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -@media screen and (max-width: 440px) { - .page-item:not(.active):not(.page-item--previous):not(.page-item--next) { - display: none; - } - -} diff --git a/packages/frontend/src/index.js b/packages/frontend/src/index.js deleted file mode 100644 index d4c711f6d..000000000 --- a/packages/frontend/src/index.js +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import { - createBrowserRouter, - RouterProvider, -} from "react-router-dom"; -import reportWebVitals from './reportWebVitals'; -import HomeRoute, {loader as homeLoader} from "./routes/home/home.route"; -import BlockRoute, { - loader as blockLoader, -} from "./routes/block/block.route"; -import ErrorPage from "./routes/error/error.route"; -import RootComponent from "./components/RootComponent"; -import BlocksRoute, {loader as blocksLoader} from "./routes/blocks/blocks.route"; -import TransactionRoute, { - loader as transactionLoader, -} from "./routes/transaction/transaction.route"; -import DataContractRoute, {loader as dataContractLoader} from "./routes/dataContract/data.contract.route"; -import DataContractsRoute from "./routes/dataContracts/data.contracts.route"; -import DocumentRoute, {loader as documentLoader} from "./routes/document/document.route"; -import IdentityRoute, {loader as identityLoader} from "./routes/identity/identity.route"; -import IdentitiesRoute, {loader as identitiesLoader} from "./routes/identities/identities.route"; - - -const router = createBrowserRouter([ - { - path: "/", - element: , - errorElement: , - children: [ - { - index: true, - element: , - loader: homeLoader, - }, - { - path: "blocks", - element: , - loader: blocksLoader, - }, - { - path: "block/:hash", - element: , - loader: blockLoader, - }, - { - path: "transaction/:txHash", - element: , - loader: transactionLoader, - }, - { - path: "dataContract/:identifier", - element: , - loader: dataContractLoader, - }, - { - path: "dataContracts", - element: , - }, - { - path: "document/:identifier", - element: , - loader: documentLoader, - }, - { - path: "identities", - element: , - loader: identitiesLoader, - }, - { - path: "identity/:identifier", - element: , - loader: identityLoader, - }, - ] - } -]); - -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - - - -); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/packages/frontend/src/routes/dataContracts/data.contracts.route.js b/packages/frontend/src/routes/dataContracts/data.contracts.route.js deleted file mode 100644 index 7965066e1..000000000 --- a/packages/frontend/src/routes/dataContracts/data.contracts.route.js +++ /dev/null @@ -1,50 +0,0 @@ -import React, {useEffect, useState} from 'react' -import * as Api from '../../util/Api' -import DataContractsList from '../../components/dataContracts/DataContractsList' - -import { - Container, - Heading, -} from '@chakra-ui/react' - -function DataContractsRoute() { - const [dataContracts, setDataContracts] = useState(null) - const [loading, setLoading] = useState(null) - const [error, setError] = useState(null) - - useEffect(() => { - Api.getDataContracts(1, 30) - .then((dataContracts) => setDataContracts(dataContracts.resultSet)) - .catch((err) => { - setError(err) - }) - .finally(() => setLoading(false)) - }, []) - - return ( -
- {error &&
Error {error}
} - {loading &&
Loading data contracts from API
} - - {dataContracts && - - - Data contracts - - - - - } - -
- ); -} - -export default DataContractsRoute; diff --git a/packages/frontend/src/routes/home/home.css b/packages/frontend/src/routes/home/home.css deleted file mode 100644 index 8822fc30c..000000000 --- a/packages/frontend/src/routes/home/home.css +++ /dev/null @@ -1,19 +0,0 @@ -.status { - display: flex; - flex-flow: column; - background-color: #491a1a; - padding: 10px; - min-width: 300px; -} - -.status_item { - display: flex; - justify-content: space-between; -} - -@media screen and (max-width: 350px) { - .status { - width: calc(100% - 20px); - min-width: auto; - } -} diff --git a/packages/frontend/src/routes/home/home.route.js b/packages/frontend/src/routes/home/home.route.js deleted file mode 100644 index c426fae6a..000000000 --- a/packages/frontend/src/routes/home/home.route.js +++ /dev/null @@ -1,142 +0,0 @@ -import React from 'react' -import * as Api from '../../util/Api' -import './home.css' -import {useLoaderData} from 'react-router-dom' -import TransactionsList from '../../components/transactions/TransactionsList' - -import { - Box, - Text, - Container, - Heading, - Flex, - Stack, - StackDivider -} from '@chakra-ui/react' - - -export async function loader({}) { - const [status, paginatedTransactions] = await Promise.all([ - Api.getStatus(), - Api.getTransactions(1, 25, 'desc') - ]) - - const transactions = paginatedTransactions.resultSet - - return {status, transactions} -} - -function HomeRoute() { - const {status, transactions} = useLoaderData(); - - const { - tenderdashVersion, - network, - appVersion, - blocksCount, - blockTimeAverage, - dataContractsCount, - documentsCount, - transfersCount, - txCount - } = status - - return ( - - - } - > - - - - Network: - {network} - - - - Tenderdash Version: - {tenderdashVersion} - - - - App Version: - {appVersion} - - - - - - - - Average block time: - {Math.ceil(blockTimeAverage)} sec. - - - - Blocks: - {blocksCount} - - - - Transactions: - {txCount} - - - - - - - - Data contracts: - {dataContractsCount} - - - - Documents: - {documentsCount} - - - - Transfers: - {transfersCount} - - - - - - - - - Last transaction - - - - - - ); -} - -export default HomeRoute; diff --git a/packages/frontend/src/routes/identities/identities.route.js b/packages/frontend/src/routes/identities/identities.route.js deleted file mode 100644 index 7ad0cdbd3..000000000 --- a/packages/frontend/src/routes/identities/identities.route.js +++ /dev/null @@ -1,41 +0,0 @@ -import {useLoaderData} from 'react-router-dom' -import * as Api from '../../util/Api' -import './identities.scss' -import IdentitiesList from '../../components/identities/IdentitiesList' - -import { - Container, - Heading, -} from '@chakra-ui/react' - - -export async function loader({params}) { - const {identifier} = params - - return await Api.getIdentities(identifier); -} - -function IdentitiesRoute() { - const identities = useLoaderData().resultSet; - - return ( - - - Identities - - - - - - ); -} - -export default IdentitiesRoute; diff --git a/packages/frontend/src/routes/identities/identities.scss b/packages/frontend/src/routes/identities/identities.scss deleted file mode 100644 index 8c6dfbeaf..000000000 --- a/packages/frontend/src/routes/identities/identities.scss +++ /dev/null @@ -1,3 +0,0 @@ -.identity { - -} \ No newline at end of file diff --git a/packages/frontend/src/styles/mixins.scss b/packages/frontend/src/styles/mixins.scss index 9d6ae9ff0..b5e0f9ea3 100644 --- a/packages/frontend/src/styles/mixins.scss +++ b/packages/frontend/src/styles/mixins.scss @@ -6,7 +6,7 @@ padding: 6px 8px; margin-bottom: 1px; line-height: 24px; - border-bottom: 1px solid var(--chakra-colors-chakra-border-color); + border-bottom: 1px solid var(--chakra-colors-gray-800); color: var(--chakra-colors-gray-100); font-family: monospace; font-size: 12pt; @@ -16,4 +16,8 @@ text-decoration: none; cursor: pointer; } + + &:last-child { + border-bottom: none; + } } \ No newline at end of file diff --git a/packages/frontend/src/styles/theme.js b/packages/frontend/src/styles/theme.js index c3b8f025f..3cb31694e 100644 --- a/packages/frontend/src/styles/theme.js +++ b/packages/frontend/src/styles/theme.js @@ -1,7 +1,11 @@ import { extendTheme } from '@chakra-ui/react' export const theme = extendTheme( { - initialColorMode: 'light', + config: { + useSystemColorMode: false, + initialColorMode: 'dark', + }, + initialColorMode: 'dark', useSystemColorMode: false, colors: { brand: { @@ -23,9 +27,13 @@ export const theme = extendTheme( { }, styles: { global: { + '*' : { + borderColor: 'gray.800' + }, 'html, body': { background: '#181d20', - }, + color: 'white' + } }, }, components: { @@ -42,8 +50,6 @@ export const theme = extendTheme( { } } } -}); - -localStorage.setItem('chakra-ui-color-mode', 'dark'); +}) -export default theme; \ No newline at end of file +export default theme \ No newline at end of file diff --git a/packages/frontend/src/styles/theme.scss b/packages/frontend/src/styles/theme.scss index 8ba74539b..5a30d1226 100644 --- a/packages/frontend/src/styles/theme.scss +++ b/packages/frontend/src/styles/theme.scss @@ -1,3 +1,7 @@ +* { + border-color: var(--chakra-colors-gray-800); +} + .InfoBlock { position: relative; padding: var(--chakra-space-3); @@ -37,4 +41,21 @@ } } } +} + +.ListNavigation { + margin-top: 10px; +} + +.disabled { + display: none; +} + +.noselect { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } \ No newline at end of file diff --git a/packages/frontend/src/util/Api.js b/packages/frontend/src/util/Api.js index eb79fdc33..3f3c972f2 100644 --- a/packages/frontend/src/util/Api.js +++ b/packages/frontend/src/util/Api.js @@ -1,4 +1,4 @@ -const BASE_URL = process.env.REACT_APP_API_BASE_URL +const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL const fetchWrapper = (url, options) => { return new Promise((resolve, reject) => { @@ -98,8 +98,8 @@ const getIdentity = (identifier) => { return call(`identity/${identifier}`, 'GET') } -const getIdentities = () => { - return call(`identities`, 'GET') +const getIdentities = (page = 1, limit = 30, order = 'asc') => { + return call(`identities?page=${page}&limit=${limit}&order=${order}`, 'GET') } const getStatus = () => { diff --git a/packages/frontend/src/util/index.js b/packages/frontend/src/util/index.js index 03a3d24c4..37cec2e61 100644 --- a/packages/frontend/src/util/index.js +++ b/packages/frontend/src/util/index.js @@ -1,4 +1,4 @@ -import {StateTransitionEnum} from "../routes/enums/state.transition.type"; +import {StateTransitionEnum} from "../app/enums/state.transition.type"; const getTransitionTypeString = (id) => { const [stateTransitionType] = Object.entries(StateTransitionEnum)