Enhance email templates with clickable links, branding, and improved styling

- Add clickable gallery links in all email templates
- Include application logo in email header and footer (custom or PicPeak default)
- Redesign emails with professional styling matching gallery login page
  - Gray background with white content box
  - PicPeak green header with centered logo
  - Clean typography and proper spacing
  - Responsive design for mobile devices
  - Styled call-to-action buttons
  - Footer with branding and copyright
- Update email processor to fetch branding settings dynamically
- Use proper API URLs for logo images in emails

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
This commit is contained in:
2025-07-10 22:19:15 +02:00
co-authored by Claude
parent 6438374258
commit 5328b4f73a
52 changed files with 3237 additions and 683 deletions
@@ -1,17 +1,24 @@
import React, { useState, useEffect } from 'react';
import { Download, Maximize2, Check, ChevronDown } from 'lucide-react';
import { useTheme } from '../../../contexts/ThemeContext';
import { AuthenticatedImage, Button } from '../../common';
import { AuthenticatedImage } from '../../common';
import type { BaseGalleryLayoutProps } from './BaseGalleryLayout';
import type { Photo } from '../../../types';
export const HeroGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
interface HeroGalleryLayoutProps extends BaseGalleryLayoutProps {
eventName?: string;
eventLogo?: string | null;
}
export const HeroGalleryLayout: React.FC<HeroGalleryLayoutProps> = ({
photos,
onPhotoClick,
onDownload,
selectedPhotos = new Set(),
isSelectionMode = false,
onPhotoSelect
onPhotoSelect,
eventName,
eventLogo
}) => {
const { theme } = useTheme();
const [heroPhoto, setHeroPhoto] = useState<Photo | null>(null);
@@ -50,30 +57,25 @@ export const HeroGalleryLayout: React.FC<BaseGalleryLayoutProps> = ({
{/* Hero Content */}
<div className="absolute inset-0 flex items-center justify-center">
<div className="text-center text-white px-4">
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold mb-4 drop-shadow-lg">
{heroPhoto.category_name || 'Featured Photo'}
</h1>
<div className="flex items-center justify-center gap-4">
<Button
variant="primary"
size="lg"
leftIcon={<Maximize2 className="w-5 h-5" />}
onClick={() => onPhotoClick(0)}
className="bg-white/20 backdrop-blur-sm hover:bg-white/30"
>
View Gallery
</Button>
<Button
variant="outline"
size="lg"
leftIcon={<Download className="w-5 h-5" />}
onClick={(e) => onDownload(heroPhoto, e)}
className="border-white text-white hover:bg-white/20"
>
Download
</Button>
</div>
<div className="text-center px-4">
{/* Logo */}
{eventLogo && (
<div className="mb-6">
<img
src={eventLogo}
alt="Event logo"
className="h-20 sm:h-24 lg:h-32 mx-auto drop-shadow-lg filter brightness-0 invert"
style={{ filter: 'drop-shadow(0 4px 6px rgba(0, 0, 0, 0.5))' }}
/>
</div>
)}
{/* Event Title */}
{eventName && (
<h1 className="text-3xl sm:text-4xl lg:text-5xl xl:text-6xl font-bold text-white drop-shadow-lg">
{eventName}
</h1>
)}
</div>
</div>