Skip to content

Commit

Permalink
feat : 데이트피커 및 일기쓰기 위젯 구현 (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
kangminguu authored Nov 1, 2024
1 parent ebd8a9d commit 6b740e2
Show file tree
Hide file tree
Showing 11 changed files with 389 additions and 10 deletions.
3 changes: 3 additions & 0 deletions public/calendar_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/widgets/date-picker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DatePicker } from './ui/DatePicker';
4 changes: 4 additions & 0 deletions src/widgets/date-picker/model/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface DatePickerProps {
initialDate?: Date;
onSelectDate: (date: Date) => void;
}
19 changes: 19 additions & 0 deletions src/widgets/date-picker/ui/DatePicker.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { DatePicker } from './DatePicker';

const meta: Meta<typeof DatePicker> = {
title: 'Widgets/UI/DatePicker',
component: DatePicker,
tags: ['autodocs']
};

export default meta;
type Story = StoryObj<typeof DatePicker>;

export const Default: Story = {
args: {
initialDate: new Date(), // 오늘 날짜로 초기화
onSelectDate: (date) => console.log('선택된 날짜:', date)
}
};
104 changes: 104 additions & 0 deletions src/widgets/date-picker/ui/DatePicker.styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import styled from 'styled-components';
import Calendar from 'react-calendar';
import 'react-calendar/dist/Calendar.css';

export const StyledCalendarWrapper = styled.div`
position: relative;
width: 330px;
display: flex;
justify-content: right;
`;

export const StyledButton = styled.button`
display: flex;
justify-content: center;
align-items: center;
width: 120px;
height: 40px;
background-color: #ffffff;
border: 1px solid rgb(0, 0, 0, 0.2);
border-radius: 1000px;
cursor: pointer;
&:hover {
background-color: rgb(0, 0, 0, 0.05);
}
`;

export const StyledImg = styled.img`
height: 22px;
`;

export const StyledCalendar = styled(Calendar)`
position: absolute;
width: 330px;
top: calc(100% + 5px); /* 버튼 아래로 5px 떨어지게 배치 */
left: 0;
z-index: 999;
border: none;
border-radius: 20px;
box-shadow: 4px 2px 10px rgba(0, 0, 0, 0.13);
background-color: #ffffff;
padding: 3% 5%;
font-family: 'Pretendard', sans-serif;
font-size: 14px;
color: #000000;
.react-calendar__navigation button:disabled {
background-color: #ffffff;
}
button:disabled {
color: #000000;
}
/* 요일 밑줄 제거 */
.react-calendar__month-view__weekdays abbr {
text-decoration: none;
font-weight: normal;
}
/* 선택된 날짜 스타일 */
.react-calendar__tile.selected {
background-color: #ff480e;
color: #ffffff;
border-radius: 10px;
}
.react-calendar__tile.react-calendar__month-view__days__day:hover {
background-color: rgb(0, 0, 0, 0.1);
color: #000000;
border-radius: 10px;
}
.react-calendar__tile.react-calendar__month-view__days__day:focus {
background-color: rgb(0, 0, 0, 0.1);
color: #000000;
border-radius: 10px;
}
.react-calendar__navigation__arrow.react-calendar__navigation__prev-button:hover,
.react-calendar__navigation__arrow.react-calendar__navigation__next-button:hover {
background-color: rgb(0, 0, 0, 0.1);
border-radius: 10px;
}
.react-calendar__navigation__arrow.react-calendar__navigation__prev-button:focus,
.react-calendar__navigation__arrow.react-calendar__navigation__next-button:focus {
background-color: rgb(0, 0, 0, 0.1);
border-radius: 10px;
}
/* 오늘 날짜 스타일 */
.react-calendar__tile.today {
border: 1px solid #ff480e;
background: #ffffff;
color: #000000;
border-radius: 10px;
}
/* 선택 불가 날짜 스타일 */
.react-calendar__tile.disabled {
color: rgb(0, 0, 0, 0.2);
background-color: #ffffff;
}
`;
88 changes: 88 additions & 0 deletions src/widgets/date-picker/ui/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React, { useState } from 'react';
import 'react-calendar/dist/Calendar.css'; // 기본 스타일 적용
import {
StyledCalendarWrapper,
StyledCalendar,
StyledButton,
StyledImg
} from './DatePicker.styled'; // 스타일드 컴포넌트 불러오기
import moment from 'moment';
import { DatePickerProps } from '../model/type';

