diff --git a/apps/web/.claude/settings.local.json b/apps/web/.claude/settings.local.json
index 8211f248..095d02ee 100644
--- a/apps/web/.claude/settings.local.json
+++ b/apps/web/.claude/settings.local.json
@@ -172,7 +172,8 @@
"Bash(TZ=America/Chicago date:*)",
"Bash(git hash-object:*)",
"Bash(git ls-tree:*)",
- "Bash(git -C /Users/antialias/projects/soroban-abacus-flashcards show HEAD:apps/web/src/app/icon/route.tsx)"
+ "Bash(git -C /Users/antialias/projects/soroban-abacus-flashcards show HEAD:apps/web/src/app/icon/route.tsx)",
+ "Bash(git -C /Users/antialias/projects/soroban-abacus-flashcards show HEAD:apps/web/package.json)"
],
"deny": [],
"ask": []
diff --git a/apps/web/src/app/create/worksheets/addition/components/ConfigPanel.tsx b/apps/web/src/app/create/worksheets/addition/components/ConfigPanel.tsx
index a67006ff..c7e258c2 100644
--- a/apps/web/src/app/create/worksheets/addition/components/ConfigPanel.tsx
+++ b/apps/web/src/app/create/worksheets/addition/components/ConfigPanel.tsx
@@ -35,106 +35,53 @@ interface ConfigPanelProps {
}
/**
- * Get display label for a rule mode
+ * Generate a human-readable summary of enabled scaffolding aids
+ * Groups by frequency: "Always: x, y • When needed: z"
*/
-function getRuleModeLabel(mode: string): string {
- switch (mode) {
- case 'always':
- return 'always'
- case 'whenRegrouping':
- return 'when regrouping'
- case 'whenMultipleRegroups':
- return '2+ regroups'
- case 'when3PlusDigits':
- return '3+ digits'
- default:
- return mode
- }
-}
-
-/**
- * Get badge color for a rule mode
- */
-function getRuleModeColor(mode: string): { bg: string; text: string } {
- switch (mode) {
- case 'always':
- return { bg: 'green.100', text: 'green.700' }
- case 'whenRegrouping':
- return { bg: 'yellow.100', text: 'yellow.700' }
- case 'whenMultipleRegroups':
- return { bg: 'orange.100', text: 'orange.700' }
- case 'when3PlusDigits':
- return { bg: 'blue.100', text: 'blue.700' }
- default:
- return { bg: 'gray.100', text: 'gray.700' }
- }
-}
-
-/**
- * Generate a human-readable summary of enabled scaffolding aids with mode badges
- */
-function getScaffoldingSummary(displayRules: any): React.ReactNode {
+function getScaffoldingSummary(displayRules: any): string {
console.log('[getScaffoldingSummary] displayRules:', displayRules)
- const scaffoldingItems: Array<{ name: string; mode: string }> = []
+ const alwaysItems: string[] = []
+ const conditionalItems: string[] = []
- if (displayRules.carryBoxes !== 'never') {
- scaffoldingItems.push({ name: 'carry boxes', mode: displayRules.carryBoxes })
- console.log('[getScaffoldingSummary] Adding carry boxes:', displayRules.carryBoxes)
- }
- if (displayRules.answerBoxes !== 'never') {
- scaffoldingItems.push({ name: 'answer boxes', mode: displayRules.answerBoxes })
- console.log('[getScaffoldingSummary] Adding answer boxes:', displayRules.answerBoxes)
- }
- if (displayRules.placeValueColors !== 'never') {
- scaffoldingItems.push({ name: 'place value colors', mode: displayRules.placeValueColors })
- console.log('[getScaffoldingSummary] Adding place value colors:', displayRules.placeValueColors)
- }
- if (displayRules.tenFrames !== 'never') {
- scaffoldingItems.push({ name: 'ten-frames', mode: displayRules.tenFrames })
- console.log('[getScaffoldingSummary] Adding ten-frames:', displayRules.tenFrames)
+ if (displayRules.carryBoxes === 'always') {
+ alwaysItems.push('carry boxes')
+ } else if (displayRules.carryBoxes !== 'never') {
+ conditionalItems.push('carry boxes')
}
- if (scaffoldingItems.length === 0) {
- console.log('[getScaffoldingSummary] Final summary: no scaffolding')
- return no scaffolding
+ if (displayRules.answerBoxes === 'always') {
+ alwaysItems.push('answer boxes')
+ } else if (displayRules.answerBoxes !== 'never') {
+ conditionalItems.push('answer boxes')
}
- console.log('[getScaffoldingSummary] Final summary:', scaffoldingItems)
+ if (displayRules.placeValueColors === 'always') {
+ alwaysItems.push('place value colors')
+ } else if (displayRules.placeValueColors !== 'never') {
+ conditionalItems.push('place value colors')
+ }
- return (
-
- {scaffoldingItems.map((item, index) => {
- const colors = getRuleModeColor(item.mode)
- return (
-
- {item.name}
-
- {getRuleModeLabel(item.mode)}
-
- {index < scaffoldingItems.length - 1 && (
- ·
- )}
-
- )
- })}
-
- )
+ if (displayRules.tenFrames === 'always') {
+ alwaysItems.push('ten-frames')
+ } else if (displayRules.tenFrames !== 'never') {
+ conditionalItems.push('ten-frames')
+ }
+
+ const parts: string[] = []
+
+ if (alwaysItems.length > 0) {
+ parts.push(`Always: ${alwaysItems.join(', ')}`)
+ }
+
+ if (conditionalItems.length > 0) {
+ parts.push(`When needed: ${conditionalItems.join(', ')}`)
+ }
+
+ const summary = parts.length > 0 ? parts.join(' • ') : 'no scaffolding'
+ console.log('[getScaffoldingSummary] Final summary:', summary)
+
+ return summary
}
interface ToggleOptionProps {
@@ -475,7 +422,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
// Find nearest presets for custom configurations
let nearestEasier: DifficultyLevel | null = null
let nearestHarder: DifficultyLevel | null = null
- let customDescription: React.ReactNode = ''
+ let customDescription = ''
if (isCustom) {
const currentRegrouping = calculateRegroupingIntensity(pAnyStart, pAllStart)
@@ -530,19 +477,7 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
// Generate custom description
const regroupingPercent = Math.round(currentRegrouping * 10)
const scaffoldingSummary = getScaffoldingSummary(displayRules)
- customDescription = (
-
- {regroupingPercent}% regrouping,
- {scaffoldingSummary}
-
- )
+ customDescription = `${regroupingPercent}% regrouping • ${scaffoldingSummary}`
}
// Calculate current difficulty position
@@ -715,21 +650,9 @@ export function ConfigPanel({ formState, onChange }: ConfigPanelProps) {
const scaffoldingSummary = getScaffoldingSummary(
preset.displayRules
)
- return (
-
- {regroupingPercent}% regrouping,
- {scaffoldingSummary}
-
- )
+ return `${regroupingPercent}% regrouping • ${scaffoldingSummary}`
})()
- : '25% regrouping, carry boxes, answer boxes, place value colors, ten-frames'}
+ : '25% regrouping • Always: carry boxes, answer boxes, place value colors, ten-frames'}
- {regroupingPercent}% regrouping,
- {scaffoldingSummary}
-
- )
+ const presetDescription = `${regroupingPercent}% regrouping • ${scaffoldingSummary}`
return (