feat: color bar respects edits + column pattern auto-correction
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 23s
CI / test-go-edu-search (push) Successful in 25s
CI / test-python-klausur (push) Failing after 1m56s
CI / test-python-agent-core (push) Successful in 14s
CI / test-nodejs-website (push) Successful in 15s

- Color bar (red/colored indicator) now only shows when word_boxes
  text still matches the cell text — editing the cell hides stale colors
- New "Auto-Korrektur" button: detects dominant prefix+number patterns
  per column (e.g. p.70, p.71) and completes partial entries (.65 → p.65)
  — requires 3+ matching entries before correcting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-24 08:38:11 +01:00
parent d6f4944bcc
commit d54814fa70
3 changed files with 90 additions and 1 deletions

View File

@@ -655,6 +655,81 @@ export function useGridEditor(sessionId: string | null) {
[grid, pushUndo],
)
// ------------------------------------------------------------------
// Column pattern auto-correction
// ------------------------------------------------------------------
/**
* Detect dominant prefix+number patterns per column and complete
* partial matches. E.g. if 3+ cells read "p.70", "p.71", etc.,
* a cell reading ".65" is corrected to "p.65".
* Returns the number of corrections made.
*/
const autoCorrectColumnPatterns = useCallback(() => {
if (!grid) return 0
pushUndo(grid.zones)
let totalFixed = 0
const numberPattern = /^(.+?)(\d+)\s*$/
setGrid((prev) => {
if (!prev) return prev
return {
...prev,
zones: prev.zones.map((zone) => {
// Group cells by column
const cellsByCol = new Map<number, { cell: (typeof zone.cells)[0]; idx: number }[]>()
zone.cells.forEach((cell, idx) => {
const arr = cellsByCol.get(cell.col_index) || []
arr.push({ cell, idx })
cellsByCol.set(cell.col_index, arr)
})
const newCells = [...zone.cells]
for (const [, colEntries] of cellsByCol) {
// Count prefix occurrences
const prefixCounts = new Map<string, number>()
for (const { cell } of colEntries) {
const m = cell.text.trim().match(numberPattern)
if (m) {
prefixCounts.set(m[1], (prefixCounts.get(m[1]) || 0) + 1)
}
}
// Find dominant prefix (>= 3 occurrences)
let dominantPrefix = ''
let maxCount = 0
for (const [prefix, count] of prefixCounts) {
if (count >= 3 && count > maxCount) {
dominantPrefix = prefix
maxCount = count
}
}
if (!dominantPrefix) continue
// Fix partial matches — entries that are just [.?\s*]NUMBER
for (const { cell, idx } of colEntries) {
const text = cell.text.trim()
if (!text || text.startsWith(dominantPrefix)) continue
const numMatch = text.match(/^[.\s]*(\d+)\s*$/)
if (numMatch) {
newCells[idx] = { ...newCells[idx], text: `${dominantPrefix}${numMatch[1]}` }
totalFixed++
}
}
}
return { ...zone, cells: newCells }
}),
}
})
if (totalFixed > 0) setDirty(true)
return totalFixed
}, [grid, pushUndo])
// ------------------------------------------------------------------
// Multi-select & bulk formatting
// ------------------------------------------------------------------
@@ -805,5 +880,6 @@ export function useGridEditor(sessionId: string | null) {
toggleCellSelection,
clearCellSelection,
toggleSelectedBold,
autoCorrectColumnPatterns,
}
}