import { Settings, Guitar, Music, Gauge } from 'lucide-react'; import { TUNINGS, INSTRUMENT_TUNINGS } from '../music/Tunings'; import { INSTRUMENT_DEFINITIONS } from '../music/InstrumentConfigs'; export type Difficulty = string; export interface RhythmSettings { mode: 'bpm' | 'seconds'; bpm: number; seconds: number; active: boolean; autoAdvance: boolean; sound: boolean; volume: number; } export interface AppSettings { difficulty: Difficulty; showHint: boolean; tuningId: string; keySignature: string; instrument: string; showTuningMeter: boolean; rhythm: RhythmSettings; zenMode: boolean; gameMode: 'sight_reading' | 'ear_training'; customMinFret?: number; customMaxFret?: number; autoPlaySightReading?: boolean; } interface ControlsProps { settings: AppSettings; onUpdateSettings: (s: AppSettings) => void; } export const Controls: React.FC = ({ settings, onUpdateSettings }) => { const handleDifficultyChange = (e: React.ChangeEvent) => { onUpdateSettings({ ...settings, difficulty: e.target.value as Difficulty }); }; const handleTuningChange = (e: React.ChangeEvent) => { onUpdateSettings({ ...settings, tuningId: e.target.value }); }; const handleInstrumentChange = (e: React.ChangeEvent) => { const newInstrumentId = e.target.value; const instDef = INSTRUMENT_DEFINITIONS[newInstrumentId]; const defaultRange = instDef.ranges[0].id; // Reset tuning if applicable, or just keep as is (it won't be shown/used) let newTuningId = settings.tuningId; if (instDef.showTuning && INSTRUMENT_TUNINGS[newInstrumentId as 'guitar' | 'bass']) { newTuningId = INSTRUMENT_TUNINGS[newInstrumentId as 'guitar' | 'bass'][0]; } onUpdateSettings({ ...settings, instrument: newInstrumentId, difficulty: defaultRange as Difficulty, tuningId: newTuningId }); }; const updateRhythm = (updates: Partial) => { onUpdateSettings({ ...settings, rhythm: { ...settings.rhythm, ...updates } }); }; // Cast instrument to specific key if needed, or use generic record access const availableTunings = INSTRUMENT_TUNINGS[settings.instrument as 'guitar' | 'bass'] || []; const currentInstrumentDef = INSTRUMENT_DEFINITIONS[settings.instrument]; return (
{/* Top Section: Settings Grid (2 Columns) */}
{/* Row 1, Col 1 */}
{/* Row 1, Col 2 (Conditional) */} {currentInstrumentDef.showTuning ? (
) :
} {/* Spacer to maintain grid flow if needed, or omit to let items flow. User asked for specific rows. If I omit, Note Set goes here. Let's omit for "Dense" feel, or keep empty div for strict rows? The request "Top row: instrument and tuning" implies if tuning is missing, maybe just 1 item? I'll output an empty div if I want to FORCE strict placement, but generally flow is better. However, "Second row: note set..." suggests structure. I will use an empty div if tuning is hidden to push Note Set to next row? Actually, grid-template-columns: 1fr 1fr. If Tuning is hidden, Note Set becomes Item 2. I'll forgo complexity and just render what's available. */} {/* Row 2, Col 1 */}
{/* Row 2, Col 2 */}
{/* Row 3: Fret Range (Full Width) */} {currentInstrumentDef.ranges.find(r => r.id === settings.difficulty)?.type === 'custom_fret' && (
Min onUpdateSettings({ ...settings, customMinFret: parseInt(e.target.value) || 0 })} className="control-input" style={{ width: '100%', padding: '4px', borderRadius: '4px', border: '1px solid rgba(255,255,255,0.2)', background: 'rgba(0,0,0,0.2)', color: 'white' }} />
Max onUpdateSettings({ ...settings, customMaxFret: parseInt(e.target.value) || 0 })} className="control-input" style={{ width: '100%', padding: '4px', borderRadius: '4px', border: '1px solid rgba(255,255,255,0.2)', background: 'rgba(0,0,0,0.2)', color: 'white' }} />
)}
{/* Bottom Section: Tools Grid (3 Columns) */}
{/* Tool 1: Tuner */}
{/* Tool 2: Metronome */}
{settings.rhythm.active && (
{settings.rhythm.mode === 'bpm' ? (
{settings.rhythm.bpm} updateRhythm({ bpm: Number(e.target.value) })} style={{ flex: 1 }} />
) : (
{settings.rhythm.seconds}s updateRhythm({ seconds: Number(e.target.value) })} style={{ flex: 1 }} />
)}
)}
{/* Tool 3: Auto-play */} {settings.gameMode === 'sight_reading' ? (
) : (
/* Empty placeholder for grid 3rd column if not sight reading? Or just 2 cols? */ )}
); };