Files
Aislo/B06_Section/B06_Section_UI_Cross_FillSlope_Notice.ts
T
eomsangdonandClaude Opus 5.5 281c71b55b refactor(logic): 348-1 순수 계산 TS 49 파일 <페이지>/logic/ 로 옮김 — 이름 앞머리 그대로 · 동작 고침 없음
- 옮김: B04 2 · B05 23 · B06 11 · A00_Common/design 13 (9,299 줄) · 이미 logic/ 에 있던 16 파일 그대로
- 안 옮김: 묶음 입구(package.json build:*) · 파이썬 · 순수지만 계산 아닌 8 (보기 결선 · 콜백 · API 타입 · 갈아끼움 알림판)
- import 266 줄(142 파일) · 시험 · 주석 · 짝 표시 문자열 경로 고침 · B05 · B06 CLAUDE.md 짝 줄 logic/
- 시험 도우미 새 경로: 가짜 require 열쇠 · B05()/B06() 부름 · 형제 import 자리 · tsc 묶어 돌리는 시험 · 정규식 · rglob
- design_view_cross 줄 한도 시험 685 → 688 (긴 import 경로 줄바꿈 3줄)
- 확인: typecheck 0 · 서버 묶음 넷(corridor · server-calc · b07-extent · b07-note) 다시 지어 코드 같음(//#region 경로 주석만 다름) · 관련 시험 270 파일 — 남은 실패 19 는 옮기기 전과 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014utrjfoW831Vc5wJUd13kL
2026-10-16 13:44:50 +09:00

87 lines
3.7 KiB
TypeScript

/* =============================================================================
* B06_Section_UI_Cross_FillSlope_Notice.ts
* 성토사면 5m 초과 **경고 줄** — 횡단 카드 목록 위 요약 한 줄 + 펼치면 측점 목록
* (2026-09-14 브레인 승인 (나)). 판정은 `_Cross_FillSlope_Warn`, 여기는 그리기만.
* 측점을 누르면 그 카드로 간다. 경고만 — 구조물을 세우거나 값을 바꾸지 않는다.
* ⭐ 2026-09-15 — 그 밑에 사면길이 3m 초과 **소단 검토 정보 한 줄**(경고 모양 아님 · 브레인 ③).
* ⭐ 138-1 — 「⚠ 포장 권장 · n측점」 줄(B05 법정 경사 제안 · 포장 범위 밖 측점 · 옛 카드 배지 자리).
* ⭐ 138-3 — 줄 전체가 카드 칸 위에 고정(sticky) · 알림 없어도 줄 유지(오른쪽 끝 열 수 칸은 부르는 쪽이 붙임).
* ⭐ 196-1 — 항목 = 짧은 이름 + 수 칩 · 긴 설명 = 호버 · 내용 칸 하나 공유(`_Notice_Chips`).
* ========================================================================== */
import type { CrossSection } from "./B06_Section_Api_Fetch";
import { BERM_INFO_TEXT, bermReviewStations } from "./logic/B06_Section_UI_Cross_Berm_Info";
import { fillSlopeLengths, slopeRunLengths } from "./logic/B06_Section_UI_Cross_Fit";
import {
FILL_SLOPE_WARN_TEXT,
fillSlopeWarnings,
type FillSlopeWarning,
} from "./logic/B06_Section_UI_Cross_FillSlope_Warn";
import { L, stationLabel } from "./B06_Section_UI_Section_Common";
import { pavedBySpecs } from "./B06_Section_Cross_Refresh";
import { createNoticeChips, type NoticeChipRow } from "./B06_Section_UI_Cross_Notice_Chips";
export interface FillSlopeNotice {
root: HTMLElement;
/** 측점 설계가 바뀔 때마다 부른다 — 연 칩은 그대로 둔다. */
update: (sections: ReadonlyArray<CrossSection>, stationInterval: number) => void;
}
/** 측점 단추 글 — 측점 + 쪽별 길이(포장 권장은 측점만) */
function rows(warnings: FillSlopeWarning[], stationInterval: number): NoticeChipRow[] {
return warnings.map(({ section, sides }) => {
const parts = sides.map(({ side, lengthM, open }) => {
const label = L(side === "left" ? "B06_Design_Ditch_Left" : "B06_Design_Ditch_Right");
return `${label} ${open ? "≥" : ""}${lengthM.toFixed(2)}m`;
});
return {
stationId: section.station_id,
text: `${stationLabel(section.chainage_m, stationInterval)} ${parts.join(" · ")}`.trim(),
};
});
}
export function createFillSlopeNotice(
onPick: (stationId: string) => void,
selected: () => string | null,
): FillSlopeNotice {
const root = document.createElement("div");
root.className = "b06-section__notice-bar";
const chips = createNoticeChips(onPick, selected);
root.append(chips.root);
return {
root,
update(sections, stationInterval) {
chips.update([
{
key: "fill",
label: L("B06_Notice_FillSlope"),
hint: FILL_SLOPE_WARN_TEXT,
tone: "warn",
rows: rows(fillSlopeWarnings(sections, fillSlopeLengths), stationInterval),
},
{
key: "pave",
label: L("B06_Notice_PaveSuggested"),
hint: L("B06_Design_Paved_Suggested"),
tone: "warn",
rows: rows(
sections
.filter((section) => section.design?.pavement_suggested && !pavedBySpecs(section))
.map((section) => ({ section, sides: [] })),
stationInterval,
),
},
{
key: "berm",
label: L("B06_Notice_Berm"),
hint: BERM_INFO_TEXT,
tone: "info",
rows: rows(bermReviewStations(sections, slopeRunLengths), stationInterval),
},
]);
},
};
}