structure migration (Next.js)
This commit is contained in:
parent
4c50c7447c
commit
e78a515307
62 changed files with 779 additions and 521 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -18,6 +18,7 @@ node_modules
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
.env
|
.env
|
||||||
|
.next
|
||||||
|
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
|
|
|
||||||
5
next-env.d.ts
vendored
Normal file
5
next-env.d.ts
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
/// <reference types="next" />
|
||||||
|
/// <reference types="next/image-types/global" />
|
||||||
|
|
||||||
|
// NOTE: This file should not be edited
|
||||||
|
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||||
29
next.config.js
Normal file
29
next.config.js
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
webpack: (config) => {
|
||||||
|
const fileLoaderRule = config.module.rules.find((rule) =>
|
||||||
|
rule.test?.test?.(".svg")
|
||||||
|
);
|
||||||
|
|
||||||
|
config.module.rules.push(
|
||||||
|
// Reapply the existing rule, but only for svg imports ending in ?url
|
||||||
|
{
|
||||||
|
...fileLoaderRule,
|
||||||
|
test: /\.svg$/i,
|
||||||
|
resourceQuery: /url/ // *.svg?url
|
||||||
|
},
|
||||||
|
// Convert all other *.svg imports to React components
|
||||||
|
{
|
||||||
|
test: /\.svg$/i,
|
||||||
|
issuer: fileLoaderRule.issuer,
|
||||||
|
resourceQuery: { not: [...fileLoaderRule.resourceQuery.not, /url/] }, // exclude if *.svg?url
|
||||||
|
use: ["@svgr/webpack"]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
321
package-lock.json
generated
321
package-lock.json
generated
|
|
@ -23,10 +23,10 @@
|
||||||
"highcharts-react-official": "^3.2.1",
|
"highcharts-react-official": "^3.2.1",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"nanoid": "^5.0.1",
|
"nanoid": "^5.0.1",
|
||||||
"react": "^18.2.0",
|
"next": "^14.2.12",
|
||||||
"react-dom": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
"react-json-view-lite": "^1.1.0",
|
"react-json-view-lite": "^1.1.0",
|
||||||
"react-router-dom": "^6.16.0",
|
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sass": "^1.68.0",
|
"sass": "^1.68.0",
|
||||||
"socket.io-client": "^4.7.5",
|
"socket.io-client": "^4.7.5",
|
||||||
|
|
@ -3519,6 +3519,146 @@
|
||||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
|
||||||
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
|
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@next/env": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-3fP29GIetdwVIfIRyLKM7KrvJaqepv+6pVodEbx0P5CaMLYBtx+7eEg8JYO5L9sveJO87z9eCReceZLi0hxO1Q=="
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-darwin-arm64": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-crHJ9UoinXeFbHYNok6VZqjKnd8rTd7K3Z2zpyzF1ch7vVNKmhjv/V7EHxep3ILoN8JB9AdRn/EtVVyG9AkCXw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-darwin-x64": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-JbEaGbWq18BuNBO+lCtKfxl563Uw9oy2TodnN2ioX00u7V1uzrsSUcg3Ep9ce+P0Z9es+JmsvL2/rLphz+Frcw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-qBy7OiXOqZrdp88QEl2H4fWalMGnSCrr1agT/AVDndlyw2YJQA89f3ttR/AkEIP9EkBXXeGl6cC72/EZT5r6rw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-linux-arm64-musl": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-EfD9L7o9biaQxjwP1uWXnk3vYZi64NVcKUN83hpVkKocB7ogJfyH2r7o1pPnMtir6gHZiGCeHKagJ0yrNSLNHw==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-linux-x64-gnu": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-iQ+n2pxklJew9IpE47hE/VgjmljlHqtcD5UhZVeHICTPbLyrgPehaKf2wLRNjYH75udroBNCgrSSVSVpAbNoYw==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-linux-x64-musl": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-rFkUkNwcQ0ODn7cxvcVdpHlcOpYxMeyMfkJuzaT74xjAa5v4fxP4xDk5OoYmPi8QNLDs3UgZPMSBmpBuv9zKWA==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"linux"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-PQFYUvwtHs/u0K85SG4sAdDXYIPXpETf9mcEjWc0R4JmjgMKSDwIU/qfZdavtP6MPNiMjuKGXHCtyhR/M5zo8g==",
|
||||||
|
"cpu": [
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-FAj2hMlcbeCV546eU2tEv41dcJb4NeqFlSXU/xL/0ehXywHnNpaYajOUvn3P8wru5WyQe6cTZ8fvckj/2XN4Vw==",
|
||||||
|
"cpu": [
|
||||||
|
"ia32"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@next/swc-win32-x64-msvc": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-yu8QvV53sBzoIVRHsxCHqeuS8jYq6Lrmdh0briivuh+Brsp6xjg80MAozUsBTAV9KNmY08KlX0KYTWz1lbPzEg==",
|
||||||
|
"cpu": [
|
||||||
|
"x64"
|
||||||
|
],
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||||
"version": "5.1.1-v1",
|
"version": "5.1.1-v1",
|
||||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||||
|
|
@ -3628,14 +3768,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@remix-run/router": {
|
|
||||||
"version": "1.9.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.9.0.tgz",
|
|
||||||
"integrity": "sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/plugin-babel": {
|
"node_modules/@rollup/plugin-babel": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||||
|
|
@ -3959,6 +4091,20 @@
|
||||||
"url": "https://github.com/sponsors/gregberge"
|
"url": "https://github.com/sponsors/gregberge"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@swc/counter": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||||
|
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@swc/helpers": {
|
||||||
|
"version": "0.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
|
||||||
|
"integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@swc/counter": "^0.1.3",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@testing-library/dom": {
|
"node_modules/@testing-library/dom": {
|
||||||
"version": "9.3.3",
|
"version": "9.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.3.tgz",
|
||||||
|
|
@ -5958,6 +6104,17 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/busboy": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||||
|
"dependencies": {
|
||||||
|
"streamsearch": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||||
|
|
@ -6026,9 +6183,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001546",
|
"version": "1.0.30001660",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz",
|
||||||
"integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==",
|
"integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
|
|
@ -6161,6 +6318,11 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/client-only": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||||
|
},
|
||||||
"node_modules/cliui": {
|
"node_modules/cliui": {
|
||||||
"version": "7.0.4",
|
"version": "7.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
|
||||||
|
|
@ -12940,6 +13102,55 @@
|
||||||
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
|
||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/next": {
|
||||||
|
"version": "14.2.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/next/-/next-14.2.12.tgz",
|
||||||
|
"integrity": "sha512-cDOtUSIeoOvt1skKNihdExWMTybx3exnvbFbb9ecZDIxlvIbREQzt9A5Km3Zn3PfU+IFjyYGsHS+lN9VInAGKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@next/env": "14.2.12",
|
||||||
|
"@swc/helpers": "0.5.5",
|
||||||
|
"busboy": "1.6.0",
|
||||||
|
"caniuse-lite": "^1.0.30001579",
|
||||||
|
"graceful-fs": "^4.2.11",
|
||||||
|
"postcss": "8.4.31",
|
||||||
|
"styled-jsx": "5.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"next": "dist/bin/next"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.17.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"@next/swc-darwin-arm64": "14.2.12",
|
||||||
|
"@next/swc-darwin-x64": "14.2.12",
|
||||||
|
"@next/swc-linux-arm64-gnu": "14.2.12",
|
||||||
|
"@next/swc-linux-arm64-musl": "14.2.12",
|
||||||
|
"@next/swc-linux-x64-gnu": "14.2.12",
|
||||||
|
"@next/swc-linux-x64-musl": "14.2.12",
|
||||||
|
"@next/swc-win32-arm64-msvc": "14.2.12",
|
||||||
|
"@next/swc-win32-ia32-msvc": "14.2.12",
|
||||||
|
"@next/swc-win32-x64-msvc": "14.2.12"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@opentelemetry/api": "^1.1.0",
|
||||||
|
"@playwright/test": "^1.41.2",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"sass": "^1.3.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@opentelemetry/api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@playwright/test": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"sass": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/no-case": {
|
"node_modules/no-case": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
|
||||||
|
|
@ -15045,9 +15256,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react": {
|
"node_modules/react": {
|
||||||
"version": "18.2.0",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||||
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
|
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
},
|
},
|
||||||
|
|
@ -15194,15 +15405,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.2.0",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"scheduler": "^0.23.0"
|
"scheduler": "^0.23.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^18.2.0"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-error-overlay": {
|
"node_modules/react-error-overlay": {
|
||||||
|
|
@ -15234,36 +15445,6 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
|
||||||
"version": "6.16.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.16.0.tgz",
|
|
||||||
"integrity": "sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@remix-run/router": "1.9.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-router-dom": {
|
|
||||||
"version": "6.16.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.16.0.tgz",
|
|
||||||
"integrity": "sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@remix-run/router": "1.9.0",
|
|
||||||
"react-router": "6.16.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8",
|
|
||||||
"react-dom": ">=16.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-scripts": {
|
"node_modules/react-scripts": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz",
|
||||||
|
|
@ -15915,9 +16096,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.23.0",
|
"version": "0.23.2",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||||
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
|
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -16486,6 +16667,14 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/streamsearch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
|
@ -16675,6 +16864,28 @@
|
||||||
"webpack": "^5.0.0"
|
"webpack": "^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/styled-jsx": {
|
||||||
|
"version": "5.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
|
||||||
|
"integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
|
||||||
|
"dependencies": {
|
||||||
|
"client-only": "0.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@babel/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"babel-plugin-macros": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stylehacks": {
|
"node_modules/stylehacks": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
|
||||||
|
|
|
||||||
11
package.json
11
package.json
|
|
@ -2,6 +2,7 @@
|
||||||
"name": "zano-explorer",
|
"name": "zano-explorer",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.17.0",
|
"@testing-library/jest-dom": "^5.17.0",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
|
|
@ -17,10 +18,10 @@
|
||||||
"highcharts-react-official": "^3.2.1",
|
"highcharts-react-official": "^3.2.1",
|
||||||
"http-proxy-middleware": "^2.0.6",
|
"http-proxy-middleware": "^2.0.6",
|
||||||
"nanoid": "^5.0.1",
|
"nanoid": "^5.0.1",
|
||||||
"react": "^18.2.0",
|
"next": "^14.2.12",
|
||||||
"react-dom": "^18.2.0",
|
"react": "^18.3.1",
|
||||||
|
"react-dom": "^18.3.1",
|
||||||
"react-json-view-lite": "^1.1.0",
|
"react-json-view-lite": "^1.1.0",
|
||||||
"react-router-dom": "^6.16.0",
|
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sass": "^1.68.0",
|
"sass": "^1.68.0",
|
||||||
"socket.io-client": "^4.7.5",
|
"socket.io-client": "^4.7.5",
|
||||||
|
|
@ -30,11 +31,11 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "cd server && npm i",
|
"postinstall": "cd server && npm i",
|
||||||
"client": "react-scripts start",
|
"client": "next dev",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject",
|
||||||
"dev": "concurrently \"npx nodemon --exec tsx ./server/server.ts\" \"npm run client\"",
|
"dev": "npx nodemon --exec tsx ./server/server.ts",
|
||||||
"start": "tsx ./server/server.ts"
|
"start": "tsx ./server/server.ts"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,18 @@ import Pool from "./schemes/Pool";
|
||||||
import Asset, { IAsset } from "./schemes/Asset";
|
import Asset, { IAsset } from "./schemes/Asset";
|
||||||
import { ITransaction } from "./schemes/Transaction";
|
import { ITransaction } from "./schemes/Transaction";
|
||||||
import BigNumber from "bignumber.js";
|
import BigNumber from "bignumber.js";
|
||||||
|
import next from "next";
|
||||||
import { rateLimit } from 'express-rate-limit';
|
import { rateLimit } from 'express-rate-limit';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const __dirname = import.meta.dirname;
|
const __dirname = import.meta.dirname;
|
||||||
|
const dev = process.env.NODE_ENV !== 'production';
|
||||||
|
const nextApp = next({ dev });
|
||||||
|
|
||||||
|
const handle = nextApp.getRequestHandler();
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
|
|
||||||
export const io = new Server(server, { transports: ['websocket', 'polling'] });
|
export const io = new Server(server, { transports: ['websocket', 'polling'] });
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -40,6 +45,9 @@ const requestsLimiter = rateLimit({
|
||||||
});
|
});
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
|
||||||
|
await nextApp.prepare();
|
||||||
|
|
||||||
await initDB();
|
await initDB();
|
||||||
await sequelize.authenticate();
|
await sequelize.authenticate();
|
||||||
await sequelize.sync();
|
await sequelize.sync();
|
||||||
|
|
@ -50,7 +58,11 @@ const requestsLimiter = rateLimit({
|
||||||
|
|
||||||
io.engine.on('headers', (headers, req) => {
|
io.engine.on('headers', (headers, req) => {
|
||||||
headers['Access-Control-Allow-Origin'] = config.frontend_api
|
headers['Access-Control-Allow-Origin'] = config.frontend_api
|
||||||
})
|
});
|
||||||
|
|
||||||
|
app.all('*', (req, res) => {
|
||||||
|
return handle(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
app.use(express.static('dist'));
|
app.use(express.static('dist'));
|
||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
|
|
@ -1121,9 +1133,7 @@ const requestsLimiter = rateLimit({
|
||||||
let localTr: any;
|
let localTr: any;
|
||||||
|
|
||||||
while (!!(localTr = bl.transactions_details.splice(0, 1)[0])) {
|
while (!!(localTr = bl.transactions_details.splice(0, 1)[0])) {
|
||||||
console.time('txs details call');
|
|
||||||
let response = await get_tx_details(localTr.id);
|
let response = await get_tx_details(localTr.id);
|
||||||
console.timeEnd('txs details call');
|
|
||||||
|
|
||||||
let tx_info = response.data.result.tx_info;
|
let tx_info = response.data.result.tx_info;
|
||||||
|
|
||||||
|
|
|
||||||
42
src/App.tsx
42
src/App.tsx
|
|
@ -1,42 +0,0 @@
|
||||||
import React, { Suspense } from "react";
|
|
||||||
import { BrowserRouter as Router, Routes, Route, Navigate } from "react-router-dom";
|
|
||||||
import Block from "./pages/Block/Block";
|
|
||||||
import { NET_MODE } from "./config/config";
|
|
||||||
|
|
||||||
const Blockchain = React.lazy(() => import("./pages/Blockchain/Blockchain"));
|
|
||||||
const AltBlocks = React.lazy(() => import("./pages/AltBlocks/AltBlocks"));
|
|
||||||
const Aliases = React.lazy(() => import("./pages/Aliases/Aliases"));
|
|
||||||
const API = React.lazy(() => import("./pages/API/API"));
|
|
||||||
const Transaction = React.lazy(() => import("./pages/Transaction/Transaction"));
|
|
||||||
const Charts = React.lazy(() => import("./pages/Charts/Charts"));
|
|
||||||
const ChartsPage = React.lazy(() => import("./pages/ChartPage/ChartPage"));
|
|
||||||
const Assets = React.lazy(() => import("./pages/Assets/Assets"));
|
|
||||||
const Asset = React.lazy(() => import("./pages/Asset/Asset"));
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<Router>
|
|
||||||
<Suspense fallback={<></>}>
|
|
||||||
<Routes>
|
|
||||||
<Route path="/" element={<Blockchain />} />
|
|
||||||
<Route path="/alt-blocks" element={<AltBlocks />} />
|
|
||||||
<Route path="/aliases" element={<Aliases />} />
|
|
||||||
<Route path="/zano_api" element={<API />} />
|
|
||||||
<Route path="/block/:hash" element={<Block />} />
|
|
||||||
<Route path="/transaction/:hash" element={<Transaction />} />
|
|
||||||
<Route path="/alt-blocks/:hash" element={<Block alt />} />
|
|
||||||
{/* <Route path="/charts" element={<Charts />} />
|
|
||||||
<Route path="/charts/:name" element={<ChartsPage />} /> */}
|
|
||||||
{/* {NET_MODE === "TEST" &&
|
|
||||||
<Route path="/assets" element={<Assets />} />
|
|
||||||
} */}
|
|
||||||
<Route path="/assets" element={<Assets />} />
|
|
||||||
<Route path="/*" element={<Navigate to="/" />} />
|
|
||||||
{/* <Route path="/assets/:id" element={<Asset />} /> */}
|
|
||||||
</Routes>
|
|
||||||
</Suspense>
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import "./Button.scss";
|
import styles from "./Button.module.scss";
|
||||||
|
|
||||||
interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
|
||||||
wrapper?: boolean
|
wrapper?: boolean
|
||||||
|
|
@ -9,7 +9,7 @@ function Button(props: ButtonProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`button ${wrapper ? "button__wrapper" : ""} ${className || ""}`}
|
className={`${styles.button} ${wrapper ? styles["button__wrapper"] : ""} ${className || ""}`}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import "./CopyButton.scss";
|
import styles from "@/components/UI/CopyButton/CopyButton.module.scss";
|
||||||
import Button from "../UI/Button/Button";
|
import Button from "@/components/UI/Button/Button";
|
||||||
import { ReactComponent as CopyImg } from "../../assets/images/UI/copy.svg";
|
import CopyImg from "@/assets/images/UI/copy.svg";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@ export default function CopyButton({ text }: { text: string }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button className={copied ? "copy-button_copied" : undefined} onClick={onClick} wrapper>
|
<Button className={copied ? styles["copy-button_copied"] : undefined} onClick={onClick} wrapper>
|
||||||
<CopyImg />
|
<CopyImg />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import "./Input.scss";
|
import styles from "./Input.module.scss";
|
||||||
|
|
||||||
interface InputProps extends React.HTMLProps<HTMLInputElement> {
|
interface InputProps extends React.HTMLProps<HTMLInputElement> {
|
||||||
onEnterPress?: () => void;
|
onEnterPress?: () => void;
|
||||||
|
|
@ -19,7 +19,7 @@ function Input(props: InputProps) {
|
||||||
<input
|
<input
|
||||||
{...restProps}
|
{...restProps}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
className={"input " + (props.className || "")}
|
className={`${styles["input"]} ${props.className ? styles[props.className] : ""}`}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import "./JsonViewStyled.scss";
|
import styles from "./JsonViewStyled.module.scss";
|
||||||
import { JsonView, darkStyles, Props } from "react-json-view-lite";
|
import { JsonView, darkStyles, Props } from "react-json-view-lite";
|
||||||
import 'react-json-view-lite/dist/index.css';
|
import 'react-json-view-lite/dist/index.css';
|
||||||
|
|
||||||
|
|
@ -6,16 +6,14 @@ function JsonViewStyled(props: Props) {
|
||||||
return (
|
return (
|
||||||
<JsonView
|
<JsonView
|
||||||
{...props}
|
{...props}
|
||||||
style={
|
style={{
|
||||||
{
|
...darkStyles,
|
||||||
...darkStyles,
|
container: styles["json__container"],
|
||||||
container: "json__container",
|
basicChildStyle: styles["json__element"],
|
||||||
basicChildStyle: "json__element",
|
numberValue: styles["json__number"]
|
||||||
numberValue: "json__number"
|
}}
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JsonViewStyled;
|
export default JsonViewStyled;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,16 @@
|
||||||
import "./Preloader.scss";
|
import styles from "./Preloader.module.scss";
|
||||||
|
|
||||||
function Preloader(props: { className?: string }) {
|
function Preloader(props: { className?: string }) {
|
||||||
const { className } = props;
|
const { className } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"lds-ellipsis " + (className || "")}><div></div><div></div><div></div><div></div></div>
|
<div className={styles["lds-ellipsis"] + " " + (className || "")}>
|
||||||
)
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Preloader;
|
export default Preloader;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import Button from "../Button/Button";
|
import Button from "../Button/Button";
|
||||||
import "./Switch.scss";
|
import styles from "./Switch.module.scss";
|
||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, SetStateAction } from "react";
|
||||||
|
|
||||||
interface SwitchProps {
|
interface SwitchProps {
|
||||||
|
|
@ -16,17 +16,17 @@ export default function Switch({
|
||||||
setIsFirstSelected
|
setIsFirstSelected
|
||||||
}: SwitchProps) {
|
}: SwitchProps) {
|
||||||
return (
|
return (
|
||||||
<div className="switch">
|
<div className={styles["switch"]}>
|
||||||
<Button
|
<Button
|
||||||
wrapper
|
wrapper
|
||||||
className={`switch__item ${isFirstSelected ? "switch__item_selected" : ""}`}
|
className={`${styles["switch__item"]} ${isFirstSelected ? styles["switch__item_selected"] : ""}`}
|
||||||
onClick={() => setIsFirstSelected(true)}
|
onClick={() => setIsFirstSelected(true)}
|
||||||
>
|
>
|
||||||
<p>{firstTitle}</p>
|
<p>{firstTitle}</p>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
wrapper
|
wrapper
|
||||||
className={`switch__item ${!isFirstSelected ? "switch__item_selected" : ""}`}
|
className={`${styles["switch__item"]} ${!isFirstSelected ? styles["switch__item_selected"] : ""}`}
|
||||||
onClick={() => setIsFirstSelected(false)}
|
onClick={() => setIsFirstSelected(false)}
|
||||||
>
|
>
|
||||||
<p>{secondTitle}</p>
|
<p>{secondTitle}</p>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
import { Link, LinkProps } from "react-router-dom";
|
import styles from "./AliasText.module.scss";
|
||||||
import "./AliasText.scss";
|
import Link, { LinkProps } from "next/link";
|
||||||
|
|
||||||
interface AliasTextProps extends LinkProps {
|
interface AliasTextProps extends LinkProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
function AliasText(props: AliasTextProps) {
|
function AliasText(props: AliasTextProps) {
|
||||||
const { children, ...restProps } = props;
|
const { children, ...restProps } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className="alias__text">
|
<span className={styles["alias__text"]}>
|
||||||
<Link {...restProps}>
|
<Link {...restProps}>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import "./Header.scss";
|
import styles from "./Header.module.scss";
|
||||||
import { ReactComponent as LogoImg } from "../../../assets/images/UI/logo.svg";
|
import LogoImg from "../../../assets/images/UI/logo.svg";
|
||||||
import { ReactComponent as BurgerImg } from "../../../assets/images/UI/burger.svg";
|
import BurgerImg from "../../../assets/images/UI/burger.svg";
|
||||||
import HeaderProps from "./Header.props";
|
import HeaderProps from "./Header.props";
|
||||||
import Button from "../../UI/Button/Button";
|
import Button from "../../UI/Button/Button";
|
||||||
import { NET_MODE } from "../../../config/config";
|
import { NET_MODE } from "../../../config/config";
|
||||||
import { Link } from "react-router-dom";
|
import Link from "next/link";
|
||||||
|
|
||||||
function Header(props: HeaderProps) {
|
function Header(props: HeaderProps) {
|
||||||
const { page, burgerOpened, setBurgerOpened } = props;
|
const { page, burgerOpened, setBurgerOpened } = props;
|
||||||
|
|
@ -14,19 +14,19 @@ function Header(props: HeaderProps) {
|
||||||
<nav className={className}>
|
<nav className={className}>
|
||||||
<Link
|
<Link
|
||||||
className={page === "Blockchain" ? "selected" : undefined}
|
className={page === "Blockchain" ? "selected" : undefined}
|
||||||
to="/"
|
href="/"
|
||||||
>
|
>
|
||||||
Blockchain
|
Blockchain
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
className={page === "Alt-blocks" ? "selected" : undefined}
|
className={page === "Alt-blocks" ? "selected" : undefined}
|
||||||
to="/alt-blocks"
|
href="/alt-blocks"
|
||||||
>
|
>
|
||||||
Alt-blocks
|
Alt-blocks
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
className={page === "Aliases" ? "selected" : undefined}
|
className={page === "Aliases" ? "selected" : undefined}
|
||||||
to="/aliases"
|
href="/aliases"
|
||||||
>
|
>
|
||||||
Aliases
|
Aliases
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -43,19 +43,19 @@ function Header(props: HeaderProps) {
|
||||||
} */}
|
} */}
|
||||||
<Link
|
<Link
|
||||||
className={page === "Assets" ? "selected" : undefined}
|
className={page === "Assets" ? "selected" : undefined}
|
||||||
to="/assets"
|
href="/assets"
|
||||||
>
|
>
|
||||||
Assets
|
Assets
|
||||||
</Link>
|
</Link>
|
||||||
{/* <Link
|
{/* <Link
|
||||||
className={page === "Charts" ? "selected" : undefined}
|
className={page === "Charts" ? "selected" : undefined}
|
||||||
to="/charts"
|
href="/charts"
|
||||||
>
|
>
|
||||||
Charts
|
Charts
|
||||||
</Link> */}
|
</Link> */}
|
||||||
<Link
|
<Link
|
||||||
className={page === "API" ? "selected" : undefined}
|
className={page === "API" ? "selected" : undefined}
|
||||||
to="/zano_api"
|
href="/zano_api"
|
||||||
>
|
>
|
||||||
API
|
API
|
||||||
</Link>
|
</Link>
|
||||||
|
|
@ -69,11 +69,11 @@ function Header(props: HeaderProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="header">
|
<header className={styles["header"]}>
|
||||||
<div className="header__top">
|
<div className={styles["header__top"]}>
|
||||||
<div className="header__top__main">
|
<div className={styles["header__top__main"]}>
|
||||||
<Link to="/">
|
<Link href="/">
|
||||||
<div className="header__logo">
|
<div className={styles["header__logo"]}>
|
||||||
<LogoImg />
|
<LogoImg />
|
||||||
<p>ZANO</p>
|
<p>ZANO</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -81,9 +81,9 @@ function Header(props: HeaderProps) {
|
||||||
<Nav />
|
<Nav />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="header__top__right">
|
<div className={styles["header__top__right"]}>
|
||||||
<Link
|
<Link
|
||||||
to={NET_MODE === "TEST" ? "https://explorer.zano.org/" : "https://testnet-explorer.zano.org/"}
|
href={NET_MODE === "TEST" ? "https://explorer.zano.org/" : "https://testnet-explorer.zano.org/"}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
|
|
@ -93,13 +93,13 @@ function Header(props: HeaderProps) {
|
||||||
</Link>
|
</Link>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setBurgerOpened(!burgerOpened)}
|
onClick={() => setBurgerOpened(!burgerOpened)}
|
||||||
className="header__burger__button"
|
className={styles["header__burger__button"]}
|
||||||
>
|
>
|
||||||
<BurgerImg />
|
<BurgerImg />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{burgerOpened && <Nav className="header__nav__mobile" />}
|
{burgerOpened && <Nav className={styles["header__nav__mobile"]} />}
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
import Button from "../../UI/Button/Button";
|
import Button from "@/components/UI/Button/Button";
|
||||||
import Input from "../../UI/Input/Input";
|
import Input from "@/components/UI/Input/Input";
|
||||||
import "./InfoTopPanel.scss";
|
import styles from "./InfoTopPanel.module.scss";
|
||||||
import { ReactComponent as SearchImg } from "../../../assets/images/UI/search.svg";
|
import SearchImg from "@/assets/images/UI/search.svg";
|
||||||
import { ReactComponent as BackImg } from "../../../assets/images/UI/back.svg";
|
import BackImg from "@/assets/images/UI/back.svg";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Fetch from "../../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import Link from "next/link";
|
||||||
import InfoTopPanelProps from "./InfoTopPanel.props";
|
import InfoTopPanelProps from "./InfoTopPanel.props";
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
function InfoTopPanel(props: InfoTopPanelProps) {
|
function InfoTopPanel(props: InfoTopPanelProps) {
|
||||||
const { burgerOpened, title, content, back, className, inputParams, contentNotHiding, inputDefaultClosed } = props;
|
const { burgerOpened, title, content, back, className, inputParams, contentNotHiding, inputDefaultClosed } = props;
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const router = useRouter();
|
||||||
|
|
||||||
const [inputClosed, setInputClosed] = useState(inputDefaultClosed || false);
|
const [inputClosed, setInputClosed] = useState(inputDefaultClosed || false);
|
||||||
const [inputState, setInputState] = useState("");
|
const [inputState, setInputState] = useState("");
|
||||||
|
|
@ -27,23 +28,23 @@ function InfoTopPanel(props: InfoTopPanelProps) {
|
||||||
if (searchInfo && typeof searchInfo === "object") {
|
if (searchInfo && typeof searchInfo === "object") {
|
||||||
const result = searchInfo.result;
|
const result = searchInfo.result;
|
||||||
if (result === "tx") {
|
if (result === "tx") {
|
||||||
return navigate("/transaction/" + input);
|
return router.push("/transaction/" + input);
|
||||||
}
|
}
|
||||||
if (result === "block") {
|
if (result === "block") {
|
||||||
return navigate("/block/" + input);
|
return router.push("/block/" + input);
|
||||||
}
|
}
|
||||||
|
|
||||||
const txByKeyimageRes = await Fetch.getTxByKeyimage(input);
|
const txByKeyimageRes = await Fetch.getTxByKeyimage(input);
|
||||||
|
|
||||||
if (txByKeyimageRes && typeof txByKeyimageRes === "object" && txByKeyimageRes.data) {
|
if (txByKeyimageRes && typeof txByKeyimageRes === "object" && txByKeyimageRes.data) {
|
||||||
return navigate("/transaction/" + input);
|
return router.push("/transaction/" + input);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.match(/^\d+$/)) {
|
if (input.match(/^\d+$/)) {
|
||||||
try {
|
try {
|
||||||
const parsedHash = await Fetch.getHashByHeight(parseInt(input, 10));
|
const parsedHash = await Fetch.getHashByHeight(parseInt(input, 10));
|
||||||
if (parsedHash) {
|
if (parsedHash) {
|
||||||
return navigate("/block/" + parsedHash);
|
return router.push("/block/" + parsedHash);
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return setNoMatch(true);
|
return setNoMatch(true);
|
||||||
|
|
@ -57,33 +58,30 @@ function InfoTopPanel(props: InfoTopPanelProps) {
|
||||||
async function onBackClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
|
async function onBackClick(event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (document.referrer) {
|
if (document.referrer) {
|
||||||
navigate(-1);
|
router.back();
|
||||||
} else {
|
} else {
|
||||||
navigate("/");
|
router.push("/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
"blockchain__info__top" + " " + className + " "
|
`${styles.blockchain__info__top} ${className} ${inputClosed ? styles.blockchain__input__closed : ""} ${burgerOpened ? styles.info__top__hidden : ""}`
|
||||||
+ (inputClosed ? "blockchain__input__closed" : "") + " "
|
|
||||||
+ (burgerOpened ? "info__top__hidden" : "")
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
||||||
{back &&
|
{back &&
|
||||||
<Link to="/" onClick={onBackClick}>
|
<Link href="/" onClick={onBackClick}>
|
||||||
<div className="info__back">
|
<div className={styles.info__back}>
|
||||||
<BackImg />
|
<BackImg />
|
||||||
<p>Back</p>
|
<p>Back</p>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
<div className={"info__top__title"}>
|
<div className={styles.info__top__title}>
|
||||||
<h4 className={contentNotHiding ? "hiding_element" : undefined}>{title}</h4>
|
<h4 className={contentNotHiding ? styles.hiding_element : undefined}>{title}</h4>
|
||||||
{!back &&
|
{!back &&
|
||||||
<div className={"info__top__content " + (!contentNotHiding ? "hiding_element" : undefined)}>
|
<div className={`${styles.info__top__content} ${!contentNotHiding ? styles.hiding_element : ""}`}>
|
||||||
{
|
{
|
||||||
content || <></>
|
content || <></>
|
||||||
}
|
}
|
||||||
|
|
@ -93,7 +91,7 @@ function InfoTopPanel(props: InfoTopPanelProps) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div className="info__top__input">
|
<div className={styles.info__top__input}>
|
||||||
{noMatch && <p>No matching records found!</p> }
|
{noMatch && <p>No matching records found!</p> }
|
||||||
{!inputParams ?
|
{!inputParams ?
|
||||||
<Input
|
<Input
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import "./JSONPopup.scss";
|
import styles from "./JSONPopup.module.scss";
|
||||||
import Popup from "../Popup/Popup";
|
import Popup from "../Popup/Popup";
|
||||||
import JSONPopupProps from "./JSONPopup.props";
|
import JSONPopupProps from "./JSONPopup.props";
|
||||||
import JsonViewStyled from "../../UI/JsonViewStyled/JsonViewStyled";
|
import JsonViewStyled from "../../UI/JsonViewStyled/JsonViewStyled";
|
||||||
import Button from "../../UI/Button/Button";
|
import Button from "../../UI/Button/Button";
|
||||||
import { ReactComponent as CrossImg } from "../../../assets/images/UI/cross.svg";
|
import CrossImg from "../../../assets/images/UI/cross.svg";
|
||||||
|
|
||||||
const JSONPopup = (props: JSONPopupProps) => {
|
const JSONPopup = (props: JSONPopupProps) => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -23,9 +23,9 @@ const JSONPopup = (props: JSONPopupProps) => {
|
||||||
|
|
||||||
function PopupContent({ close }: { close: () => void }) {
|
function PopupContent({ close }: { close: () => void }) {
|
||||||
return (
|
return (
|
||||||
<div className="json_popup__content">
|
<div className={styles["json_popup__content"]}>
|
||||||
{!hideJson &&
|
{!hideJson &&
|
||||||
<div className="json_popup__content__json">
|
<div className={styles["json_popup__content__json"]}>
|
||||||
<JsonViewStyled
|
<JsonViewStyled
|
||||||
data={json}
|
data={json}
|
||||||
/>
|
/>
|
||||||
|
|
@ -34,7 +34,7 @@ const JSONPopup = (props: JSONPopupProps) => {
|
||||||
<Button
|
<Button
|
||||||
wrapper
|
wrapper
|
||||||
onClick={close}
|
onClick={close}
|
||||||
className="json_popup__close_btn"
|
className={styles["json_popup__close_btn"]}
|
||||||
>
|
>
|
||||||
<CrossImg />
|
<CrossImg />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import { NET_MODE } from "../../../config/config";
|
import { NET_MODE } from "../../../config/config";
|
||||||
import Info from "../../../interfaces/state/Info";
|
import Info from "../../../interfaces/state/Info";
|
||||||
import VisibilityInfo from "../../../interfaces/state/VisibilityInfo";
|
import VisibilityInfo from "../../../interfaces/state/VisibilityInfo";
|
||||||
import Fetch from "../../../utils/methods";
|
|
||||||
import Utils from "../../../utils/utils";
|
import Utils from "../../../utils/utils";
|
||||||
import "./StatsPanel.scss";
|
import styles from "./StatsPanel.module.scss";
|
||||||
import { useState, useEffect, ReactNode } from "react";
|
import { useState, useEffect, ReactNode } from "react";
|
||||||
import { socket } from "../../../utils/socket";
|
import { socket } from "../../../utils/socket";
|
||||||
import { ReactComponent as BurnImg } from "../../../assets/images/UI/flame_ico.svg";
|
import BurnImg from "../../../assets/images/UI/flame_ico.svg";
|
||||||
|
|
||||||
function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: boolean }) {
|
function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: boolean }) {
|
||||||
const { visibilityInfo } = props;
|
const { visibilityInfo } = props;
|
||||||
|
|
@ -30,7 +29,6 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const transactions = info ? info.height + info.tx_count : undefined;
|
const transactions = info ? info.height + info.tx_count : undefined;
|
||||||
|
|
||||||
const infoHeight = Utils.formatNumber(info?.height, 0) || "...";
|
const infoHeight = Utils.formatNumber(info?.height, 0) || "...";
|
||||||
|
|
@ -55,23 +53,23 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
const isAmountString = typeof amount === "string";
|
const isAmountString = typeof amount === "string";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main__top__item">
|
<div className={styles["main__top__item"]}>
|
||||||
<div>
|
<div>
|
||||||
<p className="main__top__item__header">{title}</p>
|
<p className={styles["main__top__item__header"]}>{title}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="item__value">
|
<div className={styles["item__value"]}>
|
||||||
{isAmountString
|
{isAmountString
|
||||||
? <p>{amount + (!customCurrency ? " ZANO" : "")}</p>
|
? <p>{amount + (!customCurrency ? " ZANO" : "")}</p>
|
||||||
: amount
|
: amount
|
||||||
}
|
}
|
||||||
{percent &&
|
{percent &&
|
||||||
<div className="item__precent">
|
<div className={styles["item__precent"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
{percent + "%"}
|
{percent + "%"}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="item__precent__label">from total supply</p>
|
<p className={styles["item__precent__label"]}>from total supply</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -79,16 +77,15 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function BottomItem(props: { title: string, children: React.ReactNode, style?: React.CSSProperties }) {
|
function BottomItem(props: { title: string, children: React.ReactNode, style?: React.CSSProperties }) {
|
||||||
const { title, children, style } = props;
|
const { title, children, style } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main__bottom__item" style={style}>
|
<div className={styles["main__bottom__item"]} style={style}>
|
||||||
<div>
|
<div>
|
||||||
<p>{title}</p>
|
<p>{title}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bottom__item__value">
|
<div className={styles["bottom__item__value"]}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -97,44 +94,44 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
|
|
||||||
function InfoTop() {
|
function InfoTop() {
|
||||||
return (
|
return (
|
||||||
<div className="info__main__top">
|
<div className={styles["info__main__top"]}>
|
||||||
<TopItem
|
<TopItem
|
||||||
title="Staked Coins (est)"
|
title="Staked Coins (est)"
|
||||||
amount={stackedCoins}
|
amount={stackedCoins}
|
||||||
percent={percentage}
|
percent={percentage}
|
||||||
/>
|
/>
|
||||||
<TopItem
|
<TopItem
|
||||||
title="Dev Fund"
|
title="Dev Fund"
|
||||||
amount={devFund}
|
amount={devFund}
|
||||||
/>
|
/>
|
||||||
<TopItem
|
<TopItem
|
||||||
title="Real Time APY"
|
title="Real Time APY"
|
||||||
amount={`${APY}%`}
|
amount={`${APY}%`}
|
||||||
customCurrency={true}
|
customCurrency={true}
|
||||||
/>
|
/>
|
||||||
<TopItem
|
<TopItem
|
||||||
title="Zano Burned"
|
title="Zano Burned"
|
||||||
amount={
|
amount={
|
||||||
<div className="item__value__burn">
|
<div className={styles["item__value__burn"]}>
|
||||||
<BurnImg />
|
<BurnImg />
|
||||||
<p>{zanoBurned} ZANO</p>
|
<p>{zanoBurned} ZANO</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="blockchain__info__main">
|
<div className={styles["blockchain__info__main"]}>
|
||||||
{NET_MODE === "MAIN" && !props.noStats && <InfoTop/>}
|
{NET_MODE === "MAIN" && !props.noStats && <InfoTop/>}
|
||||||
<div className="info__main__bottom">
|
<div className={styles["info__main__bottom"]}>
|
||||||
<BottomItem title="Height">
|
<BottomItem title="Height">
|
||||||
<p className="item__text__large">{infoHeight}</p>
|
<p className={styles["item__text__large"]}>{infoHeight}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Difficulty">
|
<BottomItem title="Difficulty">
|
||||||
<div className="item__difficulty">
|
<div className={styles["item__difficulty"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>PoS: {posDiff}</p>
|
<p>PoS: {posDiff}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -145,13 +142,13 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
</div>
|
</div>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Coins Emitted">
|
<BottomItem title="Coins Emitted">
|
||||||
<p className="item__text__small">{coinsEmitted}</p>
|
<p className={styles["item__text__small"]}>{coinsEmitted}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Transactions">
|
<BottomItem title="Transactions">
|
||||||
<p className="item__text__large">{transactionsString}</p>
|
<p className={styles["item__text__large"]}>{transactionsString}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Hash Rate (approx):">
|
<BottomItem title="Hash Rate (approx):">
|
||||||
<div className="item__difficulty">
|
<div className={styles["item__difficulty"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>PoS: {posValue} block/day</p>
|
<p>PoS: {posValue} block/day</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -164,16 +161,14 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={styles["info__main__mobile"]}>
|
||||||
|
|
||||||
<div className="info__main__mobile">
|
|
||||||
{NET_MODE === "MAIN" && <InfoTop/>}
|
{NET_MODE === "MAIN" && <InfoTop/>}
|
||||||
<div className="info__main__bottom">
|
<div className={styles["info__main__bottom"]}>
|
||||||
<BottomItem title="Height">
|
<BottomItem title="Height">
|
||||||
<p className="item__text__large">{infoHeight}</p>
|
<p className={styles["item__text__large"]}>{infoHeight}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Difficulty">
|
<BottomItem title="Difficulty">
|
||||||
<div className="item__difficulty">
|
<div className={styles["item__difficulty"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>PoS: {posDiff}</p>
|
<p>PoS: {posDiff}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -184,14 +179,13 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
</div>
|
</div>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Coins Emitted">
|
<BottomItem title="Coins Emitted">
|
||||||
<p className="item__text__small">{coinsEmitted}</p>
|
<p className={styles["item__text__small"]}>{coinsEmitted}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Transactions">
|
<BottomItem title="Transactions">
|
||||||
<p className="item__text__large">{transactionsString}</p>
|
<p className={styles["item__text__large"]}>{transactionsString}</p>
|
||||||
</BottomItem>
|
</BottomItem>
|
||||||
<BottomItem title="Hash Rate (approx):">
|
<BottomItem title="Hash Rate (approx):">
|
||||||
|
<div className={styles["item__difficulty"]}>
|
||||||
<div className="item__difficulty">
|
|
||||||
<div>
|
<div>
|
||||||
<p>PoS: {posValue} block/day</p>
|
<p>PoS: {posValue} block/day</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -207,4 +201,4 @@ function StatsPanel(props: { visibilityInfo?: VisibilityInfo | null, noStats?: b
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StatsPanel;
|
export default StatsPanel;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import "./Table.scss";
|
import styles from "./Table.module.scss";
|
||||||
import { ReactComponent as ArrowImg } from "../../../assets/images/UI/arrow.svg";
|
import ArrowImg from "../../../assets/images/UI/arrow.svg";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import Input from "../../UI/Input/Input";
|
import Input from "../../UI/Input/Input";
|
||||||
import TableProps from "./Table.props";
|
import TableProps from "./Table.props";
|
||||||
|
|
@ -42,7 +42,7 @@ function Table(props: TableProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<table className={"table " + (!textWrap ? "table__text_nowrap" : "")}>
|
<table className={`${styles.table} ${!textWrap ? styles["table__text_nowrap"] : ""}`}>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{
|
{
|
||||||
|
|
@ -69,12 +69,12 @@ function Table(props: TableProps) {
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
{pagination &&
|
{pagination &&
|
||||||
<div className="table__pagination">
|
<div className={styles["table__pagination"]}>
|
||||||
<div className="table__pagination__pages">
|
<div className={styles["table__pagination__pages"]}>
|
||||||
<p>Pages: </p>
|
<p>Pages: </p>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
className={page === "1" ? "disabled" : undefined}
|
className={page === "1" ? styles.disabled : undefined}
|
||||||
onClick={() => changePage(-1)}
|
onClick={() => changePage(-1)}
|
||||||
>
|
>
|
||||||
<ArrowImg />
|
<ArrowImg />
|
||||||
|
|
@ -92,7 +92,7 @@ function Table(props: TableProps) {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{pagesTotal && <p>Pages total: {pagesTotal}</p>}
|
{pagesTotal && <p>Pages total: {pagesTotal}</p>}
|
||||||
<div className="table__pagination__blocks">
|
<div className={styles["table__pagination__blocks"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>Items on page: </p>
|
<p>Items on page: </p>
|
||||||
<Input
|
<Input
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import './index.scss';
|
|
||||||
import App from './App';
|
|
||||||
import reportWebVitals from './reportWebVitals';
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
|
||||||
document.getElementById('root') as HTMLElement
|
|
||||||
);
|
|
||||||
root.render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<App />
|
|
||||||
</React.StrictMode>
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import AliasText from "../../../../components/default/AliasText/AliasText";
|
import AliasText from "@/components/default/AliasText/AliasText";
|
||||||
import Table from "../../../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import Block from "../../../../interfaces/state/Block";
|
import Block from "@/interfaces/state/Block";
|
||||||
import Info from "../../../../interfaces/state/Info";
|
import Info from "@/interfaces/state/Info";
|
||||||
import Fetch from "../../../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import Utils from "../../../../utils/utils";
|
import Utils from "@/utils/utils";
|
||||||
import "./LatestBlocks.scss";
|
import styles from "./LatestBlocks.module.scss";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { socket } from "../../../../utils/socket";
|
import Link from "next/link";
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
|
|
||||||
function LatestBlocks() {
|
function LatestBlocks() {
|
||||||
|
|
||||||
|
|
@ -83,19 +82,19 @@ function LatestBlocks() {
|
||||||
const hashLink = hash ? "/block/" + hash : "/";
|
const hashLink = hash ? "/block/" + hash : "/";
|
||||||
return [
|
return [
|
||||||
<p>
|
<p>
|
||||||
<Link to={hashLink}>{e.height}</Link>
|
<Link href={hashLink}>{e.height}</Link>
|
||||||
{` (${e.type})`}
|
{` (${e.type})`}
|
||||||
</p>,
|
</p>,
|
||||||
Utils.formatTimestampUTC(e.timestamp),
|
Utils.formatTimestampUTC(e.timestamp),
|
||||||
Utils.timeElapsedString(e.timestamp),
|
Utils.timeElapsedString(e.timestamp),
|
||||||
`${e.size} bytes`,
|
`${e.size} bytes`,
|
||||||
e.transactions?.toString() || "0",
|
e.transactions?.toString() || "0",
|
||||||
<AliasText to={hashLink}>{hash}</AliasText>
|
<AliasText href={hashLink}>{hash}</AliasText>
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="blockchain__latest_blocks custom-scroll">
|
<div className={styles["blockchain__latest_blocks"] + " " + styles["custom-scroll"]}>
|
||||||
<h3>Latest Blocks</h3>
|
<h3>Latest Blocks</h3>
|
||||||
<Table
|
<Table
|
||||||
pagination
|
pagination
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import "./TransactionPool.scss";
|
import styles from "./TransactionPool.module.scss";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Button from "../../../../components/UI/Button/Button";
|
import Button from "@/components/UI/Button/Button";
|
||||||
import Table from "../../../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import AliasText from "../../../../components/default/AliasText/AliasText";
|
import AliasText from "@/components/default/AliasText/AliasText";
|
||||||
import { socket } from "../../../../utils/socket";
|
import { socket } from "@/utils/socket";
|
||||||
|
|
||||||
function TransactionPool() {
|
function TransactionPool() {
|
||||||
|
|
||||||
|
|
@ -78,12 +78,12 @@ function TransactionPool() {
|
||||||
timeAgo(new Date(element.timestamp).getTime()),
|
timeAgo(new Date(element.timestamp).getTime()),
|
||||||
element.blob_size + " bytes",
|
element.blob_size + " bytes",
|
||||||
parseInt(element.fee, 10)/10**12,
|
parseInt(element.fee, 10)/10**12,
|
||||||
<AliasText to={`/transaction/${element.tx_id}`}>{element.tx_id}</AliasText>
|
<AliasText href={`/transaction/${element.tx_id}`}>{element.tx_id}</AliasText>
|
||||||
]));
|
]));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="transaction_pool custom-scroll">
|
<div className={styles["transaction_pool"] + " custom-scroll"}>
|
||||||
<div className="transation_pool__title">
|
<div className={styles["transation_pool__title"]}>
|
||||||
<h3>Transaction Pool</h3>
|
<h3>Transaction Pool</h3>
|
||||||
<Button
|
<Button
|
||||||
style={ turnedOn ? { color: "#ff5252" } : { color: "#00c853" }}
|
style={ turnedOn ? { color: "#ff5252" } : { color: "#00c853" }}
|
||||||
|
|
@ -93,11 +93,11 @@ function TransactionPool() {
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{!turnedOn || !tableElements[0] ?
|
{!turnedOn || !tableElements[0] ?
|
||||||
<div className="transation_pool__empty">
|
<div className={styles["transation_pool__empty"]}>
|
||||||
<p>Pool is empty</p>
|
<p>Pool is empty</p>
|
||||||
</div> :
|
</div> :
|
||||||
<Table
|
<Table
|
||||||
className="transaction__table"
|
className={styles["transaction__table"]}
|
||||||
headers={tableHeaders}
|
headers={tableHeaders}
|
||||||
elements={tableElements}
|
elements={tableElements}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import "../../styles/Blockchain.scss";
|
import styles from "@/styles/Blockchain.module.scss";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import StatsPanel from "../../components/default/StatsPanel/StatsPanel";
|
import StatsPanel from "@/components/default/StatsPanel/StatsPanel";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import LatestBlocks from "./components/LatestBlocks/LatestBlocks";
|
import LatestBlocks from "./components/LatestBlocks/LatestBlocks";
|
||||||
import TransactionPool from "./components/TransactionPool/TransactionPool";
|
import TransactionPool from "./components/TransactionPool/TransactionPool";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import VisibilityInfo from "../../interfaces/state/VisibilityInfo";
|
import VisibilityInfo from "@/interfaces/state/VisibilityInfo";
|
||||||
|
|
||||||
function Blockchain() {
|
function Blockchain() {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
|
|
@ -41,7 +41,7 @@ function Blockchain() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="blockchain">
|
<div className={styles["blockchain"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Blockchain"
|
page="Blockchain"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
|
|
@ -51,7 +51,7 @@ function Blockchain() {
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
title="Blockchain"
|
title="Blockchain"
|
||||||
content={
|
content={
|
||||||
<div className="info__top__daemon">
|
<div className={styles["info__top__daemon"]}>
|
||||||
<p>Daemon state: {isOnline ? 'Online' : 'Offline'}</p>
|
<p>Daemon state: {isOnline ? 'Online' : 'Offline'}</p>
|
||||||
<p>Default network fee: 0,01</p>
|
<p>Default network fee: 0,01</p>
|
||||||
<p>Minimum network fee: 0,01</p>
|
<p>Minimum network fee: 0,01</p>
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import "../../styles/ChartPage.scss";
|
import styles from "@/styles/ChartPage.module.scss";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import HighchartsReact from "highcharts-react-official";
|
import HighchartsReact from "highcharts-react-official";
|
||||||
import Highcharts from "highcharts/highstock";
|
import Highcharts from "highcharts/highstock";
|
||||||
import { chartFontColor, chartOptions, chartRequestNames } from "../../utils/constants";
|
import { chartFontColor, chartOptions, chartRequestNames } from "@/utils/constants";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import ChartSeriesElem from "@/interfaces/common/ChartSeriesElem";
|
||||||
import ChartSeriesElem from "../../interfaces/common/ChartSeriesElem";
|
import Utils from "@/utils/utils";
|
||||||
import Utils from "../../utils/utils";
|
import Preloader from "@/components/UI/Preloader/Preloader";
|
||||||
import Preloader from "../../components/UI/Preloader/Preloader";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
interface ChartInfo {
|
interface ChartInfo {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -18,7 +18,6 @@ interface ChartInfo {
|
||||||
|
|
||||||
function ChartPage() {
|
function ChartPage() {
|
||||||
|
|
||||||
|
|
||||||
const chartsInfo: { [key: string]: ChartInfo } = {
|
const chartsInfo: { [key: string]: ChartInfo } = {
|
||||||
"avg-block-size": {
|
"avg-block-size": {
|
||||||
title: "Average Block Size",
|
title: "Average Block Size",
|
||||||
|
|
@ -58,16 +57,16 @@ function ChartPage() {
|
||||||
|
|
||||||
// The only values that chartId param can have are the keys of the chartRequestNames object.
|
// The only values that chartId param can have are the keys of the chartRequestNames object.
|
||||||
// Other values will cause redirect to the home page.
|
// Other values will cause redirect to the home page.
|
||||||
const { name: chartId } = useParams();
|
const router = useRouter();
|
||||||
|
const { name } = router.query;
|
||||||
|
const chartId: string | undefined = Array.isArray(name) ? name[0] : name;
|
||||||
|
|
||||||
const [chartSeries, setChartSeries] = useState<ChartSeriesElem[][]>([]);
|
const [chartSeries, setChartSeries] = useState<ChartSeriesElem[][]>([]);
|
||||||
const chartSeriesTitles = [
|
const chartSeriesTitles = [
|
||||||
chartsInfo[chartId || ""]?.seriesTitle || "",
|
chartsInfo[chartId || ""]?.seriesTitle || "",
|
||||||
"Hash Rate 400",
|
"Hash Rate 400",
|
||||||
"Difficulty 120"
|
"Difficulty 120"
|
||||||
]
|
];
|
||||||
|
|
||||||
const navigate = useNavigate();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchChart() {
|
async function fetchChart() {
|
||||||
|
|
@ -80,14 +79,14 @@ function ChartPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(chartId && chartRequestNames[chartId])) {
|
if (!(chartId && chartRequestNames[chartId])) {
|
||||||
navigate("/");
|
router.push("/");
|
||||||
} else {
|
} else {
|
||||||
fetchChart();
|
fetchChart();
|
||||||
}
|
}
|
||||||
}, [chartId]);
|
}, [chartId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="chart_page">
|
<div className={styles["chart_page"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Charts"
|
page="Charts"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
|
|
@ -98,11 +97,11 @@ function ChartPage() {
|
||||||
title="Charts"
|
title="Charts"
|
||||||
back
|
back
|
||||||
/>
|
/>
|
||||||
<div className="chart_page__chart__wrapper">
|
<div className={styles["chart_page__chart__wrapper"]}>
|
||||||
{
|
{
|
||||||
loading ?
|
loading ?
|
||||||
(
|
(
|
||||||
<div className="chart_page__preloader">
|
<div className={styles["chart_page__preloader"]}>
|
||||||
<Preloader />
|
<Preloader />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
@ -133,7 +132,7 @@ function ChartPage() {
|
||||||
},
|
},
|
||||||
chart: {
|
chart: {
|
||||||
...chartOptions.chart,
|
...chartOptions.chart,
|
||||||
className: "chart_page__chart",
|
className: styles["chart_page__chart"],
|
||||||
height: 700,
|
height: 700,
|
||||||
},
|
},
|
||||||
rangeSelector: {
|
rangeSelector: {
|
||||||
|
|
@ -178,4 +177,4 @@ function ChartPage() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ChartPage;
|
export default ChartPage;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
import "../../styles/Charts.scss";
|
import styles from "@/styles/Charts.module.scss";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import HighchartsReact from "highcharts-react-official";
|
import HighchartsReact from "highcharts-react-official";
|
||||||
import Highcharts from "highcharts";
|
import Highcharts from "highcharts";
|
||||||
import { chartOptions } from "../../utils/constants";
|
import { chartOptions } from "@/utils/constants";
|
||||||
import Utils from "../../utils/utils";
|
import Utils from "@/utils/utils";
|
||||||
import ChartSeriesElem from "../../interfaces/common/ChartSeriesElem";
|
import ChartSeriesElem from "@/interfaces/common/ChartSeriesElem";
|
||||||
import Preloader from "../../components/UI/Preloader/Preloader";
|
import Preloader from "@/components/UI/Preloader/Preloader";
|
||||||
import { Link } from "react-router-dom";
|
import Link from "next/link";
|
||||||
|
|
||||||
function Charts() {
|
function Charts() {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
|
|
@ -66,8 +66,8 @@ function Charts() {
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={"/charts/" + requestTitle} className="charts__chart__wrapper">
|
<Link href={"/charts/" + requestTitle} className={styles["charts__chart__wrapper"]}>
|
||||||
<div className="charts__chart__title">
|
<div className={styles["charts__chart__title"]}>
|
||||||
<p>{title}</p>
|
<p>{title}</p>
|
||||||
</div>
|
</div>
|
||||||
<HighchartsReact
|
<HighchartsReact
|
||||||
|
|
@ -86,7 +86,7 @@ function Charts() {
|
||||||
chart: {
|
chart: {
|
||||||
...chartOptions.chart,
|
...chartOptions.chart,
|
||||||
height: 280,
|
height: 280,
|
||||||
className: "charts__chart"
|
className: styles["charts__chart"]
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
enabled: false
|
enabled: false
|
||||||
|
|
@ -124,7 +124,7 @@ function Charts() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="charts">
|
<div className={styles["charts"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Charts"
|
page="Charts"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
|
|
@ -135,7 +135,7 @@ function Charts() {
|
||||||
title="Charts"
|
title="Charts"
|
||||||
/>
|
/>
|
||||||
{loaded ?
|
{loaded ?
|
||||||
<div className="charts__container">
|
<div className={styles["charts__container"]}>
|
||||||
<Chart
|
<Chart
|
||||||
title="Average Block Size"
|
title="Average Block Size"
|
||||||
requestTitle="avg-block-size"
|
requestTitle="avg-block-size"
|
||||||
|
|
@ -161,7 +161,7 @@ function Charts() {
|
||||||
requestTitle="confirm-trans-per-day"
|
requestTitle="confirm-trans-per-day"
|
||||||
/>
|
/>
|
||||||
</div> :
|
</div> :
|
||||||
<div className="charts__preloader">
|
<div className={styles["charts__preloader"]}>
|
||||||
<Preloader />
|
<Preloader />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
32
src/pages/_app.tsx
Normal file
32
src/pages/_app.tsx
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import './index.scss';
|
||||||
|
import { default as NextApp } from 'next/app';
|
||||||
|
import Head from 'next/head';
|
||||||
|
|
||||||
|
function App(data: any) {
|
||||||
|
const { Component, pageProps } = data;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Zano Trade</title>
|
||||||
|
<meta name="description" content="Peer-to-Peer Trading App on Zano blockchain" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1 user-scalable=no" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
|
||||||
|
<meta property="og:type" content="website"/>
|
||||||
|
<meta property="og:url" content="https://trade.zano.org/"/>
|
||||||
|
<meta property="og:title" content="Zano Trade"/>
|
||||||
|
<meta property="og:description" content="Peer-to-Peer Trading App on Zano blockchain"/>
|
||||||
|
<meta property="og:image" content="social-banner.png"/>
|
||||||
|
|
||||||
|
<meta property="twitter:card" content="summary_large_image"/>
|
||||||
|
<meta property="twitter:url" content="https://trade.zano.org/"/>
|
||||||
|
<meta property="twitter:title" content="Zano Trade"/>
|
||||||
|
<meta property="twitter:description" content="Peer-to-Peer Trading App on Zano blockchain"/>
|
||||||
|
<meta property="twitter:image" content="social-banner.png"/>
|
||||||
|
</Head>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
15
src/pages/_document.js
Normal file
15
src/pages/_document.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Html, Head, Main, NextScript } from 'next/document';
|
||||||
|
|
||||||
|
function Document() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head />
|
||||||
|
<body className='custom-scroll'>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Document;
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import "../../styles/Aliases.scss";
|
import styles from "@/styles/Aliases.module.scss";
|
||||||
import { useState, useEffect, useCallback } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "../../components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "../../components/default/Table/Table";
|
||||||
import Alias from "../../interfaces/state/Alias";
|
import Alias from "../../interfaces/state/Alias";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "../../utils/methods";
|
||||||
import crownImg from "../../assets/images/UI/crown.svg";
|
import CrownImg from "../../assets/images/UI/crown.svg";
|
||||||
import CommonStatsPanel from "../../components/UI/CommonStatsPanel/CommonStatsPanel";
|
import CommonStatsPanel from "../../components/UI/CommonStatsPanel/CommonStatsPanel";
|
||||||
|
|
||||||
function Aliases() {
|
function Aliases() {
|
||||||
|
|
@ -63,10 +63,10 @@ function Aliases() {
|
||||||
function ShortAlias({ alias }: { alias: string }) {
|
function ShortAlias({ alias }: { alias: string }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="short_alias">
|
<div className={styles["short_alias"]}>
|
||||||
{alias}
|
{alias}
|
||||||
<div className="short_alias__crown">
|
<div className={styles["short_alias__crown"]}>
|
||||||
<img src={crownImg} alt="" />
|
<img src={CrownImg} alt="" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -84,7 +84,7 @@ function Aliases() {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="aliases">
|
<div className={styles["aliases"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Aliases"
|
page="Aliases"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
|
|
@ -99,8 +99,8 @@ function Aliases() {
|
||||||
setState: setSearchState
|
setState: setSearchState
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<CommonStatsPanel pairs={statsPanelData} className="aliases__stats" />
|
<CommonStatsPanel pairs={statsPanelData} className={styles["aliases__stats"]} />
|
||||||
<div className="aliases__table custom-scroll">
|
<div className={`${styles["aliases__table"]} custom-scroll`}>
|
||||||
<Table
|
<Table
|
||||||
headers={tableHeaders}
|
headers={tableHeaders}
|
||||||
elements={tableElements}
|
elements={tableElements}
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
import "../../styles/AltBlocks.scss";
|
import styles from "@/styles/AltBlocks.module.scss";
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import AliasText from "../../components/default/AliasText/AliasText";
|
import AliasText from "@/components/default/AliasText/AliasText";
|
||||||
import Block from "../../interfaces/state/Block";
|
import Block from "@/interfaces/state/Block";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import Utils from "../../utils/utils";
|
import Utils from "@/utils/utils";
|
||||||
import { Link } from "react-router-dom";
|
import Link from "next/link";
|
||||||
|
|
||||||
|
|
||||||
function AltBlocks() {
|
function AltBlocks() {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
|
|
@ -38,7 +37,7 @@ function AltBlocks() {
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, [itemsOnPage, page]);
|
}, [itemsOnPage, page]);
|
||||||
|
|
||||||
const tableHeaders = [ "HEIGHT", "TIMESTAMP (UTC)", "ACTIAL TIMESTAMP (UTC)", "SIZE", "TRANSACTIONS", "HASH" ];
|
const tableHeaders = ["HEIGHT", "TIMESTAMP (UTC)", "ACTIAL TIMESTAMP (UTC)", "SIZE", "TRANSACTIONS", "HASH"];
|
||||||
|
|
||||||
const tableElements = altBlocks.map(e => {
|
const tableElements = altBlocks.map(e => {
|
||||||
const hash = e.hash;
|
const hash = e.hash;
|
||||||
|
|
@ -46,31 +45,30 @@ function AltBlocks() {
|
||||||
|
|
||||||
return [
|
return [
|
||||||
<p>
|
<p>
|
||||||
<Link to={hashLink}>{e.height}</Link>
|
<Link href={hashLink}>{e.height}</Link>
|
||||||
{` (${e.type})`}
|
{` (${e.type})`}
|
||||||
</p>,
|
</p>,
|
||||||
Utils.formatTimestampUTC(e.timestamp),
|
Utils.formatTimestampUTC(e.timestamp),
|
||||||
Utils.formatTimestampUTC(e.timestamp),
|
Utils.formatTimestampUTC(e.timestamp),
|
||||||
`${e.size} bytes`,
|
`${e.size} bytes`,
|
||||||
e.transactions?.toString() || "0",
|
e.transactions?.toString() || "0",
|
||||||
<AliasText to={hashLink}>{e.hash}</AliasText>
|
<AliasText href={hashLink}>{e.hash}</AliasText>
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="alt_blocks">
|
<div className={styles["alt_blocks"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Alt-blocks"
|
page="Alt-blocks"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
setBurgerOpened={setBurgerOpened}
|
setBurgerOpened={setBurgerOpened}
|
||||||
/>
|
/>
|
||||||
<InfoTopPanel
|
<InfoTopPanel
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
title="Alt-blocks"
|
title="Alt-blocks"
|
||||||
/>
|
/>
|
||||||
<div className="alt_blocks__table custom-scroll">
|
<div className={`${styles["alt_blocks__table"]} custom-scroll`}>
|
||||||
<Table
|
<Table
|
||||||
headers={tableHeaders}
|
headers={tableHeaders}
|
||||||
elements={tableElements}
|
elements={tableElements}
|
||||||
pagination
|
pagination
|
||||||
|
|
@ -85,4 +83,4 @@ function AltBlocks() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AltBlocks;
|
export default AltBlocks;
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import "../../styles/Asset.scss";
|
import styles from "@/styles/Asset.module.scss";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
|
|
||||||
export default function Asset() {
|
export default function Asset() {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
|
|
@ -27,13 +27,13 @@ export default function Asset() {
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
title=""
|
title=""
|
||||||
back
|
back
|
||||||
className="block__info__top"
|
className={styles["block__info__top"]}
|
||||||
/>
|
/>
|
||||||
<Table
|
<Table
|
||||||
columnsWidth={[50, 50]}
|
columnsWidth={[50, 50]}
|
||||||
headers={["NAME", "AMOUNT"]}
|
headers={["NAME", "AMOUNT"]}
|
||||||
elements={assetsRows}
|
elements={assetsRows}
|
||||||
className="asset__table"
|
className={styles["asset__table"]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
import "../../styles/Assets.scss";
|
import styles from "@/styles/Assets.module.scss";
|
||||||
import { useState, useEffect, useRef, memo, useCallback } from "react";
|
import { useState, useEffect, useRef, memo, useCallback } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import AliasText from "../../components/default/AliasText/AliasText";
|
import AliasText from "@/components/default/AliasText/AliasText";
|
||||||
import JSONPopup from "../../components/default/JSONPopup/JSONPopup";
|
import JSONPopup from "@/components/default/JSONPopup/JSONPopup";
|
||||||
import Switch from "../../components/UI/Switch/Switch";
|
import Switch from "@/components/UI/Switch/Switch";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import Button from "../../components/UI/Button/Button";
|
import Button from "@/components/UI/Button/Button";
|
||||||
import { useSearchParams } from "react-router-dom";
|
import CopyButton from "@/components/UI/CopyButton/CopyButton";
|
||||||
import CopyButton from "../../components/CopyButton/CopyButton";
|
import CommonStatsPanel from "@/components/UI/CommonStatsPanel/CommonStatsPanel";
|
||||||
import CommonStatsPanel from "../../components/UI/CommonStatsPanel/CommonStatsPanel";
|
import { useRouter } from "next/router";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
const AssetPopupBottom = memo(({ assetId }: { assetId?: string }) => {
|
const AssetPopupBottom = memo(({ assetId }: { assetId?: string }) => {
|
||||||
|
|
||||||
|
|
@ -35,11 +36,11 @@ const AssetPopupBottom = memo(({ assetId }: { assetId?: string }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
assetLink ? (
|
assetLink ? (
|
||||||
<div className="asset_popup__bottom">
|
<div className={styles["asset_popup__bottom"]}>
|
||||||
<Button onClick={copy}>{clicked ? 'Copied' : 'Copy asset link'}</Button>
|
<Button onClick={copy}>{clicked ? 'Copied' : 'Copy asset link'}</Button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="asset_popup__not_found">
|
<div className={styles["asset_popup__not_found"]}>
|
||||||
<h3>
|
<h3>
|
||||||
Asset not found or does not exist. For newly created assets, please allow one minute to appear in the explorer
|
Asset not found or does not exist. For newly created assets, please allow one minute to appear in the explorer
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -49,8 +50,8 @@ const AssetPopupBottom = memo(({ assetId }: { assetId?: string }) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function Assets() {
|
function Assets() {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const router = useRouter();
|
||||||
|
|
||||||
const ZANO_ID =
|
const ZANO_ID =
|
||||||
"d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a";
|
"d6329b5b1f7c0805b5c345f4957554002a2f557845f64d7645dae0e051a6498a";
|
||||||
|
|
@ -119,7 +120,10 @@ function Assets() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchParamAsset() {
|
async function fetchParamAsset() {
|
||||||
const assetId = decodeURIComponent(searchParams.get("asset_id") || '');
|
const assetId = decodeURIComponent(
|
||||||
|
searchParams.get('asset_id') || ""
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
if (assetId) {
|
if (assetId) {
|
||||||
const response = await Fetch.getAssetDetails(assetId);
|
const response = await Fetch.getAssetDetails(assetId);
|
||||||
|
|
@ -196,9 +200,9 @@ function Assets() {
|
||||||
const tableElements = assets.map(e => [
|
const tableElements = assets.map(e => [
|
||||||
e?.full_name || "",
|
e?.full_name || "",
|
||||||
e?.ticker || "",
|
e?.ticker || "",
|
||||||
<div className="assets__table_asset-id">
|
<div className={styles["assets__table_asset-id"]}>
|
||||||
<CopyButton text={e?.asset_id || ""} />
|
<CopyButton text={e?.asset_id || ""} />
|
||||||
<AliasText to="/" onClick={(event) => onAssetClick(event, e)}>
|
<AliasText href="/" onClick={(event) => onAssetClick(event, e)}>
|
||||||
{e?.asset_id || ""}
|
{e?.asset_id || ""}
|
||||||
</AliasText>
|
</AliasText>
|
||||||
|
|
||||||
|
|
@ -212,7 +216,7 @@ function Assets() {
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="assets">
|
<div className={styles["assets"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Assets"
|
page="Assets"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
|
|
@ -237,8 +241,8 @@ function Assets() {
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<CommonStatsPanel pairs={statsPanelData} className={"assets__stats"} />
|
<CommonStatsPanel pairs={statsPanelData} className={styles["assets__stats"]} />
|
||||||
<div className="assets__table">
|
<div className={styles["assets__table"]}>
|
||||||
<Table
|
<Table
|
||||||
headers={tableHeaders}
|
headers={tableHeaders}
|
||||||
elements={tableElements}
|
elements={tableElements}
|
||||||
|
|
@ -265,9 +269,15 @@ function Assets() {
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
onClose: () => {
|
onClose: () => {
|
||||||
if (searchParams.get("asset_id")) {
|
if (searchParams.get('asset_id')) {
|
||||||
searchParams.delete("asset_id");
|
const removeQueryParam = (param: string) => {
|
||||||
setSearchParams(searchParams);
|
const updatedQuery = router.query;
|
||||||
|
delete updatedQuery[param];
|
||||||
|
|
||||||
|
router.push({ query: updatedQuery }, undefined, { shallow: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
removeQueryParam('asset_id');
|
||||||
}
|
}
|
||||||
setNotFountPopupState(false);
|
setNotFountPopupState(false);
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
import "../../styles/Block.scss";
|
import styles from "@/styles/Block.module.scss";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import StatsPanel from "../../components/default/StatsPanel/StatsPanel";
|
import StatsPanel from "@/components/default/StatsPanel/StatsPanel";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import { ReactComponent as ArrowImg } from "../../assets/images/UI/arrow.svg";
|
import ArrowImg from "@/assets/images/UI/arrow.svg";
|
||||||
import BlockInfo from "../../interfaces/common/BlockInfo";
|
import BlockInfo from "@/interfaces/common/BlockInfo";
|
||||||
import Utils from "../../utils/utils";
|
import Utils from "@/utils/utils";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import Link from "next/link";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import Popup from "../../components/default/Popup/Popup";
|
import Popup from "@/components/default/Popup/Popup";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
interface Transaction {
|
interface Transaction {
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|
@ -24,27 +25,26 @@ function Block(props: { alt?: boolean }) {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
const [jsonPopupOpened, setJsonPopupOpened] = useState(false);
|
const [jsonPopupOpened, setJsonPopupOpened] = useState(false);
|
||||||
|
|
||||||
const { hash } = useParams();
|
const router = useRouter();
|
||||||
|
const { hashQuery } = router.query;
|
||||||
|
|
||||||
const tableHeaders = [ "HASH", "FEE", "TOTAL AMOUNT", "SIZE" ];
|
const hash = Array.isArray(hashQuery) ? hashQuery[0] : hashQuery;
|
||||||
|
|
||||||
|
const tableHeaders = ["HASH", "FEE", "TOTAL AMOUNT", "SIZE"];
|
||||||
|
|
||||||
const [blockInfo, setBlockInfo] = useState<BlockInfo | null>(null);
|
const [blockInfo, setBlockInfo] = useState<BlockInfo | null>(null);
|
||||||
const [transactions, setTransactions] = useState<Transaction[]>([]);
|
const [transactions, setTransactions] = useState<Transaction[]>([]);
|
||||||
|
|
||||||
|
|
||||||
const tableElements = transactions.map(e => [
|
const tableElements = transactions.map(e => [
|
||||||
!alt
|
!alt
|
||||||
?
|
? (
|
||||||
(
|
<Link href={"/transaction/" + (e.hash || "")} className={styles["block__table__hash"]}>
|
||||||
<Link to={"/transaction/" + (e.hash || "")} className="block__table__hash">
|
{e.hash}
|
||||||
{e.hash}
|
</Link>
|
||||||
</Link>
|
)
|
||||||
)
|
: (
|
||||||
:
|
<p className={styles["block__table__hash"]}>{e.hash}</p>
|
||||||
(
|
),
|
||||||
<p className="block__table__hash">{e.hash}</p>
|
|
||||||
),
|
|
||||||
e.fee,
|
e.fee,
|
||||||
e.amount,
|
e.amount,
|
||||||
e.size + " bytes"
|
e.size + " bytes"
|
||||||
|
|
@ -63,7 +63,7 @@ function Block(props: { alt?: boolean }) {
|
||||||
setPrevHash(prevHashFetched);
|
setPrevHash(prevHashFetched);
|
||||||
setNextHash(nextHashFetched);
|
setNextHash(nextHashFetched);
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchHash();
|
fetchHash();
|
||||||
}, [height]);
|
}, [height]);
|
||||||
|
|
||||||
|
|
@ -78,8 +78,7 @@ function Block(props: { alt?: boolean }) {
|
||||||
setHeight(result.height || null);
|
setHeight(result.height || null);
|
||||||
|
|
||||||
console.log(result);
|
console.log(result);
|
||||||
|
|
||||||
|
|
||||||
setBlockInfo({
|
setBlockInfo({
|
||||||
type: result.type === "1" ? "PoW" : "PoS",
|
type: result.type === "1" ? "PoW" : "PoS",
|
||||||
timestamp: result.timestamp || undefined,
|
timestamp: result.timestamp || undefined,
|
||||||
|
|
@ -100,24 +99,24 @@ function Block(props: { alt?: boolean }) {
|
||||||
currentTxsMedian: undefined,
|
currentTxsMedian: undefined,
|
||||||
transactions: result.tr_count || "0",
|
transactions: result.tr_count || "0",
|
||||||
transactionsSize: result.total_txs_size || "0",
|
transactionsSize: result.total_txs_size || "0",
|
||||||
alreadyGeneratedCoins: result.already_generated_coins || undefined,
|
alreadyGeneratedCoins: result.already_generated_coins || undefined,
|
||||||
object_in_json: result.object_in_json || undefined,
|
object_in_json: result.object_in_json || undefined,
|
||||||
tx_id: result.tx_id || undefined,
|
tx_id: result.tx_id || undefined,
|
||||||
prev_id: result.prev_id || undefined,
|
prev_id: result.prev_id || undefined,
|
||||||
minor_version: result?.object_in_json?.split('\"minor_version\": ')?.[1]?.split(',')?.[0] || '-',
|
minor_version: result?.object_in_json?.split('\"minor_version\": ')?.[1]?.split(',')?.[0] || '-',
|
||||||
major_version: result?.object_in_json?.split('\"major_version\": ')?.[1]?.split(',')?.[0] || '-',
|
major_version: result?.object_in_json?.split('\"major_version\": ')?.[1]?.split(',')?.[0] || '-',
|
||||||
});
|
});
|
||||||
|
|
||||||
const rawTransactionsDetails = result.transactions_details;
|
const rawTransactionsDetails = result.transactions_details;
|
||||||
|
|
||||||
const transactionsDetails =
|
const transactionsDetails =
|
||||||
typeof rawTransactionsDetails === "string"
|
typeof rawTransactionsDetails === "string"
|
||||||
? (() => {
|
? (() => {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(rawTransactionsDetails);
|
return JSON.parse(rawTransactionsDetails);
|
||||||
} catch {}
|
} catch { }
|
||||||
})()
|
})()
|
||||||
: rawTransactionsDetails;
|
: rawTransactionsDetails;
|
||||||
|
|
||||||
if (!(transactionsDetails instanceof Array)) return;
|
if (!(transactionsDetails instanceof Array)) return;
|
||||||
|
|
||||||
|
|
@ -133,14 +132,14 @@ function Block(props: { alt?: boolean }) {
|
||||||
|
|
||||||
fetchBlock();
|
fetchBlock();
|
||||||
}, [hash]);
|
}, [hash]);
|
||||||
|
|
||||||
function BlockInfo() {
|
function BlockInfo() {
|
||||||
|
|
||||||
function JsonPopup() {
|
function JsonPopup() {
|
||||||
return (
|
return (
|
||||||
<div className="block__info__json">
|
<div className={styles["block__info__json"]}>
|
||||||
{/* <button>x</button> */}
|
{/* <button>x</button> */}
|
||||||
<div className="block__info__json__content">
|
<div className={styles["block__info__json__content"]}>
|
||||||
{blockInfo?.object_in_json || ''}
|
{blockInfo?.object_in_json || ''}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -148,9 +147,9 @@ function Block(props: { alt?: boolean }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block__info">
|
<div className={styles["block__info"]}>
|
||||||
{jsonPopupOpened &&
|
{jsonPopupOpened &&
|
||||||
<Popup
|
<Popup
|
||||||
Content={JsonPopup}
|
Content={JsonPopup}
|
||||||
close={() => setJsonPopupOpened(false)}
|
close={() => setJsonPopupOpened(false)}
|
||||||
settings={{
|
settings={{
|
||||||
|
|
@ -158,34 +157,34 @@ function Block(props: { alt?: boolean }) {
|
||||||
}}
|
}}
|
||||||
scroll
|
scroll
|
||||||
blur
|
blur
|
||||||
classList={["block__json_popup"]}
|
classList={[styles["block__json_popup"]]}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<div className="block__info__title">
|
<div className={styles["block__info__title"]}>
|
||||||
<h2>Zano Block</h2>
|
<h2>Zano Block</h2>
|
||||||
<div>
|
<div>
|
||||||
{!alt && prevHash !== "" &&
|
{!alt && prevHash !== "" &&
|
||||||
<Link to={prevHash ? "/block/" + prevHash : "/"}>
|
<Link href={prevHash ? "/block/" + prevHash : "/"}>
|
||||||
<ArrowImg />
|
<ArrowImg />
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
<h2>{height}</h2>
|
<h2>{height}</h2>
|
||||||
{!alt && nextHash !== "" &&
|
{!alt && nextHash !== "" &&
|
||||||
<Link to={nextHash ? "/block/" + nextHash : "/"}>
|
<Link href={nextHash ? "/block/" + nextHash : "/"}>
|
||||||
<ArrowImg />
|
<ArrowImg />
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<p>{hash?.toUpperCase() || ""}</p>
|
<p>{hash?.toUpperCase() || ""}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="block__info__table">
|
<div className={styles["block__info__table"]}>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Type:</td>
|
<td>Type:</td>
|
||||||
<td>
|
<td>
|
||||||
<span
|
<span
|
||||||
className={`block__info__type ${blockInfo?.type === "PoS" ? "type__pos" : "type__pow"}`}
|
className={`${styles["block__info__type"]} ${blockInfo?.type === "PoS" ? styles["type__pos"] : styles["type__pow"]}`}
|
||||||
>
|
>
|
||||||
{blockInfo?.type ?? "-"}
|
{blockInfo?.type ?? "-"}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -197,7 +196,7 @@ function Block(props: { alt?: boolean }) {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>ID</td>
|
<td>ID</td>
|
||||||
<td><Link to="/">{Utils.shortenAddress(blockInfo?.tx_id ?? "-")}</Link></td>
|
<td><Link href="/">{Utils.shortenAddress(blockInfo?.tx_id ?? "-")}</Link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Actual Timestamp (UTC):</td>
|
<td>Actual Timestamp (UTC):</td>
|
||||||
|
|
@ -249,7 +248,7 @@ function Block(props: { alt?: boolean }) {
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Previous ID:</td>
|
<td>Previous ID:</td>
|
||||||
<td><Link to={`/block/${blockInfo?.prev_id}`}>{Utils.shortenAddress(blockInfo?.prev_id ?? "-")}</Link></td>
|
<td><Link href={`/block/${blockInfo?.prev_id}`}>{Utils.shortenAddress(blockInfo?.prev_id ?? "-")}</Link></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Total block size, bytes:</td>
|
<td>Total block size, bytes:</td>
|
||||||
|
|
@ -287,7 +286,7 @@ function Block(props: { alt?: boolean }) {
|
||||||
<td>JSON data:</td>
|
<td>JSON data:</td>
|
||||||
<td>
|
<td>
|
||||||
<Link
|
<Link
|
||||||
to="/"
|
href="/"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setJsonPopupOpened(true);
|
setJsonPopupOpened(true);
|
||||||
|
|
@ -301,28 +300,28 @@ function Block(props: { alt?: boolean }) {
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block">
|
<div className={styles["block"]}>
|
||||||
<Header
|
<Header
|
||||||
page="Blockchain"
|
page="Blockchain"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
setBurgerOpened={setBurgerOpened}
|
setBurgerOpened={setBurgerOpened}
|
||||||
/>
|
/>
|
||||||
<InfoTopPanel
|
<InfoTopPanel
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
title=""
|
title=""
|
||||||
back
|
back
|
||||||
className="block__info__top"
|
className={styles["block__info__top"]}
|
||||||
/>
|
/>
|
||||||
<StatsPanel noStats={true}/>
|
<StatsPanel noStats={true} />
|
||||||
<BlockInfo />
|
<BlockInfo />
|
||||||
<div className="block__transactions">
|
<div className={styles["block__transactions"]}>
|
||||||
<h2>Transactions</h2>
|
<h2>Transactions</h2>
|
||||||
<Table
|
<Table
|
||||||
headers={tableHeaders}
|
headers={tableHeaders}
|
||||||
elements={tableElements}
|
elements={tableElements}
|
||||||
/>
|
/>
|
||||||
|
|
@ -331,4 +330,4 @@ function Block(props: { alt?: boolean }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Block;
|
export default Block;
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#__next {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -72,42 +72,42 @@ button {
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-Light.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-Light.ttf) format("opentype");
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-Regular.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-Regular.ttf) format("opentype");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-Medium.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-Medium.ttf) format("opentype");
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-SemiBold.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-SemiBold.ttf) format("opentype");
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-Bold.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-Bold.ttf) format("opentype");
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
src: url(./assets/fonts/OpenSans/OpenSans-ExtraBold.ttf) format("opentype");
|
src: url(../assets/fonts/OpenSans/OpenSans-ExtraBold.ttf) format("opentype");
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Inconsolata";
|
font-family: "Inconsolata";
|
||||||
src: url(./assets/fonts/Inconsolata/Inconsolata-Regular.ttf) format("opentype");
|
src: url(../assets/fonts/Inconsolata/Inconsolata-Regular.ttf) format("opentype");
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
9
src/pages/index.tsx
Normal file
9
src/pages/index.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import Blockchain from './Blockchain/index';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<Blockchain />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
import "../../styles/Transaction.scss";
|
import styles from "@/styles/Transaction.module.scss";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import InfoTopPanel from "../../components/default/InfoTopPanel/InfoTopPanel";
|
import InfoTopPanel from "@/components/default/InfoTopPanel/InfoTopPanel";
|
||||||
import StatsPanel from "../../components/default/StatsPanel/StatsPanel";
|
import StatsPanel from "@/components/default/StatsPanel/StatsPanel";
|
||||||
import Table from "../../components/default/Table/Table";
|
import Table from "@/components/default/Table/Table";
|
||||||
import TransactionInfo, { Input } from "../../interfaces/common/TransactionInfo";
|
import TransactionInfo, { Input } from "@/interfaces/common/TransactionInfo";
|
||||||
import Fetch from "../../utils/methods";
|
import Fetch from "@/utils/methods";
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import Link from "next/link";
|
||||||
import Utils from "../../utils/utils";
|
import Utils from "@/utils/utils";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import Popup from "../../components/default/Popup/Popup";
|
import Popup from "@/components/default/Popup/Popup";
|
||||||
import { ReactComponent as CrossImg } from "../../assets/images/UI/cross.svg";
|
import CrossImg from "@/assets/images/UI/cross.svg";
|
||||||
import Button from "../../components/UI/Button/Button";
|
import Button from "@/components/UI/Button/Button";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
interface Block {
|
interface Block {
|
||||||
hash: string;
|
hash: string;
|
||||||
|
|
@ -19,8 +20,6 @@ interface Block {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Transaction() {
|
function Transaction() {
|
||||||
const [burgerOpened, setBurgerOpened] = useState(false);
|
const [burgerOpened, setBurgerOpened] = useState(false);
|
||||||
|
|
||||||
|
|
@ -30,9 +29,11 @@ function Transaction() {
|
||||||
const [popupState, setPopupState] = useState(false);
|
const [popupState, setPopupState] = useState(false);
|
||||||
const [selectedInput, setSelectedInput] = useState<Input | null>(null);
|
const [selectedInput, setSelectedInput] = useState<Input | null>(null);
|
||||||
|
|
||||||
const { hash } = useParams();
|
const router = useRouter();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const { hashQuery } = router.query;
|
||||||
|
|
||||||
|
const hash = Array.isArray(hashQuery) ? hashQuery[0] : hashQuery;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchTransaction() {
|
async function fetchTransaction() {
|
||||||
|
|
@ -81,7 +82,6 @@ function Transaction() {
|
||||||
e.convertedAmount = Utils.convertENotationToString(existingAmount?.toExponential());
|
e.convertedAmount = Utils.convertENotationToString(existingAmount?.toExponential());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
amount: e.convertedAmount,
|
amount: e.convertedAmount,
|
||||||
keyimage: e?.kimage_or_ms_id || "",
|
keyimage: e?.kimage_or_ms_id || "",
|
||||||
|
|
@ -129,7 +129,7 @@ function Transaction() {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const result = await Fetch.getOutInfo(amount, index);
|
const result = await Fetch.getOutInfo(amount, index);
|
||||||
if (result.tx_id && typeof result.tx_id === "string") {
|
if (result.tx_id && typeof result.tx_id === "string") {
|
||||||
navigate("/transaction/" + result.tx_id);
|
router.push("/transaction/" + result.tx_id);
|
||||||
setPopupState(false);
|
setPopupState(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -141,12 +141,12 @@ function Transaction() {
|
||||||
e.globalIndexes.length,
|
e.globalIndexes.length,
|
||||||
e.globalIndexes.length > 1 ?
|
e.globalIndexes.length > 1 ?
|
||||||
(
|
(
|
||||||
<Link to="/" onClick={event => showIndexesClick(event, e)}>Show all...</Link>
|
<Link href="/" onClick={event => showIndexesClick(event, e)}>Show all...</Link>
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
(
|
(
|
||||||
<Link
|
<Link
|
||||||
to="/"
|
href="/"
|
||||||
onClick={event => onIndexClick(event, e.amount, e.globalIndexes[0])}
|
onClick={event => onIndexClick(event, e.amount, e.globalIndexes[0])}
|
||||||
>
|
>
|
||||||
{e.globalIndexes[0] ?? ""}
|
{e.globalIndexes[0] ?? ""}
|
||||||
|
|
@ -158,7 +158,7 @@ function Transaction() {
|
||||||
const outsRows = transactionInfo ? (
|
const outsRows = transactionInfo ? (
|
||||||
transactionInfo.outs.map(e => [
|
transactionInfo.outs.map(e => [
|
||||||
e.amount,
|
e.amount,
|
||||||
<div className="transaction__outs__keys">
|
<div className={styles["transaction__outs__keys"]}>
|
||||||
{e.publicKeys.map(e => <p>{e}</p>)}
|
{e.publicKeys.map(e => <p>{e}</p>)}
|
||||||
</div>,
|
</div>,
|
||||||
e.globalIndex
|
e.globalIndex
|
||||||
|
|
@ -170,7 +170,7 @@ function Transaction() {
|
||||||
const amount = selectedInput?.amount || 0;
|
const amount = selectedInput?.amount || 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="transaction__indexes__popup">
|
<div className={styles["transaction__indexes__popup"]}>
|
||||||
<h3>
|
<h3>
|
||||||
Input ring set ({popupIndexes.length})
|
Input ring set ({popupIndexes.length})
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -178,7 +178,7 @@ function Transaction() {
|
||||||
{popupIndexes.map(e =>
|
{popupIndexes.map(e =>
|
||||||
(
|
(
|
||||||
<Link
|
<Link
|
||||||
to="/"
|
href="/"
|
||||||
key={e}
|
key={e}
|
||||||
onClick={event => onIndexClick(event, amount, e)}
|
onClick={event => onIndexClick(event, amount, e)}
|
||||||
>
|
>
|
||||||
|
|
@ -189,7 +189,7 @@ function Transaction() {
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
wrapper
|
wrapper
|
||||||
className="popup__cross"
|
className={styles["popup__cross"]}
|
||||||
onClick={close}
|
onClick={close}
|
||||||
>
|
>
|
||||||
<CrossImg />
|
<CrossImg />
|
||||||
|
|
@ -199,7 +199,7 @@ function Transaction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="transaction">
|
<div className={styles["transaction"]}>
|
||||||
<Header
|
<Header
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
setBurgerOpened={setBurgerOpened}
|
setBurgerOpened={setBurgerOpened}
|
||||||
|
|
@ -209,10 +209,10 @@ function Transaction() {
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
title=""
|
title=""
|
||||||
back
|
back
|
||||||
className="block__info__top"
|
className={styles["block__info__top"]}
|
||||||
/>
|
/>
|
||||||
<StatsPanel noStats={true}/>
|
<StatsPanel noStats={true}/>
|
||||||
<div className="transaction__info">
|
<div className={styles["transaction__info"]}>
|
||||||
<h2>Transaction</h2>
|
<h2>Transaction</h2>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
@ -232,7 +232,7 @@ function Transaction() {
|
||||||
<td>Size</td>
|
<td>Size</td>
|
||||||
<td>{(transactionInfo?.size || "0") + " bytes"}</td>
|
<td>{(transactionInfo?.size || "0") + " bytes"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className={"transaction__confirmation" + (!transactionInfo?.confirmations ? ' transaction__unconfirmed' : '')}>
|
<tr className={styles["transaction__confirmation"] + (!transactionInfo?.confirmations ? ` ${styles["transaction__unconfirmed"]}` : '')}>
|
||||||
<td>Confirmations</td>
|
<td>Confirmations</td>
|
||||||
<td>{transactionInfo?.confirmations || "Unconfirmed"}</td>
|
<td>{transactionInfo?.confirmations || "Unconfirmed"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -244,7 +244,7 @@ function Transaction() {
|
||||||
<td>Mixin</td>
|
<td>Mixin</td>
|
||||||
<td>{transactionInfo?.mixin || "-"}</td>
|
<td>{transactionInfo?.mixin || "-"}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr className="transaction__extra_items">
|
<tr className={styles["transaction__extra_items"]}>
|
||||||
<td>Extra items</td>
|
<td>Extra items</td>
|
||||||
<td>
|
<td>
|
||||||
{
|
{
|
||||||
|
|
@ -263,15 +263,15 @@ function Transaction() {
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className="transaction__table__wrapper">
|
<div className={styles["transaction__table__wrapper"]}>
|
||||||
<h3>From Block</h3>
|
<h3>From Block</h3>
|
||||||
<Table
|
<Table
|
||||||
className="custom-scroll"
|
className={styles["custom-scroll"]}
|
||||||
headers={[ "HASH", "HEIGHT", "TIMESTAMP (UTC)" ]}
|
headers={[ "HASH", "HEIGHT", "TIMESTAMP (UTC)" ]}
|
||||||
elements={[[
|
elements={[[
|
||||||
<Link
|
<Link
|
||||||
className="table__hash"
|
className={styles["table__hash"]}
|
||||||
to={blockOrigin?.hash ? "/block/" + blockOrigin.hash : "/"}
|
href={blockOrigin?.hash ? "/block/" + blockOrigin.hash : "/"}
|
||||||
>
|
>
|
||||||
{blockOrigin?.hash}
|
{blockOrigin?.hash}
|
||||||
</Link>,
|
</Link>,
|
||||||
|
|
@ -281,19 +281,19 @@ function Transaction() {
|
||||||
columnsWidth={[ 65, 15, 20 ]}
|
columnsWidth={[ 65, 15, 20 ]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="transaction__table__wrapper">
|
<div className={styles["transaction__table__wrapper"]}>
|
||||||
<h3>{`Inputs ( ${insRows.length} )`}</h3>
|
<h3>{`Inputs ( ${insRows.length} )`}</h3>
|
||||||
<Table
|
<Table
|
||||||
className="transaction__table__inputs custom-scroll"
|
className={`${styles["transaction__table__inputs"]} ${styles["custom-scroll"]}`}
|
||||||
headers={[ "AMOUNT", "IMAGE / MULTISIG ID", "DECOY COUNT", "GLOBAL INDEX" ]}
|
headers={[ "AMOUNT", "IMAGE / MULTISIG ID", "DECOY COUNT", "GLOBAL INDEX" ]}
|
||||||
elements={insRows}
|
elements={insRows}
|
||||||
columnsWidth={[ 15, 50, 15, 20 ]}
|
columnsWidth={[ 15, 50, 15, 20 ]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="transaction__table__wrapper">
|
<div className={styles["transaction__table__wrapper"]}>
|
||||||
<h3>{`Outputs ( ${outsRows.length} )`}</h3>
|
<h3>{`Outputs ( ${outsRows.length} )`}</h3>
|
||||||
<Table
|
<Table
|
||||||
className="custom-scroll"
|
className={styles["custom-scroll"]}
|
||||||
headers={[ "AMOUNT", "KEY", "GLOBAL INDEX / MULTISIG ID" ]}
|
headers={[ "AMOUNT", "KEY", "GLOBAL INDEX / MULTISIG ID" ]}
|
||||||
elements={outsRows}
|
elements={outsRows}
|
||||||
columnsWidth={[ 15, 65, 20 ]}
|
columnsWidth={[ 15, 65, 20 ]}
|
||||||
|
|
@ -312,4 +312,4 @@ function Transaction() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Transaction;
|
export default Transaction;
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Header from "../../components/default/Header/Header";
|
import Header from "@/components/default/Header/Header";
|
||||||
import "../../styles/API.scss";
|
import styles from "@/styles/API.module.scss";
|
||||||
import APIItemValue from "../../interfaces/common/APIItemValue";
|
import APIItemValue from "@/interfaces/common/APIItemValue";
|
||||||
import examples from "./examples";
|
import examples from "./examples";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import JsonViewStyled from "../../components/UI/JsonViewStyled/JsonViewStyled";
|
import JsonViewStyled from "@/components/UI/JsonViewStyled/JsonViewStyled";
|
||||||
|
|
||||||
interface APIEndpointItemProps {
|
interface APIEndpointItemProps {
|
||||||
title: string,
|
title: string,
|
||||||
|
|
@ -92,14 +92,14 @@ function API() {
|
||||||
const { title, values, json } = props;
|
const { title, values, json } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="api__item">
|
<div className={styles["api__item"]}>
|
||||||
<div className="api__item__title">
|
<div className={styles["api__item__title"]}>
|
||||||
<h3>{title}</h3>
|
<h3>{title}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="api__item__units">
|
<div className={styles["api__item__units"]}>
|
||||||
{
|
{
|
||||||
values?.map(e => (
|
values?.map(e => (
|
||||||
<div key={e.key} className="api__item__unit">
|
<div key={e.key} className={styles["api__item__unit"]}>
|
||||||
<div>
|
<div>
|
||||||
<p>{e.key}</p>
|
<p>{e.key}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -111,7 +111,7 @@ function API() {
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{json &&
|
{json &&
|
||||||
<div className="api__item__json">
|
<div className={styles["api__item__json"]}>
|
||||||
<p>JSON Response</p>
|
<p>JSON Response</p>
|
||||||
<JsonViewStyled
|
<JsonViewStyled
|
||||||
data={json}
|
data={json}
|
||||||
|
|
@ -137,16 +137,16 @@ function API() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="api">
|
<div className={styles["api"]}>
|
||||||
<Header
|
<Header
|
||||||
page="API"
|
page="API"
|
||||||
burgerOpened={burgerOpened}
|
burgerOpened={burgerOpened}
|
||||||
setBurgerOpened={setBurgerOpened}
|
setBurgerOpened={setBurgerOpened}
|
||||||
/>
|
/>
|
||||||
<div className="api__title">
|
<div className={styles["api__title"]}>
|
||||||
<p>API Documentation</p>
|
<p>API Documentation</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="api__items">
|
<div className={styles["api__items"]}>
|
||||||
<APIItem title="How to use" values={howToUseValues} />
|
<APIItem title="How to use" values={howToUseValues} />
|
||||||
{
|
{
|
||||||
endpoints.map(e => (
|
endpoints.map(e => (
|
||||||
|
|
@ -16,15 +16,22 @@
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
// "isolatedModules": true,
|
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx"
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["src/*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src"
|
"src"
|
||||||
],
|
],
|
||||||
"exclude": ["src/setupProxy.js"],
|
"exclude": [
|
||||||
|
"src/setupProxy.js"
|
||||||
|
],
|
||||||
"ts-node": {
|
"ts-node": {
|
||||||
"esm": true
|
"esm": true
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue