feat(ui): 헤더 단계를 시안대로 ①②③으로, 철근재료표는 ③에서 여는 화면으로
시안(11-03·11-06)의 헤더는 ① 형상 생성 · ② 형상계획 · ③ 철근배근뿐이다 (사용자 결정 2026-11-06). - 헤더의 ④ 재료 버튼을 없앰 - 철근재료표 화면(교각별 표·전체 합계·엑셀·인쇄)은 그대로 두고 ③의 [철근재료표 보기]로 연다 - 재료표 화면에 [← ③ 철근배근] 버튼, 열려 있는 동안 헤더는 ③을 강조 - 브라우저 검증 스크립트 4개가 ③을 거쳐 재료표를 열도록 수정 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2b26b7c095
commit
3d0d484524
6 files changed
+22
-14
No files matched your search
+1
-1
@@ -17,7 +17,6 @@
|
||||
<button id="nav-shape" class="step current" data-label="① 형상 생성" aria-label="① 형상 생성" type="button" aria-current="step">① 형상 <em id="step1-status"></em></button>
|
||||
<button id="nav-plan" class="step" data-label="② 형상계획" aria-label="② 형상계획" type="button">② 계획 <em id="step2-status"></em></button>
|
||||
<button id="nav-rebar" class="step" data-label="③ 철근배근" aria-label="③ 철근배근" type="button">③ 배근 <em id="step3-status"></em></button>
|
||||
<button id="nav-quantity" class="step" data-label="④ 재료표" aria-label="④ 재료표" type="button">④ 재료 <em id="step4-status"></em></button>
|
||||
</nav>
|
||||
<div class="actions">
|
||||
<span id="save-status" class="savest">저장 전</span>
|
||||
@@ -276,6 +275,7 @@
|
||||
</aside>
|
||||
<section class="panel viewer" aria-labelledby="quantity-title">
|
||||
<div class="viewer-head">
|
||||
<button id="quantity-back" class="btn-o" type="button">← ③ 철근배근</button>
|
||||
<h2 id="quantity-title">철근재료표</h2>
|
||||
<button id="quantity-export" class="btn-o" type="button">엑셀로 내보내기</button>
|
||||
<button id="quantity-print" class="btn-o" type="button">인쇄</button>
|
||||
|
||||
@@ -104,7 +104,9 @@ let ws, send;
|
||||
await until(`document.getElementById('cip-pile-cageLengthMm')?.value === '12000'`);
|
||||
check('pile panel shares the column connection', await ev(`document.querySelector('[data-cast-part="pile"]').textContent.includes('공통 연결 방식: 연속')`));
|
||||
await shot('02-pile-input');
|
||||
await click(`document.getElementById('nav-quantity')`);
|
||||
// ④ is no longer a header step (header ①②③, 2026-11-06): open the 재료표 from ③.
|
||||
await click(`document.getElementById('nav-rebar')`);
|
||||
await click(`[...document.querySelectorAll('button')].find(b=>b.textContent==='철근재료표 보기')`);
|
||||
check('quantity clearly marks incomplete design', await ev(`document.getElementById('quantity-body').textContent.includes('전체 수량 미완료') && document.getElementById('quantity-body').textContent.includes('접합부')`));
|
||||
await shot('03-quantity-incomplete');
|
||||
await click(`document.getElementById('save-project')`);
|
||||
|
||||
@@ -90,7 +90,9 @@ let ws, send;
|
||||
await until(`document.getElementById('cip-pile-cageLengthMm')?.value === '12000'`);
|
||||
check('pile panel shares the column connection', await ev(`document.querySelector('[data-cast-part="pile"]').textContent.includes('공통 연결 방식: 연속')`));
|
||||
await shot('02-pile-input');
|
||||
await click(`document.getElementById('nav-quantity')`);
|
||||
// ④ is no longer a header step (header ①②③, 2026-11-06): open the 재료표 from ③.
|
||||
await click(`document.getElementById('nav-rebar')`);
|
||||
await click(`[...document.querySelectorAll('button')].find(b=>b.textContent==='철근재료표 보기')`);
|
||||
check('quantity clearly marks incomplete design', await ev(`document.getElementById('quantity-body').textContent.includes('전체 수량 미완료') && document.getElementById('quantity-body').textContent.includes('접합부')`));
|
||||
await shot('03-quantity-incomplete');
|
||||
await click(`document.getElementById('save-project')`);
|
||||
|
||||
@@ -81,7 +81,9 @@ const delay=ms=>new Promise(r=>setTimeout(r,ms)); let ws,send;
|
||||
await send('Emulation.setDeviceMetricsOverride',{width,height:1000,deviceScaleFactor:1,mobile:false});await delay(150);
|
||||
check(`header ${width} keeps one row and no horizontal overflow`,await ev(`document.querySelector('.top').getBoundingClientRect().height<=65&&document.documentElement.scrollWidth<=innerWidth`));
|
||||
}
|
||||
await click(`document.getElementById('nav-quantity')`);
|
||||
// ④ is no longer a header step (header ①②③, 2026-11-06): open the 재료표 from ③.
|
||||
await click(`document.getElementById('nav-rebar')`);
|
||||
await click(`[...document.querySelectorAll('button')].find(b=>b.textContent==='철근재료표 보기')`);
|
||||
check('quantity contains actual dedicated mains and reports remaining incomplete details',await ev(`document.getElementById('quantity-body').textContent.includes('말뚝-P1')&&document.getElementById('quantity-body').textContent.includes('기둥-P1')&&document.getElementById('quantity-body').textContent.includes('전체 수량 미완료')`));
|
||||
await shot('04-quantity');
|
||||
await click(`document.getElementById('nav-rebar')`);await member('기둥');const beforeSave=await ev(table);
|
||||
|
||||
@@ -137,7 +137,9 @@ let ws, send;
|
||||
await click(`[...document.querySelectorAll('#rebar-issues li')].find(e=>e.textContent.includes(${JSON.stringify(text)}))?.querySelector('button')`);
|
||||
check(`${text}: warning opens unified editor`, await ev(`!!document.getElementById('cip-apply') && document.querySelector('#rebar-tabs button[aria-pressed="true"]').textContent.startsWith('기둥·말뚝')`));
|
||||
}
|
||||
await click(`document.getElementById('nav-quantity')`);
|
||||
// ④ is no longer a header step (header ①②③, 2026-11-06): open the 재료표 from ③.
|
||||
await click(`document.getElementById('nav-rebar')`);
|
||||
await click(`[...document.querySelectorAll('button')].find(b=>b.textContent==='철근재료표 보기')`);
|
||||
check('quantity remains explicitly incomplete', await ev(`document.getElementById('quantity-body').textContent.includes('전체 수량 미완료')`));
|
||||
check('no runtime exceptions', report.errors.length===0);
|
||||
report.result='PASS';
|
||||
|
||||
+9
-9
@@ -142,7 +142,7 @@ interface Pier extends PierValues {
|
||||
}
|
||||
|
||||
/** Part toggles in the order of 시안 ① "부재 표시". Each toggle controls one or more scene parts. */
|
||||
/** The four stages: ① 형상 생성, ② 형상계획, ③ 철근배근, ④ 재료표 (결과 화면). */
|
||||
/** The stages: ① 형상 생성, ② 형상계획, ③ 철근배근. 'quantity' is the 철근재료표 screen opened from ③ (시안: header ①②③, 2026-11-06). */
|
||||
type Stage = 'shape' | 'plan' | 'rebar' | 'quantity';
|
||||
|
||||
/** 부재 표시 toggles (2026-11-03). `pier` parts follow the pier scenes; `abut` names follow the abutment groups (abut-scene.ts). */
|
||||
@@ -2636,11 +2636,12 @@ function setStage(stage: Stage): void {
|
||||
placeViewer(stage);
|
||||
if (rebar3d) rebar3d.group.visible = stage === 'rebar';
|
||||
// The highlight is the 'current' class (style.css); aria-current is set alongside it for assistive tech.
|
||||
const nav: [string, Stage][] = [['nav-shape', 'shape'], ['nav-plan', 'plan'], ['nav-rebar', 'rebar'], ['nav-quantity', 'quantity']];
|
||||
for (const [id, key] of nav) {
|
||||
// The 재료표 screen belongs to ③, so ③ stays highlighted while it is open.
|
||||
const nav: [string, Stage[]][] = [['nav-shape', ['shape']], ['nav-plan', ['plan']], ['nav-rebar', ['rebar', 'quantity']]];
|
||||
for (const [id, keys] of nav) {
|
||||
const btn = $<HTMLButtonElement>(id);
|
||||
btn.classList.toggle('current', stage === key);
|
||||
btn.setAttribute('aria-current', String(stage === key));
|
||||
btn.classList.toggle('current', keys.includes(stage));
|
||||
btn.setAttribute('aria-current', String(keys.includes(stage)));
|
||||
}
|
||||
renderAll();
|
||||
}
|
||||
@@ -4478,11 +4479,11 @@ function renderRebar(): void {
|
||||
if (focused && state.rebarSelection.size) focused.scrollIntoView({ block: 'center' });
|
||||
}
|
||||
|
||||
/** ③ keeps only a link to the 철근재료표 screen ④ (승인 2026-10-23). */
|
||||
/** ③ keeps a summary line and a link to the 철근재료표 screen (opened from ③; header ①②③, 2026-11-06). */
|
||||
function renderQuantityLink(box: HTMLElement, rows: RebarRow[], incomplete: readonly string[] = []): void {
|
||||
const q = buildQuantity(rows, state.material, incomplete);
|
||||
const line = el('p', `철근재료표 · ${q.missing.length ? '계산된 부재 소계 · 전체 수량 미완료' : '합계'} ${q.kg.toFixed(1)} kg · 할증 포함 ${q.kgWithWaste.toFixed(1)} kg`, 'pnote');
|
||||
const link = el('button', '④ 재료표에서 보기', 'btn small');
|
||||
const link = el('button', '철근재료표 보기', 'btn small');
|
||||
link.type = 'button';
|
||||
link.addEventListener('click', () => setStage('quantity'));
|
||||
box.append(line, link);
|
||||
@@ -4536,7 +4537,6 @@ function renderQuantityScreen(): void {
|
||||
allButton.textContent = `전체 합계 (${generated}기)`;
|
||||
allButton.setAttribute('aria-pressed', String(state.quantityAll));
|
||||
const targets = quantityTargets();
|
||||
setHeaderStatus('step4-status', '', targets.length ? (state.quantityAll ? `${targets.length}기` : targets[0].input.name) : '예정');
|
||||
$('quantity-note').textContent = targets.length
|
||||
? `${state.quantityAll ? `전체 ${targets.length}기` : targets[0].input.name} · 할증 ${state.material.waste}% (기본 0%, 가정). 삿갓 길이는 h − 100으로 가정(Q-K5). 교각 목록에서 고른 교각만 보며, 전체를 누르면 모든 교각을 보여 줍니다.`
|
||||
: '계산된 교각이 없습니다. 교각을 생성하세요.';
|
||||
@@ -5900,7 +5900,7 @@ $<HTMLButtonElement>('regen').addEventListener('click', regenerateChanged);
|
||||
$<HTMLButtonElement>('nav-shape').addEventListener('click', () => setStage('shape'));
|
||||
$<HTMLButtonElement>('nav-plan').addEventListener('click', () => setStage('plan'));
|
||||
$<HTMLButtonElement>('nav-rebar').addEventListener('click', () => setStage('rebar'));
|
||||
$<HTMLButtonElement>('nav-quantity').addEventListener('click', () => setStage('quantity'));
|
||||
$<HTMLButtonElement>('quantity-back').addEventListener('click', () => setStage('rebar'));
|
||||
$<HTMLInputElement>('mat-fck').addEventListener('change', (ev) => setMaterial('fck', (ev.target as HTMLInputElement).value));
|
||||
$<HTMLInputElement>('mat-waste').addEventListener('change', (ev) => setWaste((ev.target as HTMLInputElement).value));
|
||||
for (const k of ['small16', 'main25', 'main35', 'main51'] as const) {
|
||||
|
||||
Reference in new issue
Block a user