From fd3cb5e8b6a610f13cb842a482e8babba2c84300 Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 13:47:04 +0700
Subject: [PATCH 1/6] chore: actitvities 3

---
 .../activities/AcitivitiesVer2/index.tsx      |   6 +-
 .../components/IncreaseNumber/index.tsx       | 161 ++++++++++++++++++
 .../activities/hooks/useGetNumberReport.tsx   |  28 +++
 src/modules/PublicSale/index.tsx              |   2 +
 src/services/public-sale.ts                   |  26 +++
 src/stores/states/activities/reducer.ts       |  11 +-
 src/stores/states/activities/selector.ts      |   1 +
 src/stores/states/activities/types.ts         |  29 +++-
 8 files changed, 258 insertions(+), 6 deletions(-)
 create mode 100644 src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
 create mode 100644 src/modules/PublicSale/activities/hooks/useGetNumberReport.tsx

diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
index cd90141c4..aac2bf2eb 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
@@ -1,6 +1,9 @@
 import React from 'react';
 import { Box, Flex, Image, Text } from '@chakra-ui/react';
 import styles from './styles.module.scss';
+import IncreaseNumber from '@/modules/PublicSale/activities/components/IncreaseNumber';
+import { useAppSelector } from '@/stores/hooks';
+import { numberReportSelector } from '@/stores/states/activities/selector';
 
 interface ICTA {
   title: string;
@@ -29,7 +32,6 @@ const GAME_LINK = {
 
 export const NormalRow = (p: { key: string, value?: string, mask?: boolean }) => {
   if (p.mask) {
-
     return (
       `
         <li>
@@ -74,7 +76,7 @@ export const LinkRow = (p: { key: string, value: string, link: string }) => {
 
 
 const ActivitiesVer2 = React.memo(() => {
-
+  const numberReport = useAppSelector(numberReportSelector)
   const TASKS = React.useMemo<GameItemProps[]>(() => {
     return [
       {
diff --git a/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx b/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
new file mode 100644
index 000000000..8ecfd39c3
--- /dev/null
+++ b/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
@@ -0,0 +1,161 @@
+import React, { useEffect, useMemo, useRef, useState } from 'react';
+
+interface IProp {
+  from?: number;
+  to: number;
+  timeSpan?: number; // seconds
+  format?: (v: number) => string | number;
+  minStep?: number;
+}
+
+const IncreaseNumber = React.memo((props: IProp) => {
+  const {
+    from = 0,
+    to,
+    timeSpan = 60, // seconds
+    format,
+    minStep = 1,
+  } = props;
+
+  const ref = useRef<HTMLSpanElement>(null);
+
+  const isCounting = useRef(false);
+  const [prev, setPrev] = useState(Number(from));
+  const [next, setNext] = useState(Number(to));
+
+  useEffect(() => {
+    setNext((p) => Number(p > to ? p : to));
+
+    return () => {
+      setPrev((p) => Number(p > to ? p : to));
+    };
+  }, [to]);
+
+  useEffect(() => {
+    setPrev((p) => Number(p > from ? p : from));
+  }, [from]);
+
+  const formatValue = useMemo(() => {
+    if (format) {
+      return format;
+    }
+    return (_v: number) => _v;
+  }, [format]);
+
+  useEffect(() => {
+    if (to) {
+      if (from) {
+        const digits = `${Number(from)}`
+          .split('')
+          .map((n) => (n === '.' ? '.' : Number(n)));
+
+        const newDigits: any[] = [0];
+
+        let timeout: ReturnType<typeof setTimeout>;
+        const step = (): void => {
+          try {
+            const index = newDigits.length - 1;
+            if (digits[index] === '.') {
+              newDigits.push(0);
+            } else if ((newDigits[index] || 0) < (digits[index] || 0)) {
+              newDigits[index] = (newDigits[index] || 0) + 1;
+            } else if (newDigits.length < digits.length) {
+              if (digits[index + 1] === '.') {
+                newDigits.push('.');
+              } else {
+                newDigits.push(0);
+              }
+            } else {
+              isCounting.current = true;
+            }
+
+            if (ref.current) {
+              const num = Number(
+                digits
+                  .map((digit, idx) => {
+                    if (newDigits[idx]) {
+                      return newDigits[idx];
+                    }
+                    if (digit === '.') {
+                      return digit;
+                    }
+                    return 0;
+                  })
+                  .join(''),
+              );
+              // console.log(num);
+              ref.current.innerHTML = `${formatValue(num)}`;
+            }
+          } catch (e) {
+            isCounting.current = true;
+          }
+
+          if (isCounting.current) {
+            if (timeout) {
+              clearTimeout(timeout);
+            }
+          } else {
+            timeout = setTimeout(() => {
+              step();
+            }, 100);
+          }
+        };
+
+        step();
+      } else {
+        isCounting.current = true;
+      }
+    }
+  }, [from, to]);
+
+  useEffect(() => {
+    let timeout: ReturnType<typeof setTimeout>;
+    const bigStep = (
+      start: number,
+      end: number,
+      step: number,
+      speed: number,
+    ) => {
+      if (step < minStep) {
+        if (ref.current) {
+          if (isCounting.current) {
+            ref.current.innerHTML = `${formatValue(next)}`;
+          }
+          // ref.current.innerHTML = `${next}`;
+        }
+      } else if (start < next) {
+        if (ref.current) {
+          if (isCounting.current) {
+            ref.current.innerHTML = `${formatValue(start)}`;
+          }
+          // ref.current.innerHTML = `${start}`;
+        }
+        timeout = setTimeout(() => {
+          const fr = start + step;
+          bigStep(fr, end, step, speed);
+        }, speed * 1000);
+      } else if (ref.current) {
+        if (isCounting.current) {
+          ref.current.innerHTML = `${formatValue(next)}`;
+        }
+        // ref.current.innerHTML = `${next}`;
+      }
+    };
+
+    const remain = next - prev;
+    const step = Math.floor(remain / 60);
+    bigStep(prev, next, step, timeSpan / 60);
+
+    return () => {
+      if (timeout) {
+        clearTimeout(timeout);
+      }
+    };
+  }, [prev, next, timeSpan, formatValue, minStep]);
+
+  return <span ref={ref} />;
+})
+
+IncreaseNumber.displayName = "IncreaseNumber";
+
+export default IncreaseNumber;
diff --git a/src/modules/PublicSale/activities/hooks/useGetNumberReport.tsx b/src/modules/PublicSale/activities/hooks/useGetNumberReport.tsx
new file mode 100644
index 000000000..9293798cc
--- /dev/null
+++ b/src/modules/PublicSale/activities/hooks/useGetNumberReport.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import { useAppDispatch } from '@/stores/hooks';
+import { getActivitiesReport } from '@/services/public-sale';
+import { setNumberReport } from '@/stores/states/activities/reducer';
+
+const useGetNumberReport = () => {
+  const dispatch = useAppDispatch();
+  
+  const fetchData = async () => {
+    try {
+      const report = await getActivitiesReport();
+      if (report) {
+        dispatch(setNumberReport(report))
+      }
+    } catch (error) {
+      // TODO:
+    }
+  }
+
+  React.useEffect(() => {
+    fetchData();
+    setInterval(() => {
+      fetchData()
+    }, 10000)
+  }, []);
+};
+
+export default useGetNumberReport;
diff --git a/src/modules/PublicSale/index.tsx b/src/modules/PublicSale/index.tsx
index e059f6ed4..7c4a941fb 100644
--- a/src/modules/PublicSale/index.tsx
+++ b/src/modules/PublicSale/index.tsx
@@ -10,9 +10,11 @@ import TopContent from '@/modules/PublicSale/topContent';
 import React from 'react';
 import IntroVideos from '@/modules/PublicSale/IntroVideos';
 import useTradeNakaEvent from '@/modules/PublicSale/activities/hooks/useTradeNakaEvent';
+import useGetNumberReport from '@/modules/PublicSale/activities/hooks/useGetNumberReport';
 
 const PublicSaleModule = () => {
   useTradeNakaEvent();
+  useGetNumberReport();
   return (
     <Box className={s.container}>
       <div className={s.contentTop}>
diff --git a/src/services/public-sale.ts b/src/services/public-sale.ts
index ded6d594b..713a539ff 100644
--- a/src/services/public-sale.ts
+++ b/src/services/public-sale.ts
@@ -9,11 +9,16 @@ import { PERP_API_URL } from '@/config';
 import { ILeaderBoardPoint } from '@/interfaces/leader-board-point';
 import axios from 'axios';
 import { camelCaseKeys } from '@/utils/normalize';
+import { AlphaRunReport, ModularReport, NakaVolumeReport, NumberReport } from '@/stores/states/activities/types';
 
 const apiClient = createAxiosInstance({
   baseURL: `${PERP_API_URL}/api`,
 });
 
+const apiReport = createAxiosInstance({
+  baseURL: "",
+});
+
 export const getPublicsaleWalletInfo = async (): Promise<
   PublicSaleWalletTokenDeposit[]
 > => {
@@ -261,3 +266,24 @@ export const requestRewardDailyShareCode = async (): Promise<any> => {
   }
   return;
 };
+
+export const getActivitiesReport = async (): Promise<NumberReport | undefined> => {
+  try {
+    const [modular, alphaRun, nakaVolume] = (
+      await Promise.allSettled([
+        apiReport.get("https://generative.xyz/generative/api/modular-workshop/statistic"),
+        apiReport.get("https://stag-perp-api.fprotocol.io/api/run-together/statistics"),
+        apiReport.get("https://api.bvm.network/api/future/report")
+      ])
+    ) as any[];
+
+    return {
+      modular: modular?.value,
+      alphaRun: alphaRun?.value,
+      nakaVolume: nakaVolume?.value,
+    }
+
+  } catch (error) {
+    return undefined;
+  }
+}
diff --git a/src/stores/states/activities/reducer.ts b/src/stores/states/activities/reducer.ts
index 142cda23a..a7104a307 100644
--- a/src/stores/states/activities/reducer.ts
+++ b/src/stores/states/activities/reducer.ts
@@ -1,11 +1,12 @@
 import { createSlice } from '@reduxjs/toolkit';
-import { ActivitiesState, IDaySecond } from './types';
+import { ActivitiesState, IDaySecond, NumberReport } from './types';
 
 const initialState: ActivitiesState = {
   daySecond: {
     topWinners: [],
     bestPNL: undefined
-  }
+  },
+  numberReport: undefined,
 };
 
 const slice = createSlice({
@@ -15,11 +16,15 @@ const slice = createSlice({
     setDaySecondActivities: (state, actions) => {
       state.daySecond = actions.payload as IDaySecond;
     },
+    setNumberReport: (state, actions) => {
+      state.numberReport = actions.payload as NumberReport;
+    },
   },
 });
 
 export const {
-  setDaySecondActivities
+  setDaySecondActivities,
+  setNumberReport
 } = slice.actions;
 
 export default slice.reducer;
diff --git a/src/stores/states/activities/selector.ts b/src/stores/states/activities/selector.ts
index bdbd7913b..2ed51d941 100644
--- a/src/stores/states/activities/selector.ts
+++ b/src/stores/states/activities/selector.ts
@@ -3,3 +3,4 @@ import { ActivitiesState } from '@/stores/states/activities/types';
 
 export const activitiesSelector = (state: RootState) => state.activities;
 export const daySecondSelector = (state: RootState) => (state.activities as ActivitiesState).daySecond;
+export const numberReportSelector = (state: RootState) => (state.activities as ActivitiesState).numberReport;
diff --git a/src/stores/states/activities/types.ts b/src/stores/states/activities/types.ts
index 1baf309dd..8b6603c7f 100644
--- a/src/stores/states/activities/types.ts
+++ b/src/stores/states/activities/types.ts
@@ -5,6 +5,33 @@ export interface IDaySecond {
   bestPNL?: CurrentBestPNL
 }
 
+export interface ModularReport {
+  total_owner: number;
+  total_model: number;
+}
+
+export interface AlphaRunReport {
+  total_circle: number;
+  total_twitter_id: number;
+  total_distance: number;
+  reward_per_km: number;
+  total_reward: number;
+  total_reward_running: number;
+  total_reward_donation: number;
+}
+
+export interface NakaVolumeReport {
+  volume: string;
+  usd_volume: string;
+}
+
+export interface NumberReport {
+  modular: ModularReport;
+  alphaRun: AlphaRunReport;
+  nakaVolume: NakaVolumeReport
+}
+
 export interface ActivitiesState {
-  daySecond: IDaySecond
+  daySecond: IDaySecond;
+  numberReport?: NumberReport;
 }

From f4905deb6dde5fcab05c70f0288370b1ee821900 Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:11:57 +0700
Subject: [PATCH 2/6] chore: update code

---
 .../activities/AcitivitiesVer2/index.tsx      | 127 +++++++++++++++++-
 .../AcitivitiesVer2/styles.module.scss        |   4 +
 .../components/IncreaseNumber/index.tsx       |   2 +-
 src/services/public-sale.ts                   |   6 +-
 src/stores/states/activities/types.ts         |   8 +-
 5 files changed, 142 insertions(+), 5 deletions(-)

diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
index 15551dc56..3de7e9bba 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
@@ -4,6 +4,9 @@ import styles from './styles.module.scss';
 import IncreaseNumber from '@/modules/PublicSale/activities/components/IncreaseNumber';
 import { useAppSelector } from '@/stores/hooks';
 import { numberReportSelector } from '@/stores/states/activities/selector';
+import { formatCurrency } from '@/utils/format';
+import { value } from 'valibot';
+import BigNumber from 'bignumber.js';
 
 interface ICTA {
   title: string;
@@ -12,6 +15,14 @@ interface ICTA {
   link?: string;
 }
 
+enum ActivityType {
+  Game,
+  Naka,
+  Modular,
+  Social,
+  AI
+}
+
 export interface GameItemProps {
   title: string;
   subTitle?: string;
@@ -19,6 +30,7 @@ export interface GameItemProps {
   ctas?: ICTA[];
   banner?: string,
   link?: string,
+  type: ActivityType
 }
 
 const GAME_LINK = {
@@ -74,6 +86,35 @@ export const LinkRow = (p: { key: string, value: string, link: string }) => {
   );
 };
 
+export const ReportRow = (p: { key: string, value: string, prefix?: string, maxDigit?: number, diffNumb?: number }) => {
+  return (
+    <Flex flexDir="row" alignItems="end">
+      {p.prefix && (
+        <span style={{ fontWeight: '500', fontSize: "12px", lineHeight: "140%" }}>
+          {p.prefix || ""}
+        </span>
+      )}
+      <IncreaseNumber
+        from={
+        new BigNumber(new BigNumber(p.value)
+          .minus(new BigNumber(p.value)
+            .div((p.diffNumb || 300))
+          )
+          .toFixed(0, BigNumber.ROUND_CEIL))
+          .toNumber()
+      }
+        to={new BigNumber(new BigNumber(p.value).toFixed(0, BigNumber.ROUND_CEIL)).toNumber()}
+        format={(_value: number) => {
+          return formatCurrency(_value, 0, p.maxDigit || 0)
+        }}
+      />
+      <Text fontSize="12px" lineHeight="120%" color="white" opacity={0.7} fontWeight="400" ml="4px">
+        {p.key}
+      </Text>
+    </Flex>
+  );
+};
+
 
 const ActivitiesVer2 = React.memo(() => {
   const numberReport = useAppSelector(numberReportSelector)
@@ -90,6 +131,7 @@ const ActivitiesVer2 = React.memo(() => {
         `,
         banner: 'banner-01.png',
         link: GAME_LINK.ARCA,
+        type: ActivityType.Game,
       },
       {
         title: 'DeFi on Bitcoin',
@@ -102,6 +144,7 @@ const ActivitiesVer2 = React.memo(() => {
         `,
         banner: 'banner-02.png',
         link: GAME_LINK.NAKA,
+        type: ActivityType.Naka,
       },
       {
         title: 'Education on Bitcoin',
@@ -114,6 +157,7 @@ const ActivitiesVer2 = React.memo(() => {
         `,
         banner: 'banner-03.png',
         link: GAME_LINK.MODULAR,
+        type: ActivityType.Modular,
       },
       {
         title: 'SocialFi on Bitcoin',
@@ -126,6 +170,7 @@ const ActivitiesVer2 = React.memo(() => {
         `,
         banner: 'banner-04.png',
         link: GAME_LINK.ALPHA,
+        type: ActivityType.Social,
       },
       {
         title: 'AI on Bitcoin',
@@ -138,9 +183,88 @@ const ActivitiesVer2 = React.memo(() => {
           </ul>
         `,
         banner: 'banner-05.png',
+        link: GAME_LINK.AI,
+        type: ActivityType.AI,
       },
     ]
-  }, [])
+  }, []);
+
+  const renderReport = (type: ActivityType) => {
+    if (!numberReport || type === ActivityType.AI) return <></>;
+    let component1: any | undefined = undefined;
+    let component2: any | undefined = undefined;
+    switch (type) {
+      case ActivityType.Game: {
+        const gameReport = numberReport.gameReport
+        if (gameReport && gameReport.total_game && gameReport.total_txs) {
+          component1 = ReportRow({
+            key: "Game plays",
+            value: gameReport.total_game.toString(),
+          });
+          component2 = ReportRow({
+            key: "Tx",
+            value: gameReport.total_txs.toString(),
+          })
+        }
+        break;
+      }
+      case ActivityType.Naka: {
+        const nakaVolume = numberReport.nakaVolume
+        if (nakaVolume && nakaVolume.usd_volume) {
+          component1 = ReportRow({
+            key: "Vols",
+            value: nakaVolume.usd_volume.toString(),
+            maxDigit: 2,
+            prefix: "$"
+          });
+        }
+        break;
+      }
+      case ActivityType.Modular: {
+        const modular = numberReport.modular
+        if (modular && modular.total_owner && modular.total_model) {
+          component1 = ReportRow({
+            key: "Builder",
+            value: modular.total_owner.toString()
+          });
+          component2 = ReportRow({
+            key: "Build",
+            value: modular.total_model.toString()
+          });
+        }
+        break;
+      }
+      // case ActivityType.Social: {
+      //   const alphaRun = numberReport.alphaRun
+      //   if (alphaRun && alphaRun.total_distance && alphaRun.total_reward) {
+      //     component1 = ReportRow({
+      //       key: `${formatCurrency(alphaRun.total_distance, 0, 2)}`,
+      //       value: "Km"
+      //     });
+      //     component2 = ReportRow({
+      //       key: `$${formatCurrency(alphaRun.total_reward, 0, 2)}`,
+      //       value: "Fund raised"
+      //     });
+      //   }
+      //   break;
+      // }
+    }
+    if (!component1 && !component2) return <></>;
+
+    return (
+      <Flex alignItems="center" gap="8px">
+        {!!component1 && (
+          component1
+        )}
+        {!!component2 && (
+          <Box w="1px" height="9px" bg="white" opacity={0.7}/>
+        )}
+        {!!component2 && (
+          component2
+        )}
+      </Flex>
+    )
+  }
 
   const renderItem = (item: GameItemProps) => {
     return (
@@ -150,6 +274,7 @@ const ActivitiesVer2 = React.memo(() => {
             {item.title}
             {!!item.subTitle && <span style={{ fontWeight: "400" }}>{item.subTitle}</span>}
           </Text>
+          {renderReport(item.type)}
         </div>
         <div className={styles.container_item_content}>
           <div dangerouslySetInnerHTML={{ __html: item.desc }}/>
diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/styles.module.scss b/src/modules/PublicSale/activities/AcitivitiesVer2/styles.module.scss
index 72d0d09d7..eed14caff 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/styles.module.scss
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/styles.module.scss
@@ -29,6 +29,10 @@
       gap: 8px;
     }
     &_header {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      justify-content: space-between;
       padding: 10px 16px;
       border-bottom: 1px solid rgba(255, 255, 255, 0.15);
     }
diff --git a/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx b/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
index 8ecfd39c3..0c8ba0824 100644
--- a/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
+++ b/src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
@@ -153,7 +153,7 @@ const IncreaseNumber = React.memo((props: IProp) => {
     };
   }, [prev, next, timeSpan, formatValue, minStep]);
 
-  return <span ref={ref} />;
+  return <span ref={ref} style={{ fontSize: 12, fontWeight: "500", lineHeight: "140%" }} />;
 })
 
 IncreaseNumber.displayName = "IncreaseNumber";
diff --git a/src/services/public-sale.ts b/src/services/public-sale.ts
index 713a539ff..725de710a 100644
--- a/src/services/public-sale.ts
+++ b/src/services/public-sale.ts
@@ -269,11 +269,12 @@ export const requestRewardDailyShareCode = async (): Promise<any> => {
 
 export const getActivitiesReport = async (): Promise<NumberReport | undefined> => {
   try {
-    const [modular, alphaRun, nakaVolume] = (
+    const [modular, alphaRun, nakaVolume, gameReport] = (
       await Promise.allSettled([
         apiReport.get("https://generative.xyz/generative/api/modular-workshop/statistic"),
         apiReport.get("https://stag-perp-api.fprotocol.io/api/run-together/statistics"),
-        apiReport.get("https://api.bvm.network/api/future/report")
+        apiReport.get("https://api.bvm.network/api/future/report"),
+        apiReport.get("https://game-state.bitcoinarcade.xyz/api/network-stats")
       ])
     ) as any[];
 
@@ -281,6 +282,7 @@ export const getActivitiesReport = async (): Promise<NumberReport | undefined> =
       modular: modular?.value,
       alphaRun: alphaRun?.value,
       nakaVolume: nakaVolume?.value,
+      gameReport: gameReport?.value
     }
 
   } catch (error) {
diff --git a/src/stores/states/activities/types.ts b/src/stores/states/activities/types.ts
index 8b6603c7f..33ce04a78 100644
--- a/src/stores/states/activities/types.ts
+++ b/src/stores/states/activities/types.ts
@@ -25,10 +25,16 @@ export interface NakaVolumeReport {
   usd_volume: string;
 }
 
+export interface GameReport {
+  total_txs: number;
+  total_game: number;
+}
+
 export interface NumberReport {
   modular: ModularReport;
   alphaRun: AlphaRunReport;
-  nakaVolume: NakaVolumeReport
+  nakaVolume: NakaVolumeReport;
+  gameReport: GameReport;
 }
 
 export interface ActivitiesState {

From 189f07e65a8404ac87bd41a64b1ad2cbcc5bf6af Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:17:39 +0700
Subject: [PATCH 3/6] chore: update code

---
 src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
index 8c449abd7..ef3e17b04 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
@@ -224,11 +224,11 @@ const ActivitiesVer2 = React.memo(() => {
         const modular = numberReport.modular
         if (modular && modular.total_owner && modular.total_model) {
           component1 = ReportRow({
-            key: "Builder",
+            key: "Builders",
             value: modular.total_owner.toString()
           });
           component2 = ReportRow({
-            key: "Build",
+            key: "Builds",
             value: modular.total_model.toString()
           });
         }

From 162d53c6a86e76740a4456216e417b29a1143200 Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:23:45 +0700
Subject: [PATCH 4/6] chore: store data

---
 src/stores/index.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/stores/index.ts b/src/stores/index.ts
index 53da83220..10423a73c 100644
--- a/src/stores/index.ts
+++ b/src/stores/index.ts
@@ -10,7 +10,7 @@ const reducers = combineReducers(reducer);
 const persistConfig = getPersistConfig({
   key: 'root',
   storage: persistLocalStorage,
-  whitelist: ['common.poolTabIndex', 'common.coinPrices', 'airdrop', 'user'],
+  whitelist: ['common.poolTabIndex', 'common.coinPrices', 'airdrop', 'user', "activities.numberReport"],
   rootReducer: reducers,
 });
 

From fb92de9b1afd2423b57bf361a680d7ade0558295 Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:42:10 +0700
Subject: [PATCH 5/6] chore: update code

---
 .../activities/AcitivitiesVer2/index.tsx      | 34 ++++++++++---------
 1 file changed, 18 insertions(+), 16 deletions(-)

diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
index ef3e17b04..6c43738b3 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
@@ -189,7 +189,7 @@ const ActivitiesVer2 = React.memo(() => {
     ]
   }, []);
 
-  const renderReport = (type: ActivityType) => {
+  const renderReport = React.useCallback((type: ActivityType) => {
     if (!numberReport || type === ActivityType.AI) return <></>;
     let component1: any | undefined = undefined;
     let component2: any | undefined = undefined;
@@ -234,20 +234,22 @@ const ActivitiesVer2 = React.memo(() => {
         }
         break;
       }
-      // case ActivityType.Social: {
-      //   const alphaRun = numberReport.alphaRun
-      //   if (alphaRun && alphaRun.total_distance && alphaRun.total_reward) {
-      //     component1 = ReportRow({
-      //       key: `${formatCurrency(alphaRun.total_distance, 0, 2)}`,
-      //       value: "Km"
-      //     });
-      //     component2 = ReportRow({
-      //       key: `$${formatCurrency(alphaRun.total_reward, 0, 2)}`,
-      //       value: "Fund raised"
-      //     });
-      //   }
-      //   break;
-      // }
+      case ActivityType.Social: {
+        const alphaRun = numberReport.alphaRun
+        if (alphaRun && alphaRun.total_distance && alphaRun.total_reward) {
+          component1 = ReportRow({
+            key: "Km",
+            value: alphaRun.total_distance.toString()
+          });
+          component2 = ReportRow({
+            key: "Fund raised",
+            value: alphaRun.total_reward.toString(),
+            maxDigit: 2,
+            prefix: "$"
+          });
+        }
+        break;
+      }
     }
     if (!component1 && !component2) return <></>;
 
@@ -264,7 +266,7 @@ const ActivitiesVer2 = React.memo(() => {
         )}
       </Flex>
     )
-  }
+  }, []);
 
   const renderItem = (item: GameItemProps) => {
     return (

From 94fbbe3ff351ff41a3702d85158019590fa62679 Mon Sep 17 00:00:00 2001
From: camewell <130561684+camewell071@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:44:58 +0700
Subject: [PATCH 6/6] chore: update ui

---
 .../PublicSale/activities/AcitivitiesVer2/index.tsx        | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
index 6c43738b3..28b35a643 100644
--- a/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
+++ b/src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
@@ -7,6 +7,8 @@ import { numberReportSelector } from '@/stores/states/activities/selector';
 import { formatCurrency } from '@/utils/format';
 import { value } from 'valibot';
 import BigNumber from 'bignumber.js';
+import { coinPricesSelector } from '@/stores/states/common/selector';
+import { Coin } from '@/stores/states/common/types';
 
 interface ICTA {
   title: string;
@@ -117,7 +119,8 @@ export const ReportRow = (p: { key: string, value: string, prefix?: string, maxD
 
 
 const ActivitiesVer2 = React.memo(() => {
-  const numberReport = useAppSelector(numberReportSelector)
+  const numberReport = useAppSelector(numberReportSelector);
+  const btcPrice = useAppSelector(coinPricesSelector)?.[Coin.BTC];
   const TASKS = React.useMemo<GameItemProps[]>(() => {
     return [
       {
@@ -243,7 +246,7 @@ const ActivitiesVer2 = React.memo(() => {
           });
           component2 = ReportRow({
             key: "Fund raised",
-            value: alphaRun.total_reward.toString(),
+            value: new BigNumber(alphaRun.total_reward.toString()).div(1e8).times(btcPrice).toString(),
             maxDigit: 2,
             prefix: "$"
           });