상담 · 고객 — feature/consultation/console
콘솔의 상담 파이프라인(C-03) · 고객 목록 · 고객 상세(C-04) 번들이다. 패키지 이름은 console_consultation.
| 화면 | 주소 | 뷰(값 · 동작을 받는다) | 페이지(라우트가 연다) |
|---|---|---|---|
| C-03 상담 파이프라인 | /consultation?tab=kanban|inbox|waitlist |
ConsultPipelineView |
ConsultPipelinePage |
| 고객 목록 | /customer |
CustomerListView |
CustomerListPage |
| C-04 고객 상세 | /customer/:id |
CustomerDetailView |
CustomerDetailPage |
지금 단계(1단계): 뷰 · 도메인 규칙 · 시험은 시험 표본(물결점 · 2026-01-15 09:00 서울 — Figma C-03/C-04 숫자를
그대로 재현)으로 끝났다. 페이지는 틀(ConsolePageFrame) + S-01 이고, 세계 연결은 2단계다 — 페이지가
PostpartumWorld · PostpartumSession 을 서비스 로케이터에서 받아 뷰 값으로 바꾸고, 뷰의 동작 콜백을 세계
트랜잭션으로 잇는다(아래 「세계 연결 자리」).
화면 · FR ↔ 구현 ↔ 시험
| FR | 내용 | 구현 | 시험 |
|---|---|---|---|
| FR-10 상담 등록 | 필수(이름 · 연락처 끝 4자리 · 예정일 · 상담일 · 상담자)가 비면 저장 못 함, 저장하면 1차 카드 | ConsultDraft(problems) · NewConsultSheet |
consult_draft_test · 뷰 「필수가 비면 저장하지 않고 칸마다 이유」 · 「필수를 채우면 저장하고 닫는다」 |
| FR-11 파이프라인 | 칸반 1차 · 2차 · 3차 · 예약 · 보류(+접수함 열), 옮기면 일시 · 담당자 · 방식 · 메모 이력, 필터(예정월 · 상담자 · 유입경로) | PipelineBoard · ConsultStageFlow(상태 머신) · PipelineFilter · ConsultCardSheet · PipelineKanban · PipelineFilterBar |
pipeline_board_test · consult_stage_flow_test · 뷰 「2차로 옮기면 … 이력 한 줄」 · 「상태 머신 밖의 단계는 고를 수 없다」 · 필터 2건 · BDD 「카드를 2차로 옮기면 메모가 이력으로」 |
| FR-12 자가 입력 접수함 | K-02 제출이 접수함에, 같은 전화번호 고객이면 「재방문 산모와 연결」 제안 | IntakeSubmission · IntakeAnswers(payload 키 = K-02 ConsultIntakeForm.payloadKeys) · RevisitMatcher · IntakeReviewCard · IntakeInboxList |
intake_answers_test · revisit_matcher_test · 뷰 「재방문 후보와 연결 · 새 고객으로 연결 · 버리기」 · 「칸반의 접수 카드 → 접수 대화상자」 · 「신청서가 없으면 S-01」 |
| FR-13 고객 상세 · 재방문 | 상담 · 예약 · 입실 · 만족도 이력 시간순, 메모 | CustomerDetail · CustomerTimelineCard · RevisitHistoryCard · CustomerMemoCard |
뷰 「이력은 시간순」 · 「재방문 산모는 지난 입실 · 만족도」 · 「메모를 남기면 …」 |
| FR-14 임신 주수 | 카드 · 목록 · 상세에서 예정일 옆 기준 시각 주수(주+일) | GestationalAge(postpartum_rules) · ConsultCardTile.dueLine |
뷰 「카드에 예정일과 임신 주수」 · C-04 머리 |
| FR-27 만실 대기 | 대기 목록 · 같은 기간 빈 객실이 있는 다른 지점 추천 · 안내 메모 | WaitlistEntry · WaitlistList · WaitlistAddSheet |
뷰 「다른 지점 안내는 메모와 함께」 · 「진행 중 카드에서 만실 대기로」 |
| FR-120 코드 발급 | 4자리 코드 · 10분 만료 | 세계 KioskCodeIssuer(postpartum_world — 이 WP 소유) · IssuedCode · IssueCodeSheet |
postpartum_world/test/src/kiosk_code_issuer_test.dart · 뷰 「4자리를 크게 · 10분 남음」 |
| NFR-08 · 역할(ia.md §5) | 대표 보기 전용(금액 보임), R¹(간호 · 신생아실 · 에스테틱 · 모유) 이름 · 호실 · 입실 기간만 | ConsultAccess · ConsultViewer · MaskedPhone |
consult_access_test · 뷰 역할 2건 · C-04 역할 노출 · 목록 「R¹ 은 전화번호로 찾지 못한다」 |
| R-1 · R-2 · R-4 | 스케일 불변 · 가용 폭 · 터치 하한 | LayoutBuilder 분기 · MinTouchTarget |
testScaleInvariant — C-03 탭 3 × (390×844 · 1180×820), C-04, 목록 × 4조합 · 아랍어 RTL |
숫자(시험 표본): 진행 중 18(1차 7 · 2차 6 · 3차 5) · 전환율 41%(상담 22건 중 9건 예약 — PostpartumFacts 식) ·
접수 2(한예나 · 차하람) · 대기 3(다른 지점 추천 가능 2) · 예약 열 = 이번 주(서울 월~일) 예약 이력의 홍윤슬 · 진새벽.
모의 경계
- 실동작: 단계 이동 규칙(상태 머신) · 필수 검증 · 재방문 판정(전화 끝 4자리가 같고, 출생 연도가 양쪽에 있으면 그것도 같다 — 이름은 언어마다 달라 비교하지 않는다) · KPI 식 · 필터 · 역할별 노출 · 코드 발급(추측하기 쉬운 코드 거름 · 10분 만료 · 활성 코드와 겹치지 않음).
- 모의: 알림톡 · 문자 발송(이력 줄만 —
MessageTrigger), QR 그림(코드만 크게 — 쓸 수 있는 QR 위젯이 없다), 결제 수단 처리(금액 · 내역은postpartum_rules결과를 그대로 보인다). - 1단계에서는 저장이 표본 · 기록기(
PipelineRecorder)로만 간다 — 새로고침하면 사라진다(2단계에서 세계에 쓴다).
세계 연결 자리(2단계)
| 뷰 값 · 동작 | 세계 |
|---|---|
ConsultPipelineData(카드 · 접수 · 대기 · KPI) |
consultations · customers · intakes(submitted) · waitlist · reservations — 지점 session.branchScope, 기준 world.now |
| 표시 이름 | DisplayProjector — PostpartumDisplayKeys.customerName · staffName · hospitalName · branchName · memoText |
| 옮기기 · 등록 · 메모 | world.transact — consultations.stage + 이력 행(일시 · 담당자 session.actor · 방식 · 메모) |
| 코드 발급 | KioskCodeIssuer.nextCode/seedOf/activeCodes → kioskPasses 행(purpose consult · issuedBy) |
| 접수 연결 · 버리기 | intakes.status + 새 고객/기존 고객 연결 · 1차 상담 행 |
| 대기 안내 · 해제 · 등록 | waitlist 행 + 상담 메모 |
| 상태 미리보기 | session.preview → S-01 · S-02 · S-03, 다른 지점 고객 주소 → S-04 |
1단계 사본 코드(lib/src/domain/code/ 의 단계 · 방식 · 태그 · 유입경로 등)는 2단계에서 postpartum_world 의 같은 이름
enum 으로 바꾼다(값 이름은 이미 같다).
Figma 와 다르게 둔 점
| Figma | 구현 | 이유 |
|---|---|---|
| 칸반 위 필터 · KPI 한 줄 | 탭(칸반 · 접수함 · 대기) + 필터 줄을 KPI 위 별도 줄로 | 접수함 · 대기를 탭으로 바로 열기(KPI 를 누르면 그 탭) · 폰 폭에서 줄이 넘치지 않게(R-2) |
| 열 5개 | 보류 열을 더해 가로 스크롤 | FR-11 의 「보류」 단계를 보이게 |
| 칸반 열 「…」 메뉴 | 없음 | 정의된 동작이 없다 |
| 접수 카드 바닥 | 「접수 시각 · 경로(태블릿/QR)」 | 접수함에서 먼저 보는 정보 |
| 날짜 「04/02」 | 로케일 형식(ko 「4. 2.」) | 11개 언어(S-18) |
| 필터 기본값 | 「전체」 | 처음 보는 사람이 카드가 숨었다고 오해하지 않게 |
| 카드 누르면 상세로 | 카드 대화상자(이력 + 옮기기) → 고객 상세 · 예약으로 | 끌어 옮기기 없이도 터치로 옮긴다(R-4) |
| QR 그림 | 4자리 코드를 크게 표시하고 같은 브라우저의 상담 태블릿 입력 안내 | 쓸 수 있는 QR 위젯이 없다(요청) |
| 고객 아바타 | 이름 첫 글자 배지(InitialBadge) |
사진 없는 데모 · 글자 크기가 원 크기를 정한다(R-1) |
| 보호자 관계 「남편」 | 「배우자」 | 세계의 GuardianRelation.spouse 이름과 같게 |
| R¹ 역할의 C-04 | 이름 · 호실 · 입실 기간만 | ia.md §5 · NFR-08 |
번역 · 자산
- 카탈로그
lib/src/i18n/11개 로케일 334키(ko 원문 → 10개). 역할 이름은 셸과 같은PostpartumRoleLabel(postpartum_ui)을 쓴다. - 아랍어에서 가린 연락처(「010-****-4821」)는 숫자 · 기호 묶음이 뒤집히지 않게 코드에서 LTR 고립으로 감싼다
(
MaskedPhone— 카탈로그에는 방향 제어 문자를 넣지 않는다). - 새 아이콘:
LucideIcons.listFilter(필터) — 앱 아이콘 묶음은 공유 생성물이라 커밋하지 않는다.