From c719f6c6ebbc43ccaef7d6b722c1d00719e16697 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 16:55:35 +0200 Subject: [PATCH 01/14] Add types for market history --- types/Hive.ts | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/types/Hive.ts b/types/Hive.ts index 05eeda8d..47121117 100644 --- a/types/Hive.ts +++ b/types/Hive.ts @@ -789,7 +789,7 @@ namespace Hive { prev_balance!: number; min_balance!: number; max_balance!: number; - date!:Date; + date!: Date; } export class Delegation { @@ -811,6 +811,32 @@ namespace Hive { total_pages!: number; operations_result!: TwoDirectionDelegations[]; } + + export class MarketHistory { + buckets!: MarketBucket[]; + } + + export class MarketBucket { + id!: number; + open!: string; + seconds!: number; + hive!: MarketData; + symbol!: MarketSymbol; + non_hive!: MarketData; + } + + export class MarketData { + high!: number; + low!: number; + open!: number; + close!: number; + volume!: number; + } + + export class MarketSymbol { + nai!: string; + precision!: number; + } } export default Hive; -- GitLab From 3c9c6501e904ecf2e6f5d2e4fdccafb8f704d273 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 16:56:23 +0200 Subject: [PATCH 02/14] Add market history api --- services/FetchingService.ts | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/services/FetchingService.ts b/services/FetchingService.ts index 5333f481..dfdd5082 100644 --- a/services/FetchingService.ts +++ b/services/FetchingService.ts @@ -39,6 +39,12 @@ type ExplorerNodeApi = { Hive.HivePosts >; }; + market_history_api: { + get_market_history: TWaxApiRequest< + { bucket_seconds: number; start: string; end: string }, + Hive.MarketHistory[] + >; + }; }; class FetchingService { @@ -446,25 +452,39 @@ class FetchingService { }); } - async geAccountAggregatedtBalanceHistory( accountName: string, coinType: string, - granularity : "daily"|"monthly"|"yearly", + granularity: "daily" | "monthly" | "yearly", direction: "asc" | "desc", fromBlock?: Date | number | undefined, toBlock?: Date | number | undefined ): Promise<Hive.AccountAggregatedBalanceHistoryResponse> { - return await this.extendedHiveChain!.restApi["balance-api"].aggregatedHistory({ + return await this.extendedHiveChain!.restApi[ + "balance-api" + ].aggregatedHistory({ accountName, "coin-type": coinType, - "granularity":granularity, + granularity: granularity, direction: direction, "from-block": fromBlock, "to-block": toBlock, }); } + async getMarketHistory( + bucketSeconds: number, + start: string, + end: string + ): Promise<Hive.MarketHistory[]> { + return await this.extendedHiveChain!.api.market_history_api.get_market_history( + { + bucket_seconds: bucketSeconds, + start, + end, + } + ); + } } const fetchingService = new FetchingService(); -- GitLab From a9a42a065c2b1dafabf928e073f64490d7ffe057 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 16:57:38 +0200 Subject: [PATCH 03/14] Create useMarketHistory hook --- hooks/common/useMarketHistory.tsx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 hooks/common/useMarketHistory.tsx diff --git a/hooks/common/useMarketHistory.tsx b/hooks/common/useMarketHistory.tsx new file mode 100644 index 00000000..00d4f2b3 --- /dev/null +++ b/hooks/common/useMarketHistory.tsx @@ -0,0 +1,27 @@ +import { useQuery, UseQueryResult } from "@tanstack/react-query"; +import fetchingService from "@/services/FetchingService"; +import Hive from "@/types/Hive"; + +const useMarketHistory = ( + bucketSeconds: number, + start: string, + end: string +) => { + const { + data: marketHistory, + isLoading: isMarketHistoryLoading, + isError: isMarketHistoryError, + }: UseQueryResult<Hive.MarketHistory> = useQuery({ + queryKey: ["account_details", bucketSeconds, start, end], + queryFn: () => fetchingService.getMarketHistory(bucketSeconds, start, end), + refetchOnWindowFocus: false, + }); + + return { + marketHistory, + isMarketHistoryLoading, + isMarketHistoryError, + }; +}; + +export default useMarketHistory; -- GitLab From b45e3a63c300cbbb4b68f1affd62c3ecf225e732 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 17:21:22 +0200 Subject: [PATCH 04/14] Create market history chart component --- components/home/MarketHistoryChart.tsx | 142 +++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 components/home/MarketHistoryChart.tsx diff --git a/components/home/MarketHistoryChart.tsx b/components/home/MarketHistoryChart.tsx new file mode 100644 index 00000000..754270d3 --- /dev/null +++ b/components/home/MarketHistoryChart.tsx @@ -0,0 +1,142 @@ +import { + LineChart, + Line, + XAxis, + YAxis, + Tooltip, + ResponsiveContainer, + Legend, +} from "recharts"; +import Hive from "@/types/Hive"; +import moment from "moment"; +import { useHiveChainContext } from "@/contexts/HiveChainContext"; +import { Card, CardContent, CardHeader } from "../ui/card"; +import { Loader2 } from "lucide-react"; +import { colorMap } from "../balanceHistory/BalanceHistoryChart"; + +const CustomTooltip = ({ + active, + payload, +}: { + active?: boolean; + payload?: any[]; +}) => { + if (active && payload && payload.length) { + return ( + <div className="bg-buttonHover text-text p-2 rounded-xl"> + {payload.map(({ payload: { date, avgPrice, volume } }) => { + return ( + <div key={date}> + <p>{`Date: ${date}`}</p> + <p>{`Average Price: $${avgPrice}`}</p> + <p>{`Volume: ${volume.toLocaleString("en-US")} HIVE`}</p> + </div> + ); + })} + </div> + ); + } + + return null; +}; + +// Using volume to calculate the average daily price of HIVE +const calculateAvgHivePrice = ( + hive: Hive.MarketData, + nonHive: Hive.MarketData +) => { + const hiveVolume = hive.volume; + const nonHiveVolume = nonHive.volume; + + return (nonHiveVolume / hiveVolume).toFixed(4); +}; + +interface MarketChartProps { + data: Hive.MarketHistory | undefined; + isLoading: boolean; + strokeColor: string; +} +interface ChartData { + date: string; + avgPrice: string; + volume: number; +} + +const MarketHistoryChart: React.FC<MarketChartProps> = ({ + data, + isLoading, + strokeColor, +}) => { + const { hiveChain } = useHiveChainContext(); + + if (!data || !hiveChain) return; + + if (isLoading) { + return ( + <div className="flex justify-center items-center"> + <Loader2 className="animate-spin mt-1 h-16 w-10 ml-10 dark:text-white" /> + </div> + ); + } + + const chartData = data.buckets.map((bucket) => { + const { hive, non_hive } = bucket; + const hiveAveragePrice = calculateAvgHivePrice(hive, non_hive); + + return { + date: moment(bucket.open).format("MMM D"), + avgPrice: hiveAveragePrice, + volume: bucket.hive.volume, + }; + }); + + const lastHivePrice = chartData[chartData.length - 1].avgPrice; + + const minValue = Math.min( + ...chartData.map((d: ChartData) => parseFloat(d.avgPrice)) + ); + const maxValue = Math.max( + ...chartData.map((d: ChartData) => parseFloat(d.avgPrice)) + ); + + return ( + <Card className="mb-3"> + <CardHeader className="flex justify-between items-center px-1 py-3"> + <h2 className="text-lg font-semibold">Hive Price Chart</h2> + </CardHeader> + <CardContent> + <ResponsiveContainer + width="100%" + height={300} + > + <LineChart data={chartData}> + <XAxis + dataKey="date" + stroke={strokeColor} + /> + <YAxis + dataKey="avgPrice" + domain={[minValue, maxValue]} + stroke={strokeColor} + /> + <Tooltip content={<CustomTooltip />} /> + <Legend + verticalAlign="top" + height={36} + /> + <Line + name={`Hive Price: $${lastHivePrice}`} + type="monotone" + dataKey="avgPrice" + stroke={colorMap.HIVE} + dot={false} + strokeWidth={2} + /> + </LineChart> + </ResponsiveContainer> + </CardContent> + </Card> + ); +}; + +export default MarketHistoryChart; -- GitLab From 7e39046793eb08567f0e3a36f46e1974cc3c7abb Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 17:21:58 +0200 Subject: [PATCH 05/14] Use market history chart in main page --- pages/index.tsx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/pages/index.tsx b/pages/index.tsx index 32dab7ba..655e2912 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -24,6 +24,15 @@ import { } from "@/components/ui/card"; import { useHeadBlockNumber } from "@/contexts/HeadBlockContext"; import { useTheme } from "@/contexts/ThemeContext"; +import useMarketHistory from "@/hooks/common/useMarketHistory"; +import MarketHistoryChart from "@/components/home/MarketHistoryChart"; +import moment from "moment"; + +const MARKET_HISTORY_INTERVAL = 86400; // 1 day +const CURRENT_TIME = moment().format("YYYY-MM-DDTHH:mm:ss"); +const MARKET_HISTORY_TIME_PERIOD = moment() + .subtract(30, "days") + .format("YYYY-MM-DDTHH:mm:ss"); export default function Home() { const { theme } = useTheme(); @@ -39,6 +48,12 @@ export default function Home() { const headBlockData = useHeadBlock(headBlockNum).headBlockData; const { blockOperations } = useBlockOperations(headBlockNum || 0); + const { marketHistory, isMarketHistoryLoading } = useMarketHistory( + MARKET_HISTORY_INTERVAL, + MARKET_HISTORY_TIME_PERIOD, + CURRENT_TIME + ); + // Filter operations that have a trx_id const trxOperations = blockOperations?.operations_result.filter( (operation) => operation.trx_id @@ -72,6 +87,11 @@ export default function Home() { opcount={opcount} /> <div className="col-span-4 md:col-span-3 lg:col-span-2"> + <MarketHistoryChart + data={marketHistory} + isLoading={isMarketHistoryLoading} + strokeColor={strokeColor} + /> <LastBlocksWidget headBlock={headBlockNum} strokeColor={strokeColor} -- GitLab From f70b45fe1bdc3cb3a057ce06b4a8b85999b3721c Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Tue, 25 Mar 2025 17:23:10 +0200 Subject: [PATCH 06/14] Export chart colors from balance history chart --- components/balanceHistory/BalanceHistoryChart.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/components/balanceHistory/BalanceHistoryChart.tsx b/components/balanceHistory/BalanceHistoryChart.tsx index 736456b2..054b319c 100644 --- a/components/balanceHistory/BalanceHistoryChart.tsx +++ b/components/balanceHistory/BalanceHistoryChart.tsx @@ -15,7 +15,6 @@ import { cn } from "@/lib/utils"; import moment from "moment"; import { ArrowDown, ArrowUp, Minus } from "lucide-react"; - interface BalanceHistoryChartProps { hiveBalanceHistoryData?: { timestamp: string; @@ -36,6 +35,12 @@ interface BalanceHistoryChartProps { quickView?: boolean; } +export const colorMap: Record<string, string> = { + HIVE: "#8884d8", + VESTS: "#82ca9d", + HBD: "#ff7300", +}; + const BalanceHistoryChart: React.FC<BalanceHistoryChartProps> = ({ hiveBalanceHistoryData, vestsBalanceHistoryData, @@ -83,12 +88,6 @@ const BalanceHistoryChart: React.FC<BalanceHistoryChartProps> = ({ return () => window.removeEventListener("resize", handleResize); }, []); - const colorMap: Record<string, string> = { - HIVE: "#8884d8", - VESTS: "#82ca9d", - HBD: "#ff7300", - }; - const dataMap: Record< string, { timestamp: string; balance_change: number; balance: number }[] -- GitLab From 108f5f451b858de8cb0363456b7d474f781f0ebd Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Wed, 26 Mar 2025 14:11:19 +0200 Subject: [PATCH 07/14] Change market history chart place --- pages/index.tsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 655e2912..a4fcfa88 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -79,19 +79,21 @@ export default function Home() { <Head> <title>Hive Explorer</title> </Head> - <div className=" page-container grid grid-cols-4 text-white gap-3"> - <HeadBlockCard - headBlockCardData={dynamicGlobalQueryData} - transactionCount={trxOpsLength} - blockDetails={headBlockData} - opcount={opcount} - /> - <div className="col-span-4 md:col-span-3 lg:col-span-2"> + <div className="page-container grid grid-cols-4 text-white gap-3"> + <div className="flex flex-col gap-3"> + <HeadBlockCard + headBlockCardData={dynamicGlobalQueryData} + transactionCount={trxOpsLength} + blockDetails={headBlockData} + opcount={opcount} + /> <MarketHistoryChart data={marketHistory} isLoading={isMarketHistoryLoading} strokeColor={strokeColor} /> + </div> + <div className="col-span-4 md:col-span-3 lg:col-span-2"> <LastBlocksWidget headBlock={headBlockNum} strokeColor={strokeColor} -- GitLab From 6412913689d45df9b5868015b55b96be3674d338 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Wed, 26 Mar 2025 14:11:56 +0200 Subject: [PATCH 08/14] Add add date with year included to a tooltip --- components/home/MarketHistoryChart.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/home/MarketHistoryChart.tsx b/components/home/MarketHistoryChart.tsx index 754270d3..560ef616 100644 --- a/components/home/MarketHistoryChart.tsx +++ b/components/home/MarketHistoryChart.tsx @@ -24,10 +24,10 @@ const CustomTooltip = ({ if (active && payload && payload.length) { return ( <div className="bg-buttonHover text-text p-2 rounded-xl"> - {payload.map(({ payload: { date, avgPrice, volume } }) => { + {payload.map(({ payload: { tooltipDate, avgPrice, volume } }) => { return ( - <div key={date}> - <p>{`Date: ${date}`}</p> + <div key={tooltipDate}> + <p>{`Date: ${tooltipDate}`}</p> <p>{`Average Price: $${avgPrice}`}</p> <p>{`Volume: ${volume.toLocaleString("en-US")} HIVE`}</p> </div> @@ -85,6 +85,7 @@ const MarketHistoryChart: React.FC<MarketChartProps> = ({ return { date: moment(bucket.open).format("MMM D"), + tooltipDate: moment(bucket.open).format("YYYY MMM D"), avgPrice: hiveAveragePrice, volume: bucket.hive.volume, }; -- GitLab From d484b7b72aae1d953b8d319ad144d84b31d78f61 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 16:05:28 +0200 Subject: [PATCH 09/14] Change cards order and add new card for hive chart --- components/home/HeadBlockCard.tsx | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/components/home/HeadBlockCard.tsx b/components/home/HeadBlockCard.tsx index 4c9625bf..89855b01 100644 --- a/components/home/HeadBlockCard.tsx +++ b/components/home/HeadBlockCard.tsx @@ -17,6 +17,7 @@ import { getBlockDifference } from "./SyncInfo"; import { Toggle } from "../ui/toggle"; import { Card, CardContent, CardHeader } from "../ui/card"; import CurrentBlockCard from "./CurrentBlockCard"; +import HeadBlockHiveChartCard from "./HeadBlockHiveChartCard"; interface HeadBlockCardProps { headBlockCardData?: Explorer.HeadBlockCardData | any; @@ -61,6 +62,7 @@ const HeadBlockCard: React.FC<HeadBlockCardProps> = ({ timeCard: true, supplyCard: true, hiveParamsCard: true, + hiveChart: false, }); const { settings, setSettings } = useUserSettingsContext(); @@ -84,6 +86,13 @@ const HeadBlockCard: React.FC<HeadBlockCardProps> = ({ }); }; + const handleHideHiveChart = () => { + setHiddenPropertiesByCard({ + ...hiddenPropertiesByCard, + hiveChart: !hiddenPropertiesByCard.hiveChart, + }); + }; + const { explorerBlockNumber, hiveBlockNumber, @@ -256,6 +265,14 @@ const HeadBlockCard: React.FC<HeadBlockCardProps> = ({ </CardHeader> <CardContent className="p-4 space-y-4"> + {/* Last Block Information */} + <CurrentBlockCard + blockDetails={blockDetails} + transactionCount={transactionCount} + opcount={opcount} + timeDifferenceInSeconds={timeDifferenceInSeconds} + liveBlockNumber={liveBlockNumber} + /> {/* Other Information*/} <div className="data-box"> <div> @@ -265,16 +282,14 @@ const HeadBlockCard: React.FC<HeadBlockCardProps> = ({ <span>Vests To Hive Ratio:</span> {liveVestsToHiveRatio} VESTS </div> </div> - {/* Last Block Information */} - <CurrentBlockCard - blockDetails={blockDetails} - transactionCount={transactionCount} - opcount={opcount} - timeDifferenceInSeconds={timeDifferenceInSeconds} - liveBlockNumber={liveBlockNumber} - /> <div> + <HeadBlockHiveChartCard + header="Hive Price Chart" + isParamsHidden={hiddenPropertiesByCard.hiveChart} + handleHideParams={handleHideHiveChart} + isLoading={isBlockCardLoading} + /> <HeadBlockPropertyCard parameters={fundAndSupplyParameters} header="Fund and Supply" -- GitLab From 24d230a752a657c501996050df34db84ccea1864 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 16:07:50 +0200 Subject: [PATCH 10/14] Remove hive price chart from main page container --- pages/index.tsx | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index a4fcfa88..ae76669a 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -14,7 +14,6 @@ import useDynamicGlobal from "@/hooks/api/homePage/useDynamicGlobal"; import { config } from "@/Config"; import useHeadBlock from "@/hooks/api/homePage/useHeadBlock"; import useBlockOperations from "@/hooks/api/common/useBlockOperations"; -import { useUserSettingsContext } from "@/contexts/UserSettingsContext"; import { Card, CardContent, @@ -24,15 +23,6 @@ import { } from "@/components/ui/card"; import { useHeadBlockNumber } from "@/contexts/HeadBlockContext"; import { useTheme } from "@/contexts/ThemeContext"; -import useMarketHistory from "@/hooks/common/useMarketHistory"; -import MarketHistoryChart from "@/components/home/MarketHistoryChart"; -import moment from "moment"; - -const MARKET_HISTORY_INTERVAL = 86400; // 1 day -const CURRENT_TIME = moment().format("YYYY-MM-DDTHH:mm:ss"); -const MARKET_HISTORY_TIME_PERIOD = moment() - .subtract(30, "days") - .format("YYYY-MM-DDTHH:mm:ss"); export default function Home() { const { theme } = useTheme(); @@ -48,12 +38,6 @@ export default function Home() { const headBlockData = useHeadBlock(headBlockNum).headBlockData; const { blockOperations } = useBlockOperations(headBlockNum || 0); - const { marketHistory, isMarketHistoryLoading } = useMarketHistory( - MARKET_HISTORY_INTERVAL, - MARKET_HISTORY_TIME_PERIOD, - CURRENT_TIME - ); - // Filter operations that have a trx_id const trxOperations = blockOperations?.operations_result.filter( (operation) => operation.trx_id @@ -87,11 +71,6 @@ export default function Home() { blockDetails={headBlockData} opcount={opcount} /> - <MarketHistoryChart - data={marketHistory} - isLoading={isMarketHistoryLoading} - strokeColor={strokeColor} - /> </div> <div className="col-span-4 md:col-span-3 lg:col-span-2"> <LastBlocksWidget -- GitLab From 2db3adad3bc311a8dbeb6d86d633ef9edda3fa7d Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 17:04:04 +0200 Subject: [PATCH 11/14] Update grid to fit chart correctly on smaller screens --- components/home/HeadBlockCard.tsx | 2 +- pages/index.tsx | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/components/home/HeadBlockCard.tsx b/components/home/HeadBlockCard.tsx index 89855b01..268af3db 100644 --- a/components/home/HeadBlockCard.tsx +++ b/components/home/HeadBlockCard.tsx @@ -228,7 +228,7 @@ const HeadBlockCard: React.FC<HeadBlockCardProps> = ({ return ( <Card - className="col-span-4 md:col-span-1" + className="col-span-12 md:col-span-4 lg:col-span-3" data-testid="head-block-card" > <CardHeader className="flex justify-between items-end py-2 border-b "> diff --git a/pages/index.tsx b/pages/index.tsx index ae76669a..2b1c1ff2 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -63,16 +63,15 @@ export default function Home() { <Head> <title>Hive Explorer</title> </Head> - <div className="page-container grid grid-cols-4 text-white gap-3"> - <div className="flex flex-col gap-3"> - <HeadBlockCard - headBlockCardData={dynamicGlobalQueryData} - transactionCount={trxOpsLength} - blockDetails={headBlockData} - opcount={opcount} - /> - </div> - <div className="col-span-4 md:col-span-3 lg:col-span-2"> + <div className="page-container grid grid-cols-12 text-white gap-3"> + <HeadBlockCard + headBlockCardData={dynamicGlobalQueryData} + transactionCount={trxOpsLength} + blockDetails={headBlockData} + opcount={opcount} + /> + + <div className="col-span-12 md:col-span-8 lg:col-span-6"> <LastBlocksWidget headBlock={headBlockNum} strokeColor={strokeColor} @@ -81,7 +80,7 @@ export default function Home() { </div> <Card - className="col-span-4 md:col-span-4 lg:col-span-1 overflow-hidden" + className="col-span-12 md:col-span-12 lg:col-span-3 overflow-hidden" data-testid="top-witnesses-sidebar" > <CardHeader className="flex justify-between items-center border-b px-1 py-3"> -- GitLab From 624b462ed0f929855e26aec70667fdb65d8f9e46 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 17:04:47 +0200 Subject: [PATCH 12/14] Create new card for hive price chart --- components/home/HeadBlockHiveChartCard.tsx | 67 ++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 components/home/HeadBlockHiveChartCard.tsx diff --git a/components/home/HeadBlockHiveChartCard.tsx b/components/home/HeadBlockHiveChartCard.tsx new file mode 100644 index 00000000..d50d0b41 --- /dev/null +++ b/components/home/HeadBlockHiveChartCard.tsx @@ -0,0 +1,67 @@ +import { ArrowDown, ArrowUp } from "lucide-react"; +import { Loader2 } from "lucide-react"; +import MarketHistoryChart from "./MarketHistoryChart"; +import moment from "moment"; +import useMarketHistory from "@/hooks/common/useMarketHistory"; + +interface HeadBlockPropertyCardProps { + header: string; + isParamsHidden: boolean; + handleHideParams: () => void; + isLoading: boolean; +} + +const MARKET_HISTORY_INTERVAL = 86400; // 1 day +const CURRENT_TIME = moment().format("YYYY-MM-DDTHH:mm:ss"); +const MARKET_HISTORY_TIME_PERIOD = moment() + .subtract(30, "days") + .format("YYYY-MM-DDTHH:mm:ss"); + +const HeadBlockHiveChartCard: React.FC<HeadBlockPropertyCardProps> = ({ + header, + isParamsHidden, + handleHideParams, + isLoading, +}) => { + const { marketHistory, isMarketHistoryLoading } = useMarketHistory( + MARKET_HISTORY_INTERVAL, + MARKET_HISTORY_TIME_PERIOD, + CURRENT_TIME + ); + + return ( + <div + className="bg-theme py-1 rounded-[6px] data-box-chart" + data-testid="expandable-list" + style={{ overflowX: "auto", width: "100%" }} + > + <div + onClick={handleHideParams} + className="h-full w-full flex items-center justify-between py-1 cursor-pointer px-1" + > + <div className="text-lg">{header}</div> + <div>{isParamsHidden ? <ArrowDown /> : <ArrowUp />}</div> + </div> + + {isLoading && !isParamsHidden ? ( + <div className="flex justify-center w-full"> + <Loader2 className="animate-spin mt-1 text-white h-8 w-8" /> + </div> + ) : ( + <div + hidden={isParamsHidden} + data-testid="content-expandable-list" + > + <div> + <MarketHistoryChart + data={marketHistory} + isLoading={isMarketHistoryLoading} + /> + </div> + </div> + )} + </div> + ); +}; + +export default HeadBlockHiveChartCard; -- GitLab From cef6fb910bc4b97e37cef5b29bb98354f209e3cf Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 17:06:40 +0200 Subject: [PATCH 13/14] Use theme locally to set stroke color in chart component --- components/home/MarketHistoryChart.tsx | 70 ++++++++++++-------------- 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/components/home/MarketHistoryChart.tsx b/components/home/MarketHistoryChart.tsx index 560ef616..bc92498f 100644 --- a/components/home/MarketHistoryChart.tsx +++ b/components/home/MarketHistoryChart.tsx @@ -13,6 +13,7 @@ import { useHiveChainContext } from "@/contexts/HiveChainContext"; import { Card, CardContent, CardHeader } from "../ui/card"; import { Loader2 } from "lucide-react"; import { colorMap } from "../balanceHistory/BalanceHistoryChart"; +import { useTheme } from "@/contexts/ThemeContext"; const CustomTooltip = ({ active, @@ -54,7 +55,6 @@ const calculateAvgHivePrice = ( interface MarketChartProps { data: Hive.MarketHistory | undefined; isLoading: boolean; - strokeColor: string; } interface ChartData { date: string; @@ -65,9 +65,9 @@ interface ChartData { const MarketHistoryChart: React.FC<MarketChartProps> = ({ data, isLoading, - strokeColor, }) => { const { hiveChain } = useHiveChainContext(); + const { theme } = useTheme(); if (!data || !hiveChain) return; @@ -99,44 +99,38 @@ const MarketHistoryChart: React.FC<MarketChartProps> = ({ const maxValue = Math.max( ...chartData.map((d: ChartData) => parseFloat(d.avgPrice)) ); + const strokeColor = theme === "dark" ? "#FFF" : "#000"; return ( - <Card className="mb-3"> - <CardHeader className="flex justify-between items-center px-1 py-3"> - <h2 className="text-lg font-semibold">Hive Price Chart</h2> - </CardHeader> - <CardContent> - <ResponsiveContainer - width="100%" - height={300} - > - <LineChart data={chartData}> - <XAxis - dataKey="date" - stroke={strokeColor} - /> - <YAxis - dataKey="avgPrice" - domain={[minValue, maxValue]} - stroke={strokeColor} - /> - <Tooltip content={<CustomTooltip />} /> - <Legend - verticalAlign="top" - height={36} - /> - <Line - name={`Hive Price: $${lastHivePrice}`} - type="monotone" - dataKey="avgPrice" - stroke={colorMap.HIVE} - dot={false} - strokeWidth={2} - /> - </LineChart> - </ResponsiveContainer> - </CardContent> - </Card> + <ResponsiveContainer + width="100%" + height={250} + > + <LineChart data={chartData}> + <XAxis + dataKey="date" + stroke={strokeColor} + /> + <YAxis + dataKey="avgPrice" + domain={[minValue, maxValue]} + stroke={strokeColor} + /> + <Tooltip content={<CustomTooltip />} /> + <Legend + verticalAlign="top" + height={36} + /> + <Line + name={`Hive Price: $${lastHivePrice}`} + type="monotone" + dataKey="avgPrice" + stroke={colorMap.HIVE} + dot={false} + strokeWidth={2} + /> + </LineChart> + </ResponsiveContainer> ); }; -- GitLab From aa05bba04684f76c775c0d83733a4794ad1159e6 Mon Sep 17 00:00:00 2001 From: Lukas <lukas.budginas@gmail.com> Date: Thu, 27 Mar 2025 17:08:44 +0200 Subject: [PATCH 14/14] Add custom style for chart card --- styles/theme.css | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/styles/theme.css b/styles/theme.css index f019e4f7..3041b9af 100644 --- a/styles/theme.css +++ b/styles/theme.css @@ -338,6 +338,19 @@ pre { flex-direction: column; /* Stack elements vertically */ } +.data-box-chart { + background-color: var(--color-extra-light-gray); + border-radius: 12px; + padding: 10px; + margin: 6px 0; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + color: var(--color-text); + font-size: 14px; + border: 1px solid var(--color-light-gray); + transition: all 0.3s ease-in-out; + flex-direction: column; +} + .data-box:hover { background-color: var(--color-row-hover); box-shadow: 0 10px 15px rgba(0, 0, 0, 0.15); /* Elevated shadow */ -- GitLab