1. 달력을 만들기 위해서 moment 패키지를 사용했다.
yarn add moment
or
npm install moment --save
2. 버튼을 누르면 해당 년도와 월이 나올 수 있도록 코드 구현
// Diary.js
import React from "react";
import moment from "moment";
const Diary = () => {
const [getMoment, setMoment] = React.useState(moment());
const [monthDay, setMonthDay] = React.useState(0);
const today = getMoment; // today === moment();
React.useEffect(() => {
const day = new Date(today);
const days = new Date(day.getFullYear(), day.getMonth()+1, 0).getDate();
setMonthDay(days);
console.log(day.getFullYear())
console.log(day.getMonth()+1);
console.log(days)
}, [today]);
return (
<>
<div className="App">
<div className="control">
<button
onClick={() => {
setMoment(getMoment.clone().subtract(1, "month"));
}}
>
이전달
</button>
<span>{today.format("YYYY 년 MM 월")}</span>
{/* YYYY는 년도 MM 은 달입니다. */}
<button
onClick={() => {
setMoment(getMoment.clone().add(1, "month"));
}}
>
다음달
</button>
</div>
<table>
<tbody>{monthDay}</tbody>
</table>
</div>
</>
);
};
export default Diary;
https://yeolceo.tistory.com/69
쉽게 배우는 React 로 달력 만들기 with Moment.js -YEOL
이번엔 react를 사용한 달력 알고리즘을 만드려고 합니다. 완성형이 예쁘다기보단 구조를 보여드리기 위함을 참고해주세요!! -Moment.js 란 javaScript에서 날짜 데이터 조작을 하기 쉽게 도와주는 라
yeolceo.tistory.com
3. 해당 월의 일자를 구하는 기능 구현 중 0월이 나옴 → getMonth()+1 해줌.
JavaScript | 해당 월의 일수 계산하기
해당 월이 몇일인지 javascript 로 알아보기 프로젝트에서 React + Typescript 사용했기 때문에 코드에서 Typescript가 적용되어 있다. 00. useState 사용 monthDay 에 계산한 값을 넣어주기 (useState 사용해서..
sooya14.tistory.com
https://myhappyman.tistory.com/155
Javascript - 입력한 년, 월의 마지막 날짜 구하기
new Date객체의 getDate()메소드를 통해 마지막 일자를 구할 수 있다. var date = new Date(년, 월, 0); date.getDate(); //마지막 날짜 //사용예 new Date(2020, 1, 0).getDate(); //31 new Date(2020, 2, 0).get..
myhappyman.tistory.com
4. 팀장님과 논의 해본 결과 이번달에는 오늘 날짜까지만 아이콘을 띄우고, 저번달까지의 기록은 해당 월의 일수만큼 아이콘을 띄우고, 다음달 기록은 띄우지 않아야 해서 if문을 많이 사용해서... 코드를 구현했다. 복잡하긴 하지만 최대한 이해하기 쉽도록 코드를 구현했다. (아닐지도...)
const [getMoment, setMoment] = React.useState(moment());
const [monthDay, setMonthDay] = React.useState(0);
const month = getMoment; // month === moment();
const arr = new Array(monthDay).fill(""); // 한꺼번에 배열 채우기
React.useEffect(() => {
const today = new Date(moment()); // 오늘 날짜
const day = new Date(month); // 사용자가 선택한 날짜
if (
today.getFullYear() + today.getMonth() ===
day.getFullYear() + day.getMonth()
) {
// 오늘
const days = new Date(today).getDate();
setMonthDay(days);
} else if (today.getFullYear() < day.getFullYear()) {
// 다음년도
setMonthDay(0);
} else if (today.getFullYear() > day.getFullYear()) {
// 전년도
const days = new Date(day.getFullYear(), day.getMonth() + 1, 0).getDate(); // 사용한 선택한 날짜의 일수
setMonthDay(days);
} else {
// 이번년도
if (day.getMonth > today.getMonth()) {
// 다음달
setMonthDay(0);
} else {
// 저번달
const days = new Date(
day.getFullYear(),
day.getMonth() + 1,
0
).getDate(); // 사용한 선택한 날짜의 일수
setMonthDay(days);
}
}
}, [month]);
https://april.gitbook.io/learning-js/chapter-8./8.2/8.2.6
8.2.6 특정 값으로 배열 채우기 - Learning JS
const arr = new Array(5).fill(1); // [1, 1, 1, 1, 1] arr.fill("a"); // ["a", "a", "a", "a", "a"] arr.fill("b", 1); // ["a", "b", "b", "b", "b"] arr.fill("c", 2, 4); // ["a", "b", "c", "c", "b"] arr.fill(5.5, -4); // ["a", 5.5, 5.5, 5.5, 5.5] arr.fill(0, -3
april.gitbook.io
https://developer.mozilla.org/ko/docs/Web/CSS/flex-wrap
flex-wrap - CSS: Cascading Style Sheets | MDN
CSS flex-wrap property는 flex-item 요소들이 강제로 한줄에 배치되게 할 것인지, 또는 가능한 영역 내에서 벗어나지 않고 여러행으로 나누어 표현 할 것인지 결정하는 속성입니다. 만약 영역 내에서 벗
developer.mozilla.org
5. 서버에서 다이어리 관련 데이터를 받아 온다는 가정 하에 사용자가 평점을 남기지 않았을 경우 default 값을 띄워 주도록 처리 해야 함.
1) 서버에서 데이터를 가져 왔다는 가정 하에 일자에 맞춰 arr 배열에 데이터를 넣어줬다.
// index => 0, diaryList => day랑 서로 일치를 해야 함.
// 1) 해당 월의 일수 길이만큼의 배열에 배열 연산자 forEach를 돌린다.
// 2) 서버에서 가져온 diaryList 배열의 길이만큼 forEach를 돌린다.
// ※ 이중 반복문을 돌리는 것과 같다.
// 3) diaryIndex에 있는 객체 데이터를 arr의 index에 넣는다. (이때, index는 0부터 시작하기 때문에 +1을 해줘서 일(day)와 맞춘다.)
arr.forEach((arrItem, arrIndex) => {
diaryList.forEach((diaryItem, diaryIndex) => {
if (arrIndex + 1 === parseInt(diaryList[diaryIndex]?.day)) {
arr[arrIndex] = diaryList[diaryIndex];
}
});
});
2) 일(day) index 안에 데이터가 ""일 경우 default 이미지를 띄운다.
: 이 부분에서 시행착오가 많았다. map을 돌렸을 때 arr의 요소들이 undefined가 떴었다. 이유는 밝히기 못했지만.. arr를useState()에 넣었더니 해결 되었다.
import React from "react";
import moment from "moment";
import { useSelector } from "react-redux";
import { history } from "../redux/configureStore";
import Charater from "../elements/Charater";
const Diary = () => {
const [getMoment, setMoment] = React.useState(moment());
const [monthDay, setMonthDay] = React.useState(0);
const arr = new Array(monthDay).fill(1); // 한꺼번에 배열 채우기
const diaryList = useSelector((state) => state.diary.diaryList);
const [test, setTest] = React.useState(arr);
React.useEffect(() => {
const today = new Date(moment()); // 오늘 날짜
const day = new Date(getMoment); // 사용자가 선택한 날짜
if (
today.getFullYear() + "_" + today.getMonth() ===
day.getFullYear() + "_" + day.getMonth()
) {
// 오늘
const days = new Date(today).getDate();
setMonthDay(days);
} else if (today.getFullYear() < day.getFullYear()) {
// 다음년도
setMonthDay(0);
} else if (today.getFullYear() > day.getFullYear()) {
// 전년도
const days = new Date(day.getFullYear(), day.getMonth(), 0).getDate(); // 사용한 선택한 날짜의 일수
setMonthDay(days);
} else {
// 이번년도
if (day.getMonth > today.getMonth()) {
// 다음달
setMonthDay(0);
} else {
// 저번달
const days = new Date(day.getFullYear(), day.getMonth(), 0).getDate(); // 사용한 선택한 날짜의 일수
setMonthDay(days);
}
}
// index => 0, diaryList => day랑 서로 일치를 해야 함.
// 1) 해당 월의 일수 길이만큼의 배열에 배열 연산자 forEach를 돌린다.
// 2) 서버에서 가져온 diaryList 배열의 길이만큼 forEach를 돌린다.
// ※ 이중 반복문을 돌리는 것과 같다.
// 3) diaryIndex에 있는 객체 데이터를 arr의 index에 넣는다. (이때, index는 0부터 시작하기 때문에 +1을 해줘서 일(day)와 맞춘다.)
arr.forEach((arrItem, arrIndex) => {
diaryList.forEach((diaryItem, diaryIndex) => {
if (arrIndex + 1 === parseInt(diaryList[diaryIndex].day)) {
arr[arrIndex] = diaryList[diaryIndex];
}
});
});
setTest(arr);
}, [getMoment, monthDay]);
const diaryDetail = (index) => {
const day = new Date(getMoment);
console.log(day.getMonth() + 1 + "월", index + "일");
};
return (
<>
<div>
<div>
<button
onClick={() => {
setMoment(getMoment.clone().subtract(1, "month"));
}}
>
이전달
</button>
<span>{getMoment.format("YYYY 년 MM 월")}</span>
{/* YYYY는 년도 MM 은 달입니다. */}
<button
onClick={() => {
setMoment(getMoment.clone().add(1, "month"));
}}
>
다음달
</button>
</div>
<p>{monthDay}</p>
<div
style={{
backgroundColor: "#dddddd",
width: "50%",
height: "80vh",
margin: "auto",
display: "flex",
flexWrap: "wrap",
padding: "10px",
}}
>
{test.map((item, index) => {
return (
<div key={index + 1 + "days"}>
{item.feelScore && item.sleepScore ? (
<Charater
shape="charater"
size="70"
feelNumber={item.feelScore}
sleepNumber={item.sleepScore}
_onClick={() => {
diaryDetail(index + 1);
}}
margin="10px"
/>
) : (
<Charater
shape="charater"
size="70"
feelNumber={0}
sleepNumber={0}
_onClick={() => {
diaryDetail(index + 1);
}}
margin="10px"
/>
)}
<div>{index + 1}</div>
</div>
);
})}
</div>
</div>
<button
onClick={() => {
history.push(`/diaryWrite/4`);
}}
>
다이어리 생성,수정
</button>
</>
);
};
export default Diary;
import zIndex from "@mui/material/styles/zIndex";
import { style } from "@mui/system";
import React from "react";
import styled from "styled-components";
const Charater = (props) => {
const { shape, size, src, _onClick, margin } = props;
const styles = {
size: size,
margin: margin
};
if (shape === "circle") {
return <ImageCircle {...styles}></ImageCircle>;
}
if (shape === "charater") {
return (
<React.Fragment>
<IconBox {...styles}>
<ImgIcon
{...styles}
style={{ zIndex: "3" }}
src={require(`../images/character/feel${props.feelNumber}.png`)}
onClick={_onClick}
/>
<ImgIcon
{...styles}
style={{ zIndex: "2" }}
src={require(`../images/character/sleep${props.sleepNumber}.png`)}
onClick={_onClick}
/>
</IconBox>
</React.Fragment>
);
}
return <React.Fragment></React.Fragment>;
};
//-- defaultProps --
Charater.defaultProps = {
shape: "circle",
src: "../images/character/sleep0.png",
size: 24,
onClick: () => {},
};
const ImageCircle = styled.div`
--size: ${(props) => props.size}px;
width: var(--size);
height: var(--size);
border-radius: var(--size);
background-image: url("${(props) => props.src}");
background-size: cover;
`;
const IconBox = styled.div`
--size: ${(props) => props.size}px;
width: var(--size);
height: var(--size);
position: "relative";
border-radius: var(--size);
background-color: aliceblue;
display: flex;
align-items: center;
justify-content: center;
${props => props.margin ? `margin : ${props.margin}` : `margin: 0 auto;`}
`;
const ImgIcon = styled.img`
--size: ${(props) => props.size}px;
width: var(--size);
position: absolute;
`;
export default Charater;
'항해 중 > 8-13주차 실전 프로젝트' 카테고리의 다른 글
[실전 프로젝트] ASMR 페이지 구현 (0) | 2021.12.30 |
---|---|
[실전 프로젝트] 다이어리 페이지 마무리, 네비게이션 바 만들기 (0) | 2021.12.29 |
[실전 프로젝트] 녹음, 녹음 파일 재생 + 보이스 페이지..? (0) | 2021.12.28 |
[실전 프로젝트] 푸쉬 알람 여부 (0) | 2021.12.27 |
[실전 프로젝트] API 설계, 기능 자료 조사, 프로젝트 기본 틀 잡기 (0) | 2021.12.24 |
댓글