export const DatePicker: React.FC<DatePickerProps> = ({
initialDate,
onSelectDate
}) => {
const [selectedDate, setSelectedDate] = useState<Date | null>(
initialDate || new Date()
);
const [isModalOpen, setIsModalOpen] = useState(false);
const today = new Date();

const handleDateChange = (
date: Date | null | [Date | null, Date | null]
) => {
if (Array.isArray(date)) {
// 날짜 범위인 경우
const [startDate, endDate] = date;
if (startDate) {
setSelectedDate(startDate);
onSelectDate(startDate); // 부모 컴포넌트로 시작 날짜 전달
}
} else if (date) {
// 단일 날짜인 경우
setSelectedDate(date);
onSelectDate(date); // 부모 컴포넌트로 선택된 날짜 전달
}

setIsModalOpen(false); // 날짜 선택 후 모달 닫기
};

const toggleModal = () => {
setIsModalOpen((prev) => !prev);
};

return (
<StyledCalendarWrapper>
<StyledButton onClick={toggleModal}>
<StyledImg src="/calendar_icon.svg" />
</StyledButton>
{isModalOpen && (
<StyledCalendar
value={selectedDate}
onChange={handleDateChange}
locale="ko-KR"
calendarType="gregory"
maxDate={today} // 오늘 이후 날짜 선택 불가
formatDay={(locale, date) => moment(date).format('D')} // 일 제거 숫자만 보이게
formatYear={(locale, date) => moment(date).format('YYYY')} // 네비게이션 눌렀을때 숫자 년도만 보이게
formatMonthYear={(locale, date) =>
moment(date).format('YYYY. MM')
} // 네비게이션에서 2023. 12 이렇게 보이도록 설정
next2Label={null} // +1년 & +10년 이동 버튼 숨기기
prev2Label={null} // -1년 & -10년 이동 버튼 숨기기
minDetail="month" // 10년단위 년도 숨기기
tileClassName={({ date, view }) => {
let classNames = '';
if (view === 'month') {
if (date > today) {
classNames = 'disabled'; // 선택 불가 날짜
}
if (date.toDateString() === today.toDateString()) {
classNames = 'today'; // 오늘 날짜
}
if (
selectedDate &&
date.toDateString() ===
selectedDate.toDateString()
) {
classNames = 'selected'; // 선택된 날짜
}
}
return classNames;
}}
/>
)}
</StyledCalendarWrapper>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export const Container = styled.div`
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
`;
8 changes: 7 additions & 1 deletion src/widgets/write-diary/model/type.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export interface WriteDiaryContainerProps {
onDiarySubmit: () => void;
onDiarySubmit: (data: {
selectedDate: Date;
title: string;
content: string;
isPublic: boolean;
}) => void;
initialDate?: Date;
}
19 changes: 19 additions & 0 deletions src/widgets/write-diary/ui/WriteDiaryContainer.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Meta, StoryObj } from '@storybook/react';
import { WriteDiaryContainer } from './WriteDiaryContainer';

const meta: Meta<typeof WriteDiaryContainer> = {
title: 'Widgets/UI/WriteDiaryContainer',
component: WriteDiaryContainer,
tags: ['autodocs']
};

export default meta;
type Story = StoryObj<typeof WriteDiaryContainer>;

export const Default: Story = {
args: {
// onDiarySubmit: (e) => {
// console.log(e);
// }
}
};
38 changes: 34 additions & 4 deletions src/widgets/write-diary/ui/WriteDiaryContainer.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,40 @@ import styled from 'styled-components';

export const Container = styled.div`
display: flex;
flex-direction: column;
width: 100%;
gap: 20px;
// 임시 스타일
height: 200px;
border-radius: 10px;
background-color: #eeeeee;
// background-color: #eeeeee;
`;

export const SelectDateContainer = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
`;

export const DateContainer = styled.div`
font-size: 24px;
font-weight: bold;
font-family: 'Pretendard', sans-serif;
`;

export const DatePickeContainer = styled.div``;

export const TitleContainer = styled.div``;

export const ContentContainer = styled.div``;

export const VisibilityControlsContainer = styled.div`
width: 100%;
display: flex;
justify-content: right;
`;

export const ButtonContainer = styled.div`
width: 100%;
display: flex;
justify-content: center;
`;
Loading

0 comments on commit 6b740e2

Please sign in to comment.