From bd5a2661d4945a1b1d4b5313861060655bbbbb59 Mon Sep 17 00:00:00 2001
From: Dima Rifai <dima.rifai@gmail.com>
Date: Fri, 27 Dec 2024 09:09:54 +0200
Subject: [PATCH] Issue 394 - Create the logic for balance history charts

---
 .../account/AccountBalanceHistoryCard.tsx     | 138 ++++++++++
 components/account/AccountDetailsSection.tsx  |   7 +-
 .../balanceHistory/BalanceHistoryChart.tsx    | 254 ++++++++++++++++++
 .../home/searches/BalanceHistorySearch.tsx    |  94 +++++--
 hooks/api/balanceHistory/useBalanceHistory.ts |   2 +-
 pages/balanceHistory/[accountName].tsx        | 138 ++++++++--
 6 files changed, 583 insertions(+), 50 deletions(-)
 create mode 100644 components/account/AccountBalanceHistoryCard.tsx
 create mode 100644 components/balanceHistory/BalanceHistoryChart.tsx

diff --git a/components/account/AccountBalanceHistoryCard.tsx b/components/account/AccountBalanceHistoryCard.tsx
new file mode 100644
index 00000000..1fe5785c
--- /dev/null
+++ b/components/account/AccountBalanceHistoryCard.tsx
@@ -0,0 +1,138 @@
+import React, { useState, useMemo } from "react";
+import { ArrowDown, ArrowUp } from "lucide-react";
+import { Card, CardContent, CardHeader } from "../ui/card";
+import Explorer from "@/types/Explorer";
+import Link from "next/link";
+import {
+  Tooltip,
+  TooltipProvider,
+  TooltipTrigger,
+  TooltipContent,
+} from "@radix-ui/react-tooltip";
+import useBalanceHistory from "@/hooks/api/balanceHistory/useBalanceHistory";
+import BalanceHistoryChart from "../balanceHistory/BalanceHistoryChart";
+import moment from "moment";
+import { useRouter } from "next/router";
+
+// Define the type for balance operation data
+
+type AccountBalanceHistoryCardProps = {
+  header: string;
+  userDetails: Explorer.FormattedAccountDetails;
+};
+
+const AccountBalanceHistoryCard: React.FC<AccountBalanceHistoryCardProps> = ({
+  header,
+  userDetails,
+}) => {
+  const [isBalancesHidden, setIsBalancesHidden] = useState(false);
+  const defaultFromDate = React.useMemo(
+    () => moment().subtract(1, "month").toDate(),
+    []
+  );
+  const router = useRouter();
+  const accountNameFromRoute = (router.query.accountName as string)?.slice(1);
+
+  const {
+    accountBalanceHistory: hiveBalanceHistory,
+    isAccountBalanceHistoryLoading: hiveBalanceHistoryLoading,
+    isAccountBalanceHistoryError: hiveBalanceHistoryError,
+  } = useBalanceHistory(
+    accountNameFromRoute,
+    "HIVE",
+    undefined,
+    undefined,
+    "asc",
+    defaultFromDate
+  );
+
+  const {
+    accountBalanceHistory: vestsBalanceHistory,
+    isAccountBalanceHistoryLoading: vestsBalanceHistoryLoading,
+    isAccountBalanceHistoryError: vestsBalanceHistoryError,
+  } = useBalanceHistory(
+    accountNameFromRoute,
+    "VESTS",
+    undefined,
+    undefined,
+    "asc",
+    defaultFromDate
+  );
+
+  const {
+    accountBalanceHistory: hbdBalanceHistory,
+    isAccountBalanceHistoryLoading: hbdBalanceHistoryLoading,
+    isAccountBalanceHistoryError: hbdBalanceHistoryError,
+  } = useBalanceHistory(
+    accountNameFromRoute,
+    "HBD",
+    undefined,
+    undefined,
+    "asc",
+    defaultFromDate
+  );
+
+  const staticData = [
+    { timestamp: "2023-01-01", balance: 100 },
+    { timestamp: "2023-02-01", balance: 110 },
+    { timestamp: "2023-03-01", balance: 120 },
+  ];
+
+
+  const handleBalancesVisibility = () => {
+    setIsBalancesHidden(!isBalancesHidden);
+  };
+
+  return (
+    <Card data-testid="properties-dropdown" className="overflow-hidden pb-0">
+      <CardHeader className="p-0">
+        <div
+          onClick={handleBalancesVisibility}
+          className="flex justify-between items-center p-2 hover:bg-rowHover cursor-pointer px-4"
+        >
+          <div className="text-lg">{header}</div>
+          <div className="flex">
+            <TooltipProvider>
+              <Tooltip>
+                <TooltipTrigger asChild>
+                  <Link
+                    href={`/balanceHistory/@${userDetails.name}`}
+                    data-testid="balance-history-link"
+                    className="text-link text-sm underline"
+                    onClick={(e) => e.stopPropagation()}
+                  >
+                    <span>Details</span>
+                  </Link>
+                </TooltipTrigger>
+                <TooltipContent
+                  side="top"
+                  align="start"
+                  sideOffset={5}
+                  alignOffset={10}
+                  className="border-0"
+                >
+                  <div className="bg-theme text-text p-2 text-sm">
+                    <p>Click Here for Balance History</p>
+                  </div>
+                </TooltipContent>
+              </Tooltip>
+            </TooltipProvider>
+            <span>{isBalancesHidden ? <ArrowDown /> : <ArrowUp />}</span>
+          </div>
+        </div>
+      </CardHeader>
+      <CardContent hidden={isBalancesHidden} data-testid="balance-history-content">
+        <BalanceHistoryChart
+          hiveBalanceHistoryData={hiveBalanceHistory?.operations_result || []}
+          vestsBalanceHistoryData={vestsBalanceHistory?.operations_result || []}
+          hbdBalanceHistoryData={hbdBalanceHistory?.operations_result || []}
+          quickView={true}
+ className="h-[340px]"
+        />
+       
+      </CardContent>
+    </Card>
+  );
+};
+
+export default AccountBalanceHistoryCard;
diff --git a/components/account/AccountDetailsSection.tsx b/components/account/AccountDetailsSection.tsx
index 719fccb2..76749644 100644
--- a/components/account/AccountDetailsSection.tsx
+++ b/components/account/AccountDetailsSection.tsx
@@ -15,7 +15,7 @@ import AccountVestingDelegationsCard from "./AccountVestingDelegationsCard";
 import AccountRcDelegationsCard from "./AccountRcDelegationsCard";
 import AccountBalanceCard from "./AccountBalanceCard";
 import Explorer from "@/types/Explorer";
