AI Studio Änderungen integriert #1
8 changed files with 95 additions and 4 deletions
0
bun.lock
Normal file
0
bun.lock
Normal file
0
data/database.json
Normal file
0
data/database.json
Normal file
17
server.ts
17
server.ts
|
|
@ -47,6 +47,23 @@ async function initDatabase(): Promise<AuthorData> {
|
|||
modified = true;
|
||||
}
|
||||
|
||||
// Ensure customSection fields exist for all profiles
|
||||
if (parsed.scifi && parsed.scifi.customSectionTitle === undefined) {
|
||||
parsed.scifi.customSectionTitle = defaultAuthorData.scifi.customSectionTitle;
|
||||
parsed.scifi.customSectionContent = defaultAuthorData.scifi.customSectionContent;
|
||||
modified = true;
|
||||
}
|
||||
if (parsed.erotica && parsed.erotica.customSectionTitle === undefined) {
|
||||
parsed.erotica.customSectionTitle = defaultAuthorData.erotica.customSectionTitle;
|
||||
parsed.erotica.customSectionContent = defaultAuthorData.erotica.customSectionContent;
|
||||
modified = true;
|
||||
}
|
||||
if (parsed.clara && parsed.clara.customSectionTitle === undefined) {
|
||||
parsed.clara.customSectionTitle = defaultAuthorData.clara.customSectionTitle;
|
||||
parsed.clara.customSectionContent = defaultAuthorData.clara.customSectionContent;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified) {
|
||||
await fs.writeFile(DATA_FILE, JSON.stringify(parsed, null, 2), "utf-8");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ export default function AdminPanel({ onLogout }: AdminPanelProps) {
|
|||
/>
|
||||
</div>
|
||||
<div className="space-y-1 md:col-span-2">
|
||||
<label className="text-xs font-mono text-slate-4000 uppercase text-slate-400">Über Mich / Biografie</label>
|
||||
<label className="text-xs font-mono text-slate-400 uppercase">Über Mich / Biografie</label>
|
||||
<textarea
|
||||
rows={8}
|
||||
value={profile.bio}
|
||||
|
|
@ -571,6 +571,40 @@ export default function AdminPanel({ onLogout }: AdminPanelProps) {
|
|||
className="w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-white outline-none focus:border-indigo-500 text-sm font-sans"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Custom Highlight Section */}
|
||||
<div className="md:col-span-2 border-t border-slate-800/80 pt-6 mt-2 space-y-4">
|
||||
<div>
|
||||
<h4 className="text-sm font-bold text-white flex items-center gap-2">
|
||||
<Sparkles className="w-4 h-4 text-cyan-400" />
|
||||
<span>Zusätzlicher Textabschnitt (unten auf der Seite)</span>
|
||||
</h4>
|
||||
<p className="text-xs text-slate-500">Ein frei gestaltbarer Infobereich, der am Ende des Portfolios (nach dem Bücherregal) dargestellt wird. Ideal für Termine, Lesungen, Newsletter-Aufrufe oder persönliche Grüße. Leer lassen, um den Bereich auszublenden.</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-1 md:col-span-2">
|
||||
<label className="text-xs font-mono text-slate-400 uppercase">Abschnitts-Titel</label>
|
||||
<input
|
||||
type="text"
|
||||
value={profile.customSectionTitle || ""}
|
||||
onChange={(e) => updateProfileField("customSectionTitle", e.target.value)}
|
||||
placeholder="z.B. Lesungen, Kontakt oder Newsletter"
|
||||
className="w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-white outline-none focus:border-indigo-500 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1 md:col-span-2">
|
||||
<label className="text-xs font-mono text-slate-400 uppercase">Abschnitts-Inhalt (Text)</label>
|
||||
<textarea
|
||||
rows={4}
|
||||
value={profile.customSectionContent || ""}
|
||||
onChange={(e) => updateProfileField("customSectionContent", e.target.value)}
|
||||
placeholder="Ihr individueller Textabschnitt..."
|
||||
className="w-full px-3 py-2 bg-slate-950 border border-slate-800 rounded-xl text-white outline-none focus:border-indigo-500 text-sm font-sans"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,22 @@ export default function ClaraPortfolio({ data }: ClaraPortfolioProps) {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
{/* Customizable Custom Section */}
|
||||
{data.customSectionContent && data.customSectionContent.trim() !== "" && (
|
||||
<section id="garten-notiz" className="space-y-6 pt-8 border-t border-[#4A5D50]/20">
|
||||
<div className="bg-gradient-to-br from-[#4A5D50]/10 to-stone-900/40 p-8 rounded-2xl border border-[#4A5D50]/30 max-w-3xl mx-auto text-center space-y-4">
|
||||
{data.customSectionTitle && (
|
||||
<h3 className="text-xl md:text-2xl font-serif text-stone-100">
|
||||
{data.customSectionTitle}
|
||||
</h3>
|
||||
)}
|
||||
<p className="text-stone-300 text-sm md:text-base leading-relaxed italic whitespace-pre-wrap">
|
||||
{data.customSectionContent}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
</main>
|
||||
|
||||
{/* Book details modular modal */}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,22 @@ export default function EroticaPortfolio({ data }: EroticaPortfolioProps) {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
{/* Customizable Custom Section */}
|
||||
{data.customSectionContent && data.customSectionContent.trim() !== "" && (
|
||||
<section id="exklusiv-notiz" className="space-y-6 pt-8 border-t border-orange-950/20">
|
||||
<div className="bg-gradient-to-br from-orange-950/20 to-neutral-900/40 p-8 rounded-2xl border border-orange-950/40 max-w-3xl mx-auto text-center space-y-4">
|
||||
{data.customSectionTitle && (
|
||||
<h3 className="text-xl md:text-2xl font-serif text-amber-100">
|
||||
{data.customSectionTitle}
|
||||
</h3>
|
||||
)}
|
||||
<p className="text-neutral-300 text-sm md:text-base leading-relaxed italic whitespace-pre-wrap">
|
||||
{data.customSectionContent}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
</main>
|
||||
|
||||
{/* Book details modular modal */}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ export const defaultAuthorData: AuthorData = {
|
|||
spotifyPlaylistId: "37i9dQZF1DX4g8Gs5YmN17",
|
||||
genres: ["Science-Fantasy", "Cyberpunk", "Abyssal"]
|
||||
}
|
||||
]
|
||||
],
|
||||
customSectionTitle: "Vorträge & Messen",
|
||||
customSectionContent: "Besuchen Sie mich auf der nächsten Buchmesse am Stand für spekulative Phantastik. Ich freue mich auf den intergalaktischen Austausch mit meinen Leserinnen und Lesern!"
|
||||
},
|
||||
erotica: {
|
||||
name: "M. S. Velvet",
|
||||
|
|
@ -93,7 +95,9 @@ export const defaultAuthorData: AuthorData = {
|
|||
spotifyPlaylistId: "37i9dQZF1DX2U76YeeG0Ug",
|
||||
genres: ["Sinnlicher Thriller", "BDSM-Touch", "Maskerade"]
|
||||
}
|
||||
]
|
||||
],
|
||||
customSectionTitle: "Sinnliche Lesungen & Salon-Abende",
|
||||
customSectionContent: "Tragen Sie sich in meinen privaten Briefverteiler ein, um exklusive Einladungen zu meinen intimen Salon-Lesungen in Berlin und Wien zu erhalten. Die Plätze sind streng limitiert."
|
||||
},
|
||||
clara: {
|
||||
name: "Clara Finch",
|
||||
|
|
@ -140,6 +144,8 @@ export const defaultAuthorData: AuthorData = {
|
|||
spotifyPlaylistId: "37i9dQZF1DWZqd5YICuS9g",
|
||||
genres: ["Prosa", "Natur-Essays", "Minimalismus"]
|
||||
}
|
||||
]
|
||||
],
|
||||
customSectionTitle: "Die Philosophie des Mooses",
|
||||
customSectionContent: "Auf meinen geführten Waldspaziergängen und Schreib-Retreats lade ich Sie ein, die Stille des Waldes neu zu erfahren und Ihre Gedanken auf das Papier fließen zu lassen. Schreiben Sie mir gern für Termine und Buchungsanfragen."
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ export interface AuthorProfile {
|
|||
heroSubtitle: string;
|
||||
projects: Project[];
|
||||
books: Book[];
|
||||
customSectionTitle?: string;
|
||||
customSectionContent?: string;
|
||||
}
|
||||
|
||||
export interface AuthorData {
|
||||
|
|
|
|||
Loading…
Reference in a new issue