Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
0xmegalodon committed Feb 2, 2024
2 parents 07f5531 + 6ef6687 commit e2ebc9c
Show file tree
Hide file tree
Showing 10 changed files with 402 additions and 8 deletions.
138 changes: 135 additions & 3 deletions src/modules/PublicSale/activities/AcitivitiesVer2/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
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';
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;
Expand All @@ -9,13 +17,22 @@ interface ICTA {
link?: string;
}

enum ActivityType {
Game,
Naka,
Modular,
Social,
AI
}

export interface GameItemProps {
title: string;
subTitle?: string;
desc: string | any;
ctas?: ICTA[];
banner?: string,
link?: string,
type: ActivityType
}

const GAME_LINK = {
Expand All @@ -29,7 +46,6 @@ const GAME_LINK = {

export const NormalRow = (p: { key: string, value?: string, mask?: boolean }) => {
if (p.mask) {

return (
`
<li>
Expand Down Expand Up @@ -72,9 +88,39 @@ 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 ActivitiesVer2 = React.memo(() => {
const numberReport = useAppSelector(numberReportSelector);
const btcPrice = useAppSelector(coinPricesSelector)?.[Coin.BTC];
const TASKS = React.useMemo<GameItemProps[]>(() => {
return [
{
Expand All @@ -88,6 +134,7 @@ const ActivitiesVer2 = React.memo(() => {
`,
banner: 'banner-01_1.png',
link: GAME_LINK.ARCA,
type: ActivityType.Game,
},
{
title: 'DeFi on Bitcoin',
Expand All @@ -100,6 +147,7 @@ const ActivitiesVer2 = React.memo(() => {
`,
banner: 'banner-02.png',
link: GAME_LINK.NAKA,
type: ActivityType.Naka,
},
{
title: 'Education on Bitcoin',
Expand All @@ -112,6 +160,7 @@ const ActivitiesVer2 = React.memo(() => {
`,
banner: 'banner-03.png',
link: GAME_LINK.MODULAR,
type: ActivityType.Modular,
},
{
title: 'SocialFi on Bitcoin',
Expand All @@ -124,6 +173,7 @@ const ActivitiesVer2 = React.memo(() => {
`,
banner: 'banner-04.png',
link: GAME_LINK.ALPHA,
type: ActivityType.Social,
},
{
title: 'AI on Bitcoin',
Expand All @@ -136,9 +186,90 @@ const ActivitiesVer2 = React.memo(() => {
</ul>
`,
banner: 'banner-05.png',
link: GAME_LINK.AI,
type: ActivityType.AI,
},
]
}, [])
}, []);

const renderReport = React.useCallback((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: "Builders",
value: modular.total_owner.toString()
});
component2 = ReportRow({
key: "Builds",
value: modular.total_model.toString()
});
}
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: new BigNumber(alphaRun.total_reward.toString()).div(1e8).times(btcPrice).toString(),
maxDigit: 2,
prefix: "$"
});
}
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 (
Expand All @@ -148,6 +279,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 }}/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
161 changes: 161 additions & 0 deletions src/modules/PublicSale/activities/components/IncreaseNumber/index.tsx
Original file line number Diff line number Diff line change
@@ -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} style={{ fontSize: 12, fontWeight: "500", lineHeight: "140%" }} />;
})

IncreaseNumber.displayName = "IncreaseNumber";

export default IncreaseNumber;
Loading

0 comments on commit e2ebc9c

Please sign in to comment.