κ·λν μ²λ
μ μν μμ°μ± μλΉμ€λ₯Ό 6μ£Όκ° 5λͺ
μ΄μ κ°λ°νλ€.
π μλΉμ€ ꡬ경κ°κΈ°
λμ₯μ μ¬λ¬ ν΅κ³λ₯Ό 보μ¬μ£Όλ λμ₯ κ΄λ¦¬ νν© νμ΄μ§λ₯Ό 맑μ ꡬν μ€ μλ
μ λΉν΄
μμ
μκ° μ¦κ°/κ°μμ¨ νν©μ 보μ¬μ£Όλ UIλ₯Ό κ·Ήμ μΌλ‘ νννκΈ° μν΄ μ«μ μΉ΄μ΄ν
μ λλ©μ΄μ
μ ꡬννλ€.
import React, { useEffect, useState } from "react";
import styled, { keyframes } from "styled-components";
import { useDispatch, useSelector } from "react-redux";
import { getRateDB } from "../../redux/modules/analysis";
import { ShimmerThumbnail } from "react-shimmer-effects";
import WorkTimeBarChart from "./WorkTimeBarChart";
const WorkTime = ({ workTimeData }) => {
const dispatch = useDispatch();
// 2οΈβ£ μ¦κ°/κ°μμ¨ response κ° useSelector λ‘ λΆλ¬μ€κΈ°
const rateData = useSelector((state) => state.analysis.rate);
const [count, setCount] = useState(0);
const [windowSize, setWindowSize] = useState(getWindowSize());
const is_loaded = useSelector((state) => state.analysis.worktime_is_loaded);
// 1οΈβ£ μ¦κ°/κ°μμ¨ λ°μ΄ν° API νΈμΆ
useEffect(() => {
dispatch(getRateDB());
}, []);
// 3οΈβ£ μΉ΄μ΄ν
μ λλ©μ΄μ
end κ° λ°μμ¨ λ°μ΄ν°λ‘ μ μ©
const end = rateData?.rate;
const start = 0;
const duration = 1000;
const frameRate = 1000 / 60;
const totalFrame = Math.round(duration / frameRate);
const easeOutExpo = (number) => {
return number === 1 ? 1 : 1 - Math.pow(2, -10 * number);
};
// 4οΈβ£ useEffectλ‘ νλ©΄μ΄ κ·Έλ €μ§ λλ§λ€ μΉ΄μ΄ν
μ λλ©μ΄μ
μ€ν
useEffect(() => {
let currentNumber = start;
const counter = setInterval(() => {
// 5οΈβ£ currentNumber / totalFrame μ΄ 1μ κ°κΉμμ§μλ‘ λλ¦¬κ² μΉ΄μ΄ν
const progress = easeOutExpo(++currentNumber / totalFrame);
if (rateData.rate) setCount(Math.round(end * progress));
if (progress === 1) {
clearInterval(counter);
}
}, frameRate);
}, [end, frameRate, start, totalFrame]);
// μλμ° μ¬μ΄μ¦ μΆμ
useEffect(() => {
function handleWindowResize() {
setWindowSize(getWindowSize());
}
window.addEventListener("resize", handleWindowResize);
return () => {
window.removeEventListener("resize", handleWindowResize);
};
}, []);
function getWindowSize() {
const { innerWidth, innerHeight } = window;
return { innerWidth, innerHeight };
}
return (
<>
<Wrap>
<TitleWrap>
<SmileIcon>πͺ</SmileIcon>
{windowSize.innerWidth > 760 ? (
<Title>
μλ
μ λΉν΄ μ¬ν΄ μμ
μκ°μ΄ <br />
{rateData.rate ? count + "%" : "0%"}{" "}
{rateData.rateText ? rateData.rateText : "μ¦κ°"}
νμ΄μ
</Title>
) : (
<TitleM>
μλ
μ λΉν΄ <br /> μ¬ν΄ μμ
μκ°μ΄ <br />
{rateData.rate ? count + "%" : "0%"}{" "}
{rateData.rateText ? rateData.rateText : "μ¦κ°"}
νμ΄μ
</TitleM>
)}
</TitleWrap>
{is_loaded ? (
<WorkTimeBarChart workTimeData={workTimeData} />
) : (
<ShimmerThumbnail className="thumNail-weather" height={160} rounded />
)}
</Wrap>
</>
);
};
const Wrap = styled.div`
background: #ffffff;
box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.25);
border-radius: 10px;
padding: 20px;
grid-column: 7 / 10;
grid-row: 2 / 3;
display: flex;
flex-direction: column;
justify-content: space-between;
@media only screen and (max-width: 760px) {
padding: 20px 20px 30px 20px;
grid-column: 2 / 3;
grid-row: 3 / 4;
}
`;
// 6οΈβ£ ν¬λͺ
νλ€κ° μλ‘ μ€λ₯΄λ₯΅ μ¬λΌμ€λ μ λλ©μ΄μ
const boxFade = keyframes`
0% {
opacity: 0;
transform: translateY(10%);
}
30% {
opacity: 0.3;
transform: translateY(6%);
}
100% {
opacity: 1;
transform: translateY(0);
}
`;
const TitleWrap = styled.div`
display: flex;
flex-direction: row;
animation: ${boxFade} 1s;
`;
const SmileIcon = styled.span`
font-size: 24px;
`;
const Title = styled.span`
font-size: 24px;
font-weight: 700;
margin-left: 10px;
text-align: left;
`;
const TitleM = styled.span`
font-size: 24px;
font-weight: 700;
margin-left: 10px;
text-align: left;
margin-bottom: 30px;
`;
export default WorkTime;
μμ μκ° μΉ΄λ νλμλ λ§μ λν μΌμ μ κ²½μΌλ€ π