62 lines
No EOL
2 KiB
TypeScript
62 lines
No EOL
2 KiB
TypeScript
import React from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { ChevronLeft } from 'lucide-react';
|
|
import { Update } from '../utils/updates';
|
|
import Comments from './Comments';
|
|
|
|
interface UpdateDetailProps {
|
|
update: Update;
|
|
content?: string;
|
|
}
|
|
|
|
const UpdateDetail: React.FC<UpdateDetailProps> = ({ update, content }) => {
|
|
const navigate = useNavigate();
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<div className="max-w-4xl mx-auto px-6">
|
|
<button
|
|
onClick={() => navigate('/updates')}
|
|
className="flex items-center space-x-2 text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 mb-8 transition-colors"
|
|
>
|
|
<ChevronLeft className="w-4 h-4" />
|
|
<span>{t('updates.back_to_list')}</span>
|
|
</button>
|
|
|
|
<article className="prose prose-lg dark:prose-invert max-w-none">
|
|
<header className="mb-8">
|
|
<div className="flex items-center space-x-2 text-sm text-blue-600 dark:text-blue-400 mb-2">
|
|
<time dateTime={update.date}>{update.date}</time>
|
|
<span>•</span>
|
|
<div className="flex space-x-2">
|
|
{update.tags.map((tag) => (
|
|
<span
|
|
key={tag}
|
|
className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
|
|
>
|
|
{t(`updates.tags.${tag}`)}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<h1 className="text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
|
{update.title}
|
|
</h1>
|
|
</header>
|
|
|
|
{content ? (
|
|
<div dangerouslySetInnerHTML={{ __html: content }} />
|
|
) : (
|
|
<p className="text-gray-600 dark:text-gray-300 text-lg">
|
|
{update.summary}
|
|
</p>
|
|
)}
|
|
|
|
<Comments title={update.title} />
|
|
</article>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default UpdateDetail; |