settings page created

This commit is contained in:
michalcourson
2026-02-22 13:10:22 -05:00
parent b8f26496a0
commit 86e30e6ec3
3 changed files with 236 additions and 7 deletions

View File

@ -0,0 +1,196 @@
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import './App.css';
import TextField from '@mui/material/TextField';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
type AudioDevice = {
id: string;
label: string;
};
type Settings = {
httpPort: string;
inputDevice: AudioDevice;
outputDevice: AudioDevice;
recordingLength: number;
outputFolder: string;
};
const defaultSettings: Settings = {
httpPort: '',
inputDevice: { id: '', label: '' },
outputDevice: { id: '', label: '' },
recordingLength: 0,
outputFolder: '',
};
const fetchAudioDevices = async (): Promise<AudioDevice[]> => {
// Replace with actual backend call
// Example: return window.api.getAudioDevices();
return [
{ id: 'default-in', label: 'Default Input' },
{ id: 'mic-1', label: 'Microphone 1' },
{ id: 'default-out', label: 'Default Output' },
{ id: 'spk-1', label: 'Speakers 1' },
];
};
const sendSettingsToBackend = (settings: Settings) => {
// Replace with actual backend call
// Example: window.api.updateSettings(settings);
console.log('Settings updated:', settings);
};
export default function SettingsPage() {
const [settings, setSettings] = useState<Settings>(defaultSettings);
const [inputDevices, setInputDevices] = useState<AudioDevice[]>([]);
const [outputDevices, setOutputDevices] = useState<AudioDevice[]>([]);
const navigate = useNavigate();
useEffect(() => {
fetchAudioDevices()
.then((devices) => {
// For demo, split devices by id
setInputDevices(devices.filter((d) => d.id.includes('in')));
setOutputDevices(devices.filter((d) => d.id.includes('out')));
return devices;
})
.catch((error) => {
console.error('Error fetching audio devices:', error);
});
}, []);
useEffect(() => {
sendSettingsToBackend(settings);
}, [settings]);
const handleChange = () => {
// const { name, value } = e.target;
// setSettings((prev) => ({
// ...prev,
// [name]: value,
// }));
};
const handleFolderChange = async () => {
// Replace with actual folder picker
// Example: const folder = await window.api.selectFolder();
const folder = window.prompt(
'Enter output folder path:',
settings.outputFolder,
);
if (folder !== null) {
setSettings((prev) => ({
...prev,
outputFolder: folder,
}));
}
};
return (
<div className="min-w-screen min-h-screen bg-midnight text-offwhite flex items-center justify-center relative">
<div className="w-3/4 min-w-[600px] max-w-[800px] self-start flex flex-col font-sans bg-midnight text-offwhite p-6 rounded-lg relative">
{/* X Close Button */}
<button
type="button"
className="absolute top-6 right-6 text-3xl font-bold text-offwhite bg-transparent hover:text-plumDark"
aria-label="Close settings"
onClick={() => navigate('/')}
>
×
</button>
<span className="text-2xl font-bold mb-4">Settings</span>
<div className="mb-4 flex justify-between">
<span>HTTP Port:</span>
<TextField
variant="standard"
type="text"
name="httpPort"
value={settings.httpPort}
onChange={(e) => {
setSettings((prev) => ({ ...prev, httpPort: e.target.value }));
}}
className="ml-2 text-white w-[150px]"
/>
</div>
<div className="mb-4 flex justify-between">
<span>Input Audio Device:</span>
<Select
variant="standard"
name="inputDevice"
value={settings.inputDevice}
onChange={(e) => {
setSettings((prev) => ({ ...prev, inputDevice: e.target.value }));
}}
className="ml-2 w-64"
>
{inputDevices.map((dev) => (
<MenuItem key={dev.id} value={dev.id}>
{dev.label}
</MenuItem>
))}
</Select>
</div>
<div className="mb-4 flex justify-between">
<span>Output Audio Device:</span>
<Select
variant="standard"
name="outputDevice"
value={settings.outputDevice}
onChange={(e) => {
setSettings((prev) => ({
...prev,
outputDevice: e.target.value,
}));
}}
className="ml-2 w-64"
>
{outputDevices.map((dev) => (
<MenuItem key={dev.id} value={dev.id}>
{dev.label}
</MenuItem>
))}
</Select>
</div>
<div className="mb-4 flex justify-between">
<span>Recording Length (seconds):</span>
<TextField
variant="standard"
type="text"
name="recordingLength"
value={settings.recordingLength}
onChange={(e) => {
setSettings((prev) => ({
...prev,
recordingLength: e.target.value,
}));
}}
className="ml-2 w-[150px]"
/>
</div>
<div className="mb-4 flex justify-between">
<span>Clip Output Folder:</span>
<div className="flex justify-end">
<TextField
variant="standard"
type="text"
name="outputFolder"
value={settings.outputFolder}
className="ml-2 w-[300px]"
/>
<button
type="button"
onClick={handleFolderChange}
className="ml-2 px-3 py-1 rounded bg-plumDark text-offwhite hover:bg-plum"
>
...
</button>
</div>
</div>
</div>
</div>
);
}