2025-10-24 23:33:08 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import { Card, Group, Text, Badge, Box } from "@mantine/core";
|
|
|
|
|
import { useState } from "react";
|
|
|
|
|
import type { AlbumTheme } from "@/lib/themes";
|
|
|
|
|
import type { Track } from "@/lib/ListTypes";
|
2025-10-25 01:26:25 +00:00
|
|
|
import TrackModal from "./TrackModal";
|
2025-10-24 23:33:08 +00:00
|
|
|
|
|
|
|
|
interface TrackCardProps {
|
|
|
|
|
track: Track;
|
|
|
|
|
index: number;
|
|
|
|
|
theme: AlbumTheme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function TrackCard({ track, index, theme }: TrackCardProps) {
|
|
|
|
|
const [isHovered, setIsHovered] = useState(false);
|
2025-10-25 01:26:25 +00:00
|
|
|
const [modalOpened, setModalOpened] = useState(false);
|
2025-10-24 23:33:08 +00:00
|
|
|
|
|
|
|
|
return (
|
2025-10-25 01:26:25 +00:00
|
|
|
<>
|
|
|
|
|
<Card
|
|
|
|
|
onClick={() => setModalOpened(true)}
|
|
|
|
|
className="backdrop-blur-sm transition-all duration-300"
|
|
|
|
|
style={{
|
|
|
|
|
background: isHovered ? theme.card.backgroundHover : theme.card.background,
|
|
|
|
|
border: `1px solid ${isHovered ? theme.border.light : theme.card.border}`,
|
|
|
|
|
cursor: "pointer",
|
|
|
|
|
// transform: isHovered ? "translateY(-2px)" : "translateY(0)",
|
|
|
|
|
boxShadow: isHovered ? `0 8px 24px ${theme.primary.DEFAULT}30` : "none",
|
|
|
|
|
}}
|
|
|
|
|
onMouseEnter={() => setIsHovered(true)}
|
|
|
|
|
onMouseLeave={() => setIsHovered(false)}
|
|
|
|
|
>
|
|
|
|
|
<Group justify="space-between" align="center">
|
|
|
|
|
<Group gap="md">
|
|
|
|
|
<Box
|
|
|
|
|
style={{
|
|
|
|
|
minWidth: "40px",
|
|
|
|
|
height: "40px",
|
|
|
|
|
display: "flex",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
background: theme.primary.DEFAULT,
|
|
|
|
|
borderRadius: "8px",
|
|
|
|
|
fontWeight: 700,
|
|
|
|
|
fontSize: "18px",
|
|
|
|
|
color: theme.text.contrast,
|
|
|
|
|
boxShadow: `0 4px 12px ${theme.primary.DEFAULT}60`,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{index + 1}
|
|
|
|
|
</Box>
|
|
|
|
|
<Text size="lg" fw={500} style={{ color: theme.text.primary }}>
|
|
|
|
|
{track.label}
|
|
|
|
|
</Text>
|
|
|
|
|
</Group>
|
2025-10-24 23:33:08 +00:00
|
|
|
|
2025-10-25 01:26:25 +00:00
|
|
|
<Group gap="md">
|
|
|
|
|
<Group gap="xs">
|
|
|
|
|
{track.studioUrl && (
|
|
|
|
|
<Badge
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="filled"
|
|
|
|
|
style={{
|
|
|
|
|
background: theme.badges.studio,
|
|
|
|
|
color: theme.text.contrast,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Studio
|
|
|
|
|
</Badge>
|
|
|
|
|
)}
|
|
|
|
|
{track.emilyLive && (
|
|
|
|
|
<Badge
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="filled"
|
|
|
|
|
style={{
|
|
|
|
|
background: theme.badges.liveEmily,
|
|
|
|
|
color: theme.text.contrast,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
Emily Live
|
|
|
|
|
</Badge>
|
|
|
|
|
)}
|
|
|
|
|
{track.lpLive && (
|
|
|
|
|
<Badge
|
|
|
|
|
size="sm"
|
|
|
|
|
variant="filled"
|
|
|
|
|
style={{
|
|
|
|
|
background: theme.badges.liveLP,
|
|
|
|
|
color: theme.text.contrast,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
LP Live
|
|
|
|
|
</Badge>
|
|
|
|
|
)}
|
|
|
|
|
</Group>
|
|
|
|
|
<Text
|
|
|
|
|
size="sm"
|
|
|
|
|
fw={500}
|
|
|
|
|
style={{
|
|
|
|
|
color: theme.text.muted,
|
|
|
|
|
fontFamily: "monospace",
|
|
|
|
|
background: theme.background.tertiary,
|
|
|
|
|
padding: "4px 12px",
|
|
|
|
|
borderRadius: "6px",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{track.duration}
|
|
|
|
|
</Text>
|
2025-10-24 23:33:08 +00:00
|
|
|
</Group>
|
|
|
|
|
</Group>
|
2025-10-25 01:26:25 +00:00
|
|
|
</Card>
|
|
|
|
|
<TrackModal opened={modalOpened} onClose={() => setModalOpened(false)} track={track} theme={theme} />
|
|
|
|
|
</>
|
2025-10-24 23:33:08 +00:00
|
|
|
);
|
|
|
|
|
}
|