Add Next.js web app
Feed with live updates and pinning, profiles with follow/pin, featured song picker, settings for all music services, and account deletion. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MzFywujuH9TiuXbr9vjoX8
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { SERVICE_LABELS, type NowPlayingDTO, type StreamingService } from '@musicshare/shared';
|
||||
import { timeAgo } from '@musicshare/shared';
|
||||
import { Avatar } from './Avatar';
|
||||
import { TrackCard } from './TrackCard';
|
||||
|
||||
export function NowPlayingCard({
|
||||
np,
|
||||
preferred,
|
||||
showUser = true,
|
||||
pinned,
|
||||
onTogglePin,
|
||||
}: {
|
||||
np: NowPlayingDTO;
|
||||
preferred: StreamingService | null | undefined;
|
||||
showUser?: boolean;
|
||||
pinned?: boolean;
|
||||
onTogglePin?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<article className={`card ${pinned ? 'card-pinned' : ''}`}>
|
||||
<header className="card-header">
|
||||
{showUser && (
|
||||
<Link href={`/u/${np.user.username}`} className="user-chip">
|
||||
<Avatar user={np.user} size={28} />
|
||||
<span>{np.user.displayName ?? np.user.username}</span>
|
||||
</Link>
|
||||
)}
|
||||
<span className="row">
|
||||
<span className={`status ${np.isPlaying ? 'status-live' : ''}`}>
|
||||
{np.isPlaying ? 'Listening now' : `Played ${timeAgo(np.updatedAt)}`}
|
||||
<span className="muted"> via {SERVICE_LABELS[np.source]}</span>
|
||||
</span>
|
||||
{onTogglePin && (
|
||||
<button
|
||||
className={`pin ${pinned ? 'pinned' : ''}`}
|
||||
onClick={onTogglePin}
|
||||
aria-pressed={pinned}
|
||||
title={pinned ? 'Unpin from top of feed' : 'Pin to top of feed'}
|
||||
>
|
||||
{pinned ? '★' : '☆'}
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
</header>
|
||||
<TrackCard track={np.track} preferred={preferred} />
|
||||
</article>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user