diff --git a/apps/flame-defi/app/earn/components/MarketSummary/MarketSummary.tsx b/apps/flame-defi/app/earn/components/MarketSummary/MarketSummary.tsx index 35ab13e..0b68396 100644 --- a/apps/flame-defi/app/earn/components/MarketSummary/MarketSummary.tsx +++ b/apps/flame-defi/app/earn/components/MarketSummary/MarketSummary.tsx @@ -1,11 +1,49 @@ +import { useEffect, useState } from "react"; import { MarketSummaryCard } from "./MarketSummaryCard"; +// TODO: Use fetched values. +const VALUE_DEPOSIT = 1000000; +const VALUE_BORROW = 75000; + export const MarketSummary = () => { + const [countDeposit, setCountDeposit] = useState(null); + const [countBorrow, setCountBorrow] = useState(null); + + const [isAnimating, setIsAnimating] = useState(false); + + useEffect(() => { + // Prevent counter animation when number is too low. + // May need to adjust based on the expected maximum value. + const multiplier = 0.1; + const countDepositMinimum = VALUE_DEPOSIT * multiplier; + const countBorrowMinimum = VALUE_BORROW * multiplier; + + if ( + countDeposit !== null && + countBorrow !== null && + countDeposit > countDepositMinimum && + countBorrow > countBorrowMinimum + ) { + setIsAnimating(true); + } + }, [countDeposit, countBorrow]); + return (
- {/* TODO: Use fetched values. */} - - + +
); }; diff --git a/apps/flame-defi/app/earn/components/MarketSummary/MarketSummaryCard.tsx b/apps/flame-defi/app/earn/components/MarketSummary/MarketSummaryCard.tsx index 68d7230..f6e0bee 100644 --- a/apps/flame-defi/app/earn/components/MarketSummary/MarketSummaryCard.tsx +++ b/apps/flame-defi/app/earn/components/MarketSummary/MarketSummaryCard.tsx @@ -1,37 +1,65 @@ import { Skeleton } from "@repo/ui/shadcn-primitives"; import Big from "big.js"; -import React, { useEffect, useState } from "react"; +import React, { useEffect } from "react"; import { FormattedNumber } from "react-intl"; import { Card } from "../Card"; interface MarketSummaryCardProps { label: React.ReactNode; value: number; + count: number | null; + setCount: (value: number) => void; + /** + * Sync animation state between multiple cards. + */ + isAnimating: boolean; } -export const MarketSummaryCard = ({ label, value }: MarketSummaryCardProps) => { - const [count, setCount] = useState(null); - +export const MarketSummaryCard = ({ + label, + value, + count, + setCount, + isAnimating, +}: MarketSummaryCardProps) => { useEffect(() => { let isMounted = true; const counter = (minimum: number, maximum: number) => { - for (let count = minimum; count <= maximum; count++) { - setTimeout(() => { - if (isMounted) { - setCount(count); - } - }, 5000); - } + let i = minimum; + + const updateCount = () => { + if (isMounted && i <= maximum) { + setCount(i); + + // Increment counter based on proximity to maximum so multiple cards have synced animations. + const range = maximum - minimum; + const progress = (i - minimum) / range; + const step = Math.max(1, (Math.log10(1 + 9 * progress) * range) / 10); + + i += Math.ceil(step); + + setTimeout(updateCount, 10); + } + + if (isMounted && i > maximum) { + setCount(maximum); + } + }; + + updateCount(); + + return () => { + isMounted = false; + }; }; - const minimum = value - 10000; - counter(minimum < 0 ? 0 : minimum, value); + counter(0, value); return () => { isMounted = false; }; - }, [value]); + }, [value, setCount]); return ( @@ -48,7 +76,7 @@ export const MarketSummaryCard = ({ label, value }: MarketSummaryCardProps) => { /> - +