Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 14 additions & 28 deletions src/app/(public)/events/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import JsonLd from '@/components/JsonLd'
import MarkdownContent from '@/components/MarkdownContent'
import ArtistCard from '@/components/artists/ArtistCard'
import EventTimetable from '@/components/events/EventTimetable'
import NoirDonateSection from '@/components/noir/sections/NoirDonateSection'
import { getHomepageSections } from '@/lib/sections'
import type { NoirDonateContent } from '@/lib/noir-home-defaults'

export const dynamic = 'force-dynamic'

Expand All @@ -23,10 +26,6 @@ function formatRange(start: Date, end: Date | null): string {
return `${dayFmt.format(start)} – ${fmt.format(end)}`
}

function formatPrice(price: number | null, currency: string): string {
if (price === null) return 'auf Anfrage'
return new Intl.NumberFormat('de-DE', { style: 'currency', currency }).format(price)
}

export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params
Expand All @@ -44,6 +43,10 @@ export default async function EventDetailPage({ params }: Props) {
const event = await getEvent(slug)
if (!event) notFound()

// Reuse the homepage's "Spenden & Tickets" content so the section matches 1:1.
const sections = await getHomepageSections()
const donateContent = (sections.find((s) => s.type === 'noir_donate')?.content ?? null) as NoirDonateContent | null

const lineup = event.appearances.filter((a) => a.artist)
const seenArtists = new Set<string>()
const uniqueLineup = lineup.filter((a) => {
Expand All @@ -53,6 +56,7 @@ export default async function EventDetailPage({ params }: Props) {
})

return (
<>
<div className="mx-auto max-w-4xl px-4 py-14 sm:px-6 lg:px-8">
<JsonLd
data={buildEventJsonLd({
Expand Down Expand Up @@ -113,30 +117,6 @@ export default async function EventDetailPage({ params }: Props) {
</section>
)}

{/* Preise */}
{event.priceTiers.length > 0 && (
<section className="mb-10">
<h2 className="mb-4 font-display text-2xl font-bold text-brand-text">Preise</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
{event.priceTiers.map((t) => (
<div key={t.id} className="glass-card rounded-section p-5">
<div className="flex items-baseline justify-between gap-2">
<h3 className="font-display text-lg font-bold text-brand-text">{t.name}</h3>
<span className="shrink-0 font-semibold text-brand-accent">{formatPrice(t.price, t.currency)}</span>
</div>
{t.description && <p className="mt-1 text-sm text-brand-text-muted">{t.description}</p>}
{t.isSoldOut && <span className="mt-2 inline-block rounded-pill bg-red-100 px-3 py-0.5 text-xs font-semibold text-red-700">Ausverkauft</span>}
{t.buyUrl && !t.isSoldOut && (
<a href={t.buyUrl} target="_blank" rel="noopener noreferrer nofollow" className="btn-secondary mt-3 inline-block px-4 py-1.5 text-sm">
Ticket kaufen
</a>
)}
</div>
))}
</div>
</section>
)}

{/* Ticket-CTA */}
{event.ticketUrl && (
<section className="text-center">
Expand All @@ -146,5 +126,11 @@ export default async function EventDetailPage({ params }: Props) {
</section>
)}
</div>

{/* Tickets & Spenden – identisch zur Startseite (ersetzt die Preisliste) */}
<div className="nh">
<NoirDonateSection content={donateContent} />
</div>
</>
)
}
2 changes: 1 addition & 1 deletion src/components/admin/MarkdownEditorField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export default function MarkdownEditorField({
onClick={() => switchMode(mode)}
className={`px-2.5 py-1 text-xs font-medium rounded-full transition-colors ${
editorMode === mode
? 'bg-white text-brand-text shadow-sm'
? 'bg-white text-brand-text shadow-sm dark:bg-slate-600'
: 'text-brand-text-muted hover:text-brand-text'
}`}
>
Expand Down
6 changes: 3 additions & 3 deletions src/components/admin/editor/SlashCommandMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,18 +183,18 @@ export function SlashCommandMenu({ onInsert, onClose, position }: SlashCommandMe
return (
<div
ref={menuRef}
className="fixed z-50 w-72 max-h-80 bg-white rounded-xl shadow-xl border border-gray-200 overflow-hidden flex flex-col animate-fade-in"
className="fixed z-50 w-72 max-h-80 bg-white dark:bg-slate-800 rounded-xl shadow-xl border border-gray-200 dark:border-slate-600 overflow-hidden flex flex-col animate-fade-in"
style={position ? { top: position.top, left: position.left } : { top: '50%', left: '50%', transform: 'translate(-50%, -50%)' }}
>
<div className="p-2 border-b border-gray-100">
<div className="p-2 border-b border-gray-100 dark:border-slate-700">
<input
ref={inputRef}
type="text"
value={search}
onChange={(e) => setSearch(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Block suchen..."
className="w-full text-sm border border-gray-200 rounded-lg px-3 py-1.5 focus:outline-none focus:ring-2 focus:ring-brand-accent/30"
className="w-full text-sm border border-gray-200 dark:border-slate-600 bg-white dark:bg-slate-900 text-brand-text dark:text-slate-100 placeholder:text-brand-text-light dark:placeholder:text-slate-400 rounded-lg px-3 py-1.5 focus:outline-none focus:ring-2 focus:ring-brand-accent/30"
/>
</div>
<div className="flex-1 overflow-y-auto p-1">
Expand Down
8 changes: 4 additions & 4 deletions src/components/layout/HeaderClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ export default function HeaderClient({ navigation, settings }: HeaderClientProps
{/* Desktop CTA + dark mode */}
<div className="hidden lg:flex items-center gap-3">
<DarkModeToggle />
<Link href="/unterstuetzung" className="btn-primary text-sm px-5 py-2.5">
Spenden
<Link href="/events/e-ventschau-2026#spenden" className="btn-primary text-sm px-5 py-2.5">
Tickets
</Link>
</div>

Expand Down Expand Up @@ -356,11 +356,11 @@ export default function HeaderClient({ navigation, settings }: HeaderClientProps
{/* CTA button */}
<div className="pt-6">
<Link
href="/unterstuetzung"
href="/events/e-ventschau-2026#spenden"
className="btn-primary text-base w-full text-center block"
onClick={() => setMobileOverlayOpen(false)}
>
Spenden
Tickets
</Link>
</div>
</div>
Expand Down