Dashboard: Kalender naechster Eintrag mit TT.MM. HH:MM, Schnellzugriff 4 pro Reihe zentriert
This commit is contained in:
@@ -437,19 +437,17 @@ function BottomNav({ active, setActive, user, onLogout, updateInfo, onUpdateClic
|
|||||||
// ── Dashboard Widgets ─────────────────────────────────────────────────────────
|
// ── Dashboard Widgets ─────────────────────────────────────────────────────────
|
||||||
// ── QuickLinks Carousel (Mobile) ─────────────────────────────────────────────
|
// ── QuickLinks Carousel (Mobile) ─────────────────────────────────────────────
|
||||||
function QuickLinksCarousel({ links }) {
|
function QuickLinksCarousel({ links }) {
|
||||||
const iconW = 58; const gap = 6;
|
const perRow = 4;
|
||||||
const containerW = window.innerWidth - 28;
|
const gap = 6;
|
||||||
const perRow = Math.max(3, Math.floor((containerW + gap) / (iconW + gap)));
|
|
||||||
const pageSize = perRow * 2;
|
const pageSize = perRow * 2;
|
||||||
const pageCount = Math.ceil(links.length / pageSize);
|
const pageCount = Math.ceil(links.length / pageSize);
|
||||||
|
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const scrollRef = useRef(null);
|
const scrollRef = useRef(null);
|
||||||
|
|
||||||
// Sync scroll position → page indicator
|
|
||||||
const onScroll = () => {
|
const onScroll = () => {
|
||||||
if (!scrollRef.current) return;
|
if (!scrollRef.current) return;
|
||||||
const p = Math.round(scrollRef.current.scrollLeft / containerW);
|
const p = Math.round(scrollRef.current.scrollLeft / scrollRef.current.offsetWidth);
|
||||||
setPage(p);
|
setPage(p);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -457,18 +455,17 @@ function QuickLinksCarousel({ links }) {
|
|||||||
const canRight = page < pageCount - 1;
|
const canRight = page < pageCount - 1;
|
||||||
|
|
||||||
const scrollTo = (p) => {
|
const scrollTo = (p) => {
|
||||||
scrollRef.current?.scrollTo({ left: p * containerW, behavior:'smooth' });
|
scrollRef.current?.scrollTo({ left: p * scrollRef.current.offsetWidth, behavior:'smooth' });
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pageCount <= 1) return (
|
if (pageCount <= 1) return (
|
||||||
<div style={{ display:'grid', gridTemplateColumns:`repeat(${perRow}, 1fr)`, gap }}>
|
<div style={{ display:'grid', gridTemplateColumns:`repeat(${perRow}, 1fr)`, gap, justifyItems:'center' }}>
|
||||||
{links.map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
{links.map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ position:'relative' }}>
|
<div style={{ position:'relative' }}>
|
||||||
{/* Scroll container – overflow hidden so nothing peeks */}
|
|
||||||
<div ref={scrollRef} onScroll={onScroll} style={{
|
<div ref={scrollRef} onScroll={onScroll} style={{
|
||||||
display:'flex', overflowX:'auto', scrollSnapType:'x mandatory',
|
display:'flex', overflowX:'auto', scrollSnapType:'x mandatory',
|
||||||
scrollbarWidth:'none', WebkitOverflowScrolling:'touch',
|
scrollbarWidth:'none', WebkitOverflowScrolling:'touch',
|
||||||
@@ -479,8 +476,9 @@ function QuickLinksCarousel({ links }) {
|
|||||||
display:'grid',
|
display:'grid',
|
||||||
gridTemplateColumns:`repeat(${perRow}, 1fr)`,
|
gridTemplateColumns:`repeat(${perRow}, 1fr)`,
|
||||||
gridTemplateRows:'repeat(2, auto)',
|
gridTemplateRows:'repeat(2, auto)',
|
||||||
|
justifyItems:'center',
|
||||||
gap, flexShrink:0, scrollSnapAlign:'start',
|
gap, flexShrink:0, scrollSnapAlign:'start',
|
||||||
width: containerW,
|
width:'100%', minWidth:'100%',
|
||||||
}}>
|
}}>
|
||||||
{links.slice(pi*pageSize, (pi+1)*pageSize).map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
{links.slice(pi*pageSize, (pi+1)*pageSize).map(l => <QuickLinkIcon key={l.id} l={l}/>)}
|
||||||
</div>
|
</div>
|
||||||
@@ -2383,10 +2381,7 @@ export default function App() {
|
|||||||
const [user,setUser]=useState(null);
|
const [user,setUser]=useState(null);
|
||||||
const [active,setActiveRaw]=useState('dashboard');
|
const [active,setActiveRaw]=useState('dashboard');
|
||||||
const setActive = (page) => {
|
const setActive = (page) => {
|
||||||
if (window.__newBuildAvailable) {
|
import('./main.jsx').then(m => m.reloadIfNewBuild?.()).catch(()=>{});
|
||||||
window.location.reload();
|
|
||||||
return; // kein Rendern mehr, Reload läuft
|
|
||||||
}
|
|
||||||
setActiveRaw(page);
|
setActiveRaw(page);
|
||||||
};
|
};
|
||||||
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
const [toastMsg,setToastMsg]=useState({msg:'',type:'success'});
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ export default function CalendarWidget() {
|
|||||||
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:9, flexShrink:0 }}>
|
<span style={{ color:'rgba(255,255,255,0.35)', fontFamily:'monospace', fontSize:9, flexShrink:0 }}>
|
||||||
{nextEvent.allDay
|
{nextEvent.allDay
|
||||||
? nextEvent.dtstart.toLocaleDateString('de-DE',{day:'numeric',month:'short'})
|
? nextEvent.dtstart.toLocaleDateString('de-DE',{day:'numeric',month:'short'})
|
||||||
: nextEvent.dtstart.toLocaleTimeString('de-DE',{hour:'2-digit',minute:'2-digit'})
|
: nextEvent.dtstart.toLocaleString('de-DE',{day:'2-digit',month:'2-digit',hour:'2-digit',minute:'2-digit'})
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user