diff --git a/public/icons/check.svg b/public/icons/check.svg new file mode 100644 index 0000000..f8929ca --- /dev/null +++ b/public/icons/check.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/app/(header-footer-layout)/address/[address]/address.scss b/src/app/(header-footer-layout)/address/[address]/address.scss new file mode 100644 index 0000000..561290e --- /dev/null +++ b/src/app/(header-footer-layout)/address/[address]/address.scss @@ -0,0 +1,46 @@ +.eye_tooltip_container { + @apply relative; + @apply cursor-pointer; + + &:hover { + .tooltip { + @apply block; + } + } + + .tooltip { + @apply hidden; + @apply absolute; + @apply bg-white; + @apply dark:bg-abrandc-dark-blackish; + @apply dark:shadow-white-lg-y-axis; + + + + @apply top-1/2; + @apply -translate-y-1/2; + left: calc(100% + 8px); + + // arrow + &::before { + content: ''; + @apply absolute; + @apply border-solid; + @apply border-transparent; + @apply border-r-8; + @apply border-l-0; + @apply border-t-8; + @apply border-b-8; + + @apply top-1/2; + @apply -translate-y-1/2; + @apply right-full; + + @apply border-r-white; + @apply dark:border-r-abrandc-dark-blackish; + + // border-right-color: ; // match the background color of the tooltip + // box-shadow: px 0 2px 5px rgba(0, 0, 0, 0.1); + } + } +} \ No newline at end of file diff --git a/src/app/(header-footer-layout)/address/[address]/blocks.component.tsx b/src/app/(header-footer-layout)/address/[address]/blocks.component.tsx new file mode 100644 index 0000000..400bd5a --- /dev/null +++ b/src/app/(header-footer-layout)/address/[address]/blocks.component.tsx @@ -0,0 +1,259 @@ +'use client'; + +import Link from 'next/link'; +import Image from 'next/image'; +import { useState } from 'react'; +import { useFormik } from 'formik'; +import * as yup from 'yup'; +import { useQuery } from 'react-query'; +import { useRouter } from 'next/navigation'; + +import TableSkeleton from 'src/components/internal/table-skeleton/table-skeleton.component'; +import Tooltip from 'src/components/internal/tooltip/tooltip.component'; +import Pagination from 'src/components/internal/pagination/pagination.component'; +import QuickPagination from 'src/components/internal/quick-pagination/quick-pagination.component'; +import ErrorComponent from 'src/components/error/error.component'; + +import { BnToDec, shortenAddress, timeAgo } from 'src/shared/utils/formatters'; +import { copyToClipboard, isAddress, isHash } from 'src/shared/utils/functions'; +import QueryApi from 'src/shared/api/query-api'; + +import QUERY_KEYS from 'src/static/query.keys'; +import ROUTES from 'src/static/router.data'; + +const headers = [ + { + id: 0, + name: 'Block', + thClass: 'xl:px-8 px-2', + }, + { + id: 1, + name: 'Age', + thClass: 'xl:px-8 px-2', + }, + { + id: 2, + name: 'Txns', + thClass: 'xl:px-8 px-2', + }, + { + id: 3, + name: 'Fee Recipient', + thClass: 'xl:px-8 px-2', + }, + { + id: 4, + name: 'Reward', // Direction + thClass: 'xl:px-8 px-2', + }, +]; + +type BlockComponentProps = { + address: string; + page: number; + setPage: (page: number) => void; + count: number; + setCount: (count: number) => void; +}; + +export default function BlockComponent({ + address, + page, + setPage, + count, + setCount, +}: BlockComponentProps) { + // *~~*~~*~~ Txn history ~~*~~*~~* // + + const [paginationMetadata, setPaginationMetadata] = useState({ + currentPage: 1, + totalPages: 1, + startIndex: 0, + endIndex: 0, + totalItems: 0, + itemsPerPage: 0, + nextPage: 0, + previousPage: 0, + }); + + // txnHistory + + const { + data: blockData, + isLoading: blockLoading, + isError: blockError, + } = useQuery( + [QUERY_KEYS.blocks_Created, address, page, count], + () => QueryApi.user.blocksCreated(address, page, count), + { + cacheTime: 0, + onSuccess: (data) => { + setPaginationMetadata(data.metadata); + }, + } + ); + + console.log('BlockComponentProps', blockData?.metadata); + + function handlePageChange(page: number) { + setPage(page); + } + + if (blockError || (!blockLoading && !blockData)) return ; + + if (blockData?.blocks.length === 0) { + return ( +
+
+

+ This address never participated in the creation of blocks on PWR Chain. +

+
+
+ ); + } + + return ( +
+ {/* Title */} +
+ {blockLoading ? ( +
+
+
+
+ ) : blockData?.blocks.length === 0 ? null : ( + <> +
+

+ More than {blockData?.metadata.totalItems} Blocks found +

+

+ (Showing the latest records) +

+
+
+ +
+ + )} +
+ {/* Table */} +
+ {blockLoading ? ( + + ) : ( + + {/* table header */} + + + {headers.map((header, idx) => ( + + ))} + + + + {/* table body */} + + {blockData?.blocks.map((block, idx) => ( + + {/* Block */} + + + {/* Age */} + + + {/* txns */} + + + {/* fee recipient */} + + + {/* Reward */} + + + ))} + +
+ {header.name.length > 0 && ( +
+
+ {header.name} +
+ {/*
+ +
*/} +
+ )} +
+ + {block.blockHeight} + + +
+ {timeAgo(block.timeStamp)} +
+
+
+ + {block.txnsCount} + +
+
+
+ + {shortenAddress(block.blockSubmitter, 4)} + + + + + +
+
+
+ {BnToDec(block.blockReward.toString(), 9, 9)} PWR +
+
+ )} +
+ +
+ +
+
+ ); +} diff --git a/src/app/(header-footer-layout)/address/[address]/page.tsx b/src/app/(header-footer-layout)/address/[address]/page.tsx index 974ea80..1a7afab 100644 --- a/src/app/(header-footer-layout)/address/[address]/page.tsx +++ b/src/app/(header-footer-layout)/address/[address]/page.tsx @@ -3,8 +3,10 @@ import Link from 'next/link'; import Image from 'next/image'; import { useState } from 'react'; - +import { useFormik } from 'formik'; +import * as yup from 'yup'; import { useQuery } from 'react-query'; +import { useRouter } from 'next/navigation'; import TableSkeleton from 'src/components/internal/table-skeleton/table-skeleton.component'; import Tooltip from 'src/components/internal/tooltip/tooltip.component'; @@ -14,54 +16,14 @@ import ErrorComponent from 'src/components/error/error.component'; import OverviewBoxSkeleton from 'src/components/skeletons/address/overview-box.skeleton'; import { BnToDec, shortenAddress, timeAgo } from 'src/shared/utils/formatters'; -import { copyToClipboard, isAddress } from 'src/shared/utils/functions'; +import { copyToClipboard, isAddress, isHash } from 'src/shared/utils/functions'; import QueryApi from 'src/shared/api/query-api'; import QUERY_KEYS from 'src/static/query.keys'; import ROUTES from 'src/static/router.data'; - -const headers = [ - { - id: 0, - name: 'Txn Hash', - thClass: 'xl:px-8 px-2', - }, - { - id: 1, - name: 'Type', - thClass: 'xl:px-8 px-2', - }, - { - id: 2, - name: 'Block', - thClass: 'xl:px-8 px-2', - }, - { - id: 3, - name: 'Timestamp', - thClass: 'xl:px-8 px-2', - }, - { - id: 4, - name: 'From', - thClass: 'xl:pl-8 pl-2 pr-2', - }, - { - id: 5, - name: '', // Direction - thClass: ' px-2', - }, - { - id: 6, - name: 'To', - thClass: 'xl:pr-8 pr-2 pl-2', - }, - { - id: 7, - name: 'Value', - thClass: 'xl:px-8 px-2', - }, -]; +import TextButton from 'src/components/internal/text-button/text-button.component'; +import TransactionComponent from './transcations.component'; +import BlockComponent from './blocks.component'; type AddressPageProps = { params: { @@ -71,6 +33,15 @@ type AddressPageProps = { export default function AddressPage({ params }: AddressPageProps) { const address = params.address; + const { push } = useRouter(); + + const [activeTab, setActiveTab] = useState('transactions'); + const [page, setPage] = useState(1); + const [count, setCount] = useState(10); + + const handleTabChange = (tab: string) => { + setActiveTab(tab); + }; // *~~*~~*~~ account balance ~~*~~*~~* // const { @@ -82,23 +53,40 @@ export default function AddressPage({ params }: AddressPageProps) { cacheTime: 0, }); - // *~~*~~*~~ Txn history ~~*~~*~~* // - - const [page, setPage] = useState(1); - const [count, setCount] = useState(10); - - const [paginationMetadata, setPaginationMetadata] = useState({ - currentPage: 1, - totalPages: 1, - startIndex: 0, - endIndex: 0, - totalItems: 0, - itemsPerPage: 0, - nextPage: 0, - previousPage: 0, + const formik = useFormik({ + initialValues: { + search: '', + }, + validationSchema: yup.object({ + search: yup + .string() + .test( + 'is-address-hash-or-number', + 'Search term must be an address, a hash, or a number', + (value) => + isAddress(value || '') || isHash(value || '') || !isNaN(Number(value)) + ), + }), + onSubmit: (values) => { + const { search } = values; + const address = isAddress(search); + const hash = isHash(search); + const number = !isNaN(Number(search)); + + if (address) { + // Navigate to the address page for 42-character input + push(`${ROUTES.address}/${search}`); + } else if (hash) { + // Navigate to the transaction page for 66-character input + push(`${ROUTES.transactions}/${search}`); + } else if (number) { + // Navigate to the block page for number input + push(`${ROUTES.blocks}/${search}`); + } + }, }); - // txnHistory + // *~~*~~*~~ Txn history ~~*~~*~~* // const { data: txnHistoryData, @@ -110,29 +98,9 @@ export default function AddressPage({ params }: AddressPageProps) { { staleTime: 1000 * 60 * 5, cacheTime: 0, - onSuccess: (data) => { - setPaginationMetadata(data.metadata); - }, } ); - - function handlePageChange(page: number) { - setPage(page); - } - - function SkeletonStatBox() { - return ( -
-
-
-
-
- Loading... -
-
-
- ); - } + console.log('txnHistoryData', txnHistoryData); if ( balanceError || @@ -142,8 +110,10 @@ export default function AddressPage({ params }: AddressPageProps) { ) return ; + const { values, touched, dirty, errors, handleChange, handleBlur, handleSubmit } = formik; + return ( -
+
{/* Title */}

@@ -232,10 +202,13 @@ export default function AddressPage({ params }: AddressPageProps) {
- {shortenAddress(txnHistoryData.hashOfLastTxnSent)} + {shortenAddress( + txnHistoryData.firstLastTransactions.lastTransaction + .txnHash + )}
@@ -268,10 +245,13 @@ export default function AddressPage({ params }: AddressPageProps) {
- {shortenAddress(txnHistoryData.hashOfFirstTxnSent)} + {shortenAddress( + txnHistoryData.firstLastTransactions.firstTransaction + .txnHash + )}
@@ -302,218 +286,83 @@ export default function AddressPage({ params }: AddressPageProps) {

- {/* Table */} -
- {/* Title */} -
- {txnHistoryLoading ? ( -
-
-
-
- ) : txnHistoryData.transactions.length === 0 ? null : ( - <> -
-

- More than {txnHistoryData.metadata.totalItems} transactions - found -

-

- (Showing the latest records) -

-
-
- -
- - )} +
+ {/* Tab navigation */} +
+ +
- {/* Table */} -
- {txnHistoryLoading ? ( - - ) : txnHistoryData.transactions.length === 0 ? ( -
-

- No transactions found -

-
- ) : ( - <> - - {/* table header */} - - - {headers.map((header, idx) => ( - - ))} - - - - {/* table body */} - - {txnHistoryData.transactions.map((txn, idx) => ( - - {/* txn hash */} - - - {/* type */} - - - {/* block */} - - - {/* time ago */} - - - {/* from */} - - - {/* direction */} - - - {/* To */} - - - {/* value */} - - - ))} - -
- {header.name.length > 0 && ( -
-
- {header.name} -
- {/*
- -
*/} -
- )} -
-
-
- -
- - - {shortenAddress(txn.txnHash)} - -
-
-
- {txn.txnType} -
-
- - {txn.block} - - -
- {timeAgo(txn.timeStamp)} -
-
-
- - {shortenAddress(txn.from, 4)} - - - - - -
-
-
-
- -
-
-
-
- {isAddress(txn.to) ? ( - - {shortenAddress(txn.to, 4)} - - ) : ( - - {txn.to} - - )} - - - - -
-
-
- {BnToDec(txn.value, 9)} PWR -
-
- -
- -
- +
+
+ {/* input contianer */} +
+ +
- - )} +
+
+ + {/* Tab content */} +
+ {activeTab === 'transactions' ? ( + + ) : ( + + )} +
); } diff --git a/src/app/(header-footer-layout)/address/[address]/transcations.component.tsx b/src/app/(header-footer-layout)/address/[address]/transcations.component.tsx new file mode 100644 index 0000000..62abca7 --- /dev/null +++ b/src/app/(header-footer-layout)/address/[address]/transcations.component.tsx @@ -0,0 +1,358 @@ +'use client'; + +import Link from 'next/link'; +import Image from 'next/image'; +import { useState } from 'react'; +import { useFormik } from 'formik'; +import * as yup from 'yup'; +import { useQuery } from 'react-query'; +import { useRouter } from 'next/navigation'; + +import TableSkeleton from 'src/components/internal/table-skeleton/table-skeleton.component'; +import Tooltip from 'src/components/internal/tooltip/tooltip.component'; +import Pagination from 'src/components/internal/pagination/pagination.component'; +import QuickPagination from 'src/components/internal/quick-pagination/quick-pagination.component'; +import ErrorComponent from 'src/components/error/error.component'; + +import { BnToDec, shortenAddress, timeAgo } from 'src/shared/utils/formatters'; +import { copyToClipboard, isAddress, isHash } from 'src/shared/utils/functions'; +import QueryApi from 'src/shared/api/query-api'; + +import QUERY_KEYS from 'src/static/query.keys'; +import ROUTES from 'src/static/router.data'; +import TransactionTooltipDetails from 'src/components/internal/transaction-tooltip-details/transaction-tooltip-details'; +import './address.scss'; + +const headers = [ + { + id: 0, + name: 'Txn Hash', + thClass: 'xl:px-8 px-2', + }, + { + id: 1, + name: 'Type', + thClass: 'xl:px-8 px-2', + }, + { + id: 2, + name: 'Block', + thClass: 'xl:px-8 px-2', + }, + { + id: 3, + name: 'Timestamp', + thClass: 'xl:px-8 px-2', + }, + { + id: 4, + name: 'From', + thClass: 'xl:pl-8 pl-2 pr-2', + }, + { + id: 5, + name: '', // Direction + thClass: ' px-2', + }, + { + id: 6, + name: 'To', + thClass: 'xl:pr-8 pr-2 pl-2', + }, + { + id: 7, + name: 'Value', + thClass: 'xl:px-8 px-2', + }, +]; + +type TransactionComponentProps = { + address: string; + page: number; + setPage: (page: number) => void; + count: number; + setCount: (count: number) => void; +}; + +let met: any = null; + +export default function TransactionComponent({ + address, + page, + setPage, + count, + setCount, +}: TransactionComponentProps) { + // *~~*~~*~~ account balance ~~*~~*~~* // + const { + data: balanceData, + isLoading: balanceLoading, + isError: balanceError, + } = useQuery([QUERY_KEYS.balance, address], () => QueryApi.user.balance(address), { + staleTime: 1000 * 60 * 5, + cacheTime: 0, + }); + + // *~~*~~*~~ Txn history ~~*~~*~~* // + + const [paginationMetadata, setPaginationMetadata] = useState( + met || { + currentPage: 1, + totalPages: 1, + startIndex: 0, + endIndex: 0, + totalItems: 0, + itemsPerPage: 0, + nextPage: 0, + previousPage: 0, + } + ); + + // txnHistory + + const { + data: txnHistoryData, + isLoading: txnHistoryLoading, + isError: txnHistoryError, + } = useQuery( + [QUERY_KEYS.txn_history, address, page, count], + () => QueryApi.user.txnHistory(address, page, count), + { + cacheTime: 0, + onSuccess: (data) => { + setPaginationMetadata(data.metadata); + met = data.metadata; + }, + } + ); + console.log('TransactionComponentProps', txnHistoryData?.metadata); + + function handlePageChange(newPage: number) { + setPage(newPage); + } + + if ( + balanceError || + (!balanceLoading && !balanceData) || + txnHistoryError || + (!txnHistoryLoading && !txnHistoryData) + ) + return ; + + return ( +
+ {/* Title */} +
+ {txnHistoryLoading ? ( +
+
+
+
+ ) : txnHistoryData.transactions.length === 0 ? null : ( + <> +
+

+ More than {txnHistoryData.metadata.totalItems} transactions found +

+

+ (Showing the latest records) +

+
+
+ +
+ + )} +
+ {/* Table */} +
+ {txnHistoryLoading ? ( + + ) : txnHistoryData.transactions.length === 0 ? ( +
+

No transactions found

+
+ ) : ( + <> + + {/* table header */} + + + {headers.map((header, idx) => ( + + ))} + + + + {/* table body */} + + {txnHistoryData.transactions.map((txn, idx) => ( + + {/* txn hash */} + + + {/* type */} + + + {/* block */} + + + {/* time ago */} + + + {/* from */} + + + {/* direction */} + + + {/* To */} + + + {/* value */} + + + ))} + +
+ {header.name.length > 0 && ( +
+
+ {header.name} +
+ {/*
+ +
*/} +
+ )} +
+
+
+ + +
+ +
+
+ + + {shortenAddress(txn.txnHash)} + +
+
+
+ {txn.txnType} +
+
+ + {txn.block} + + +
+ {timeAgo(txn.timeStamp)} +
+
+
+ + {shortenAddress(txn.from, 4)} + + + + + +
+
+
+
+ +
+
+
+
+ {isAddress(txn.to) ? ( + + {shortenAddress(txn.to, 4)} + + ) : ( + + {txn.to} + + )} + + + + +
+
+
+ {BnToDec(txn.value, 9)} PWR +
+
+ +
+ +
+ +
+ + )} +
+
+ ); +} diff --git a/src/app/(header-footer-layout)/blocks/[blocknumber]/page.tsx b/src/app/(header-footer-layout)/blocks/[blocknumber]/page.tsx index 5ea57ce..bb4782b 100644 --- a/src/app/(header-footer-layout)/blocks/[blocknumber]/page.tsx +++ b/src/app/(header-footer-layout)/blocks/[blocknumber]/page.tsx @@ -152,7 +152,7 @@ export default function SingleBlock({ params }: BlockTransactionsProps) {

{block_data.txnsCount} transactions {' '} @@ -179,7 +179,7 @@ export default function SingleBlock({ params }: BlockTransactionsProps) {
{block_data.blockSubmitter} @@ -193,7 +193,7 @@ export default function SingleBlock({ params }: BlockTransactionsProps) { copyToClipboard(block_data.blockSubmitter) } > - +
diff --git a/src/app/(header-footer-layout)/blocks/[blocknumber]/transactions/page.tsx b/src/app/(header-footer-layout)/blocks/[blocknumber]/transactions/page.tsx index d2b2f57..722ac2f 100644 --- a/src/app/(header-footer-layout)/blocks/[blocknumber]/transactions/page.tsx +++ b/src/app/(header-footer-layout)/blocks/[blocknumber]/transactions/page.tsx @@ -195,7 +195,7 @@ export default function BlockTransactions({ params }: BlockTransactionsProps) { {shortenAddress(txn.txnHash)} @@ -206,7 +206,7 @@ export default function BlockTransactions({ params }: BlockTransactionsProps) { {txn.blockNumber} @@ -224,7 +224,7 @@ export default function BlockTransactions({ params }: BlockTransactionsProps) {
{shortenAddress(txn.from, 4)} @@ -235,7 +235,7 @@ export default function BlockTransactions({ params }: BlockTransactionsProps) { trigger="click" >
-
- - - - - - Success -
+ {txnData.success ? ( + // Success Status +
+ + + + + Success +
+ ) : ( + // Fail Status with Error Message +
+
+ + + + + Fail +
+ {/* Error message if it exists */} + {txnData.errorMessage && ( +
+

+ {txnData.errorMessage} +

+
+ )} +
+ )} {/* Block */} @@ -152,10 +194,25 @@ export default function TransactionDetails({ params }: TransactionDetailsProps)
- + + + + {' '} {txnData.blockNumber} @@ -210,7 +267,7 @@ export default function TransactionDetails({ params }: TransactionDetailsProps)
{txnData.from} @@ -220,7 +277,7 @@ export default function TransactionDetails({ params }: TransactionDetailsProps) trigger="click" >
@@ -241,7 +298,7 @@ export default function TransactionDetails({ params }: TransactionDetailsProps) <> {/* {item.value} */} {txnData.to} @@ -252,7 +309,7 @@ export default function TransactionDetails({ params }: TransactionDetailsProps) trigger="click" > @@ -318,7 +375,7 @@ export default function TransactionDetails({ params }: TransactionDetailsProps) {/* Data (Hex) */}
-
+

Data (Hex)

@@ -326,21 +383,60 @@ export default function TransactionDetails({ params }: TransactionDetailsProps) */}
-
+

- {txnData.data} + {txnData.data || '0x'}

-
+ + {/* Extra Data */} + + {txnData.extraData ? ( +
+
+

+ Extra Data (JSON) +

+ {/* + + */} +
+
+
+											
+												{JSON.stringify(txnData.extraData, null, 2)}
+											
+										
+
+ + + +
+ ) : null} )}
diff --git a/src/app/(header-footer-layout)/transactions/page.tsx b/src/app/(header-footer-layout)/transactions/page.tsx index 69253f3..5237991 100644 --- a/src/app/(header-footer-layout)/transactions/page.tsx +++ b/src/app/(header-footer-layout)/transactions/page.tsx @@ -224,10 +224,11 @@ export default function Transactions() { {txnsData.transactions.map((txn, idx) => ( {/* txn hash */} @@ -246,14 +247,13 @@ export default function Transactions() { usdFee={txn.txnFeeInUsd} fee={txn.txnFee} nonce={txn.nonceOrValidationHash} - />
{shortenAddress(txn.txnHash)} @@ -264,7 +264,7 @@ export default function Transactions() { {txn.block} @@ -282,7 +282,7 @@ export default function Transactions() {
{shortenAddress(txn.from, 4)} @@ -293,7 +293,7 @@ export default function Transactions() { trigger="click" >
{/* Transactions, blocks, nodes */} -
+
{infoLoading ? ( <> @@ -263,20 +269,14 @@ export default function Home() { )}
- {/* Graph */} -
-
-

- TRANSACTION HISTORY IN 14 DAYS -

- -
- {/* */} - - - {/* */} -
-
+
+ {infoLoading ? ( + + ) : infoData?.fourteenDaysTxn ? ( + + ) : ( +

Loading transaction history...

+ )}
@@ -293,10 +293,11 @@ export default function Home() { [1, 1, 1, 1, 1].map((item, idx) => (
@@ -307,7 +308,7 @@ export default function Home() {
VIEW ALL BLOCKS @@ -327,10 +328,11 @@ export default function Home() { [1, 2, 3, 4, 5].map((_, idx) => (
@@ -342,7 +344,7 @@ export default function Home() { VIEW ALL TRANSACTIONS diff --git a/src/components/internal/chart/chart.component.tsx b/src/components/internal/chart/chart.component.tsx new file mode 100644 index 0000000..272e773 --- /dev/null +++ b/src/components/internal/chart/chart.component.tsx @@ -0,0 +1,153 @@ +import React, { useEffect, useState } from 'react'; +import dynamic from 'next/dynamic'; +import { ApexOptions } from 'apexcharts'; +const Chart = dynamic(() => import('react-apexcharts'), { ssr: false }); + +type TransactionData = { + [key: number]: number; +}; + +type TransactionChartProps = { + data: TransactionData; +}; + +const TransactionChart = ({ data }: TransactionChartProps) => { + const [seriesData, setSeriesData] = useState([]); + const [categories, setCategories] = useState(['192']); + + useEffect(() => { + if (data && Object.keys(data).length > 0) { + const dates = Object.keys(data).map((timestamp) => { + const date = new Date(parseInt(timestamp) * 1000); + return date.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + }); + }); + const values = Object.values(data); + + setCategories(dates); + setSeriesData(values); + } + }, [data]); + + const minValue = Math.min(...seriesData); + const maxValue = Math.max(...seriesData); + + const options: ApexOptions = { + chart: { + type: 'area', + toolbar: { show: false }, + zoom: { enabled: false }, + }, + dataLabels: { enabled: false }, + stroke: { curve: 'smooth', width: 2, colors: ['#112FF8'] }, // Updated line color to #112FF8 + grid: { show: false }, + xaxis: { + type: 'category', + categories, + labels: { + show: true, + style: { + colors: '#737289', // Custom color for Y-axis labels (change to your desired color) + fontSize: '12px', // Adjust font size if necessary + fontWeight: 'bold', + }, + rotate: 0, // Prevents diagonal rotation + formatter: function (value: any, timestamp: any) { + // Show only the first day, middle day, and last day + const idx = categories.indexOf(value); + + if (idx === 0 || idx === 6 || idx === 13) { + return value; + } + return ''; + }, + }, // Show x-axis labels + axisBorder: { show: false }, + axisTicks: { show: false }, + }, + yaxis: { + show: true, // Show y-axis labels + min: Math.floor(minValue / 1000) * 1000, + max: Math.ceil(maxValue / 1000) * 1000, + labels: { + formatter: (value) => { + if (value === Math.floor(minValue / 1000) * 1000) { + return `${Math.floor(value / 1000)}k`; + } else if (value === Math.ceil(maxValue / 1000) * 1000) { + return `${Math.ceil(value / 1000)}k`; + } + return ''; + }, + style: { + colors: '#737289', // Custom color for Y-axis labels (change to your desired color) + fontSize: '12px', // Adjust font size if necessary + fontWeight: 'bold', + }, + }, + }, + tooltip: { + enabled: true, + x: { + formatter: (value, { dataPointIndex }) => { + return categories[dataPointIndex] ? categories[dataPointIndex] : 'N/A'; + }, + }, + y: { + formatter: (value) => { + return Math.round(value).toString(); + }, + }, + }, + markers: { + size: 0, // No visible points on the chart + }, + fill: { + type: 'gradient', + gradient: { + shade: 'light', + type: 'vertical', + shadeIntensity: 1, + gradientToColors: ['rgba(224, 223, 234, 0)'], // Transparent part of the gradient + inverseColors: false, + opacityFrom: 1, // Full opacity at the start + opacityTo: 0, // Fully transparent at the end + stops: [0, 100], + colorStops: [ + { + offset: 0, + color: '#CCCCFE', // Start color (matching #CCCCFE) + opacity: 1, + }, + { + offset: 100, + color: 'rgba(224, 223, 234, 0)', // End color + opacity: 0, + }, + ], + }, + }, + colors: ['#112FF8'], // Line color to #112FF8 + }; + + const series = [ + { + name: 'Transactions', + data: seriesData.length ? seriesData : [0], + }, + ]; + + return ( +
+

+ Transaction History in 14 Days +

+
+ {' '} +
+
+ ); +}; + +export default TransactionChart; \ No newline at end of file diff --git a/src/components/internal/root-page/latest-blocks-table.tsx b/src/components/internal/root-page/latest-blocks-table.tsx index 2ba0f19..ade56b5 100644 --- a/src/components/internal/root-page/latest-blocks-table.tsx +++ b/src/components/internal/root-page/latest-blocks-table.tsx @@ -45,7 +45,7 @@ export default function LatestBlocksTable({ blocks }: LatestBlocksProps) { {/* block number */} {block.blockHeight} @@ -65,7 +65,7 @@ export default function LatestBlocksTable({ blocks }: LatestBlocksProps) {
{shortenAddress(block.blockSubmitter, 4)} @@ -76,9 +76,9 @@ export default function LatestBlocksTable({ blocks }: LatestBlocksProps) {
- {block.txnsCount} txns + {block.txnsCount} txns
diff --git a/src/components/internal/root-page/latest-txns-table.tsx b/src/components/internal/root-page/latest-txns-table.tsx index ca369f4..cdcf276 100644 --- a/src/components/internal/root-page/latest-txns-table.tsx +++ b/src/components/internal/root-page/latest-txns-table.tsx @@ -46,7 +46,7 @@ export default function LatestTxnsTable({ transactions }: LatestTransactionsProp {/* block number */} {shortenAddress(txn.txnHash, 4)} @@ -66,7 +66,7 @@ export default function LatestTxnsTable({ transactions }: LatestTransactionsProp
{shortenAddress(txn.from, 4)} @@ -79,12 +79,12 @@ export default function LatestTxnsTable({ transactions }: LatestTransactionsProp {isAddress(txn.to) ? ( {shortenAddress(txn.to, 4)} ) : ( - + {txn.to} )} diff --git a/src/components/internal/search-bar/search-bar.scss b/src/components/internal/search-bar/search-bar.scss index d46a334..23ac21e 100644 --- a/src/components/internal/search-bar/search-bar.scss +++ b/src/components/internal/search-bar/search-bar.scss @@ -1,32 +1,42 @@ .search-bar-container { + @apply cursor-pointer; + @apply w-full; @apply px-6; @apply py-2; - @apply flex; @apply gap-x-4; @apply border; @apply border-agrey-300; + @apply hover:border-ablue-200; + @apply focus:border-abrandc-dark-black; + @apply focus-within:border-abrandc-dark-black; + + @apply dark:focus-within:border-white; + @apply dark:focus:border-white; + @apply dark:hover:border-ablue-300; @apply dark:border-agrey-800; @apply rounded-2xl; } - .search-bar-input { @apply flex-grow; @apply min-w-0; @apply h-12; @apply py-2; + @apply cursor-pointer; + @apply focus:outline-none; @apply bg-transparent; @apply text-agrey-600; // focus - @apply focus:outline-none; } .search-bar-nav-container { + @apply cursor-pointer; + @apply w-full; @apply px-6; @apply py-2; diff --git a/src/components/internal/stat-box/stat-box.component.tsx b/src/components/internal/stat-box/stat-box.component.tsx index 48f5199..1ac3767 100644 --- a/src/components/internal/stat-box/stat-box.component.tsx +++ b/src/components/internal/stat-box/stat-box.component.tsx @@ -1,18 +1,29 @@ import Image from 'next/image'; +import Tooltip from '../tooltip/tooltip.component'; type StatBoxProps = { title: string; valueComp: any; - icon?: string ; + icon?: string; + tooltipText?: string; }; -function StatBox({ title, valueComp, icon }: StatBoxProps) { +function StatBox({ title, valueComp, icon, tooltipText }: StatBoxProps) { return (
{icon && }
-

{title}

+
+

{title}

+ {tooltipText && ( + + + + )} +

{valueComp()}

diff --git a/src/components/skeletons/root/chart-skeleton.tsx b/src/components/skeletons/root/chart-skeleton.tsx new file mode 100644 index 0000000..7564c2d --- /dev/null +++ b/src/components/skeletons/root/chart-skeleton.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +export default function ChartSkeleton() { + return ( +
+ {/* Skeleton for the title */} +
+ + {/* Skeleton for the chart area */} +
+ + {/* Accessible loading text */} + Loading chart... +
+ ); +} diff --git a/src/layout/header/header.component.tsx b/src/layout/header/header.component.tsx index 4a6a583..90f54d5 100644 --- a/src/layout/header/header.component.tsx +++ b/src/layout/header/header.component.tsx @@ -55,11 +55,11 @@ export default function HeaderComponent() { label: 'Blocks', href: ROUTES.blocks, }, - // { - // id: 2, - // label: 'Nodes', - // href: ROUTES.nodes, - // }, + { + id: 2, + label: 'Nodes', + href: ROUTES.nodes, + }, ]; const navigation = [ @@ -76,6 +76,10 @@ export default function HeaderComponent() { // href: '#', // }, // { + // label: 'Tokens', + // href: '#', + // }, + // { // label: 'NFTs', // href: '#', // }, diff --git a/src/layout/header/searchbar-header.component.tsx b/src/layout/header/searchbar-header.component.tsx index 13502e2..a27d5bf 100644 --- a/src/layout/header/searchbar-header.component.tsx +++ b/src/layout/header/searchbar-header.component.tsx @@ -55,11 +55,11 @@ export default function SearchBarHeaderComponent() { label: 'Blocks', href: ROUTES.blocks, }, - // { - // id: 2, - // label: 'Nodes', - // href: ROUTES.nodes, - // }, + { + id: 2, + label: 'Nodes', + href: ROUTES.nodes, + }, ]; const navigation = [ @@ -160,10 +160,12 @@ export default function SearchBarHeaderComponent() { {/* desktop menu */}
-
+
Transactions @@ -178,6 +180,14 @@ export default function SearchBarHeaderComponent() {
+
+ + Nodes + +
{/* dropdown */} {/*
@@ -221,7 +231,7 @@ export default function SearchBarHeaderComponent() { disabled={!dirty || !touched || !formik.isValid} type="submit" > - +
Transactions
-
Blocks
- + +
Nodes
+ {/*