import React from 'react'; import { Head, Link, usePage } from '@inertiajs/react'; import { useLocalizedRoutes } from '@/hooks/useLocalizedRoutes'; import { useTranslation } from 'react-i18next'; import MarketingLayout from '@/layouts/mainWebsite'; import { Card, CardContent } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Separator } from '@/components/ui/separator'; import { Button } from '@/components/ui/button'; import { Alert, AlertDescription } from '@/components/ui/alert'; interface PostSummary { id: number; slug: string; title: string; excerpt?: string; excerpt_html?: string; featured_image?: string; published_at?: string; author?: { name?: string } | string; } interface PaginationLink { url: string | null; label: string; active: boolean; } interface Props { posts: { data: PostSummary[]; links: PaginationLink[]; current_page: number; last_page: number; }; } const MarkdownPreview: React.FC<{ html?: string; fallback?: string; className?: string }> = ({ html, fallback, className }) => { if (html && html.trim().length > 0) { return
; } if (!fallback) { return null; } return

{fallback}

; }; const Blog: React.FC = ({ posts }) => { const { localizedPath } = useLocalizedRoutes(); const { props } = usePage<{ supportedLocales?: string[] }>(); const supportedLocales = useMemo( () => (props.supportedLocales && props.supportedLocales.length > 0 ? props.supportedLocales : ['de', 'en']), [props.supportedLocales] ); const { t, i18n } = useTranslation('marketing'); const locale = i18n.language || 'de'; const articles = posts?.data ?? []; const isLandingLayout = posts.current_page === 1; const featuredPost = isLandingLayout ? articles[0] : null; const gridPosts = isLandingLayout ? articles.slice(1, 4) : []; const listPosts = isLandingLayout ? [] : articles; const dateLocale = locale === 'en' ? 'en-US' : 'de-DE'; const buildArticleHref = React.useCallback( (slug?: string | null) => { if (!slug) { return '#'; } return localizedPath(`/blog/${encodeURIComponent(slug)}`); }, [localizedPath] ); const formatPublishedDate = React.useCallback( (raw?: string) => { if (!raw) { return ''; } try { return new Date(raw).toLocaleDateString(dateLocale, { day: 'numeric', month: 'long', year: 'numeric', }); } catch (error) { console.warn('[Marketing Blog] Unable to parse date', { raw, error }); return raw; } }, [dateLocale] ); const resolvePaginationHref = React.useCallback( (raw?: string | null) => { if (!raw) { return null; } try { const parsed = new URL( raw, typeof window !== 'undefined' ? window.location.origin : 'http://localhost' ); const normalized = `${parsed.pathname}${parsed.search}`; const localePrefixRegex = new RegExp(`^/(${supportedLocales.join('|')})(/|$)`); if (localePrefixRegex.test(parsed.pathname)) { return normalized; } return localizedPath(normalized); } catch (error) { console.warn('[Marketing Blog] Fallback resolving pagination link', { raw, error }); return localizedPath(raw); } }, [localizedPath, supportedLocales] ); const renderPagination = () => { if (!posts.links || posts.links.length <= 3) { return null; } return (
{posts.links.map((link, index) => { const href = resolvePaginationHref(link.url); const labelText = link.label?.trim() || '…'; if (!href) { return ( ); } return ( ); })}
); }; const renderPostMeta = (post: PostSummary) => (
{t('blog.by')} {typeof post.author === 'string' ? post.author : post.author?.name || t('blog.team')} {t('blog.published_at')} {formatPublishedDate(post.published_at)}
); const renderLandingGrid = () => { if (!featuredPost) { return ( {t('blog.empty')} ); } return (
{t('blog.posts_title')}

{featuredPost.title || 'Untitled'}

{renderPostMeta(featuredPost)}
{featuredPost.featured_image && ( {featuredPost.title} )} {!featuredPost.featured_image && (
Fotospiel Stories
)}
{gridPosts.length > 0 && (
{gridPosts.map((post) => ( {post.featured_image && (
{post.title}
)}

{post.title || 'Untitled'}

{renderPostMeta(post)} ))}
)}
); }; const renderListView = () => (
{listPosts.map((post) => (
{post.featured_image && ( {post.title} )}

{post.title || 'Untitled'}

{renderPostMeta(post)}
))} {listPosts.length === 0 && ( {t('blog.empty')} )}
); return (
Fotospiel Blog

{t('blog.hero_title')}

{t('blog.hero_description')}

{t('blog.posts_title')}

{isLandingLayout ? renderLandingGrid() : renderListView()} {renderPagination()}
); }; Blog.layout = (page: React.ReactNode) => page; export default Blog;