import { useEffect, useState } from "react"; import Markdown from "react-markdown"; import { Book, Project, AuthorProfile, LegalDocument, PortfolioTheme } from "../types"; import { BookOpen, Star, HelpCircle, Award, Compass, ArrowRight, ExternalLink, Moon, Mail, Instagram, AtSign, Share2, FileText, MessageCircle, Download, ChevronDown, ChevronUp } from "lucide-react"; import SpotlightSection from "./SpotlightSection"; import LegalModal from "./LegalModal"; import ProjectDetailMedia from "./ProjectDetailMedia"; import SpotifyConsentPlayer from "./SpotifyConsentPlayer"; import AccessibleModal from "./AccessibleModal"; interface PortfolioPageProps { data: AuthorProfile; legalDocuments?: LegalDocument[]; theme: PortfolioTheme; } function safeExternalUrl(value: string): string | null { try { const url = new URL(value); return url.protocol === "https:" || url.protocol === "http:" ? url.toString() : null; } catch { return null; } } const themeDefaults: Record = { cosmic: { accent: "#06b6d4", secondary: "#a855f7", background: "#020617", card: "#0f172a", badge: "Geschichten & Welten", subtitle: "AUTORINNEN- UND AUTORENPORTFOLIO" }, velvet: { accent: "#f97316", secondary: "#f59e0b", background: "#0a0a0a", card: "#171717", badge: "Literatur & Leidenschaft", subtitle: "AUTORINNEN- UND AUTORENPORTFOLIO" }, botanical: { accent: "#8FA797", secondary: "#B59EB1", background: "#0c0a09", card: "#1c1917", badge: "Poesie & Gedanken", subtitle: "AUTORINNEN- UND AUTORENPORTFOLIO" }, romance: { accent: "#e11d48", secondary: "#f59e0b", background: "#10070b", card: "#1f1117", badge: "Geschichten & Gefühle", subtitle: "AUTORINNEN- UND AUTORENPORTFOLIO" }, }; export default function PortfolioPage({ data, legalDocuments = [], theme }: PortfolioPageProps) { const [selectedBook, setSelectedBook] = useState(null); const [selectedProject, setSelectedProject] = useState(null); const [legalModalOpen, setLegalModalOpen] = useState(false); const [activeLegalId, setActiveLegalId] = useState(null); const [shareNotice, setShareNotice] = useState(""); const [showAllDownloads, setShowAllDownloads] = useState(false); const relevantLegalDocs = legalDocuments; const defaults = themeDefaults[theme]; const accentColor = data.accentColor || defaults.accent; const secondaryColor = data.secondaryColor || defaults.secondary; const bgColor = data.backgroundColor || defaults.background; const cardBgColor = data.cardBgColor || defaults.card; const fontClass = data.fontFamily === "serif" ? "font-serif" : data.fontFamily === "mono" ? "font-mono" : "font-sans"; const customSectionLinks = (data.customSectionLinks || []).slice(0, 3).flatMap((link) => { const url = safeExternalUrl(link.url); return link.label.trim() && url ? [{ label: link.label.trim(), url }] : []; }); const displayedBooks = data.books.map((book, index) => ({ book, index })).sort((left, right) => { if (!left.book.seriesName && !right.book.seriesName) return left.index - right.index; if (!left.book.seriesName) return 1; if (!right.book.seriesName) return -1; const seriesComparison = left.book.seriesName.localeCompare(right.book.seriesName, "de"); return seriesComparison || Number(left.book.seriesNumber || 0) - Number(right.book.seriesNumber || 0) || left.index - right.index; }).map(({ book }) => book); const availableDownloads = (data.downloads || []).filter((entry) => entry.pdfUrl || entry.epubUrl); const visibleDownloads = showAllDownloads ? availableDownloads : availableDownloads.slice(0, 3); const syncDetailFromUrl = () => { const params = new URLSearchParams(window.location.search); setSelectedBook(data.books.find((book) => book.id === params.get("book")) || null); setSelectedProject(data.projects.find((project) => project.id === params.get("project")) || null); }; useEffect(() => { syncDetailFromUrl(); window.addEventListener("popstate", syncDetailFromUrl); return () => window.removeEventListener("popstate", syncDetailFromUrl); }, [data]); const openDetail = (kind: "book" | "project", id: string) => { const url = new URL(window.location.href); url.search = ""; url.searchParams.set(kind, id); window.history.pushState({}, "", url); syncDetailFromUrl(); }; const closeDetail = () => { const url = new URL(window.location.href); url.search = ""; window.history.replaceState({}, "", url); setSelectedBook(null); setSelectedProject(null); }; const shareDetail = async (title: string) => { try { if (navigator.share) await navigator.share({ title, url: window.location.href }); else { await navigator.clipboard.writeText(window.location.href); setShareNotice("Link wurde kopiert."); window.setTimeout(() => setShareNotice(""), 3000); } } catch (error) { if (error instanceof DOMException && error.name === "AbortError") return; setShareNotice("Der Link konnte nicht kopiert werden."); } }; const toggleDownloads = () => { const isCollapsing = showAllDownloads; setShowAllDownloads((current) => !current); if (isCollapsing) window.requestAnimationFrame(() => document.getElementById("downloads")?.scrollIntoView({ behavior: "smooth", block: "start" })); }; return (
{/* Hero Banner Background if present */} {data.heroBannerUrl && (
)} {/* Decorative starry background with magical aura */}
{/* Hero Section */}
{/* Subtle magical/futuristic accent */}
{data.badgeText || defaults.badge}

{data.heroTitle || data.name}

{data.heroSubtitle || defaults.subtitle}

{/* Main Container */}
{/* Section 1: Über mich */}
{/* Outer neon ring */}
{data.name}

{data.aboutTitle || "Über den Autor"}

{data.bio}

{(data.bioTag1Label || data.bioTag1Value) && (
{data.bioTag1Label || "Fokus"}
{data.bioTag1Value || "Literatur"}
)} {(data.bioTag2Label || data.bioTag2Value) && (
{data.bioTag2Label || "Welten"}
{data.bioTag2Value || "Geschichten"}
)} {(data.bioTag3Label || data.bioTag3Value) && (
{data.bioTag3Label || "Stil"}
{data.bioTag3Value || "Atmosphärisch"}
)}
{/* Section 1.5: Spotlight / Neuerscheinung */} {data.books?.find(b => b.isSpotlight) && ( b.isSpotlight)!} title={data.spotlightTitle} subtitle={data.spotlightSubtitle} accentColor={accentColor} secondaryColor={secondaryColor} cardBgColor={cardBgColor} /> )} {/* Section 2: Aktuelle Projekte */}

