Changelog: Was ist neu? Button + Unread-Tracking

This commit is contained in:
2026-05-29 10:09:47 +02:00
parent b91b742dd8
commit b1e2bfdeec
3 changed files with 50 additions and 5 deletions

View File

@@ -1172,7 +1172,7 @@ function PushScheduler({ toast }) {
}
// ── Changelog Modal ───────────────────────────────────────────────────────────
function ChangelogModal({ user, toast, onClose }) {
function ChangelogModal({ user, toast, onClose, onRead }) {
const isAdmin = user?.role === 'admin';
const [entries, setEntries] = useState([]);
const [form, setForm] = useState({ version:'', title:'', body:'' });
@@ -1181,6 +1181,7 @@ function ChangelogModal({ user, toast, onClose }) {
useEffect(()=>{
api('/dashboard/changelog').then(setEntries).catch(()=>{});
api('/dashboard/changelog/read',{method:'POST'}).then(()=>{ if(onRead) onRead(); }).catch(()=>{});
},[]);
const add = async () => {
@@ -1286,7 +1287,7 @@ function ChangelogModal({ user, toast, onClose }) {
);
}
function Dashboard({ toast, mobile, setActive, unreadMsgs=0, unreadBoard=0, unreadPromoted=0, onBoardRead, user }) {
function Dashboard({ toast, mobile, setActive, unreadMsgs=0, unreadBoard=0, unreadPromoted=0, onBoardRead, unreadChangelog=0, onChangelogRead, user }) {
const [now, setNow] = useState(new Date());
const [showBoard, setShowBoard] = useState(false);
const [showChangelog, setShowChangelog] = useState(false);
@@ -1294,10 +1295,21 @@ function Dashboard({ toast, mobile, setActive, unreadMsgs=0, unreadBoard=0, unre
return (
<div style={{ padding: mobile ? '14px 12px 90px' : '36px 44px', maxWidth:1100 }}>
{showBoard && <BoardModal user={user} toast={toast} onClose={()=>setShowBoard(false)} onRead={onBoardRead}/>}
{showChangelog && <ChangelogModal user={user} toast={toast} onClose={()=>setShowChangelog(false)}/>}
{showChangelog && <ChangelogModal user={user} toast={toast} onClose={()=>setShowChangelog(false)} onRead={onChangelogRead}/>}
<div style={{ marginBottom:16, display:'flex', alignItems:'flex-start', justifyContent:'space-between' }}>
<div>
<h1 style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:mobile ? 17 : 22, margin:0 }}>Dashboard</h1>
<div style={{ display:'flex', alignItems:'center', gap:10 }}>
<h1 style={{ color:'#fff', fontFamily:"'Space Mono',monospace", fontSize:mobile ? 17 : 22, margin:0 }}>Dashboard</h1>
{unreadChangelog > 0 && (
<button onClick={()=>setShowChangelog(true)} style={{
background:'linear-gradient(135deg,rgba(78,205,196,0.15),rgba(78,205,196,0.05))',
border:'1px solid rgba(78,205,196,0.3)', borderRadius:20,
color:'#4ecdc4', cursor:'pointer', fontFamily:'monospace',
fontSize:10, padding:'3px 10px', letterSpacing:0.5,
animation:'pulse 2s infinite',
}}> Was ist neu?</button>
)}
</div>
<p style={{ color:'rgba(255,255,255,0.55)', fontFamily:'monospace', fontSize:10, marginTop:3 }}>
{now.toLocaleDateString('de-DE', { weekday:'long', day:'numeric', month:'long' })}
{' · '}
@@ -2158,6 +2170,7 @@ export default function App() {
const [unreadMsgs, setUnreadMsgs] = useState(0);
const [unreadBoard, setUnreadBoard] = useState(0);
const [unreadPromoted, setUnreadPromoted] = useState(0);
const [unreadChangelog,setUnreadChangelog]= useState(0);
const [authChecked, setAuthChecked] = useState(false);
useEffect(()=>{
@@ -2198,6 +2211,14 @@ export default function App() {
return()=>clearInterval(t);
},[user]);
useEffect(()=>{
if(!user)return;
const poll=()=>api('/dashboard/changelog/unread').then(d=>setUnreadChangelog(d.unread||0)).catch(()=>{});
poll();
const t=setInterval(poll,60*1000);
return()=>clearInterval(t);
},[user]);
useEffect(()=>{
if(!user)return;
const poll=()=>api('/tools/nachrichten/unread').then(d=>setUnreadMsgs(d.count||0)).catch(()=>{});
@@ -2245,7 +2266,7 @@ export default function App() {
unreadMsgs={unreadMsgs}/>
)}
<main style={mainStyle}>
{active==='dashboard' && <Dashboard toast={toast} mobile={mobile} setActive={setActive} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} user={user}/>}
{active==='dashboard' && <Dashboard toast={toast} mobile={mobile} setActive={setActive} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} user={user}/>}
{active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user}/>}
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive}/>}
</main>