Skip to content

Commit a448ab1

Browse files
committed
feat: DayPicker 컴포넌트 생성 및 마감일 설정 기능 구현
1 parent f9b5776 commit a448ab1

5 files changed

Lines changed: 731 additions & 20 deletions

File tree

components/plans/DatePicker.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
'use client';
2+
3+
import * as Popover from '@radix-ui/react-popover';
4+
import { format } from 'date-fns';
5+
import { ko } from 'date-fns/locale';
6+
import { CalendarIcon } from 'lucide-react';
7+
import { useState } from 'react';
8+
import { DayPicker } from 'react-day-picker';
9+
import 'react-day-picker/dist/style.css';
10+
11+
interface DatePickerProps {
12+
date: Date | undefined;
13+
setDate: (date: Date | undefined) => void;
14+
}
15+
16+
const DatePicker = ({ date, setDate }: DatePickerProps) => {
17+
const [isOpen, setIsOpen] = useState(false);
18+
19+
const handleSelectDate = (selectedDate: Date | undefined) => {
20+
setDate(selectedDate);
21+
setIsOpen(false); // 날짜 고르면 팝오버 닫기
22+
};
23+
24+
return (
25+
<Popover.Root open={isOpen} onOpenChange={setIsOpen}>
26+
<Popover.Trigger asChild>
27+
<button
28+
className={`bg-background flex items-center gap-1.5 rounded-md border-2 px-2 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-200 ${
29+
date
30+
? 'bg-background border-[#d5dcfb] text-gray-900 hover:bg-gray-50'
31+
: 'bg-surface border-gray-200 text-gray-400 hover:text-gray-600'
32+
} focus:outline-none`}
33+
>
34+
<CalendarIcon size={16} />
35+
{date ? format(date, 'yyyy-MM-dd') : <span>마감일 선택</span>}
36+
</button>
37+
</Popover.Trigger>
38+
39+
<Popover.Portal>
40+
<Popover.Content
41+
className="animate-in fade-in zoom-in-95 z-50 rounded-xl border border-gray-100 bg-white p-2 shadow-xl duration-200"
42+
align="start" // 버튼의 왼쪽 라인에 맞춰서 열림
43+
sideOffset={5} // 버튼과 5px 간격
44+
>
45+
<DayPicker
46+
mode="single" // 날짜 하나만 선택
47+
selected={date} // 현재 선택된 날짜 표시
48+
onSelect={handleSelectDate} // 선택 핸들러
49+
locale={ko} // 한국어 달력 (월, 요일)
50+
// 커스텀 스타일 (Tailwind 색상 적용)
51+
modifiersClassNames={{
52+
selected:
53+
'bg-purple-600 text-white hover:bg-purple-500 rounded-full', // 선택된 날짜 색상
54+
today: 'text-purple-600 font-bold', // 오늘 날짜 색상
55+
}}
56+
// DayPicker 기본 스타일 오버라이드 (선택사항)
57+
styles={{
58+
head_cell: { width: '40px', color: '#9ca3af' },
59+
cell: { width: '40px' },
60+
day: { margin: 'auto', borderRadius: '50%' },
61+
}}
62+
/>
63+
</Popover.Content>
64+
</Popover.Portal>
65+
</Popover.Root>
66+
);
67+
};
68+
69+
export default DatePicker;

components/plans/InlineAddTaskForm.tsx

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useState } from 'react';
44
import { Calendar, Plus, X } from 'lucide-react';
5+
import DatePicker from './DatePicker';
56

67
interface InlineAddTaskFormProps {
78
onSave: (text: string, date?: Date) => Promise<void>; // 저장 핸들러
@@ -15,8 +16,7 @@ export default function InlineAddTaskForm({
1516
const [text, setText] = useState('');
1617
const [isSubmitting, setIsSubmitting] = useState(false);
1718

18-
// 날짜 라이브러리를 붙일 예정이므로 지금은 임시 상태
19-
const [selectedDate, setSelectedDate] = useState<Date | undefined>(undefined);
19+
const [deadline, setDeadline] = useState<Date | undefined>();
2020

2121
const handleSubmit = async (e?: React.FormEvent) => {
2222
e?.preventDefault();
@@ -25,7 +25,7 @@ export default function InlineAddTaskForm({
2525
setIsSubmitting(true);
2626

2727
try {
28-
await onSave(text, selectedDate);
28+
await onSave(text, deadline);
2929
setText(''); // 저장 후 초기화
3030
onCancel(); // 저장 후 닫기
3131
} catch (error) {
@@ -45,7 +45,7 @@ export default function InlineAddTaskForm({
4545
};
4646

4747
return (
48-
<div className="border-border-focus-blue mb-2 flex items-center gap-3 rounded-xl border-2 bg-white p-2 pl-4 shadow-sm">
48+
<div className="mt-2 mb-2 flex items-center gap-3 rounded-xl border-2 border-[#D5DCFB] bg-white p-2 pl-4 shadow-sm">
4949
{/* 1. 체크박스 자리 (비활성 모양) */}
5050
<div className="flex h-6 w-6 shrink-0 items-center justify-center rounded-md border border-gray-200 bg-gray-50">
5151
<Plus size={14} className="text-gray-400" />
@@ -66,14 +66,7 @@ export default function InlineAddTaskForm({
6666

6767
{/* 3. 마감일 버튼 (요청하신 부분) */}
6868
<div className="flex items-center">
69-
<button
70-
type="button"
71-
className="flex items-center gap-1.5 rounded-md bg-gray-100 px-2 py-1 text-xs text-gray-600 transition-colors hover:bg-gray-200"
72-
onClick={() => alert('나중에 달력 라이브러리 연결될 곳!')}
73-
>
74-
<Calendar size={12} />
75-
{selectedDate ? selectedDate.toLocaleDateString() : '마감일 설정'}
76-
</button>
69+
<DatePicker date={deadline} setDate={setDeadline} />
7770
</div>
7871
</div>
7972

components/plans/PlanSection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ export default function PlanSection({
215215
) : (
216216
<button
217217
onClick={() => setIsAddingTask(true)}
218-
className="mt-2 flex w-full items-center justify-center gap-1 rounded-xl border-2 border-dashed border-[#556BD6]/30 py-3 text-sm font-medium text-[#556BD6] transition-colors hover:bg-[#556BD6]/5"
218+
className="mt-2 flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-[#556BD6]/30 py-3 text-sm font-medium text-[#556BD6] transition-colors hover:bg-[#556BD6]/5"
219219
>
220220
<Plus size={16} /> 새 하위항목 추가
221221
</button>

0 commit comments

Comments
 (0)