94 lines
3.3 KiB
TypeScript
94 lines
3.3 KiB
TypeScript
import { Music } from 'lucide-react';
|
|
import { Card, CardContent, CardDescription, CardHeader } from '@/components/ui/card';
|
|
import { ContentTransition } from '@/components/ui/content-transition';
|
|
import { useTranslation } from '@/hooks/useTranslation';
|
|
import { Link } from 'react-router-dom';
|
|
|
|
interface LibraryItem {
|
|
id: string;
|
|
title: string;
|
|
description?: string;
|
|
}
|
|
|
|
interface SectionHeaderProps {
|
|
title: string;
|
|
viewAllPath?: string;
|
|
}
|
|
|
|
function SectionHeader({ title, viewAllPath }: SectionHeaderProps) {
|
|
const { t } = useTranslation();
|
|
return (
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h2 className="text-heading-3">{title}</h2>
|
|
{viewAllPath && (
|
|
<Link
|
|
to={viewAllPath}
|
|
className="text-caption hover:text-foreground transition-colors"
|
|
>
|
|
{t('dashboard.viewAll')} →
|
|
</Link>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface RecentTracksCardProps {
|
|
items: LibraryItem[];
|
|
isLoading: boolean;
|
|
}
|
|
|
|
export function RecentTracksCard({ items, isLoading }: RecentTracksCardProps) {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<Card variant="glass">
|
|
<CardHeader>
|
|
<SectionHeader title={t('dashboard.recentTracks')} viewAllPath="/library" />
|
|
<CardDescription>
|
|
{t('dashboard.recentTracksDescription')}
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ContentTransition
|
|
isLoading={isLoading}
|
|
skeleton={
|
|
<div className="space-y-4">
|
|
{[...Array(3)].map((_, i) => (
|
|
<div key={i} className="flex items-center space-x-4 animate-pulse">
|
|
<div className="w-10 h-10 bg-muted rounded" />
|
|
<div className="flex-1 space-y-2">
|
|
<div className="h-3 bg-muted rounded w-3/4" />
|
|
<div className="h-2 bg-muted rounded w-1/2" />
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
}
|
|
>
|
|
<div className="space-y-4">
|
|
{items.slice(0, 3).map((item) => (
|
|
<div key={item.id} className="flex items-center space-x-4 p-2 rounded-lg hover:bg-white/5 transition-colors duration-[var(--duration-fast)] cursor-pointer group border border-transparent hover:border-white/5">
|
|
<div className="w-10 h-10 bg-muted/50 rounded flex items-center justify-center border border-border group-hover:border-primary/50 transition-colors shadow-lg">
|
|
<Music className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-colors" />
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate text-foreground group-hover:text-primary transition-colors">
|
|
{item.title}
|
|
</p>
|
|
<p className="text-xs text-muted-foreground truncate group-hover:text-foreground/80">
|
|
{item.description || 'No description'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
{items.length === 0 && (
|
|
<p className="text-sm text-muted-foreground text-center py-8">
|
|
{t('dashboard.noTracksInLibrary')}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</ContentTransition>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|