potty-chart/src/ScoreCounter.tsx

73 lines
1.9 KiB
TypeScript

import React, {useState, useEffect} from 'react';
import {useSpring, animated} from '@react-spring/web';
import './ScoreCounter.css';
let scrollInterval: ReturnType<typeof setInterval>;
const points = {
attempt: 1,
scheduledPoop: 5,
selfPoop: 10,
cleanUndies: 50,
streakBonus: [50, 60, 80, 100, 120, 140, 150]
};
const calcPoints = (stats: Stats) => {
return stats.attempts * points.attempt +
stats.scheduledPoops * points.scheduledPoop +
stats.selfPoops * points.selfPoop +
stats.cleanUndies * points.cleanUndies;
//+ stats.streaks.reduce((p,s,i) => p + s * points.streakBonus[i]);
};
const getShakeStyle = () => {
const xr = Math.random();
const yr = Math.random();
const rr = Math.random();
const sr = Math.random();
return {
x: Math.floor(xr * 30) - 15,
y: Math.floor(yr * 30) - 15,
rotate: Math.floor((rr * 40)) - 20,
scale: sr * 0.3 + .80
};
};
const ScoreCounter = ({stats}: {stats: Stats}) => {
const score = calcPoints(stats);
const [showing, setShowing] = useState<number>(score);
const restState = { x: 0, y: 0, rotate: 0, scale: 1};
const [springs, api] = useSpring(() => (restState));
useEffect(() => {
scrollInterval = setInterval(() => {
setShowing(n => {
const delta = Math.ceil(Math.abs(n - score)/5);
if(n < score) {
api.start(getShakeStyle());
return n + delta;
} else if( n > score) {
api.start(getShakeStyle());
return n - delta;
} else {
clearInterval(scrollInterval);
Promise.all(api.start(
{x:0, y: -10, rotate: 0, scale: 1.25})).then(() => {
api.start(restState);
});;
return n;
}
});
}, 80);
return () => clearInterval(scrollInterval);
}, [score]);
return <animated.span style={{display: "inline-block", ...springs}} className="score-counter">{showing}</animated.span>;
};
export default ScoreCounter;