Skip to content

Commit

Permalink
feat: add animated-counter component for dynamic values
Browse files Browse the repository at this point in the history
closes #1
  • Loading branch information
rocktimsaikia committed Jul 28, 2024
1 parent 69523bc commit a0a783c
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Compound Interest Calculator

A minimal compound interest calculator that displays the total return of a compounded investment over a specified time period.
A minimal compound interest investment calculator that displays the total returns over a specified time period, interest rate and compounding frequency.


[![Deployment](https://github.com/rocktimsaikia/compound-interest-calculator/actions/workflows/deploy.yml/badge.svg)](https://github.com/rocktimsaikia/compound-interest-calculator/actions/workflows/deploy.yml)
Expand Down
13 changes: 10 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useEffect, useState } from "react";
import compounder from "compounder";
import AnimatedCounter from "./components/animated-counter";

type CompoundingFrequency = "quarterly" | "semi-annually" | "annually";

Expand Down Expand Up @@ -196,15 +197,21 @@ export default function App() {
<div className="mt-24 grid grid-cols-3 text-center">
<div>
<p className="text-gray-500">Principal Amount</p>
<p>{principalAmount.toLocaleString("en-IN")}</p>
<div>
<AnimatedCounter start={principalAmount} locale="en-IN" />
</div>
</div>
<div>
<p className="text-gray-500">Total Interest</p>
<p>{totalInterest.toLocaleString("en-IN")}</p>
<p>
<AnimatedCounter start={totalInterest} locale="en-IN" />
</p>
</div>
<div>
<p className="text-gray-500">Total Amount</p>
<p>{totalAmount.toLocaleString("en-IN")}</p>
<p>
<AnimatedCounter start={totalAmount} locale="en-IN" />
</p>
</div>
</div>
</div>
Expand Down
46 changes: 46 additions & 0 deletions src/components/animated-counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useRef, useState } from "react";

interface Props {
start: number;
duration?: number;
locale?: string;
}

export default function AnimatedCounter({
start,
duration = 200,
locale,
}: Props) {
const [count, setCount] = useState(start); // State to keep track of the current count
const prevStartRef = useRef(start); // Ref to store the previous start value

// Update the previous start value when start changes
useEffect(() => {
prevStartRef.current = start;
}, [start]);

// Previous start value
const prevStart = prevStartRef.current;

// Animate the count when the start value changes
useEffect(() => {
// If start value changes, animate the count
if (prevStart !== start) {
let startTimestamp: DOMHighResTimeStamp;

const step = (timestamp: DOMHighResTimeStamp) => {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1); // Calculate progress
setCount(Math.floor(progress * (start - prevStart) + prevStart)); // Update count based on progress

if (progress < 1) {
window.requestAnimationFrame(step); // Continue animation
}
};

window.requestAnimationFrame(step); // Start animation
}
}, [start, duration]);

return <span>{locale ? count.toLocaleString(locale) : count}</span>; // Render the current count
}

0 comments on commit a0a783c

Please sign in to comment.