feat(plan): 형상계획 ②에 교대 부재 목록과 부재별 카드 추가 (1단계)
- 부재 · 교대 목록(받침, 벽체·흉벽, 날개벽, 접속슬래브, 지반·지층)과 각 행의 값·변경 표시 (src/core/abut/member-list.ts) - 행을 누르면 그 부재의 카드만 표시. 날개벽 형식은 별도 카드로 분리 - 접속슬래브·지반·지층은 값만 표시 (입력은 2단계) - 모델 변경 없음. 테스트 630건 통과, 타입 검사·빌드 통과. 브라우저 시각 확인은 미실시 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
929f8eb4a2
commit
18524460e8
5 files changed
+169
-2
No files matched your search
+46
-2
@@ -11,6 +11,7 @@ import { ABUT_DETAIL_LABELS, abutInputRows, abutSummaryRows } from './core/abut/
|
||||
import { applyAbutEdit, applyBearingEdit, applyShapeEdit, ABUT_EDIT_FIELDS, SHAPE_EDIT_FIELDS, restoreAbutDefault, setWingForm } from './core/abut/edit';
|
||||
import { ABUT_SHAPE_DEFAULT, resolveShape } from './core/abut/shape';
|
||||
import { abutShown, piersShown } from './core/abut/visibility';
|
||||
import { abutMemberRows, ABUT_MEMBER_EDITABLE, type AbutMemberId } from './core/abut/member-list';
|
||||
import { abutSectionSvg } from './view/abut-section-svg';
|
||||
import type { WingForm } from './core/abut/geometry';
|
||||
import { buildMembers } from './core/abut/members';
|
||||
@@ -129,6 +130,8 @@ const state = {
|
||||
abutments: [] as AbutRecord[],
|
||||
/** 교대 편집 카드에서 고른 교대 (2026-11-03). */
|
||||
abutActive: null as string | null,
|
||||
/** The 부재 · 교대 row whose card is open in ② (2026-11-03). */
|
||||
abutMember: 'bearing' as AbutMemberId,
|
||||
/** The editable part of the 교대 panel is open (2026-11-03). */
|
||||
abutEditOpen: false,
|
||||
/** 교대 기본값 (가져온 그대로), for 기본값 복원. */
|
||||
@@ -611,7 +614,7 @@ function focusAbut(name: string): void {
|
||||
/** The 교대 입력 panel slots of ① (replaces the pier info) and ② (under the list). */
|
||||
const ABUT_SLOTS = {
|
||||
shape: { root: 'abut-panel', name: 'abut-panel-name', input: 'abut-panel-input', toggle: 'abut-panel-edit-toggle', editor: 'abut-panel-editor', summary: 'abut-panel-summary', basic: 'abut-panel-basic', bearings: 'abut-panel-bearings', shape: 'abut-panel-shape', msg: 'abut-panel-msg', prefix: 'abs' },
|
||||
plan: { root: 'abut-panel-plan', name: 'abut-panel-plan-name', input: 'abut-panel-plan-input', toggle: 'abut-panel-plan-edit-toggle', editor: 'abut-panel-plan-editor', summary: 'abut-panel-plan-summary', basic: 'abut-panel-plan-basic', bearings: 'abut-panel-plan-bearings', shape: 'abut-panel-plan-shape', msg: 'abut-panel-plan-msg', prefix: 'abp' },
|
||||
plan: { wing: 'abut-panel-plan-wing', root: 'abut-panel-plan',name: 'abut-panel-plan-name', input: 'abut-panel-plan-input', toggle: 'abut-panel-plan-edit-toggle', editor: 'abut-panel-plan-editor', summary: 'abut-panel-plan-summary', basic: 'abut-panel-plan-basic', bearings: 'abut-panel-plan-bearings', shape: 'abut-panel-plan-shape', msg: 'abut-panel-plan-msg', prefix: 'abp' },
|
||||
} as const;
|
||||
|
||||
/** Shows the 교대 입력 in place of the pier info when an abutment is selected (2026-11-03). */
|
||||
@@ -625,6 +628,44 @@ function renderAbutEditor(): void {
|
||||
box.hidden = !rec;
|
||||
if (rec) fillAbutSlot(slot, rec);
|
||||
}
|
||||
if (rec) {
|
||||
renderAbutMembers(rec);
|
||||
applyAbutMemberCard(rec);
|
||||
} else {
|
||||
$<HTMLUListElement>('abut-members').replaceChildren();
|
||||
}
|
||||
}
|
||||
|
||||
/** The 부재 · 교대 rows in ②: each row's value and the card it opens (2026-11-03, phase 1). */
|
||||
function renderAbutMembers(rec: AbutRecord): void {
|
||||
const box = $<HTMLUListElement>('abut-members');
|
||||
const slabWidth = abutSummaryRows(rec).find(([label]) => label === '접속슬래브 폭')?.[1] ?? '—';
|
||||
box.replaceChildren();
|
||||
for (const row of abutMemberRows(rec, slabWidth)) {
|
||||
const btn = el('button', undefined, 'pier-name');
|
||||
btn.type = 'button';
|
||||
btn.setAttribute('aria-pressed', String(row.id === state.abutMember));
|
||||
btn.append(el('span', row.label), el('span', row.summary, 'muted small'));
|
||||
if (row.changed) btn.append(el('span', '변경', 'badge'));
|
||||
btn.addEventListener('click', () => {
|
||||
state.abutMember = row.id;
|
||||
state.abutEditOpen = true;
|
||||
renderAll();
|
||||
});
|
||||
const li = el('li');
|
||||
li.append(btn);
|
||||
box.append(li);
|
||||
}
|
||||
}
|
||||
|
||||
/** Shows only the card of the open row in the ② 교대 editor; the basic items stay visible. */
|
||||
function applyAbutMemberCard(rec: AbutRecord): void {
|
||||
const member = state.abutMember;
|
||||
const group = (id: string) => $<HTMLElement>(id).closest<HTMLElement>('details') ?? $<HTMLElement>(id);
|
||||
group('abut-panel-plan-bearings').hidden = member !== 'bearing';
|
||||
group('abut-panel-plan-shape').hidden = member !== 'shape';
|
||||
$<HTMLElement>('abut-panel-plan-wing').hidden = member !== 'wing';
|
||||
$<HTMLElement>('abut-panel-plan-msg').textContent = ABUT_MEMBER_EDITABLE[member] ? '' : `${rec.name} 입력은 2단계에서 추가합니다. 현재 값만 보여 줍니다.`;
|
||||
}
|
||||
|
||||
/** Fills one 교대 입력 panel: the basic items, the 받침 values and the 형상 values. Each change is checked and applied. */
|
||||
@@ -651,6 +692,9 @@ function fillAbutSlot(slot: (typeof ABUT_SLOTS)[keyof typeof ABUT_SLOTS], rec: A
|
||||
const shape = $<HTMLDivElement>(slot.shape);
|
||||
const msg = $<HTMLParagraphElement>(slot.msg);
|
||||
basic.replaceChildren();
|
||||
// ② puts the wing forms in their own card; ① keeps them in the basic items.
|
||||
const wingBox = 'wing' in slot ? $<HTMLDivElement>(slot.wing) : basic;
|
||||
wingBox.replaceChildren();
|
||||
bearings.replaceChildren();
|
||||
shape.replaceChildren();
|
||||
// 삽도 (벽체·흉벽 개략 단면): the values it names are the card's values, so the drawing follows each change.
|
||||
@@ -700,7 +744,7 @@ function fillAbutSlot(slot: (typeof ABUT_SLOTS)[keyof typeof ABUT_SLOTS], rec: A
|
||||
for (const [value, text] of [['general', '일반형'], ['short', '단축형'], ['none', '없음']] as const) sel.appendChild(new Option(text, value));
|
||||
sel.value = rec.wings?.[side] ?? 'general';
|
||||
sel.addEventListener('change', () => apply(setWingForm(rec, side, sel.value as WingForm)));
|
||||
basic.append(lab, sel);
|
||||
wingBox.append(lab, sel);
|
||||
}
|
||||
const restore = el('button', '기본값으로 되돌리기', 'btn small');
|
||||
restore.type = 'button';
|
||||
|
||||
Reference in new issue
Block a user