-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat continue calendar * feat : 달력 컴포넌트 1차 개발 완료 * feat : 달력 컴포넌트 1차 개발 완료 * feat : 달력 컴포넌트 1차 개발 완료
- Loading branch information
Showing
13 changed files
with
419 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
src/features/calendar/calendar-logic/calendarDataFetch.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export const calendarDataFetch = async (activeMonth: string) => { | ||
const userEmail = '[email protected]'; | ||
const split = activeMonth.split('-'); | ||
try { | ||
const response = await fetch( | ||
`https://td3axvf8x7.execute-api.ap-northeast-2.amazonaws.com/moodi/diary?limit=40&user_email=${userEmail}&year=${split[0]}&month=${split[1]}` | ||
); | ||
if (!response.ok) { | ||
throw new Error('데이터를 가져오는데 실패했습니다.'); | ||
} | ||
const data = await response.json(); | ||
return data; | ||
} catch (error) { | ||
console.error(error); | ||
return null; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import moment from 'moment'; | ||
|
||
export const handleTileClick = ( | ||
date: Date, | ||
event: React.MouseEvent<HTMLButtonElement> | ||
) => { | ||
const target = event.currentTarget.querySelector( | ||
'.custom-tile-content' | ||
) as HTMLElement; | ||
const id = target?.getAttribute('data-id'); | ||
const dateString = moment(date).format('YYYY-MM-DD'); | ||
|
||
if (id) { | ||
alert(`${id}로 이동`); | ||
} else { | ||
alert(`${dateString}의 작성 페이지로 이동.`); | ||
} | ||
}; | ||
|
||
export const getActiveMonth = ( | ||
activeStartDate: moment.MomentInput, | ||
setActiveMonth: React.Dispatch<React.SetStateAction<string>> | ||
) => { | ||
const newActiveMonth = moment(activeStartDate).format('YYYY-MM'); | ||
setActiveMonth(newActiveMonth); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { StyledCalendar, DateInnerContent } from './calendarUiCss'; | ||
import { useState, useEffect } from 'react'; | ||
import moment from 'moment'; | ||
import { calendarDataFetch } from '../calendar-logic/calendarDataFetch'; | ||
import { | ||
getActiveMonth, | ||
handleTileClick | ||
} from '../calendar-logic/calendarLogic'; | ||
import { getEmoticonPath } from '../get-emotion-path/getEmotionPath'; | ||
|
||
const CalendarUi: React.FC = () => { | ||
const curDate = new Date(); | ||
const [vlu, onChange] = useState(curDate); | ||
const monthOfActiveDate = moment(vlu).format('YYYY-MM'); | ||
const [activeMonth, setActiveMonth] = useState(monthOfActiveDate); | ||
const [fetchedData, setFetchedData] = useState< | ||
{ id: number; created_date: string; emotion: string | null }[] | ||
>([]); | ||
const weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; | ||
|
||
// fetchedData에 데이터를 저장 | ||
const loadDates = async () => { | ||
const data = await calendarDataFetch(activeMonth); | ||
if (data) { | ||
const dates = data.map( | ||
(entry: { | ||
id: number; | ||
created_date: string; | ||
emotion: string | null; | ||
}) => ({ | ||
id: entry.id, | ||
created_date: moment(entry.created_date).format( | ||
'YYYY-MM-DD' | ||
), | ||
emotion: entry.emotion | ||
}) | ||
); | ||
setFetchedData(dates); | ||
} | ||
}; | ||
|
||
// 일기 여부에 따라 class주어주기 | ||
const getTileClassName = (dateparam: Date): string => { | ||
const dateString = moment(dateparam).format('YYYY-MM-DD'); | ||
const isCheckedDate = fetchedData.some( | ||
(entry) => entry.created_date === dateString | ||
); | ||
|
||
return isCheckedDate ? 'diary-date' : 'nodiary-date'; | ||
}; | ||
|
||
// fetchedData에서 아이템마다 id와 emotion 데이터 넣기 | ||
const getTileContent = ({ date }: { date: Date }) => { | ||
const dateString = moment(date).format('YYYY-MM-DD'); | ||
const matchedEntry = fetchedData.find( | ||
(entry) => entry.created_date === dateString | ||
); | ||
|
||
if (matchedEntry && matchedEntry.emotion) { | ||
return ( | ||
<DateInnerContent | ||
data-id={matchedEntry.id} | ||
data-date={matchedEntry.created_date} | ||
emotion={getEmoticonPath(matchedEntry.emotion)} | ||
className="custom-tile-content" | ||
/> | ||
); | ||
} | ||
return null; // 해당 날짜와 일치하는 데이터가 없으면 null 반환 | ||
}; | ||
|
||
useEffect(() => { | ||
loadDates(); | ||
}, [activeMonth]); | ||
|
||
return ( | ||
<StyledCalendar | ||
onActiveStartDateChange={({ activeStartDate }) => | ||
getActiveMonth(activeStartDate, setActiveMonth) | ||
} | ||
formatDay={(locale, d) => d.getDate().toString()} | ||
formatShortWeekday={(locale, d) => weekDays[d.getDay()]} | ||
tileClassName={({ date }) => getTileClassName(date)} | ||
onClickDay={(date, event) => handleTileClick(date, event)} | ||
tileContent={getTileContent} | ||
/> | ||
); | ||
}; | ||
|
||
export default CalendarUi; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
import Calendar, { CalendarType } from 'react-calendar'; | ||
import styled from 'styled-components'; | ||
|
||
export const StyledCalendar = styled(Calendar).attrs({ | ||
calendarType: 'gregory' as CalendarType | ||
})` | ||
width: 100%; | ||
max-width: 960px; | ||
background-color: rgba(255, 255, 255, 1); | ||
border: none; | ||
font-family: 'Pretendard', sans-serif; | ||
//년월컨테이너 | ||
.react-calendar__navigation { | ||
display: flex; | ||
padding: 2rem 0; | ||
//년월선택ui | ||
button { | ||
border: none; | ||
border-radius: 10px; | ||
background-color: white; | ||
outline: none; | ||
font-size: 1.5rem; | ||
font-family: 'Pretendard', sans-serif; | ||
&:hover { | ||
background-color: rgba(0, 0, 0, 0.05); | ||
cursor: pointer; | ||
} | ||
} | ||
//년월텍스트 | ||
.react-calendar__navigation__label { | ||
font-size: 1rem; | ||
border: 1px solid rgba(0, 0, 0, 0.1); | ||
margin: 0 1rem; | ||
} | ||
} | ||
//날짜/년월/10년 아이템 | ||
.react-calendar__tile { | ||
max-width: initial !important; | ||
padding: 15px; | ||
height: 100px; | ||
background-color: white; | ||
border-radius: 28px; | ||
border: 1px solid rgba(0, 0, 0, 0.2); | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: space-between; | ||
&:hover { | ||
background-color: rgba(0, 0, 0, 0.05); | ||
cursor: pointer; | ||
} | ||
} | ||
//10년박스 | ||
.react-calendar__century-view__decades { | ||
display: grid !important; | ||
grid-template-columns: repeat(4, 1fr); | ||
column-gap: 0.5rem; | ||
row-gap: 1rem; | ||
} | ||
//년박스 | ||
.react-calendar__decade-view__years { | ||
display: grid !important; | ||
grid-template-columns: repeat(4, 1fr); | ||
column-gap: 0.5rem; | ||
row-gap: 1rem; | ||
} | ||
//월박스 | ||
.react-calendar__year-view__months { | ||
display: grid !important; | ||
grid-template-columns: repeat(4, 1fr); | ||
column-gap: 0.5rem; | ||
row-gap: 1rem; | ||
} | ||
//날짜박스 | ||
.react-calendar__month-view__days { | ||
display: grid !important; | ||
grid-template-columns: repeat(7, 1fr); | ||
column-gap: 0.5rem; | ||
row-gap: 1rem; | ||
// 체크된 날짜 스타일 | ||
.diary-date { | ||
border: 1px solid rgba(0, 0, 0, 0.25); | ||
} | ||
// 체크되지 않은 날짜 스타일 | ||
.nodiary-date { | ||
border: 1px solid rgba(0, 0, 0, 0.08); | ||
position: relative; | ||
&:hover { | ||
background-color: rgba(0, 0, 0, 0.1); | ||
cursor: pointer; | ||
} | ||
&:hover::after { | ||
content: ''; | ||
display: block; | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
transform: translate(-40%, -40%); | ||
width: 20px; | ||
height: 20px; | ||
background-size: contain; | ||
background-repeat: no-repeat; | ||
background-image: url('calendar_plus.svg'); | ||
} | ||
} | ||
// 현재날짜 | ||
.react-calendar__tile--now { | ||
background-color: #ffeee9; | ||
border: 1px solid #ff480e; | ||
color: black; | ||
} | ||
// 앞뒤월의 날 | ||
.react-calendar__month-view__days__day--neighboringMonth { | ||
visibility: hidden !important; | ||
pointer-events: none !important; | ||
} | ||
} | ||
//요일박스 | ||
.react-calendar__month-view__weekdays { | ||
padding: 1rem 0; | ||
//요일아이템 | ||
.react-calendar__month-view__weekdays__weekday { | ||
text-align: center; | ||
abbr { | ||
font-size: 14px; | ||
text-decoration: none; | ||
} | ||
} | ||
} | ||
`; | ||
|
||
interface DateInnerContentProps { | ||
emotion: string | null; | ||
} | ||
|
||
export const DateInnerContent = styled.div<DateInnerContentProps>` | ||
background-image: url(${(props) => props.emotion}); | ||
width: 40px; | ||
height: 40px; | ||
background-size: contain; | ||
background-repeat: no-repeat; | ||
align-self: flex-end; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
export const getEmoticonPath = (emotion: string) => { | ||
const emotionMap: Record<string, string> = { | ||
기뻐요: 'emoji_happy', | ||
'자신 있어요': 'emoji_confident', | ||
감사해요: 'emoji_grateful', | ||
편안해요: 'emoji_comfortable', | ||
신이나요: 'emoji_excited', | ||
즐거워요: 'emoji_fun', | ||
만족스러워요: 'emoji_satisfied', | ||
사랑스러워요: 'emoji_lovely', | ||
모르겠어요: 'emoji_not_sure', | ||
부끄러워요: 'emoji_embarrassed', | ||
놀라워요: 'emoji_surprised', | ||
'아무생각이 없어요': 'emoji_blank', | ||
슬퍼요: 'emoji_sad', | ||
우울해요: 'emoji_depressed', | ||
실망스러워요: 'emoji_disappointed', | ||
후회돼요: 'emoji_regret', | ||
짜증나요: 'emoji_annoyed', | ||
화나요: 'emoji_angry', | ||
외로워요: 'emoji_lonley', | ||
충격받았어요: 'emoji_shocked', | ||
곤란해요: 'emoji_awkward' | ||
}; | ||
|
||
const svgName = emotionMap[emotion]; | ||
if (!svgName) { | ||
return null; // 매칭되는 감정이 없을 경우 | ||
} | ||
|
||
return `emoji/${svgName}.svg`; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import CalendarUi from './calendar-ui/CalendarUi'; | ||
import { CalendarWrapper } from './indexCss'; | ||
|
||
const Calendar = () => { | ||
return ( | ||
<CalendarWrapper> | ||
<CalendarUi /> | ||
</CalendarWrapper> | ||
); | ||
}; | ||
|
||
export default Calendar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const CalendarWrapper = styled.div` | ||
display: flex; | ||
justify-content: center; | ||
`; |
Oops, something went wrong.