상담신청서(K-02) — feature/consult_intake/app
데스크 태블릿(834 세로) · QR 휴대폰(390)에서 산모가 직접 쓰는 상담신청서다. 패키지 이름은 consult_intake.
| 화면 | 주소 | 뷰 | 페이지 |
|---|---|---|---|
| K-02 상담신청서 | /consult_intake |
ConsultIntakeFormView(값 · 동작을 받는다) |
ConsultIntakeWizardPage(세계에 잇는다) |
여섯 단계: 기본 정보 → 출산 정보 → 희망 조리 → 유입 경로 · 문의 → 보호자 → 확인 · 동의. 틀은 공용
KioskFrame(postpartum_ui — 머리 · 진행 · 바닥 단추)이고, 머리의 「앱 이름 · 지점 · 기기」는 셸의
KioskChromeScope 를 따른다. 셸이 아직 범위를 주지 않으면 페이지가 세계에서 읽어(지점 = DisplayProjector
의 branchName, 기기 = 코드의 deviceId 유무) 씌운다.
세계 계약(docs/demo-world.md §2)
- 세계 · 세션은 서비스 로케이터에서 받는다(
PostpartumWorld·PostpartumSession— binding 의존 없음). 없으면 S-05. - 세션의 코드(
passId)가 없거나, 상담 코드가 아니거나, 제출됐거나, 만료(업무 시계 기준)면/code(K-01)로 보낸다. - 제출 = 한 트랜잭션(
ConsultIntakeSubmission):intakes행intake_NNNN{passId, deviceId?, branchId, submittedAt, status: submitted, payload}+kioskPasses의status: submitted·submittedAt. 코드가 없으면WorldRowMissing, 상담 코드가 아니거나 · 이미 제출됐거나 · 다른 기기가 작성 중이면StateError— 아무것도 쓰지 않는다. - 트랜잭션 뒤
session.endPass()→/done(K-05). 「처음으로」는 확인 뒤 입력을 지우고endPass()→/code. - 떠나는 동안(제출 · 처음으로)에는 코드가 놓여도
/code로 되돌리지 않는다 —/done이동과 겨루지 않게.
payload 키는 콘솔 접수함이 읽는 IntakeAnswers.keys 와 같은 19개다(ConsultIntakeForm.payloadKeys — 시험이
목록을 고정한다). 날짜는 YYYY-MM-DD, 코드 값은 세계 enum 이름(natural · nights13 · momCommunity · spouse …),
빈 칸은 넣지 않는다.
화면 · FR ↔ 구현 ↔ 시험
| FR | 내용 | 구현 | 시험 |
|---|---|---|---|
| FR-121 자가 작성 | 단계를 오가도 입력 유지, 필수 검증 뒤 제출 | ConsultIntakeForm(problemsAt · firstIncompleteStep) · 화면 맨 위 컨트롤러 묶음 |
consult_intake_form_test 11 · 뷰 「단계를 오가도 적은 값이 남고 …」 · 「필수 칸이 비면 넘어가지 않고 이유」 · 「제출을 누르면 막힌 첫 단계로」 |
| FR-12(만드는 쪽) | 제출이 접수함으로 | ConsultIntakeSubmission |
consult_intake_submission_test 2 · 페이지 「제출 — intakes 행 · 코드 submitted … K-05」 · BDD 「여섯 단계를 적고 제출하면 상담실장 접수함으로」 |
| FR-123 제출 뒤 정리 | 세션이 끝나고 뒤로 가도 입력이 다시 보이지 않음 | endPass() + 쓸 수 없는 코드는 /code 로 |
페이지 「코드가 쓸 수 없으면 K-01 로」 4(없음 · 입실 코드 · 제출됨 · 만료) · 「처음으로는 코드를 놓고 K-01」 · BDD 「처음으로 …」 |
| FR-120(쓰는 쪽) | 10분 만료 | PostpartumKioskPass.isExpiredAt(world.now) |
페이지 「만료됐다 — 업무 시계가 만료 시각을 지났다」 |
| DDR-06 동의 | 필수(개인정보)와 선택(알림톡 · 문자) 분리 | 확인 단계 _Consent 2줄 · 「자세히」 |
뷰 「필수 동의 없이는 제출하지 않는다 — 선택 동의는 없어도 된다」 · 「자세히」 |
| NFR-08 최소 수집 | 연락처는 끝 4자리 | 숫자만 · 4자 제한 입력 | 뷰 「끝 4자리 칸은 숫자 네 개까지만」 |
| FR-14 | 예정일 → 오늘 기준 임신 주수 | GestationalAge(postpartum_rules) |
뷰 「오늘 기준 임신 31주 1일」 |
| S-05 | 세계가 없으면 서버 없음 화면 | ServerMissingView |
페이지 「S-05」 |
| R-1 · R-2 · R-4 | 스케일 불변 · 가용 폭 · 터치 하한 | _FieldGrid(640 이상 두 열) · KioskFrame |
testScaleInvariant — 6단계 × (390×844 · 834×1194) × 4조합(키오스크 테마) · 아랍어 RTL |
골든: consult_intake_basic · consult_intake_birth · consult_intake_confirm(ko · en · ar pairwise — CI 러너가 만든다).
BDD: test/src/bdd/consult_intake_wizard.feature 3 시나리오(공용 세계 · 메모리 저장소).
모의 경계
- 실동작: 단계 검증 · 제출 트랜잭션 · 코드 상태 · 세션 정리 · 주수 계산. 같은 탭의 콘솔 접수함이 같은
intakes행을 읽는다. - 모의: 개인정보 수집(문구에 「데모 — 실제로는 모으지 않아요」), QR 로 휴대폰에서 여는 경로(코드의
deviceId가 없으면 「휴대폰」으로 보일 뿐 — QR 그림 · 휴대폰 진입 화면은 셸 몫). - 아직 아님(2단계): 바닥의 「자동 저장됨 · 시각」은 입력이 바뀐 시각이고, 기기 저장소에 쓰지는 않는다 — 탭을
새로 고치면 입력이 사라진다. 뷰의
onChanged로 코드별 임시본을 세계 저장소 이름공간에 쓰고 「처음으로」 · 제출에서 지우는 일이 남았다. - 조립 스캐폴드의 옛 경로(
IConsultIntakeRepository· 모의 저장소 ·ConsultIntakeWizardBloc· 커널DemoWorld시드seedConsultIntakeDemoWorld)는 화면이 더 쓰지 않는다. 시드 등록이 셸 (app/app/lib/src/di/register_demo_world.dart)에 있어 이 WP 에서 걷지 않았다.
Figma 와 다르게 둔 점
| Figma | 구현 | 이유 |
|---|---|---|
| 「제출하기」 · 「제출 중…」 | 공용 틀의 「제출」(제출하는 동안 누를 수 없음) | K-01 ~ K-05 가 같은 바닥 단추를 쓴다(공용 KioskFrame) |
| 진행 줄 문구 | 공용 틀의 「n / 6 · 단계 · 다음 · 다음 단계」 | 같은 이유 |
| QR 그림 | 없음(콘솔이 코드를 크게 보인다) | 쓸 수 있는 QR 위젯이 없다 |
| 날짜 입력 | coui DatePicker — 달력은 업무 시계의 달(2026-01)에서 연다 |
기기 시계(실제 오늘)로 열면 데모 세계와 달이 어긋난다 |
| 보호자 관계 「남편」 | 「배우자」 | 세계의 GuardianRelation.spouse 와 같게 |
번역
- 카탈로그
lib/src/i18n/11개 로케일 114키. 산모가 읽는 말투(존댓말 · 짧게)로 옮겼고, 유입경로 · 관계 · 객실 · 기간 · 분만 형태는 콘솔 카탈로그와 같은 말을 쓴다. - 안내 문구가 인용하는 「처음으로」는 공용 틀(postpartum_ui)의 머리 단추 이름과 로케일마다 같게 맞췄다.