fix(view): alert [보기] highlights the bar it is about (시안 ③, spec §6.1)
[보기] only switched the member tab. The alert now names its bar (RB-F08 → B2), and [보기] switches to the member, highlights that row, and scrolls to it. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
140d34a844
commit
488b65af31
3 files changed
+11
-1
No files matched your search
@@ -31,6 +31,8 @@ export interface RebarWarning {
|
|||||||
message: string;
|
message: string;
|
||||||
/** Where the alert points: a member tab, or the 공통 설정 (for I02). */
|
/** Where the alert points: a member tab, or the 공통 설정 (for I02). */
|
||||||
target: RebarRow['member'] | 'common';
|
target: RebarRow['member'] | 'common';
|
||||||
|
/** The bar the alert is about, so that [보기] can highlight its row. */
|
||||||
|
bar?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Table metadata per bar (코핑철근.md, 확대기초철근 (1).md, 기둥철근 (1).md, 받침블럭철근.md). */
|
/** Table metadata per bar (코핑철근.md, 확대기초철근 (1).md, 기둥철근 (1).md, 받침블럭철근.md). */
|
||||||
@@ -154,7 +156,7 @@ export function rebarSummary(model: PierModel, m: Material = DEFAULT_MATERIAL):
|
|||||||
const split = splitPieces(b.length, 25.4, m.fyS, m.fck, STANDARD_BAR);
|
const split = splitPieces(b.length, 25.4, m.fyS, m.fck, STANDARD_BAR);
|
||||||
if (split) {
|
if (split) {
|
||||||
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: split.pieceLength, note: `${note}, 2조각 이음 (추천안, 겹침 ${Math.round(split.lap)})` });
|
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: split.pieceLength, note: `${note}, 2조각 이음 (추천안, 겹침 ${Math.round(split.lap)})` });
|
||||||
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(b.length)} mm > 정척 ${STANDARD_BAR} mm: 2조각 이음을 추천안으로 적용 (Q-B6).`, target: 'footing' });
|
warnings.push({ code: 'RB-F08', message: `${b.name} 길이 ${Math.round(b.length)} mm > 정척 ${STANDARD_BAR} mm: 2조각 이음을 추천안으로 적용 (Q-B6).`, target: 'footing', bar: b.name });
|
||||||
} else {
|
} else {
|
||||||
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note });
|
rows.push({ member: 'footing', name: b.name, size: b.size, count: b.count, length: b.length, note });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ const state = {
|
|||||||
stage: 'shape' as 'shape' | 'plan' | 'rebar',
|
stage: 'shape' as 'shape' | 'plan' | 'rebar',
|
||||||
/** ③ 공통 설정 (fck · fy). */
|
/** ③ 공통 설정 (fck · fy). */
|
||||||
material: { ...DEFAULT_MATERIAL } as Material,
|
material: { ...DEFAULT_MATERIAL } as Material,
|
||||||
|
/** Bar highlighted on ③ after [보기] (시안 ③ 알림). */
|
||||||
|
rebarFocus: null as string | null,
|
||||||
/** Member tab on ③ (철근표). */
|
/** Member tab on ③ (철근표). */
|
||||||
rebarMember: 'coping' as RebarRow['member'],
|
rebarMember: 'coping' as RebarRow['member'],
|
||||||
/** Member card selected on ② (시안 ② 부재 목록). */
|
/** Member card selected on ② (시안 ② 부재 목록). */
|
||||||
@@ -737,6 +739,7 @@ function renderRebar(): void {
|
|||||||
nameCell.classList.add('bar-no');
|
nameCell.classList.add('bar-no');
|
||||||
// Clicking a 번호 highlights that row (시안: 번호를 누르면 그 철근만 강조).
|
// Clicking a 번호 highlights that row (시안: 번호를 누르면 그 철근만 강조).
|
||||||
nameCell.addEventListener('click', () => tr.classList.toggle('hl'));
|
nameCell.addEventListener('click', () => tr.classList.toggle('hl'));
|
||||||
|
if (r.name === state.rebarFocus) tr.classList.add('hl');
|
||||||
tr.append(
|
tr.append(
|
||||||
el('td', ROLE[r.name] ?? '—'),
|
el('td', ROLE[r.name] ?? '—'),
|
||||||
nameCell,
|
nameCell,
|
||||||
@@ -766,7 +769,9 @@ function renderRebar(): void {
|
|||||||
$<HTMLInputElement>('mat-fck').focus();
|
$<HTMLInputElement>('mat-fck').focus();
|
||||||
$<HTMLInputElement>('mat-fck').scrollIntoView({ block: 'center' });
|
$<HTMLInputElement>('mat-fck').scrollIntoView({ block: 'center' });
|
||||||
} else {
|
} else {
|
||||||
|
// [보기]: go to the member and highlight the bar the alert is about.
|
||||||
state.rebarMember = w.target;
|
state.rebarMember = w.target;
|
||||||
|
state.rebarFocus = w.bar ?? null;
|
||||||
renderAll();
|
renderAll();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -783,6 +788,8 @@ function renderRebar(): void {
|
|||||||
}
|
}
|
||||||
$('step3-status').textContent = `계산됨 · 경고 ${warnings.length}`;
|
$('step3-status').textContent = `계산됨 · 경고 ${warnings.length}`;
|
||||||
renderMaterial();
|
renderMaterial();
|
||||||
|
const focused = box.querySelector('tr.hl');
|
||||||
|
if (focused && state.rebarFocus) focused.scrollIntoView({ block: 'center' });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 구분 (role) of each bar, as in the 시안 ③ table. */
|
/** 구분 (role) of each bar, as in the 시안 ③ table. */
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ describe('③ 철근표 요약 (P1)', () => {
|
|||||||
it('B9: 320 bars; warnings: B2 needs a splice (13646 > 12000)', () => {
|
it('B9: 320 bars; warnings: B2 needs a splice (13646 > 12000)', () => {
|
||||||
expect(count('B9')).toBe(320);
|
expect(count('B9')).toBe(320);
|
||||||
expect(warnings.map((w) => w.code)).toEqual(['I02', 'RB-F08']); // defaults are assumed values (I02)
|
expect(warnings.map((w) => w.code)).toEqual(['I02', 'RB-F08']); // defaults are assumed values (I02)
|
||||||
|
expect(warnings.find((w) => w.code === 'RB-F08')!.bar).toBe('B2');
|
||||||
// B2 is split into two pieces (추천안): each piece is about half the 13646 bar plus half the lap.
|
// B2 is split into two pieces (추천안): each piece is about half the 13646 bar plus half the lap.
|
||||||
expect(rows.find((r) => r.name === 'B2')!.length!).toBeCloseTo(7776, 0);
|
expect(rows.find((r) => r.name === 'B2')!.length!).toBeCloseTo(7776, 0);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user