feat: Dashboard Auto-Refresh bei Navigation, Bestätigungs-Badge auf Favoriten, User→Favoriten-Tab
This commit is contained in:
@@ -1988,7 +1988,9 @@ function Dashboard({ toast, mobile, setActive, setDevToolsNav, unreadMsgs=0, unr
|
|||||||
setActive('media');
|
setActive('media');
|
||||||
setTimeout(()=>window.dispatchEvent(new CustomEvent('media-navigate',{detail:'favoriten'})),80);
|
setTimeout(()=>window.dispatchEvent(new CustomEvent('media-navigate',{detail:'favoriten'})),80);
|
||||||
} else {
|
} else {
|
||||||
api('/tools/media/favorites/user-notify',{method:'POST',body:{}}).then(()=>setUnackedFavs({count:0,isAdmin:false})).catch(()=>{});
|
api('/tools/media/favorites/user-notify',{method:'POST',body:{}})
|
||||||
|
.then(()=>{ setUnackedFavs({count:0,isAdmin:false}); setActive('media'); setTimeout(()=>window.dispatchEvent(new CustomEvent('media-navigate',{detail:'favoriten'})),80); })
|
||||||
|
.catch(()=>{});
|
||||||
}
|
}
|
||||||
}} style={{
|
}} style={{
|
||||||
background:'rgba(245,158,11,0.12)', border:'1px solid rgba(245,158,11,0.35)',
|
background:'rgba(245,158,11,0.12)', border:'1px solid rgba(245,158,11,0.35)',
|
||||||
@@ -3618,9 +3620,8 @@ export default function App() {
|
|||||||
const [active,setActiveRaw]=useState('dashboard');
|
const [active,setActiveRaw]=useState('dashboard');
|
||||||
const [devToolsNav, setDevToolsNav] = useState(null);
|
const [devToolsNav, setDevToolsNav] = useState(null);
|
||||||
const setActive = (page) => {
|
const setActive = (page) => {
|
||||||
// Reload nur beim Klick auf Dashboard und nur wenn ein neuer Build vorliegt
|
|
||||||
// und keine Eingabe aktiv ist (schützt ungespeicherte Eingaben)
|
|
||||||
if (page === 'dashboard' && window.__newBuildAvailable && window.__safeReloadIfNewBuild?.()) return;
|
if (page === 'dashboard' && window.__newBuildAvailable && window.__safeReloadIfNewBuild?.()) return;
|
||||||
|
if (page === 'dashboard') setDashboardKey(k => k + 1); // Force-Refresh
|
||||||
setActiveRaw(page);
|
setActiveRaw(page);
|
||||||
};
|
};
|
||||||
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
||||||
@@ -3630,6 +3631,7 @@ export default function App() {
|
|||||||
const [unreadChangelog,setUnreadChangelog]= useState(0);
|
const [unreadChangelog,setUnreadChangelog]= useState(0);
|
||||||
const [unackedFavs, setUnackedFavs] = useState({count:0,isAdmin:false});
|
const [unackedFavs, setUnackedFavs] = useState({count:0,isAdmin:false});
|
||||||
const [mediaInitTab, setMediaInitTab] = useState(null);
|
const [mediaInitTab, setMediaInitTab] = useState(null);
|
||||||
|
const [dashboardKey, setDashboardKey] = useState(0);
|
||||||
|
|
||||||
const [authChecked, setAuthChecked] = useState(false);
|
const [authChecked, setAuthChecked] = useState(false);
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
@@ -3728,7 +3730,7 @@ export default function App() {
|
|||||||
unreadMsgs={unreadMsgs}/>
|
unreadMsgs={unreadMsgs}/>
|
||||||
)}
|
)}
|
||||||
<main ref={mainRef} style={mainStyle}>
|
<main ref={mainRef} style={mainStyle}>
|
||||||
{active==='dashboard' && <Dashboard toast={toast} mobile={mobile} setActive={setActive} setDevToolsNav={setDevToolsNav} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} unackedFavs={unackedFavs} user={user}/>}
|
{active==='dashboard' && <Dashboard key={dashboardKey} toast={toast} mobile={mobile} setActive={setActive} setDevToolsNav={setDevToolsNav} unreadMsgs={unreadMsgs} unreadBoard={unreadBoard} unreadPromoted={unreadPromoted} onBoardRead={()=>{ setUnreadBoard(0); setUnreadPromoted(0); }} unreadChangelog={unreadChangelog} onChangelogRead={()=>setUnreadChangelog(0)} unackedFavs={unackedFavs} user={user}/>}
|
||||||
{active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user} nav={devToolsNav}/>}
|
{active==='admin' && <AdminPanel toast={toast} mobile={mobile} user={user} nav={devToolsNav}/>}
|
||||||
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'?{nav:devToolsNav}:{})} {...(activeTool.id==='media' ? {initTab:mediaInitTab, onInitTabConsumed:()=>setMediaInitTab(null)} : {})}/>}
|
{activeTool && <activeTool.component toast={toast} mobile={mobile} setActive={setActive} {...(activeTool.id==='devtools'?{nav:devToolsNav}:{})} {...(activeTool.id==='media' ? {initTab:mediaInitTab, onInitTabConsumed:()=>setMediaInitTab(null)} : {})}/>}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -526,12 +526,21 @@ function SucheGrid({ onOpenModal, xrelIds, onXrelLoaded }) {
|
|||||||
function FavCard({ f, onOpenModal, onRemove }) {
|
function FavCard({ f, onOpenModal, onRemove }) {
|
||||||
const genres = (() => { try { return JSON.parse(f.genres||'[]'); } catch { return []; } })();
|
const genres = (() => { try { return JSON.parse(f.genres||'[]'); } catch { return []; } })();
|
||||||
const fskStyle = FSK_COLOR(f.fsk);
|
const fskStyle = FSK_COLOR(f.fsk);
|
||||||
|
const isAcked = !!f.acknowledged && !f.user_notified;
|
||||||
return (
|
return (
|
||||||
<div onClick={() => onOpenModal({ id: f.tmdb_id, media_type: f.media_type || 'movie' })} style={{
|
<div onClick={() => onOpenModal({ id: f.tmdb_id, media_type: f.media_type || 'movie' })} style={{
|
||||||
display:'flex', gap:12, alignItems:'flex-start',
|
display:'flex', gap:12, alignItems:'flex-start',
|
||||||
background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.06)',
|
background: isAcked ? 'rgba(74,222,128,0.05)' : 'rgba(255,255,255,0.03)',
|
||||||
|
border: `1px solid ${isAcked ? 'rgba(74,222,128,0.25)' : 'rgba(255,255,255,0.06)'}`,
|
||||||
borderRadius:8, padding:'10px 12px', cursor:'pointer', position:'relative',
|
borderRadius:8, padding:'10px 12px', cursor:'pointer', position:'relative',
|
||||||
}}>
|
}}>
|
||||||
|
{isAcked && (
|
||||||
|
<div style={{position:'absolute',top:6,right:44,background:'rgba(74,222,128,0.15)',
|
||||||
|
border:'1px solid rgba(74,222,128,0.35)',borderRadius:10,padding:'2px 8px',
|
||||||
|
color:'#4ade80',fontFamily:'monospace',fontSize:9,pointerEvents:'none'}}>
|
||||||
|
✓ bestätigt
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div style={{ width:44, height:66, flexShrink:0, borderRadius:5, overflow:'hidden', background:'#111' }}>
|
<div style={{ width:44, height:66, flexShrink:0, borderRadius:5, overflow:'hidden', background:'#111' }}>
|
||||||
{f.poster_path
|
{f.poster_path
|
||||||
? <img src={POSTER + f.poster_path} alt={f.title} style={{ width:'100%', height:'100%', objectFit:'cover', display:'block' }} />
|
? <img src={POSTER + f.poster_path} alt={f.title} style={{ width:'100%', height:'100%', objectFit:'cover', display:'block' }} />
|
||||||
|
|||||||
Reference in New Issue
Block a user