soroban-abacus-flashcards/apps/web
Thomas Hallock 5b6db588a2 fix: refactor worksheet config persistence to blacklist approach + Storybook stories
This commit addresses a critical bug where shared worksheets showed incorrect page counts,
and refactors the config extraction architecture to prevent future sharing bugs.

## Bug Fix: Shared Worksheet Page Count

**Problem:** When sharing a 100-page worksheet, opening the share link showed only 4 pages.

**Root Cause:**
- `extractConfigFields()` correctly excluded `total` (derived state)
- `validateWorksheetConfig()` incorrectly used `formState.total ?? 20` as fallback
- Result: Shared worksheets defaulted to `total: 20` instead of calculating from `pages × problemsPerPage`

**Solution:**
- Calculate `total = problemsPerPage × pages` from PRIMARY state
- Never use `formState.total` as source of truth - it's derived!

```typescript
// Before (bug)
const total = formState.total ?? 20

// After (fix)
const problemsPerPage = formState.problemsPerPage ?? 20
const pages = formState.pages ?? 1
const total = problemsPerPage * pages  // 100 pages × 20 problems = 2000 ✓
```

## Architecture: Blacklist Refactor

**Problem:** Multiple incidents where new config fields broke shared worksheets because
we forgot to update the extraction whitelist.

**Old Approach (FRAGILE):**
```typescript
// Manually list every field - easy to forget new ones!
return {
  problemsPerPage: formState.problemsPerPage,
  cols: formState.cols,
  // ... 30+ fields manually listed
}
```

**New Approach (ROBUST):**
```typescript
// Automatically include everything except derived/ephemeral fields
const { rows, total, date, ...persistedFields } = formState
return persistedFields
```

**Benefits:**
-  New config fields automatically work in shared worksheets
-  Only need to update if adding DERIVED fields (rare)
-  Much harder to accidentally break sharing

## Documentation

Added comprehensive docs explaining PRIMARY vs DERIVED state:

**Architecture docs:**
- `.claude/WORKSHEET_CONFIG_PERSISTENCE.md` - Full architecture, examples, history
- `src/app/create/worksheets/README_CONFIG_PERSISTENCE.md` - Quick reference

**In-code docs:**
- `extractConfigFields.ts` - Blacklist approach, field categories, usage
- `validation.ts` - PRIMARY → DERIVED state calculation with examples
- `types.ts` - Field category markers (PRIMARY/DERIVED/EPHEMERAL)

## Storybook Stories

Added comprehensive Storybook stories for worksheet generator components:

**Component Stories:**
- `AdditionWorksheetClient.stories.tsx` - Full generator with virtual loading demos
- `ConfigSidebar.stories.tsx` - Configuration panel with all tabs
- `ResponsivePanelLayout.stories.tsx` - Desktop/mobile layout variations
- `WorksheetPreview.stories.tsx` - Preview component with different states
- `PagePlaceholder.stories.tsx` - Animated loading placeholders

**Config Panel Stories:**
- `OverallDifficultySlider.stories.tsx` - Difficulty slider variations
- `RuleDropdown.stories.tsx` - Display rule dropdown states
- `ToggleOption.stories.tsx` - Toggle option component

**Placeholder Enhancements:**
- Added fast-cycling animated problem variations (0.5-1s cycles)
- Bigger, bolder, higher-contrast math elements
- Removed redundant "Loading page..." overlay
- Added keyframes: wiggle, shimmer, fadeInScale, slideInRight, morphWidth, colorShift

**Storybook Config:**
- Renamed `preview.ts` → `preview.tsx` for JSX support
- Updated `main.ts` for Panda CSS integration

## Testing

Manual test checklist for sharing:
1. Create 100-page worksheet (2000 problems)
2. Click "Share"
3. Open share link in incognito
4. Verify: Shows 100 pages, 2000 total problems ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 11:26:36 -06:00
..
.claude fix: refactor worksheet config persistence to blacklist approach + Storybook stories 2025-11-13 11:26:36 -06:00
.storybook fix: refactor worksheet config persistence to blacklist approach + Storybook stories 2025-11-13 11:26:36 -06:00
__tests__
content/blog
data fix: align share persistence with user session logic 2025-11-11 12:03:32 -06:00
docs
drizzle feat: add skill configuration system with interactive 2D difficulty plot 2025-11-11 15:04:28 -06:00
e2e
public
scripts worksheet studio 2025-11-11 11:44:40 -06:00
src fix: refactor worksheet config persistence to blacklist approach + Storybook stories 2025-11-13 11:26:36 -06:00
.dockerignore.test
.gitignore
CARD_SORTING_PORT_PLAN.md
COMPLEMENT_RACE_PORT_PLAN.md
DEVELOPMENT_STANDARDS.md
LINTING.md
README.md
biome.jsonc
drizzle.config.ts
eslint.config.js
next-env.d.ts
next.config.js
package.json feat: add worksheet sharing infrastructure with database persistence 2025-11-11 11:17:44 -06:00
panda.config.ts fix: refactor worksheet config persistence to blacklist approach + Storybook stories 2025-11-13 11:26:36 -06:00
playwright.config.ts
pnpm-lock.yaml
server.js
svg-processing-test.js
test-arcade-api.sh
test-flashcards-final.pdf
test-flashcards.pdf
test-simplified.pdf
test_fullscreen_persistence.html
test_panda_simple.html
tsconfig.json worksheet studio 2025-11-11 11:44:40 -06:00
tsconfig.server.json
vitest.config.ts

README.md

Test deployment - Mon Nov 3 16:31:57 CST 2025