From 312448caff2906c0885ebc9db2a0d85bbd375186 Mon Sep 17 00:00:00 2001 From: mysdpy30s Date: Tue, 12 Sep 2023 14:42:48 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat:=20Timer=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Timer/TimerApp.tsx | 110 ++++++++++++++++++++++++++++++ src/pages/Timer.tsx | 32 ++++++++- 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/components/Timer/TimerApp.tsx diff --git a/src/components/Timer/TimerApp.tsx b/src/components/Timer/TimerApp.tsx new file mode 100644 index 00000000..1ca61bbe --- /dev/null +++ b/src/components/Timer/TimerApp.tsx @@ -0,0 +1,110 @@ +import React from "react"; +import { useState, useEffect } from "react"; +import { styled } from "styled-components"; + +// 타이머 스타일링 +interface TimerProps { + fontSize?: string; +} +const TimerText = styled.div` + font-size: ${(props) => props.fontSize || "1.5rem"}; +`; + +const TimerBtn = styled.button` + color: white; + background-color: #3956a3; + padding: 15px 30px; + font-size: 1.5rem; + border: none; + border-radius: 5px; + cursor: pointer; +`; + +const TimerApp = () => { + const nowDate = new Date().toLocaleDateString("ko-KR", { + year: "2-digit", + month: "2-digit", + day: "2-digit", + weekday: "narrow", + }); + + const [nowTime, setNowTime] = useState( + new Date().toLocaleTimeString(), + ); // 현재 시간 표시 + const [startWorkTime, setStartWorkTime] = useState(null); // 출근 시간 기록 + const [finishWorkTime, setFinishWorkTime] = useState(null); // 퇴근 시간 기록 + + const UpdateTime = () => { + let nowTime = new Date().toLocaleTimeString(); + setNowTime(nowTime); + }; + + useEffect(() => { + const interval = setInterval(UpdateTime, 1000); + + return () => { + clearInterval(interval); + }; + }, []); + + const recordStartWork = (e: React.MouseEvent) => { + e.preventDefault(); + // 현재 시간을 출근 시간으로 기록 + const startWorkTime = new Date(); + const hours = startWorkTime.getHours().toString().padStart(2, "0"); + const minutes = startWorkTime.getMinutes().toString().padStart(2, "0"); + const seconds = startWorkTime.getSeconds().toString().padStart(2, "0"); + setStartWorkTime(`${hours}:${minutes}:${seconds}`); + }; + const recordFinishWork = (e: React.MouseEvent) => { + e.preventDefault(); + // 현재 시간을 퇴근 시간으로 기록 + const finishWorkTime = new Date(); + const hours = finishWorkTime.getHours().toString().padStart(2, "0"); + const minutes = finishWorkTime.getMinutes().toString().padStart(2, "0"); + const seconds = finishWorkTime.getSeconds().toString().padStart(2, "0"); + setFinishWorkTime(`${hours}:${minutes}:${seconds}`); + }; + + const calcWorkTime = () => { + if (startWorkTime && finishWorkTime) { + const startTime = startWorkTime.split(":"); + const finishTime = finishWorkTime.split(":"); + const startHours = parseInt(startTime[0], 10); + const startMinutes = parseInt(startTime[1], 10); + const finishHours = parseInt(finishTime[0], 10); + const finishMinutes = parseInt(finishTime[1], 10); + + let hours = finishHours - startHours; + let minutes = finishMinutes - startMinutes; + + if (minutes < 0) { + hours -= 1; + minutes += 60; + } + + return `오늘 총 근무 시간은 ${hours}시간 ${minutes}분 입니다.`; + } + }; + + return ( +
+
+
+ TODAY {nowDate} +
+
+ {nowTime} +
+
+ 출근 |{" "} + 퇴근 +
+ {startWorkTime &&
출근! {startWorkTime}
} + {finishWorkTime &&
퇴근! {finishWorkTime}
} + {startWorkTime && finishWorkTime &&
{calcWorkTime()}
} +
+ ); +}; + +export default TimerApp; diff --git a/src/pages/Timer.tsx b/src/pages/Timer.tsx index 9941ca8d..aa6bace5 100644 --- a/src/pages/Timer.tsx +++ b/src/pages/Timer.tsx @@ -1,7 +1,37 @@ import React from "react"; +import { styled } from "styled-components"; +import TimerApp from "../components/Timer/TimerApp"; + +const TimerBorder = styled.div` + width: 100vw; + height: 100vh; + border: 2px solid #3956a3; + border-radius: 40px; + padding: 20px; + box-sizing: border-box; + white-space: pre-line; + display: flex; + justify-content: flex-end; +`; + +const TextAlign = styled.div` + text-align: right; +`; const Timer = () => { - return
Timer
; + return ( + + +
+
+
+ 환영합니다. OOO 님! + +
+
+
+
+ ); }; export default Timer; From d5932988fd5a324e20f7d443fa9f0555b210b31d Mon Sep 17 00:00:00 2001 From: mysdpy30s Date: Tue, 12 Sep 2023 19:05:45 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Update:=20Timer=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Timer/TimerApp.tsx | 144 ++++++++++++++++++++++++++---- src/pages/Timer.tsx | 1 + 2 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/components/Timer/TimerApp.tsx b/src/components/Timer/TimerApp.tsx index 1ca61bbe..8a2cc4c8 100644 --- a/src/components/Timer/TimerApp.tsx +++ b/src/components/Timer/TimerApp.tsx @@ -1,6 +1,12 @@ import React from "react"; import { useState, useEffect } from "react"; import { styled } from "styled-components"; +import { Button, Alert } from "antd"; +import { + ClockCircleOutlined, + CheckOutlined, + PoweroffOutlined, +} from "@ant-design/icons"; // 타이머 스타일링 interface TimerProps { @@ -10,14 +16,15 @@ const TimerText = styled.div` font-size: ${(props) => props.fontSize || "1.5rem"}; `; -const TimerBtn = styled.button` - color: white; - background-color: #3956a3; - padding: 15px 30px; - font-size: 1.5rem; - border: none; - border-radius: 5px; - cursor: pointer; +const TimerAlign = styled.div` + style={ + display: "flex", + flexDirection: "column", + justifyContent: "right", + alignItems: "center"}`; + +const GreetingText = styled.div` + font-size: 1.3rem; `; const TimerApp = () => { @@ -33,6 +40,12 @@ const TimerApp = () => { ); // 현재 시간 표시 const [startWorkTime, setStartWorkTime] = useState(null); // 출근 시간 기록 const [finishWorkTime, setFinishWorkTime] = useState(null); // 퇴근 시간 기록 + const [startWorkBtnClicked, setStartWorkBtnClicked] = + useState(false); // 출근 버튼 클릭 가능 상태로 시작 + const [finishWorkBtnClicked, setFinishWorkBtnClicked] = + useState(false); // 퇴근 버튼 클릭 가능 상태로 시작 + const [clickedStartBtnText, setClickedStartBtnText] = useState(""); // 출근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 + const [clickedFinishBtnText, setClickedFinishBtnText] = useState(""); // 퇴근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 const UpdateTime = () => { let nowTime = new Date().toLocaleTimeString(); @@ -55,15 +68,25 @@ const TimerApp = () => { const minutes = startWorkTime.getMinutes().toString().padStart(2, "0"); const seconds = startWorkTime.getSeconds().toString().padStart(2, "0"); setStartWorkTime(`${hours}:${minutes}:${seconds}`); + setStartWorkBtnClicked(true); // 출근 시간 기록 후 버튼 비활성화 + setClickedStartBtnText(nowTime); }; + const recordFinishWork = (e: React.MouseEvent) => { e.preventDefault(); // 현재 시간을 퇴근 시간으로 기록 + + if (!startWorkBtnClicked) { + return alert("출근한 상태일 때만 퇴근 기록이 가능합니다!"); + } + const finishWorkTime = new Date(); const hours = finishWorkTime.getHours().toString().padStart(2, "0"); const minutes = finishWorkTime.getMinutes().toString().padStart(2, "0"); const seconds = finishWorkTime.getSeconds().toString().padStart(2, "0"); setFinishWorkTime(`${hours}:${minutes}:${seconds}`); + setFinishWorkBtnClicked(true); // 퇴근 시간 기록 후 버튼 비활성화 + setClickedFinishBtnText(nowTime); }; const calcWorkTime = () => { @@ -89,19 +112,104 @@ const TimerApp = () => { return (
-
-
- TODAY {nowDate} -
+
- {nowTime} +
+ TODAY {nowDate} +
+
+ + +   + {nowTime} + +
-
- 출근 |{" "} - 퇴근 +
+
+
+ +  |  +
- {startWorkTime &&
출근! {startWorkTime}
} - {finishWorkTime &&
퇴근! {finishWorkTime}
} + {startWorkBtnClicked && !finishWorkBtnClicked && ( + +
좋은 하루 보내세요😊
+
+ )} + {startWorkBtnClicked && finishWorkBtnClicked && ( + +
오늘도 수고하셨습니다!👍
+
+ )} {startWorkTime && finishWorkTime &&
{calcWorkTime()}
} ); diff --git a/src/pages/Timer.tsx b/src/pages/Timer.tsx index aa6bace5..a03bdbdb 100644 --- a/src/pages/Timer.tsx +++ b/src/pages/Timer.tsx @@ -12,6 +12,7 @@ const TimerBorder = styled.div` white-space: pre-line; display: flex; justify-content: flex-end; + font-size: 1rem; `; const TextAlign = styled.div` From e12ccee49dc8617eb21d6e13f0f23652c275adf9 Mon Sep 17 00:00:00 2001 From: mysdpy30s Date: Wed, 13 Sep 2023 12:52:52 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Update:=20Timer=20Modal=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=9D=BC=EB=B6=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Timer/TimerApp.tsx | 19 +++++++------- src/pages/Timer.tsx | 41 ++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/components/Timer/TimerApp.tsx b/src/components/Timer/TimerApp.tsx index 8a2cc4c8..2f89cabf 100644 --- a/src/components/Timer/TimerApp.tsx +++ b/src/components/Timer/TimerApp.tsx @@ -23,8 +23,8 @@ const TimerAlign = styled.div` justifyContent: "right", alignItems: "center"}`; -const GreetingText = styled.div` - font-size: 1.3rem; +const GreetingText = styled.div` + font-size: "1.5rem"; `; const TimerApp = () => { @@ -44,8 +44,9 @@ const TimerApp = () => { useState(false); // 출근 버튼 클릭 가능 상태로 시작 const [finishWorkBtnClicked, setFinishWorkBtnClicked] = useState(false); // 퇴근 버튼 클릭 가능 상태로 시작 - const [clickedStartBtnText, setClickedStartBtnText] = useState(""); // 출근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 - const [clickedFinishBtnText, setClickedFinishBtnText] = useState(""); // 퇴근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 + const [clickedStartBtnText, setClickedStartBtnText] = useState(""); // 출근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 + const [clickedFinishBtnText, setClickedFinishBtnText] = useState(""); // 퇴근 버튼이 클릭됐을 때 해당 시각을 버튼에 표시 + const [userName, setUserName] = useState(""); const UpdateTime = () => { let nowTime = new Date().toLocaleTimeString(); @@ -115,7 +116,7 @@ const TimerApp = () => {
- TODAY {nowDate} + TODAY {nowDate}
@@ -141,7 +142,7 @@ const TimerApp = () => { onClick={recordStartWork} disabled={startWorkBtnClicked} style={{ - width: "120px", + width: "130px", height: "60px", backgroundColor: startWorkBtnClicked ? "gray" : "#3956A3", color: startWorkBtnClicked ? "#5F5F5F" : "white", @@ -160,7 +161,7 @@ const TimerApp = () => { ) : ( <> -  출근 완료! +  출근!
{clickedStartBtnText} @@ -174,7 +175,7 @@ const TimerApp = () => { onClick={recordFinishWork} disabled={finishWorkBtnClicked} style={{ - width: "120px", + width: "130px", height: "60px", backgroundColor: finishWorkBtnClicked ? "gray" : "#728AC9", color: finishWorkBtnClicked ? "#5F5F5F" : "white", @@ -193,7 +194,7 @@ const TimerApp = () => { ) : ( <> -  퇴근 완료! +  퇴근!
{clickedFinishBtnText} diff --git a/src/pages/Timer.tsx b/src/pages/Timer.tsx index a03bdbdb..031ddbca 100644 --- a/src/pages/Timer.tsx +++ b/src/pages/Timer.tsx @@ -1,37 +1,50 @@ -import React from "react"; +import React, { useState } from "react"; import { styled } from "styled-components"; import TimerApp from "../components/Timer/TimerApp"; -const TimerBorder = styled.div` - width: 100vw; - height: 100vh; +const TimerContainer = styled.div` + width: 320px; + height: 260px; border: 2px solid #3956a3; border-radius: 40px; - padding: 20px; + padding: 15px 25px; box-sizing: border-box; white-space: pre-line; display: flex; justify-content: flex-end; font-size: 1rem; + z-index: 999; + position: absolute; + top: 10%; + right: 5%; `; const TextAlign = styled.div` text-align: right; `; +const CloseModalBtn = styled.div` + width: 5px; + height: 5px; + cursor: pointer; + color: #535353; +`; +// const [closeModal, setCloseModal] = useState(false); + const Timer = () => { + // const closeModal = () => { + // setCloseModal(true); + // }; + return ( - + + X -
-
-
- 환영합니다. OOO 님! - -
-
+
+ 환영합니다. OOO 님! +
-
+ ); };