feat(core,view): input cards with change tracking (plan B1 · C2)
- Three values per pier: defaults (as imported), input (generated), draft (current cards). Overrides = draft vs defaults; pending = draft vs input. - Editable now: 코핑 폭, 코핑 길이, 말뚝 길이. Changing a card does not touch the 3D view until 다시 생성; the header and the card show 변경 n. - Revert puts a field back to its imported default. - Project files store defaults and draft (optional; v1 files still open). - Tests: 코핑 폭 3100 → 3300 gives one override and one pending change; regenerating clears pending but keeps the override; revert; file round trip. - Not verified in a browser (no debuggable Chrome in this session). Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f5303e4c2b
commit
0b62f694c5
7 files changed
+239
-9
No files matched your search
@@ -0,0 +1,45 @@
|
||||
import type { PierInput } from './types';
|
||||
|
||||
/**
|
||||
* Inputs the user can change on the 2단계 cards (spec §5.2 · plan C2). Each one maps to a field of PierInput.
|
||||
* Extend this list as more cards are enabled; the tracking below works on any of these keys.
|
||||
*/
|
||||
export const EDITABLE_FIELDS = [
|
||||
{ key: 'copingWidthMm', label: '코핑 폭 B', unit: 'mm' },
|
||||
{ key: 'copingLengthMm', label: '코핑 길이 L', unit: 'mm' },
|
||||
{ key: 'pileLengthMm', label: '말뚝 길이', unit: 'mm' },
|
||||
] as const;
|
||||
|
||||
export type EditableKey = (typeof EDITABLE_FIELDS)[number]['key'];
|
||||
|
||||
/** Keys whose values differ between two inputs. */
|
||||
export function changedKeys(a: PierInput, b: PierInput): EditableKey[] {
|
||||
return EDITABLE_FIELDS.map((f) => f.key).filter((key) => a[key] !== b[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The three values a pier carries while it is edited (spec §5.5, plan B1):
|
||||
* - defaults: the values as imported from the sheet (기본값, shown as "기본 3100").
|
||||
* - input: the values the 3D model was generated from (생성본).
|
||||
* - draft: the values the user currently has in the cards (현재 입력).
|
||||
*/
|
||||
export interface PierValues {
|
||||
defaults: PierInput;
|
||||
input: PierInput;
|
||||
draft: PierInput;
|
||||
}
|
||||
|
||||
/** Overrides: draft differs from the imported default (주황 표시, "변경 n건" in the card). */
|
||||
export function overrideKeys(p: PierValues): EditableKey[] {
|
||||
return changedKeys(p.defaults, p.draft);
|
||||
}
|
||||
|
||||
/** Pending: draft differs from the generated model, so the 3D view is out of date (미반영 변경). */
|
||||
export function pendingKeys(p: PierValues): EditableKey[] {
|
||||
return changedKeys(p.input, p.draft);
|
||||
}
|
||||
|
||||
/** Puts one field back to its imported default in the draft. */
|
||||
export function revertDraft(p: PierValues, key: EditableKey): PierInput {
|
||||
return { ...p.draft, [key]: p.defaults[key] };
|
||||
}
|
||||
+10
-1
@@ -14,8 +14,12 @@ export interface ProjectInfo {
|
||||
|
||||
export interface ProjectPier {
|
||||
id: string;
|
||||
/** Input as read from the spreadsheet. The 3D model is not stored; it is regenerated on open (spec §8). */
|
||||
/** Generated input: the values the 3D model was built from. The model is not stored; it is regenerated on open (spec §8). */
|
||||
input: PierInput;
|
||||
/** Values as imported from the sheet (기본값). Missing in files saved before change tracking: input is used. */
|
||||
defaults?: PierInput;
|
||||
/** Values currently in the cards (현재 입력). Missing in older files: input is used. */
|
||||
draft?: PierInput;
|
||||
}
|
||||
|
||||
export interface ProjectFile {
|
||||
@@ -54,6 +58,11 @@ export function parseProject(text: string): ProjectFile {
|
||||
if (typeof input.name !== 'string' || !Array.isArray(input.ips) || !Array.isArray(input.bearings)) {
|
||||
throw new Error(`교각 ${i + 1}(${String(input.name)}): 입력 형식이 맞지 않습니다.`);
|
||||
}
|
||||
for (const extra of [p.defaults, p.draft]) {
|
||||
if (extra !== undefined && (typeof extra !== 'object' || extra === null || typeof extra.name !== 'string')) {
|
||||
throw new Error(`교각 ${i + 1}(${input.name}): defaults 또는 draft 형식이 맞지 않습니다.`);
|
||||
}
|
||||
}
|
||||
});
|
||||
return obj as ProjectFile;
|
||||
}
|
||||
Reference in new issue
Block a user