- 항목 = 짧은 이름 + 측점 수 칩(성토 5m↑ · 포장 권장 · 소단 검토) · 0 이면 숨김 - 펼침 = 줄 아래 내용 칸 하나(누른 칩 목록만 · 다시 누르면 닫힘 · 한 번에 하나) - 긴 법령 설명 · 측점 없는 구조물 줄 까닭 글 = 공용 호버 - sticky · 열 수 칸 · 카드 scroll-margin 그대로 · 새 시험 test_196_1 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01STqEqztUthVFBmEP18wBSz
84 lines
3.6 KiB
TypeScript
84 lines
3.6 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 "./B06_Section_UI_Cross_Berm_Info";
|
|
import { fillSlopeLengths, slopeRunLengths } from "./B06_Section_UI_Cross_Fit";
|
|
import {
|
|
FILL_SLOPE_WARN_TEXT,
|
|
fillSlopeWarnings,
|
|
type FillSlopeWarning,
|
|
} from "./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): FillSlopeNotice {
|
|
const root = document.createElement("div");
|
|
root.className = "b06-section__notice-bar";
|
|
const chips = createNoticeChips(onPick);
|
|
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),
|
|
},
|
|
]);
|
|
},
|
|
};
|
|
}
|