# DateSheetHost · PlanSheetHost · MissedSheet · CategorySheetHost

Calendar 앱의 시트 네 가지다. 날짜 고르기, Mordy 계획 항목 메뉴, 어제 못한 계획 정리, 카테고리 고르기. 앞의 둘과 마지막은 앱 루트에 한 번 두고 함수 호출로 연다.

- 분류: Calendar 앱
- 가져오기: `import { DateSheetHost, PlanSheetHost, MissedSheet, CategorySheetHost } from '@/cal/sheets'`
- 코드 위치: `apps/calendar/src/cal/sheets.tsx:41` (Mordy 저장소 60df633)
- 웹 페이지: https://developers.moring.co/tds/components/calendar-sheets

## 미리보기

실제 컴포넌트를 그린 화면은 https://developers.moring.co/tds/components/calendar-sheets 에서 볼 수 있다. 서비스 색 선택기로 Mordy, Morit 색을 바꿔 볼 수 있다.

## 언제 쓰는가

### 쓴다
- 이 컴포넌트는 Mordy Calendar 앱(`apps/calendar/src/cal`)에만 있다.
- 날짜 고르기: `await pickDate({ title, value, today })` 또는 여러 날(`pickDates`)을 부른다. 날짜, 날짜 없음(`null`), 닫음(`undefined`)을 돌려준다.
- 계획 항목 메뉴: `openPlan(plan, today)`. "Mordy에서 풀기", "오늘로 옮기기", "다른 날로 옮기기" 등을 보인다.
- 어제 못한 계획: `MissedSheet`. 자동으로 옮기지 않고 항목마다 사용자가 정한다.
- 카테고리 고르기: `await pickCategory(value)`. 새 카테고리도 만들 수 있다.

### 쓰지 않는다
- 사용자 몰래 계획을 옮기지 않는다. 어제 못한 계획은 항상 사용자가 정한다.
- 시트 위에 시트를 겹치지 않는다. 앞 시트가 닫힌 뒤 다음 시트를 연다.

## 종류

| 이름 | 설명 |
| --- | --- |
| DateSheetHost | `Calendar`로 날짜를 고르고 "n일로 정하기" 버튼. 여러 날 시험이면 날짜를 모두 눌러 "n일 선택"(최대 14일). |
| PlanSheetHost | `Sheet`와 행동 목록. Mordy 앱이 없으면 설치 안내를 한다. |
| MissedSheet | 어제 못한 계획 목록과 항목별 선택. |
| CategorySheetHost | 카테고리 목록(없음, 내 카테고리, 시험으로 묶기)과 "새 카테고리"(이름 + `ColorRow` + 만들기). |

## 크기

| 이름 | 값 | 설명 |
| --- | --- | --- |
| 기본 | `Sheet` | 카테고리 목록은 최대 높이 440. |

## 상태

| 상태 | 모습과 동작 |
| --- | --- |
| 키보드 입력 중 | 새 카테고리를 만들 때는 시트가 짧아지도록 양식만 보인다. |

## 사용 방법

### 앱 루트에 두기

```tsx
import { CategorySheetHost, DateSheetHost, PlanSheetHost } from '@/cal/sheets';

<DateSheetHost />
<PlanSheetHost />
<CategorySheetHost />
```

### 날짜 고르기

```tsx
import { pickDate } from '@/cal/sheets';

const date = await pickDate({ title: '마감일', value: item.date, today, allowNone: true });
if (date === undefined) return; // 닫음
save({ date });
```

### 어제 못한 계획

```tsx
<MissedSheet visible={open} items={missedPlan} today={today} onClose={() => setOpen(false)} />
```

### 속성(props)

| 함수 | 형태 | 설명 |
| --- | --- | --- |
| `pickDate` | `—` | 날짜 하나를 고른다. 날짜 문자열, 날짜 없음이면 `null`, 닫으면 `undefined`. |
| `pickDates` | `—` | 여러 날(시험일)을 고른다. 정렬된 날짜 목록, 닫으면 `undefined`. |
| `openPlan` | `—` | Mordy 계획 항목 메뉴를 연다. |
| `pickCategory` | `—` | 카테고리를 고른다. 카테고리 id, 없음이면 `null`, 닫으면 `undefined`. |
| `openInMordy` | `—` | Mordy 앱에서 풀이를 시작한다. 앱이 없으면 스토어를 안내한다. |

#### DateSheetHost

속성이 없다.

#### PlanSheetHost

속성이 없다.

#### MissedSheet

| 이름 | 타입 | 기본값 | 필수 | 설명 |
| --- | --- | --- | --- | --- |
| `visible` | `boolean` | — | 필수 | 열려 있는지. |
| `items` | `PlanItem[]` | — | 필수 | 어제 못한 계획 항목 목록. |
| `today` | `string` | — | 필수 | 오늘 날짜. |
| `onClose` | `() => void` | — | 필수 | 닫을 때 호출된다. |

#### CategorySheetHost

속성이 없다.

`DateSheetHost`, `PlanSheetHost`, `CategorySheetHost`는 속성이 없다. 앱 루트에 한 번씩 두고 위 함수로 연다.

## 치수와 토큰

| 항목 | 값 |
| --- | --- |
| 공통 | 모두 `Sheet`(제목 줄, ✕, 끌어서 닫기) |
| 날짜 버튼 | `PrimaryButton`(화살표 없음). 고르기 전에는 `disabled`와 "날짜를 골라 주세요" |

## 접근성

- `Sheet`의 접근성을 그대로 따른다.
- 카테고리 행은 `radio`이고 선택 상태가 전달된다.

## 잘한 예와 잘못한 예

- 잘한 예: 선택 전에는 버튼에 "날짜를 골라 주세요"처럼 이유를 글자로 쓴다.
- 잘못한 예: 어제 못한 계획을 사용자 몰래 오늘로 옮기지 않는다.

## 함께 보는 컴포넌트

- [Sheet](https://developers.moring.co/tds/components/sheet.md): 화면 아래에서 올라오는 시트다. 위쪽 두 모서리가 둥글고, 손잡이와 제목 줄, 닫기 버튼이 있다.
- [Calendar](https://developers.moring.co/tds/components/date-calendar.md): 한 달 달력에서 여러 날짜를 고르는 컴포넌트다. 시험 날짜를 고를 때 쓴다.
- [ColorRow](https://developers.moring.co/tds/components/color-row.md): 과목 팔레트 8색을 동그란 점으로 늘어놓고 하나를 고르는 컴포넌트다. 카테고리와 캘린더의 색을 정할 때 쓴다.
- [PlanRow](https://developers.moring.co/tds/components/plan-row.md): Mordy가 만든 학습 계획 한 줄이다. 체크 원, 제목, "Mordy" 표지, 푼 문제 진행률(막대)이 있다. 직접 옮긴 계획에는 자물쇠가 붙는다.