-
+import AccountBalanceHistoryCard from "./AccountBalanceHistoryCard";
 interface AccountDetailsSectionProps {
   accountName: string;
   refetchAccountOperations: QueryObserverResult<Hive.AccountOperationsResponse>["refetch"];
@@ -66,6 +66,11 @@ const AccountDetailsSection: React.FC<AccountDetailsSectionProps> = ({
         header="Wallet"
         userDetails={accountDetails}
       />
+      <AccountBalanceHistoryCard
+        header="Balance History"
+        userDetails={accountDetails}
+      />
+
       <AccountDetailsCard
         header="Properties"
         userDetails={accountDetails}
diff --git a/components/balanceHistory/BalanceHistoryChart.tsx b/components/balanceHistory/BalanceHistoryChart.tsx
new file mode 100644
index 00000000..e69c1ccf
--- /dev/null
+++ b/components/balanceHistory/BalanceHistoryChart.tsx
@@ -0,0 +1,254 @@
+import React, { useState, useEffect } from "react";
+import { Line, LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Legend, ResponsiveContainer, Brush } from "recharts";
+import { formatNumber } from "@/lib/utils";
+import { cn } from "@/lib/utils";
+import moment from "moment";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faArrowDown,faArrowUp } from "@fortawesome/free-solid-svg-icons";
+interface BalanceHistoryChartProps {
+  hiveBalanceHistoryData?: { timestamp: string; balance_change: number; balance: number }[]; 
+  vestsBalanceHistoryData?: { timestamp: string; balance_change: number; balance: number }[]; 
+  hbdBalanceHistoryData?: { timestamp: string; balance_change: number; balance: number }[]; 
+  className?: string;
+  quickView?: boolean;
+}
+
+const BalanceHistoryChart: React.FC<BalanceHistoryChartProps> = ({
+  hiveBalanceHistoryData,
+  vestsBalanceHistoryData,
+  hbdBalanceHistoryData,
+  className = "",
+  quickView = false,
+}) => {
+  const availableCoins: string[] = [];
+
+  if (hiveBalanceHistoryData && hiveBalanceHistoryData.length > 0) availableCoins.push("HIVE");
+  if (vestsBalanceHistoryData && vestsBalanceHistoryData.length > 0) availableCoins.push("VESTS");
+  if (hbdBalanceHistoryData && hbdBalanceHistoryData.length > 0) availableCoins.push("HBD");
+
+  // Ensure we render a message only if there's no data available at all
+ /* if (availableCoins.length === 0) {
+    return (
+      <div className="w-full text-center py-8">
+        <p className="text-sm">No balance information found.</p>
+      </div>
+    );
+  }*/
+
+  const defaultSelectedCoinType = availableCoins.length === 1 ? availableCoins[0] : "HIVE";
+  const [selectedCoinType, setSelectedCoinType] = useState<string>(defaultSelectedCoinType);
+  const [isMobile, setIsMobile] = useState<boolean>(window.innerWidth < 480);
+  const [hiddenDataKeys, setHiddenDataKeys] = useState<string[]>([]);
+
+  useEffect(() => {
+    const handleResize = () => {
+      setIsMobile(window.innerWidth < 480);
+    };
+
+    window.addEventListener("resize", handleResize);
+    return () => window.removeEventListener("resize", handleResize);
+  }, []);
+
+  /*useEffect(() => {
+    if (availableCoins.length === 1) {
+      setSelectedCoinType(availableCoins[0]);
+    } else if (availableCoins.length > 1 && !availableCoins.includes(selectedCoinType)) {
+      setSelectedCoinType(availableCoins[0]);
+    }
+  }, [availableCoins,selectedCoinType]);*/
+
+  const colorMap: Record<string, string> = {
+    "HIVE": "#8884d8",
+    "VESTS": "#82ca9d",
+    "HBD": "#ff7300",
+  };
+
+  const dataMap: Record<string, { timestamp: string; balance_change: number; balance: number }[]> = {
+    HIVE: hiveBalanceHistoryData || [],
+    VESTS: vestsBalanceHistoryData || [],
+    HBD: hbdBalanceHistoryData || [],
+  };
+
+  const handleCoinTypeChange = (coinType: string) => {
+    setSelectedCoinType(coinType);
+  };
+
+  const CustomTooltip = ({
+    active,
+    payload,
+    label,
+  }: {
+    active?: boolean;
+    payload?: any[];
+    label?: string;
+  }) => {
+    if (quickView || !active || !payload || payload.length === 0) return null;
+  
+    // Get the actual balance from the data
+    const actualBalance = dataMap[selectedCoinType]?.find(
+      (item) => item.timestamp === label
+    )?.balance ?? 0;
+    const balanceChange = payload[0]?.payload.balance_change ?? 0;
+  
+    // Determine if the balance change is positive or negative
+    const isPositiveChange = balanceChange > 0;
+  
+    return (
+      <div className="bg-theme dark:bg-theme p-2 rounded border border-explorer-light-gray">
+        <p className="font-bold">{`Date: ${label}`}</p>
+        {payload.map((pld, index) => (
+          <div key={index} style={{ color: pld.stroke }}>
+            <div>
+              {/* Displaying arrow icon instead of balance change text */}
+              {isPositiveChange ? (
+                <FontAwesomeIcon
+                  icon={faArrowUp}
+                  size="sm"
+                  className="bg-green-400 p-[1.2px]" // Green for positive
+                />
+              ) : (
+                <FontAwesomeIcon
+                  icon={faArrowDown}
+                  size="sm"
+                  color="red"
+                  className="bg-red-400 p-[1.2px]" // Red for negative
+                />
+
+              )}
+              {` ${formatNumber(
+                balanceChange,
+                selectedCoinType === "VESTS",
+                false
+              )}`}
+            </div>
+            {/* Show the actual balance */}
+            <div>{`Balance: ${formatNumber(
+              actualBalance,
+              selectedCoinType === "VESTS",
+              false
+            )}`}</div>
+          </div>
+        ))}
+      </div>
+    );
+  };
+  
+
+  const renderCoinButtons = () => {
+    return availableCoins.map((coinType) => (
+      <button
+        key={coinType}
+        onClick={() => handleCoinTypeChange(coinType)}
+        className={cn(
+          "px-2 py-1 text-sm rounded m-[1px]",
+          selectedCoinType === coinType
+            ? "bg-blue-500 text-white"
+            : "bg-gray-200 text-black hover:bg-gray-300 dark:bg-gray-600 dark:text-white hover:dark:bg-gray-500"
+        )}
+      >
+        {coinType}
+      </button>
+    ));
+  };
+
+  const getMinMax = (data: { balance: number }[]) => {
+    const balance = data.map(item => item.balance);
+    const minValue = Math.min(...balance);
+    const maxValue = Math.max(...balance);
+    return [minValue, maxValue];
+  };
+
+  if (!selectedCoinType) {
+    return null; 
+  }
+
+  const [minValue, maxValue] = getMinMax(dataMap[selectedCoinType]);
+
+  // Determine the interval based on the length of the data
+  const tickInterval = Math.ceil(dataMap[selectedCoinType].length / 10);
+
+  return (
+    <div className={cn("w-full", className)}>
+      {availableCoins.length > 1 && (
+        <div className="flex justify-end mb-4">{renderCoinButtons()}</div>
+      )}
+
+      <ResponsiveContainer width="100%" height="100%">
+        <LineChart
+          data={dataMap[selectedCoinType] || []}
+          margin={{ top: 20, right: 30, left: 20, bottom: isMobile ? 100 : 60 }}
+        >
+          <CartesianGrid strokeDasharray="3 3" />
+          <XAxis
+            dataKey="timestamp"
+            tick={quickView ? false : true}
+            interval={tickInterval}
+            tickFormatter={(value) => moment(value).format("MMM D")} // Formatting dates to be more readable
+            style={{ fontSize: "10px" }}
+            angle={isMobile ? -90 : 0}
+            dx={isMobile ? -8 : 0}
+            dy={isMobile ? 20 : 10}
+          />
+          <YAxis
+            domain={[minValue, maxValue]}
+            tickFormatter={(tick) => {
+              if (selectedCoinType === "VESTS") {
+                const valueInK = tick / 1000;
+
+                let formattedValue = formatNumber(valueInK, true, false);
+
+                formattedValue = formattedValue.split(".")[0];
+
+                return `${formattedValue} K`;
+              }
+
+              // For other coin types, use the usual formatting
+              return formatNumber(tick, selectedCoinType === "VESTS", false);
+            }}
+            style={{ fontSize: "10px" }}
+            tickCount={6}
+          />
+          <Tooltip content={<CustomTooltip />} />
+         
+          <Line
+            type="monotone"
+            dataKey="balance"
+            stroke={colorMap[selectedCoinType]}
+            activeDot={{ r: 6 }}
+            name={selectedCoinType}
+            dot={false}
+            hide={hiddenDataKeys.includes("balance")}
+          />
+          <Legend
+            onClick={(event) => {
+              const { dataKey } = event;
+              const isHidden = hiddenDataKeys.includes(dataKey);
+              if (isHidden) {
+                setHiddenDataKeys(
+                  hiddenDataKeys.filter((key) => key !== dataKey)
+                );
+              } else {
+                setHiddenDataKeys([...hiddenDataKeys, dataKey]);
+              }
+            }}
+          />
+          {!quickView && (
+            <Brush
+              dataKey="timestamp"
+              height={30}
+              stroke="var(--color-switch-off)"
+              fill="var(--color-background)"
+              travellerWidth={10}
+              tickFormatter={(value) => moment(value).format("MMM D")}
+              y={380}
+              className="text-xs"
+            />
+          )}
+          
+        </LineChart>
+      </ResponsiveContainer>
+    </div>
+  );
+};
+
+export default BalanceHistoryChart;
\ No newline at end of file
diff --git a/components/home/searches/BalanceHistorySearch.tsx b/components/home/searches/BalanceHistorySearch.tsx
index a3afb6e8..de75d003 100644
--- a/components/home/searches/BalanceHistorySearch.tsx
+++ b/components/home/searches/BalanceHistorySearch.tsx
@@ -6,6 +6,8 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
 
 import useSearchRanges from "@/hooks/common/useSearchRanges";
 import useURLParams from "@/hooks/common/useURLParams";
+import OperationTypesDialog from "@/components/OperationTypesDialog";
+import useAccountOperationTypes from "@/hooks/api/accountPage/useAccountOperationTypes";
 
 interface AccountSearchParams {
   accountName?: string | undefined;
@@ -19,7 +21,7 @@ interface AccountSearchParams {
   rangeSelectKey: string | undefined;
   page: number | undefined;
   filters: boolean[];
-  coinType?: string; 
+  coinType?: string;
 }
 
 const defaultSearchParams: AccountSearchParams = {
@@ -42,6 +44,30 @@ const BalanceHistorySearch = () => {
   const COIN_TYPES = ["HIVE", "VESTS", "HBD"];
   const router = useRouter();
   const accountNameFromRoute = (router.query.accountName as string)?.slice(1);
+  const { accountOperationTypes } =
+    useAccountOperationTypes(accountNameFromRoute);
+  const [selectedOperationTypes, setSelectedOperationTypes] = useState<
+    number[]
+  >([]);
+  const [singleOperationTypeId, setSingleOperationTypeId] = useState<
+    number | undefined
+  >(undefined);
+  const [fieldContent, setFieldContent] = useState<string>("");
+  const [selectedKeys, setSelectedKeys] = useState<string[] | undefined>(
+    undefined
+  );
+  const [selectedIndex, setSelectedIndex] = useState<string>("");
+
+  const changeSelectedOperationTypes = (operationTypesIds: number[]) => {
+    if (operationTypesIds.length === 1) {
+      setSingleOperationTypeId(operationTypesIds[0]);
+    } else {
+      setSingleOperationTypeId(undefined);
+    }
+    setSelectedKeys(undefined);
+    setFieldContent("");
+    setSelectedOperationTypes(operationTypesIds);
+  };
 
   const { paramsState, setParams } = useURLParams(
     {
@@ -65,7 +91,6 @@ const BalanceHistorySearch = () => {
 
   const [initialSearch, setInitialSearch] = useState<boolean>(false);
   const [filters, setFilters] = useState<boolean[]>([]);
- 
 
   const searchRanges = useSearchRanges();
 
@@ -129,8 +154,11 @@ const BalanceHistorySearch = () => {
 
   const handleCoinTypeChange = (newCoinType: string) => {
     setCoinType(newCoinType);
-    setParams({ ...paramsState, coinType: newCoinType });
-    
+    setParams({
+      ...paramsState,
+      coinType: newCoinType,
+      page: undefined, // Reset the page when the coin type changes
+    });
   };
 
   const handleFilterClear = () => {
@@ -144,48 +172,66 @@ const BalanceHistorySearch = () => {
     setFilters([]);
   };
 
-    useEffect(() => {
+  useEffect(() => {
     if (paramsState.coinType) {
       setCoinType(paramsState.coinType);
-      }
+    }
     if (paramsState && !initialSearch) {
       handleSearch();
     }
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [paramsState]);
 
-
   return (
     <>
       <p className="m-2 mb-6 mt-6">
         Find balance history of given account by coin and range.
       </p>
-     
+
       <Card className="mb-4">
         <CardHeader>
-          <CardTitle>Filters</CardTitle>
+          <CardTitle className="">Filters</CardTitle>
         </CardHeader>
         <CardContent>
           <div className="flex items-center mb-3">
-              <select
-                value={coinType}
-                onChange={(e) => handleCoinTypeChange(e.target.value)}
-                className="w-[180px] border border-gray-300 p-2 rounded bg-theme dark:bg-theme"
-              >
-                {COIN_TYPES.map((type) => (
-                  <option key={type} value={type}>
-                    {type}
-                  </option>
-                ))}
-              </select>
-            
+            <select
+              value={coinType}
+              onChange={(e) => handleCoinTypeChange(e.target.value)}
+              className="w-[180px] border border-gray-300 p-2 rounded bg-theme dark:bg-theme"
+            >
+              {COIN_TYPES.map((type) => (
+                <option key={type} value={type}>
+                  {type}
+                </option>
+              ))}
+            </select>
           </div>
           <SearchRanges rangesProps={searchRanges} />
-          <div className="flex items-center justify-between m-2">
-            <Button onClick={() => handleSearch(true)} data-testid="apply-filters">
+          {/* Operations Types commented for now
+          <div className="flex items-center mb-10 mt-2">
+        <OperationTypesDialog
+          operationTypes={accountOperationTypes}
+          selectedOperations={selectedOperationTypes}
+          setSelectedOperations={/*changeSelectedOperationTypes}
+          buttonClassName="bg-gray-500"
+          triggerTitle={/*getOperationButtonTitle(
+            selectedOperationTypes,
+            accountOperationTypes
+          )}
+        /> 
+      </div> */}
+          <div>
+            <Button
+              onClick={() => handleSearch(true)}
+              data-testid="apply-filters"
+            >
               <span>Apply filters</span>
             </Button>
-            <Button onClick={() => handleFilterClear()} data-testid="clear-filters">
+            <Button
+              onClick={() => handleFilterClear()}
+              data-testid="clear-filters"
+              className="ml-2"
+            >
               <span>Clear filters</span>
             </Button>
           </div>
diff --git a/hooks/api/balanceHistory/useBalanceHistory.ts b/hooks/api/balanceHistory/useBalanceHistory.ts
index 011554b9..d4bacfa3 100644
--- a/hooks/api/balanceHistory/useBalanceHistory.ts
+++ b/hooks/api/balanceHistory/useBalanceHistory.ts
@@ -20,7 +20,7 @@ const useBalanceHistory = (
     return await fetchingService.geAccounttBalanceHistory(
       accountName,
       coinType,
-      page ? page : 1,
+      page,
       pageSize,
       direction,
       fromDate ? fromDate : undefined,
diff --git a/pages/balanceHistory/[accountName].tsx b/pages/balanceHistory/[accountName].tsx
index 6cca43e3..3225736f 100644
--- a/pages/balanceHistory/[accountName].tsx
+++ b/pages/balanceHistory/[accountName].tsx
@@ -2,7 +2,8 @@ import { useRouter } from "next/router";
 import Head from "next/head";
 import Image from "next/image";
 import Link from "next/link";
-
+import React from "react";
+import moment from "moment";
 import { config } from "@/Config";
 
 import { Loader2 } from "lucide-react";
@@ -17,13 +18,66 @@ import { getHiveAvatarUrl } from "@/utils/HiveBlogUtils";
 import BalanceHistoryTable from "@/components/balanceHistory/BalanceHistoryTable";
 import BalanceHistorySearch from "@/components/home/searches/BalanceHistorySearch";
 import { Card, CardHeader } from "@/components/ui/card";
+import BalanceHistoryChart from "@/components/balanceHistory/BalanceHistoryChart";
+
+interface Operation {
+  timestamp: number;  // Timestamp in seconds
+  balance: number;    // Balance associated with the operation
+}
+
+const prepareData = (operations: Operation[]) => {
+  if (!operations || operations.length === 0) return [];
+
+  // Create a map to store the balance and balance change for each day
+  const dailyData = new Map<string, { balance: number; balance_change: number }>();
+
+  operations.forEach((operation: any) => {  // Adjusted the type to match the structure of the data you provided
+    let date;
+    if (typeof operation.timestamp === 'string') {
+      date = new Date(operation.timestamp);
+    } else if (typeof operation.timestamp === 'number') {
+      date = new Date(operation.timestamp * 1000);
+    } else {
+      return;  // Skip this operation if the timestamp is invalid
+    }
+
+    if (!isNaN(date.getTime())) {
+      const dateString = date.toISOString().split('T')[0]; // Get date in YYYY-MM-DD format
+
+      let balance_change = parseInt(operation.balance_change, 10);
+      let balance = parseInt(operation.balance, 10);
+
+      // Update the map with the latest balance and balance change for the day
+      if (dailyData.has(dateString)) {
+        dailyData.get(dateString)!.balance_change += balance_change; // Accumulate balance changes for the same day
+        dailyData.get(dateString)!.balance = balance;  // Update the balance for the day
+      } else {
+        dailyData.set(dateString, { balance, balance_change });
+      }
+    }
+  });
+
+  // Convert the map to an array of objects with the required fields
+  const preparedData = Array.from(dailyData.entries()).map(([date, data]) => ({
+    timestamp: date,      // Use the date string directly
+    balance: data.balance,
+    balance_change: data.balance_change, // The sum of balance changes for the day
+  }));
+
+  return preparedData;
+};
 
 export default function BalanceHistory() {
   const router = useRouter();
   const accountNameFromRoute = (router.query.accountName as string)?.slice(1);
 
   // Fetch account details
-  const { accountDetails, isAccountDetailsLoading, isAccountDetailsError ,notFound } = useAccountDetails(accountNameFromRoute, false);
+  const {
+    accountDetails,
+    isAccountDetailsLoading,
+    isAccountDetailsError,
+    notFound,
+  } = useAccountDetails(accountNameFromRoute, false);
 
   interface BalanceHistorySearchParams {
     accountName?: string;
@@ -70,7 +124,8 @@ export default function BalanceHistory() {
     page,
   } = paramsState;
 
-  let effectiveFromBlock = paramsState.fromBlock || fromDateParam;
+  const defaultFromDate = React.useMemo(() => moment().subtract(1, "month").toDate(), []);
+  let effectiveFromBlock = paramsState.fromBlock || fromDateParam || defaultFromDate;
   let effectiveToBlock = paramsState.toBlock || toDateParam;
 
   if (
@@ -95,13 +150,39 @@ export default function BalanceHistory() {
     effectiveToBlock
   );
 
+
+  const defaultChartSize = 6000;
+
+  const chartPageSize = (accountBalanceHistory?.total_operations !== undefined && accountBalanceHistory.total_operations !== 0 && accountBalanceHistory.total_operations < defaultChartSize)
+    ? accountBalanceHistory.total_operations
+    : defaultChartSize;
+  const chartData = useBalanceHistory(
+    accountNameFromRoute,
+    paramsState.coinType,
+    undefined,
+    chartPageSize,
+    "asc",
+    effectiveFromBlock,
+    effectiveToBlock
+  );
+
+  const preparedData = chartData.accountBalanceHistory
+    ? prepareData(chartData.accountBalanceHistory.operations_result)
+    : [];
+  // Determine the message to display based on the filters
+  let message = "";
+  if (effectiveFromBlock === defaultFromDate && !fromBlockParam && !toBlockParam) {
+    message = "Showing Results for the last month.";
+  } else {
+    message = "Showing Results with applied filters.";
+  }
+
   return (
     <>
       <Head>
         <title>@{accountNameFromRoute} - Hive Explorer</title>
       </Head>
 
-      {/* Loading state for account details */}
       {isAccountDetailsLoading ? (
         <div className="flex justify-center text-center items-center">
           <Loader2 className="animate-spin mt-1 text-black h-12 w-12 ml-3" />
@@ -114,7 +195,6 @@ export default function BalanceHistory() {
             <Card data-testid="account-details">
               <CardHeader>
                 <div className="flex flex-wrap items-center justify-between gap-4 bg-theme dark:bg-theme">
-                  {/* Avatar and Name */}
                   <div className="flex items-center gap-4">
                     <Image
                       className="rounded-full border-2 border-explorer-orange"
@@ -125,15 +205,8 @@ export default function BalanceHistory() {
                       data-testid="user-avatar"
                     />
                     <div>
-                      <h2
-                        className="text-lg font-semibold text-gray-800 dark:text-white"
-                        data-testid="account-name"
-                      >
-                        <Link
-                          className="text-link"
-                          href={`/@${accountNameFromRoute}`}
-                        >
-                          {" "}
+                      <h2 className="text-lg font-semibold text-gray-800 dark:text-white" data-testid="account-name">
+                        <Link className="text-link" href={`/@${accountNameFromRoute}`}>
                           {accountNameFromRoute}
                         </Link>
                         / <span className="text-text">Balance History</span>
@@ -144,10 +217,8 @@ export default function BalanceHistory() {
               </CardHeader>
             </Card>
 
-            {/* Filter Options (Always visible) */}
             <BalanceHistorySearch />
 
-            {/* Show Error Message if No Balance History and No Loading State */}
             {!isAccountBalanceHistoryLoading && !accountBalanceHistory?.total_operations ? (
               <div className="w-full my-4 text-center">
                 No operations were found.
@@ -157,15 +228,34 @@ export default function BalanceHistory() {
                 <Loader2 className="animate-spin mt-1 h-12 w-12 ml-3" />
               </div>
             ) : (
-              // Show the table when balance history exists
-              <BalanceHistoryTable
-                operations={convertBalanceHistoryResultsToTableOperations(
-                  accountBalanceHistory
+              <>
+                
+                <Card data-testid="account-details">
+                  {/* Display the message */}
+                  {message && (
+                  <div className="p-4 bg-gray-100 dark:bg-gray-700 rounded-lg mb-4 text-center text-sm text-gray-500">
+                    {message}<br/>
+                    Results are limited to {defaultChartSize} records and grouped by day.<br/>
+  
+                  </div>
                 )}
-                total_operations={accountBalanceHistory.total_operations}
-                total_pages={accountBalanceHistory.total_pages}
-                current_page={paramsState.page}
-              />
+
+                  <BalanceHistoryChart
+                    hiveBalanceHistoryData={(!paramsState.coinType || paramsState.coinType === "HIVE") ? preparedData : undefined}
+                    vestsBalanceHistoryData={paramsState.coinType === "VESTS" ? preparedData : undefined}
+                    hbdBalanceHistoryData={paramsState.coinType === "HBD" ? preparedData : undefined}
+                    quickView={false}
+                    className="h-[450px] mb-10 mr-0 pr-1 pb-6"
+                  />
+                </Card>
+
+                <BalanceHistoryTable
+                  operations={convertBalanceHistoryResultsToTableOperations(accountBalanceHistory)}
+                  total_operations={accountBalanceHistory.total_operations}
+                  total_pages={accountBalanceHistory.total_pages}
+                  current_page={paramsState.page}
+                />
+              </>
             )}
           </div>
         )
-- 
GitLab