Skip to content

Commit b979954

Browse files
committed
Refactor: Refactoring Record page
1 parent 942ae6e commit b979954

File tree

14 files changed

+652
-599
lines changed

14 files changed

+652
-599
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { keyframes } from "@emotion/react";
2+
import styled from "@emotion/styled";
3+
4+
const NoLogContainerFadeKeyframe = keyframes`
5+
from {
6+
opacity: 0;
7+
transform: translate3d(0, calc(-14px * 4 + 30px), 0);
8+
}
9+
10+
to {
11+
opacity: 1;
12+
transform: translate3d(0, calc(-14px * 4), 0);
13+
}
14+
`;
15+
16+
export const NoLogContainer = styled.div`
17+
width: 100%;
18+
min-height: inherit;
19+
20+
display: flex;
21+
flex-direction: column;
22+
justify-content: center;
23+
align-items: center;
24+
25+
font-size: 24px;
26+
gap: 0.8em;
27+
28+
color: #626262;
29+
30+
opacity: 0;
31+
transform: translate3d(0, calc(-14px * 4 + 30px), 0);
32+
animation: ${NoLogContainerFadeKeyframe} 0.4s cubic-bezier(0.2, 0, 0, 1) 0.65s
33+
forwards;
34+
35+
svg {
36+
font-size: 4em;
37+
}
38+
39+
div {
40+
display: flex;
41+
flex-direction: column;
42+
justify-content: center;
43+
align-items: center;
44+
45+
gap: 0.3em;
46+
47+
.title {
48+
font-size: 1em;
49+
font-weight: 500;
50+
}
51+
52+
.description {
53+
font-size: 0.68em;
54+
}
55+
}
56+
57+
@media screen and (max-width: 1270px) {
58+
font-size: 22px;
59+
}
60+
61+
@media screen and (max-width: 800px) {
62+
font-size: 18px;
63+
}
64+
`;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { FaBoxOpen } from "react-icons/fa";
2+
import { NoLogContainer } from "./NoLog.styled";
3+
import { languageOptionValueAtom as LOV } from "../../../../shared/atom";
4+
import { useRecoilValue } from "recoil";
5+
6+
export default function NoLog() {
7+
const language = useRecoilValue(LOV);
8+
9+
return (
10+
<NoLogContainer>
11+
<FaBoxOpen />
12+
<div>
13+
<span
14+
className="title"
15+
style={{ letterSpacing: language === "kor" ? "0" : "1.5px" }}
16+
>
17+
{language === "kor" ? "비어있음" : "EMPTY"}
18+
</span>
19+
<span className="description">
20+
{language === "kor"
21+
? "먼저 타이머를 시작해 10분 이상의 시간을 기록해보세요."
22+
: "Start the timer over 10 minutes first."}
23+
</span>
24+
</div>
25+
</NoLogContainer>
26+
);
27+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import styled from "@emotion/styled";
2+
3+
export const CardContainer = styled.div<{ accentColor: string }>`
4+
width: 100%;
5+
height: 150px;
6+
7+
display: flex;
8+
9+
.time-displayer {
10+
width: 150px;
11+
height: 100%;
12+
13+
display: flex;
14+
flex-direction: column;
15+
justify-content: center;
16+
align-items: center;
17+
18+
font-size: 42px;
19+
line-height: 1em;
20+
font-family: ${({ theme }) => theme.font.family.poppins};
21+
font-weight: 200;
22+
23+
border-radius: 24px;
24+
background-color: ${({ theme }) => theme.background.secondary};
25+
26+
.hr {
27+
margin: 0.25em 0;
28+
width: 100%;
29+
height: 4px;
30+
background-color: ${({ theme }) => theme.background.primary};
31+
}
32+
}
33+
34+
.info-container {
35+
font-size: 16px;
36+
37+
width: 100%;
38+
height: 100%;
39+
padding: 16px 0;
40+
padding-left: 48px;
41+
42+
display: flex;
43+
flex-direction: column;
44+
justify-content: space-between;
45+
46+
.pause-info {
47+
font-size: 2.8em;
48+
font-weight: 500;
49+
color: ${(props) => props.accentColor};
50+
51+
.percentage {
52+
font-family: ${({ theme }) => theme.font.family.poppins};
53+
line-height: 1em;
54+
}
55+
56+
.goal {
57+
display: inline-flex;
58+
justify-content: center;
59+
align-items: center;
60+
61+
svg {
62+
font-size: 0.8em;
63+
filter: brightness(1.3);
64+
}
65+
}
66+
}
67+
68+
.date-info {
69+
font-size: 1.15em;
70+
display: flex;
71+
flex-direction: column;
72+
gap: 0.2em;
73+
74+
.full-date {
75+
color: #a0a0a0;
76+
font-size: 0.8em;
77+
}
78+
}
79+
}
80+
81+
@media screen and (max-width: 800px) {
82+
.info-container {
83+
padding-left: 36px;
84+
}
85+
}
86+
87+
@media screen and (max-width: 500px) {
88+
.info-container > .pause-info {
89+
font-size: 2.4em;
90+
}
91+
92+
.time-displayer {
93+
font-size: 36px;
94+
95+
.hr {
96+
margin: 0.33em 0;
97+
}
98+
}
99+
}
100+
`;
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { useRecoilValue } from "recoil";
2+
import { IRecordCardProps } from "./RecordCard.type";
3+
import {
4+
languageOptionValueAtom as LOV,
5+
clockColorValueAtom as CCV,
6+
} from "../../../../shared/atom";
7+
import { getDayGapBetween } from "../../../../utils/time";
8+
import { CardContainer } from "./RecordCard.styled";
9+
import { Theme } from "../../../../styles/theme";
10+
import { RiFlag2Fill } from "react-icons/ri";
11+
import { getDateString } from "./RecordCard.util";
12+
13+
export default function RecordCard({
14+
duration,
15+
endTime,
16+
paused,
17+
completeRatio,
18+
}: IRecordCardProps) {
19+
const language = useRecoilValue(LOV);
20+
const clockColor = useRecoilValue(CCV);
21+
22+
const getMinSec = () => {
23+
const min = Math.floor(duration / 1000 / 60).toString();
24+
const sec = (Math.floor(duration / 1000) % 60).toString();
25+
26+
return {
27+
min: min.length < 2 ? `0${min}` : min,
28+
sec: sec.length < 2 ? `0${sec}` : sec,
29+
};
30+
};
31+
32+
const getCompletePercentage = () => {
33+
return (Math.floor(completeRatio * 1000) / 10).toFixed(1);
34+
};
35+
36+
const getHowMuchDateAgo = () => {
37+
const dayGap = getDayGapBetween(new Date(), endTime);
38+
39+
if (dayGap === 0) return language === "kor" ? "오늘" : "Today";
40+
if (dayGap < 7)
41+
return language === "kor" ? `${dayGap}일 전` : `${dayGap}d ago`;
42+
if (dayGap < 30)
43+
return language === "kor"
44+
? `${Math.floor(dayGap / 7)}주 전`
45+
: `${Math.floor(dayGap / 7)}w ago`;
46+
if (dayGap < 365)
47+
return language === "kor"
48+
? `${Math.floor(dayGap / 30)}달 전`
49+
: `${Math.floor(dayGap / 30)}m ago`;
50+
return language === "kor"
51+
? `${Math.floor(dayGap / 365)}년 전`
52+
: `${Math.floor(dayGap / 365)}y ago`;
53+
};
54+
55+
return (
56+
<CardContainer accentColor={`${Theme.clock.color[clockColor]}`}>
57+
<div className="time-displayer">
58+
<div className="min">{getMinSec().min}</div>
59+
<div className="hr"></div>
60+
<div className="sec">{getMinSec().sec}</div>
61+
</div>
62+
<div className="info-container">
63+
<div className="date-info">
64+
<span className="date-ago">{getHowMuchDateAgo()}</span>
65+
<span className="full-date">{getDateString(endTime, language)}</span>
66+
</div>
67+
<div className="pause-info">
68+
{paused ? (
69+
<div className="percentage">{getCompletePercentage()}</div>
70+
) : (
71+
<div className="goal">
72+
<RiFlag2Fill />
73+
</div>
74+
)}
75+
</div>
76+
</div>
77+
</CardContainer>
78+
);
79+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { LanguageOptionType } from "../../../shared/types";
2+
3+
export function getDateString(time: Date, language: LanguageOptionType) {
4+
const monthName = [
5+
"Jan",
6+
"Feb",
7+
"Mar",
8+
"Apr",
9+
"May",
10+
"Jun",
11+
"Jul",
12+
"Aug",
13+
"Sep",
14+
"Oct",
15+
"Nov",
16+
"Dec",
17+
];
18+
19+
if (language === "kor")
20+
return `${time.getFullYear()}${
21+
time.getMonth() + 1
22+
}${time.getDate()}일`;
23+
24+
return `${
25+
monthName[time.getMonth()]
26+
} ${time.getDate()}, ${time.getFullYear()}`;
27+
}

0 commit comments

Comments
 (0)