Neue Branding-Page und Gäste-PWA reagiert nun auf Branding-Einstellungen vom event-admin. Implemented local Google Fonts pipeline and admin UI selects for branding and invites.
- Added fonts:sync-google command (uses GOOGLE_FONTS_API_KEY, generates /public/fonts/google files, manifest, CSS, cache flush) and
exposed manifest via new GET /api/v1/tenant/fonts endpoint with fallbacks for existing local fonts.
- Imported generated fonts CSS, added API client + font loader hook, and wired branding page font fields to searchable selects (with
custom override) that auto-load selected fonts.
- Invites layout editor now offers font selection per element with runtime font loading for previews/export alignment.
- New tests cover font sync command and font manifest API.
Tests run: php artisan test --filter=Fonts --testsuite=Feature.
Note: repository already has other modified files (e.g., EventPublicController, SettingsStoreRequest, guest components, etc.); left
untouched. Run php artisan fonts:sync-google after setting the API key to populate /public/fonts/google.
This commit is contained in:
@@ -20,6 +20,9 @@ export default function HomePage() {
|
||||
const { completedCount } = useGuestTaskProgress(token ?? '');
|
||||
const { t, locale } = useTranslation();
|
||||
const { branding } = useEventBranding();
|
||||
const headingFont = branding.typography?.heading ?? branding.fontFamily ?? undefined;
|
||||
const bodyFont = branding.typography?.body ?? branding.fontFamily ?? undefined;
|
||||
const radius = branding.buttons?.radius ?? 12;
|
||||
|
||||
const heroStorageKey = token ? `guestHeroDismissed_${token}` : 'guestHeroDismissed';
|
||||
const [heroVisible, setHeroVisible] = React.useState(() => {
|
||||
@@ -133,7 +136,7 @@ export default function HomePage() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6 pb-32">
|
||||
<div className="space-y-6 pb-32" style={bodyFont ? { fontFamily: bodyFont } : undefined}>
|
||||
{heroVisible && (
|
||||
<HeroCard
|
||||
name={displayName}
|
||||
@@ -147,7 +150,7 @@ export default function HomePage() {
|
||||
/>
|
||||
)}
|
||||
|
||||
<section className="space-y-4" style={branding.fontFamily ? { fontFamily: branding.fontFamily } : undefined}>
|
||||
<section className="space-y-4" style={headingFont ? { fontFamily: headingFont } : undefined}>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<h2 className="text-base font-semibold text-foreground">Starte dein Fotospiel</h2>
|
||||
@@ -163,7 +166,7 @@ export default function HomePage() {
|
||||
onShuffle={shuffleMissionPreview}
|
||||
/>
|
||||
<EmotionActionCard />
|
||||
<UploadActionCard token={token} accentColor={accentColor} secondaryAccent={secondaryAccent} />
|
||||
<UploadActionCard token={token} accentColor={accentColor} secondaryAccent={secondaryAccent} radius={radius} bodyFont={bodyFont} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -328,15 +331,23 @@ function UploadActionCard({
|
||||
token,
|
||||
accentColor,
|
||||
secondaryAccent,
|
||||
radius,
|
||||
bodyFont,
|
||||
}: {
|
||||
token: string;
|
||||
accentColor: string;
|
||||
secondaryAccent: string;
|
||||
radius: number;
|
||||
bodyFont?: string;
|
||||
}) {
|
||||
return (
|
||||
<Card
|
||||
className="overflow-hidden border-0 text-white shadow-sm"
|
||||
style={{ background: `linear-gradient(120deg, ${accentColor}, ${secondaryAccent})` }}
|
||||
style={{
|
||||
background: `linear-gradient(120deg, ${accentColor}, ${secondaryAccent})`,
|
||||
borderRadius: `${radius}px`,
|
||||
fontFamily: bodyFont,
|
||||
}}
|
||||
>
|
||||
<CardContent className="flex flex-col gap-3 py-5">
|
||||
<div className="flex items-center gap-3">
|
||||
@@ -348,7 +359,11 @@ function UploadActionCard({
|
||||
<p className="text-sm text-white/80">Kamera öffnen oder ein Foto aus deiner Galerie wählen.</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button asChild className="bg-white/90 text-slate-900 hover:bg-white">
|
||||
<Button
|
||||
asChild
|
||||
className="bg-white/90 text-slate-900 hover:bg-white"
|
||||
style={{ borderRadius: `${radius}px` }}
|
||||
>
|
||||
<Link to={`/e/${encodeURIComponent(token)}/upload`}>Foto hochladen</Link>
|
||||
</Button>
|
||||
</CardContent>
|
||||
|
||||
Reference in New Issue
Block a user