Files
flxn-app/src/features/spotify/components/spotify-controls-bar.tsx
2025-09-12 14:27:59 -05:00

210 lines
5.8 KiB
TypeScript

import { ActionIcon, Box, Group, Loader, Text, Tooltip } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import {
PlayIcon,
PauseIcon,
SkipBackIcon,
SkipForwardIcon,
GearIcon,
SpotifyLogoIcon,
FloppyDiskIcon,
ClockCounterClockwiseIcon,
} from '@phosphor-icons/react';
import { useSpotify } from '@/lib/spotify/hooks';
import { useAuth } from '@/contexts/auth-context';
import SpotifySheet from './spotify-sheet';
const SpotifyControlsBar = () => {
const { roles } = useAuth();
const isAdmin = roles?.includes('Admin') || false;
const [sheetOpened, { open: openSheet, close: closeSheet }] = useDisclosure(false);
const {
isAuthenticated,
playbackState,
currentTrack,
isLoading,
error,
play,
pause,
skipNext,
skipPrevious,
activeDevice,
capturedState,
isCaptureLoading,
isResumeLoading,
capturePlaybackState,
resumePlaybackState,
} = useSpotify();
if (!isAdmin) return null;
if (!isAuthenticated) {
return (
<Box py="md" mb="md">
<Group justify="center" gap="sm">
<SpotifyLogoIcon size={24} color="var(--mantine-color-green-6)" />
<Text size="sm" c="dimmed">
Connect Spotify
</Text>
<ActionIcon
variant="light"
color="green"
size="lg"
onClick={openSheet}
loading={isLoading}
>
<GearIcon size={18} />
</ActionIcon>
</Group>
<SpotifySheet opened={sheetOpened} onClose={closeSheet} />
</Box>
);
}
const isPlaying = playbackState?.is_playing || false;
const hasActiveDevice = !!activeDevice;
return (
<Box py="md" mb="md">
<Group justify="center" gap="md" align="center">
{currentTrack && (
<Group gap="sm" style={{ maxWidth: 400 }}>
{currentTrack.album.images[2] && (
<img
src={currentTrack.album.images[2].url}
alt={currentTrack.album.name}
style={{
width: 48,
height: 48,
borderRadius: 4,
flexShrink: 0
}}
/>
)}
<Box style={{ minWidth: 0, flex: 1 }}>
<Text size="sm" fw={600} truncate>
{currentTrack.name}
</Text>
<Text size="xs" c="dimmed" truncate>
{currentTrack.artists.map(a => a.name).join(', ')}
</Text>
<Text size="xs" c="dimmed" truncate>
{currentTrack.album.name}
</Text>
</Box>
</Group>
)}
<Group gap="xs">
<Tooltip label="Previous track">
<ActionIcon
variant="light"
size="lg"
onClick={skipPrevious}
disabled={!hasActiveDevice || isLoading}
loading={isLoading}
>
<SkipBackIcon size={18} />
</ActionIcon>
</Tooltip>
<Tooltip label={isPlaying ? 'Pause' : 'Play'}>
<ActionIcon
variant="filled"
color="green"
size="xl"
onClick={() => isPlaying ? pause() : play()}
disabled={!hasActiveDevice || isLoading}
loading={isLoading}
>
{isPlaying ? <PauseIcon size={24} /> : <PlayIcon size={24} />}
</ActionIcon>
</Tooltip>
<Tooltip label="Next track">
<ActionIcon
variant="light"
size="lg"
onClick={skipNext}
disabled={!hasActiveDevice || isLoading}
loading={isLoading}
>
<SkipForwardIcon size={18} />
</ActionIcon>
</Tooltip>
</Group>
<Group gap="xs">
<Tooltip label={'Capture current state'}>
<ActionIcon
variant="light"
color={capturedState ? 'blue' : 'gray'}
size="lg"
onClick={capturePlaybackState}
disabled={!hasActiveDevice || isLoading || isCaptureLoading}
loading={isCaptureLoading}
>
<FloppyDiskIcon size={18} />
</ActionIcon>
</Tooltip>
<Tooltip label={capturedState ? 'Restore captured state' : 'No state captured'}>
<ActionIcon
variant="light"
color={capturedState ? 'blue' : 'gray'}
size="lg"
onClick={resumePlaybackState}
disabled={!capturedState || !hasActiveDevice || isLoading || isResumeLoading}
loading={isResumeLoading}
>
<ClockCounterClockwiseIcon size={18} />
</ActionIcon>
</Tooltip>
</Group>
<Group gap="xs">
{activeDevice && (
<Box>
<Text size="xs" c="dimmed">
Playing on {activeDevice.name}
</Text>
</Box>
)}
<Tooltip label="Spotify settings">
<ActionIcon
variant="light"
color="green"
size="lg"
onClick={openSheet}
>
<GearIcon size={18} />
</ActionIcon>
</Tooltip>
</Group>
</Group>
{error && (
<Group justify="center" mt="xs">
<Text size="xs" c="red">
{error}
</Text>
</Group>
)}
{isAuthenticated && !hasActiveDevice && !isLoading && (
<Group justify="center" mt="xs">
<Text size="xs" c="orange">
No active device. Please select a device in settings.
</Text>
</Group>
)}
<SpotifySheet opened={sheetOpened} onClose={closeSheet} />
</Box>
);
};
export default SpotifyControlsBar;