65 lines
1.7 KiB
TypeScript
65 lines
1.7 KiB
TypeScript
import { Group, Avatar, Text, Box } from "@mantine/core";
|
|
import { MusicNoteIcon } from "@phosphor-icons/react";
|
|
|
|
interface Song {
|
|
song_id: string;
|
|
song_name: string;
|
|
song_artist: string;
|
|
song_album: string;
|
|
song_start?: number;
|
|
song_end?: number;
|
|
song_image_url: string;
|
|
}
|
|
|
|
interface SongSummaryProps {
|
|
song: Song | undefined;
|
|
}
|
|
|
|
const SongSummary = ({ song }: SongSummaryProps) => {
|
|
const formatTime = (seconds: number | undefined) => {
|
|
if (seconds === undefined) return null;
|
|
const minutes = Math.floor(seconds / 60);
|
|
const remainingSeconds = seconds % 60;
|
|
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
|
|
};
|
|
|
|
if (!song?.song_name) {
|
|
return (
|
|
<Group gap="xs" c="dimmed">
|
|
<MusicNoteIcon size={16} />
|
|
<Text size="sm" c="dimmed">No song selected</Text>
|
|
</Group>
|
|
);
|
|
}
|
|
|
|
const hasTimeSegment = song.song_start !== undefined && song.song_end !== undefined;
|
|
|
|
return (
|
|
<Group gap="sm" wrap="nowrap">
|
|
{song.song_image_url && (
|
|
<Avatar
|
|
src={song.song_image_url}
|
|
size={32}
|
|
radius="sm"
|
|
/>
|
|
)}
|
|
<Box style={{ flex: 1, minWidth: 0 }}>
|
|
<Text size="sm" fw={500} truncate>
|
|
{song.song_name}
|
|
</Text>
|
|
<Group gap="xs" wrap="nowrap">
|
|
<Text size="xs" c="dimmed" truncate style={{ flex: 1 }}>
|
|
{song.song_artist}
|
|
</Text>
|
|
{hasTimeSegment && (
|
|
<Text size="xs" c="dimmed" fw={700}>
|
|
{formatTime(song.song_start)} - {formatTime(song.song_end)}
|
|
</Text>
|
|
)}
|
|
</Group>
|
|
</Box>
|
|
</Group>
|
|
);
|
|
};
|
|
|
|
export default SongSummary; |