feat(abacus): add nativeAbacusNumbers setting to schema and UI

Adds the nativeAbacusNumbers setting that was being used by Rithmomachia
but was never committed, causing CI build failures.

Changes:
- Add nativeAbacusNumbers boolean field to abacus_settings schema
- Add database migration for the new field (default: false)
- Add UI toggle in AbacusDisplayDropdown
- Update AbacusSettingsSync to exclude nativeAbacusNumbers from
  abacus-react sync (it's app-specific, not abacus component config)

This setting allows displaying numbers as abaci throughout the app
where practical, used by arcade games like Rithmomachia.

Fixes TypeScript build errors in:
- src/arcade-games/rithmomachia/components/PlayingGuideModal.tsx
- src/arcade-games/rithmomachia/components/RithmomachiaGame.tsx

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock
2025-10-31 20:44:02 -05:00
parent ff9a4a10a9
commit 79f7347d48
6 changed files with 1084 additions and 1 deletions

View File

@@ -0,0 +1,3 @@
-- Custom SQL migration file, put your code below! --
-- Add native_abacus_numbers column to abacus_settings table
ALTER TABLE `abacus_settings` ADD `native_abacus_numbers` integer DEFAULT 0 NOT NULL;

File diff suppressed because it is too large Load Diff

View File

@@ -85,6 +85,13 @@
"when": 1760800000000,
"tag": "0011_add_room_game_configs",
"breakpoints": true
},
{
"idx": 12,
"version": "6",
"when": 1761939039939,
"tag": "0012_damp_mongoose",
"breakpoints": true
}
]
}

View File

@@ -9,6 +9,7 @@ import { useState } from 'react'
import { Z_INDEX } from '../constants/zIndex'
import { css } from '../../styled-system/css'
import { hstack, stack } from '../../styled-system/patterns'
import { useAbacusSettings, useUpdateAbacusSettings } from '../hooks/useAbacusSettings'
interface AbacusDisplayDropdownProps {
isFullscreen?: boolean
@@ -21,6 +22,8 @@ export function AbacusDisplayDropdown({
}: AbacusDisplayDropdownProps) {
const [open, setOpen] = useState(false)
const { config, updateConfig, resetToDefaults } = useAbacusDisplay()
const { data: abacusSettings } = useAbacusSettings()
const { mutate: updateAbacusSettings } = useUpdateAbacusSettings()
const handleOpenChange = (isOpen: boolean) => {
setOpen(isOpen)
@@ -246,6 +249,16 @@ export function AbacusDisplayDropdown({
/>
</FormField>
)}
<FormField label="Native Abacus Numbers" isFullscreen={isFullscreen}>
<SwitchField
checked={abacusSettings?.nativeAbacusNumbers ?? false}
onCheckedChange={(checked) =>
updateAbacusSettings({ nativeAbacusNumbers: checked })
}
isFullscreen={isFullscreen}
/>
</FormField>
</div>
</div>
</DropdownMenu.Content>

View File

@@ -45,7 +45,24 @@ export function AbacusSettingsSync() {
// Only sync if config has changed since last sync
if (configJson !== lastSyncedConfigRef.current) {
console.log('🔄 Syncing abacus settings to API')
updateApiSettings(config)
// Only sync abacus-react config fields, not app-specific fields like nativeAbacusNumbers
const abacusReactFields = {
colorScheme: config.colorScheme,
beadShape: config.beadShape,
colorPalette: config.colorPalette,
hideInactiveBeads: config.hideInactiveBeads,
coloredNumerals: config.coloredNumerals,
scaleFactor: config.scaleFactor,
showNumbers: config.showNumbers,
animated: config.animated,
interactive: config.interactive,
gestures: config.gestures,
soundEnabled: config.soundEnabled,
soundVolume: config.soundVolume,
}
updateApiSettings(abacusReactFields)
lastSyncedConfigRef.current = configJson
}
}, [config, updateApiSettings])

View File

@@ -60,6 +60,11 @@ export const abacusSettings = sqliteTable('abacus_settings', {
/** Sound volume (0.0 - 1.0) */
soundVolume: real('sound_volume').notNull().default(0.8),
/** Display numbers as abaci throughout the app where practical */
nativeAbacusNumbers: integer('native_abacus_numbers', { mode: 'boolean' })
.notNull()
.default(false),
})
export type AbacusSettings = typeof abacusSettings.$inferSelect