55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
import { Music } from "lucide-react";
|
|
import { Project } from "../types";
|
|
|
|
interface ProjectDetailMediaProps {
|
|
project: Project;
|
|
accentColor: string;
|
|
}
|
|
|
|
function normalizeSpotifyPlaylistId(value?: string): string | null {
|
|
if (!value) return null;
|
|
const trimmed = value.trim();
|
|
const urlMatch = trimmed.match(/open\.spotify\.com\/playlist\/([a-zA-Z0-9]+)/);
|
|
const candidate = urlMatch?.[1] || trimmed;
|
|
return /^[a-zA-Z0-9]+$/.test(candidate) ? candidate : null;
|
|
}
|
|
|
|
export default function ProjectDetailMedia({ project, accentColor }: ProjectDetailMediaProps) {
|
|
const playlistId = normalizeSpotifyPlaylistId(project.spotifyPlaylistId);
|
|
|
|
if (!project.imageUrl && !playlistId) return null;
|
|
|
|
return (
|
|
<div className="space-y-5">
|
|
{project.imageUrl && (
|
|
<div className="overflow-hidden rounded-xl border border-white/10 bg-black/20 shadow-lg">
|
|
<img
|
|
src={project.imageUrl}
|
|
alt={`Motiv zum Projekt ${project.title}`}
|
|
className="block w-full h-auto"
|
|
loading="lazy"
|
|
referrerPolicy="no-referrer"
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{playlistId && (
|
|
<div className="space-y-2">
|
|
<div className="flex items-center gap-2 text-xs font-semibold uppercase tracking-wider" style={{ color: accentColor }}>
|
|
<Music className="h-4 w-4" />
|
|
<span>Playlist zum Schreibprojekt</span>
|
|
</div>
|
|
<iframe
|
|
title={`Spotify-Playlist zu ${project.title}`}
|
|
src={`https://open.spotify.com/embed/playlist/${playlistId}?utm_source=generator&theme=0`}
|
|
width="100%"
|
|
height="152"
|
|
allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
|
|
loading="lazy"
|
|
className="rounded-xl border-0"
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|