// Announcements — team broadcast board. Owner/admin/manager post notices // (holidays, flyers, text); every member sees them + gets a notification. // Members are read-only. (() => { const { Card, Avatar } = window.TechyFuelOSDesignSystem_be0222; function fmtWhen(d) { if (!d) return ''; // API returns "YYYY-MM-DD HH:MM:SS" in UTC (no zone) — normalise before parse. const dt = new Date(String(d).replace(' ', 'T') + (String(d).endsWith('Z') ? '' : 'Z')); if (isNaN(dt)) return ''; return dt.toLocaleString('en-GB', { day: '2-digit', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' }); } function Announcements() { useLucide(); const [rows, setRows] = React.useState([]); const [loading, setLoading] = React.useState(true); const [modalOpen, setModalOpen] = React.useState(false); const [saving, setSaving] = React.useState(false); const [form, setForm] = React.useState({ title: '', body: '', image_url: '' }); const [imgUploading, setImgUploading] = React.useState(false); const canPost = ['owner', 'admin', 'manager'].includes(window.TFMyRole); const load = React.useCallback(() => { if (!window.API || !window.API.getAnnouncements) { setLoading(false); return; } setLoading(true); window.API.getAnnouncements().then(r => { if (r.data) setRows(r.data); }).catch(() => {}).finally(() => setLoading(false)); }, []); React.useEffect(() => { load(); // Opening this screen clears the announcements badge. try { window.TFClearAnnouncementsBadge && window.TFClearAnnouncementsBadge(); } catch {} }, [load]); function set(k, v) { setForm(f => ({ ...f, [k]: v })); } async function uploadImage(file) { if (!file || !window.API || !window.API.uploadFile) return; if (!file.type.startsWith('image')) { alert('Please pick an image (JPG/PNG).'); return; } setImgUploading(true); try { const rec = await window.API.uploadFile('files', `announcement/${Date.now()}`, file); const url = rec && (rec.url || rec.file_url); if (url) set('image_url', url); else alert('Upload failed. Please try again.'); } catch (e) { alert('Could not upload the flyer. Please try again.'); } setImgUploading(false); } function openAdd() { setForm({ title: '', body: '', image_url: '' }); setModalOpen(true); } async function save() { if (!form.title.trim() || !window.API) return; setSaving(true); try { const { data } = await window.API.createAnnouncement(form); if (data) setRows(prev => [data, ...prev]); setModalOpen(false); } catch (e) { alert('Could not post the announcement. Please try again.'); } setSaving(false); } async function remove(a) { if (!window.confirm('Delete this announcement?')) return; setRows(prev => prev.filter(r => r.id !== a.id)); try { await window.API.deleteAnnouncement(a.id); } catch {} } return (
Company-wide notices — holidays, updates & flyers for the whole team.