{data.projectsTitle || "Aktuelle Projekte"}

{data.projectsSubtitle || "Ein exklusiver Blick auf das, was sich gerade auf meinem Schreib-Amboss befindet."}

Aktuell in Arbeit
{data.projects.map((project) => ( ))}
{/* Section 3: Bücherregal */}

{data.booksTitle || "Das Bücherregal"}

{data.booksSubtitle || "Veröffentlichte Meilensteine. Klicken oder Tippen Sie auf ein Cover, um Geheimnisse zu enthüllen."}

{displayedBooks.map((book) => ( ))}
{availableDownloads.length > 0 && (

{data.downloadsTitle || "Kurzgeschichten & Downloads"}

{data.downloadsSubtitle &&

{data.downloadsSubtitle}

}
{availableDownloads.length > 3 && (
)}
)} {/* Section 4: Custom Highlight Section if present */} {(data.customSectionTitle || data.customSectionContent || customSectionLinks.length > 0) && (
CUSTOM_INFO_MODULE
{data.customSectionTitle && (

{data.customSectionTitle}

)} {data.customSectionContent && ( )} {customSectionLinks.length > 0 && ( )}
)} {(data.contactEmail || data.instagramUrl || data.threadsUrl || data.discordUrl) && (

Kontakt & Social Media

Weitere Neuigkeiten, Einblicke und Kontaktmöglichkeiten.

{data.contactEmail && ( E-Mail )} {safeExternalUrl(data.instagramUrl || "") && ( Instagram )} {safeExternalUrl(data.threadsUrl || "") && ( Threads )} {safeExternalUrl(data.discordUrl || "") && ( Discord )}
)}
{shareNotice &&
{shareNotice}
} {/* Book details modular interface modal */} {selectedBook && ( {/* Close Button */}
{/* Book Cover */}
{selectedBook.title}
{(selectedBook.ebookLink || selectedBook.buyLink) && E-Book} {selectedBook.paperbackLink && Taschenbuch} {selectedBook.samplePdfUrl && Leseprobe (PDF)}
{/* Book Details */}
Erschienen: {selectedBook.publishedYear} {selectedBook.genres?.map((genre) => ( {genre} ))}

{selectedBook.title}

{selectedBook.subtitle && (

{selectedBook.subtitle}

)} {selectedBook.seriesName && (

{selectedBook.seriesName}{selectedBook.seriesNumber !== undefined && selectedBook.seriesNumber !== "" ? ` · Band ${selectedBook.seriesNumber}` : ""}

)}
{selectedBook.description}
{/* Privacy-friendly Spotify player */} {selectedBook.spotifyPlaylistId && selectedBook.spotifyPlaylistId.trim() !== "" && ( )}
)} {/* Project details modular modal */} {selectedProject && ( {/* Close Button */}
Status: {selectedProject.status || "In Arbeit"} Aktuelles Projekt

{selectedProject.title}

{data.projectProgressLabel ? `${data.projectProgressLabel.toUpperCase()}:` : "FORTSCHRITT:"} {selectedProject.progress}%
{data.projectExcerptBadge && (
{data.projectExcerptBadge}
)}

{data.projectExcerptTitle || "Projekt-Exzerpt & Fortschrittsnotizen"}

{selectedProject.description || "Für dieses Schreibprojekt wurden noch keine weiteren Details abgelegt."}
)} {/* Styled Footer */}

© {new Date().getFullYear()} {data.name}. Alle Rechte vorbehalten.

{data.footerText || "Geschichten, Projekte und Veröffentlichungen."}

{relevantLegalDocs.length > 0 && (
{relevantLegalDocs.map((doc) => ( ))}
)}
{/* Legal Modal */} setLegalModalOpen(false)} documents={relevantLegalDocs} initialDocId={activeLegalId} accentColor={accentColor} secondaryColor={secondaryColor} fontFamily={data.fontFamily || "sans"} />
); }