import React from 'react';
import { Head, Link } 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 { motion, useReducedMotion } from 'framer-motion';
interface AdjacentPost {
slug: string;
title: string;
excerpt?: string;
excerpt_html?: string;
}
interface HeadingItem {
text: string;
slug: string;
level: number;
}
interface Props {
post: {
id: number;
title: string;
excerpt?: string;
excerpt_html?: string;
content: string;
content_html: string;
headings?: HeadingItem[];
featured_image?: string;
published_at: string;
author?: { name: string };
slug: string;
url?: string;
previous_post?: AdjacentPost | null;
next_post?: AdjacentPost | null;
};
}
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 BlogShow: React.FC = ({ post }) => {
const { localizedPath } = useLocalizedRoutes();
const { t, i18n } = useTranslation('blog_show');
const [copied, setCopied] = React.useState(false);
const locale = i18n.language || 'de';
const dateLocale = locale === 'en' ? 'en-US' : 'de-DE';
const shouldReduceMotion = useReducedMotion();
const viewportOnce = { once: true, amount: 0.25 };
const revealUp = {
hidden: { opacity: 0, y: shouldReduceMotion ? 0 : 18 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.6, ease: [0.22, 1, 0.36, 1] },
},
};
const stagger = {
hidden: {},
visible: { transition: { staggerChildren: 0.12 } },
};
const formattedDate = React.useMemo(() => {
try {
return new Date(post.published_at).toLocaleDateString(dateLocale, {
day: 'numeric',
month: 'long',
year: 'numeric'
});
} catch (error) {
console.warn('[Marketing BlogShow] Failed to format date', error);
return post.published_at;
}
}, [post.published_at, dateLocale]);
const handleCopyLink = React.useCallback(() => {
if (typeof navigator === 'undefined' || !navigator.clipboard) {
return;
}
navigator.clipboard.writeText(post.url || window.location.href).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}).catch((error) => {
console.warn('[Marketing BlogShow] Failed to copy link', error);
});
}, [post.url]);
const shareUrl = post.url || (typeof window !== 'undefined' ? window.location.href : '');
const encodedShareUrl = encodeURIComponent(shareUrl);
const encodedTitle = encodeURIComponent(post.title);
const shareLinks = [
{
key: 'whatsapp',
label: t('share_whatsapp'),
href: `https://wa.me/?text=${encodedTitle}%20${encodedShareUrl}`
},
{
key: 'linkedin',
label: t('share_linkedin'),
href: `https://www.linkedin.com/sharing/share-offsite/?url=${encodedShareUrl}`
},
{
key: 'email',
label: t('share_email'),
href: `mailto:?subject=${encodedTitle}&body=${encodedShareUrl}`
}
];
const canUseNativeShare = typeof navigator !== 'undefined' && typeof navigator.share === 'function';
const buildArticleHref = React.useCallback((slug?: string | null) => {
if (!slug) {
return '#';
}
return localizedPath(`/blog/${encodeURIComponent(slug)}`);
}, [localizedPath]);
return (
{t('back_to_blog')}
Fotospiel Stories
{post.title}
{t('by_author')} {post.author?.name || t('team')}
•
{t('published_on')} {formattedDate}
{post.featured_image ? (
) : (
Fotospiel Stories
)}
{t('summary_title')}
{t('toc_title')}
{post.headings && post.headings.length > 0 ? (
) : (
{t('toc_empty')}
)}
{t('sidebar_author_title')}
{post.author?.name || t('team')}
{t('sidebar_author_description')}
{t('share_title')}
{t('share_hint')}
{canUseNativeShare && (
)}
{(post.previous_post || post.next_post) && (
{post.previous_post && (
{t('previous_post')}
{post.previous_post.title}
)}
{post.next_post && (
{t('next_post')}
{post.next_post.title}
)}
)}
);
};
BlogShow.layout = (page: React.ReactNode) => page;
export default BlogShow;