import {useCallback, useEffect, useState} from 'react'; import {useTranslation} from 'react-i18next'; import {Loader2, Pencil, Send, Trash2} from 'lucide-react'; import {toast} from 'sonner'; import {Button} from '@/components/ui/button'; import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card'; import {Input} from '@/components/ui/input'; import {Label} from '@/components/ui/label'; import {Textarea} from '@/components/ui/textarea'; import NewsEntry from '../components/NewsEntry.jsx'; import PageContainer from '../components/PageContainer.jsx'; import {MAX_NEWS_TEXT_LENGTH, MAX_NEWS_TITLE_LENGTH} from '../utils/limits.js'; import {createNews, deleteNews, fetchAdminNews, updateNews} from '../utils/news.js'; const emptyForm = () => ({titleEn: '', titleDe: '', textEn: '', textDe: ''}); /** * PLATFORM_ADMIN only: publish, preview, edit and delete the "What's new" entries. Auth checks the role. */ export default function AdminNewsPage() { const {t} = useTranslation(); const [entries, setEntries] = useState([]); const [status, setStatus] = useState('loading'); const [form, setForm] = useState(emptyForm); const [editing, setEditing] = useState(null); const [busy, setBusy] = useState(false); const load = useCallback(async () => { try { const response = await fetchAdminNews(); if (response.status === 401) return; if (response.status === 403) { setStatus('forbidden'); return; } if (!response.ok) { setStatus('error'); return; } setEntries((await response.json()).results); setStatus('ready'); } catch (err) { console.error('Admin news error:', err); setStatus('error'); } }, []); useEffect(() => { load(); }, [load]); const run = async (request, doneKey, onOk) => { setBusy(true); try { const response = await request(); if (response.status === 401) return; if (response.ok) { toast.success(t(doneKey)); onOk?.(); await load(); } else { toast.error(t('ADMIN_NEWS.ERROR')); } } catch (err) { console.error('Admin news action error:', err); toast.error(t('INFO.ERROR.NETWORK_FAILURE')); } finally { setBusy(false); } }; const trimmed = () => ({ titleEn: form.titleEn.trim(), titleDe: form.titleDe.trim(), textEn: form.textEn.trim(), textDe: form.textDe.trim(), }); const reset = () => { setForm(emptyForm()); setEditing(null); }; const submit = (event) => { event.preventDefault(); const news = trimmed(); if (editing == null) run(() => createNews(news), 'ADMIN_NEWS.CREATED', reset); else run(() => updateNews(editing, news), 'ADMIN_NEWS.UPDATED', reset); }; const edit = (entry) => { setEditing(entry.id); setForm({titleEn: entry.titleEn, titleDe: entry.titleDe ?? '', textEn: entry.textEn, textDe: entry.textDe ?? ''}); }; const remove = (entry) => { if (!window.confirm(t('ADMIN_NEWS.CONFIRM_DELETE'))) return; run(() => deleteNews(entry.id), 'ADMIN_NEWS.DELETED', () => editing === entry.id && reset()); }; const change = (field) => (event) => setForm({...form, [field]: event.target.value}); if (status === 'forbidden') { return (

{t('ADMIN_NEWS.NO_ACCESS')}

); } return ( {t(editing == null ? 'ADMIN_NEWS.NEW' : 'ADMIN_NEWS.EDIT')}