veza/apps/web/src/features/settings/components/PlaybackSettings.tsx
senke 902f4840d5 [FE-PAGE-004] fe-page: Complete Settings page implementation
- Added Account Settings section with password change, data export, and account deletion
- Added Playback Settings section with audio quality, volume, crossfade, and autoplay controls
- Updated SettingsTabs to include Account and Playback tabs (5 tabs total)
- Added PlaybackSettings interface to types
- Integrated account management features (password change, data export, account deletion)
- Added audio playback controls (quality selector, volume slider, crossfade slider, autoplay toggle)
2025-12-24 12:48:28 +01:00

126 lines
3.5 KiB
TypeScript

import { Label } from '@/components/ui/label';
import { Select } from '@/components/ui/select';
import { Slider } from '@/components/ui/slider';
import { Checkbox } from '@/components/ui/checkbox';
import { PlaybackSettings as PlaybackSettingsType } from '../types/settings';
// FE-PAGE-004: Complete Settings page implementation - Playback Settings
interface PlaybackSettingsProps {
playback: PlaybackSettingsType;
onChange: (playback: PlaybackSettingsType) => void;
}
const audioQualities = [
{ value: 'low', label: 'Low (64 kbps)' },
{ value: 'medium', label: 'Medium (128 kbps)' },
{ value: 'high', label: 'High (256 kbps)' },
{ value: 'lossless', label: 'Lossless (FLAC)' },
];
export function PlaybackSettings({
playback,
onChange,
}: PlaybackSettingsProps) {
const handleQualityChange = (value: string | string[]) => {
const qualityValue = Array.isArray(value) ? value[0] : value;
onChange({
...playback,
quality: qualityValue as 'low' | 'medium' | 'high' | 'lossless',
});
};
const handleVolumeChange = (value: number[]) => {
onChange({
...playback,
volume: value[0],
});
};
const handleCrossfadeChange = (value: number[]) => {
onChange({
...playback,
crossfade: value[0],
});
};
const handleAutoplayChange = (checked: boolean) => {
onChange({
...playback,
autoplay: checked,
});
};
return (
<div className="space-y-6">
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="quality">Audio Quality</Label>
<Select
options={audioQualities}
value={playback.quality}
onChange={handleQualityChange}
placeholder="Select audio quality"
name="quality"
/>
<p className="text-xs text-muted-foreground">
Higher quality uses more bandwidth
</p>
</div>
<div className="space-y-2">
<Label htmlFor="volume">
Default Volume: {Math.round(playback.volume * 100)}%
</Label>
<Slider
id="volume"
min={0}
max={1}
step={0.01}
value={[playback.volume]}
onValueChange={handleVolumeChange}
className="w-full"
/>
<p className="text-xs text-muted-foreground">
Default volume when starting playback
</p>
</div>
<div className="space-y-2">
<Label htmlFor="crossfade">
Crossfade: {playback.crossfade}s
</Label>
<Slider
id="crossfade"
min={0}
max={12}
step={1}
value={[playback.crossfade]}
onValueChange={handleCrossfadeChange}
className="w-full"
/>
<p className="text-xs text-muted-foreground">
Fade duration between tracks (0-12 seconds)
</p>
</div>
<div className="flex items-center justify-between pt-4 border-t">
<div className="space-y-0.5">
<Label htmlFor="autoplay">Autoplay</Label>
<p className="text-sm text-muted-foreground">
Automatically play next track in queue
</p>
</div>
<Checkbox
id="autoplay"
checked={playback.autoplay}
onCheckedChange={(checked) =>
handleAutoplayChange(checked === true)
}
/>
</div>
</div>
</div>
);
}