import { Settings, Guitar, Music, Gauge } from 'lucide-react'; import { TUNINGS, INSTRUMENT_TUNINGS } from '../music/Tunings'; import { INSTRUMENT_DEFINITIONS } from '../music/InstrumentConfigs'; import { getTempoMarking } from '../music/TempoMarkings'; import { TuningMeter } from './TuningMeter'; import { useSettings } from '../context/useSettings'; import { type Difficulty, type RhythmSettings } from '../types/SettingsTypes'; interface ControlsProps { currentPitch: { note: string; cents: number } | null; } export const Controls: React.FC = ({ currentPitch }) => { const { settings, updateSettings } = useSettings(); // Alias to minimize refactor, or just use updateSettings. const onUpdateSettings = updateSettings; 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' }} />
Max onUpdateSettings({ ...settings, customMaxFret: parseInt(e.target.value) || 0 })} className="control-input" style={{ width: '100%', padding: '4px' }} />
)}
{/* Bottom Section: Tools Grid (2 Columns now) */}
{/* Tool 1: Tuner */}
{settings.showTuningMeter && (
)}
{/* Tool 2: Metronome */}
{settings.rhythm.active && (
{settings.rhythm.mode === 'bpm' ? (
updateRhythm({ bpm: Math.max(1, parseInt(e.target.value) || 60) })} className="control-input" style={{ width: '48px', textAlign: 'center', padding: '2px' }} /> updateRhythm({ bpm: Number(e.target.value) })} style={{ flex: 1 }} />
{getTempoMarking(settings.rhythm.bpm)}
) : (
{settings.rhythm.seconds}s updateRhythm({ seconds: Number(e.target.value) })} style={{ flex: 1 }} />
)}
)}
{/* Tool 3: Auto-play */}
); };