From f01ee372800720f5e70d423899d4e9a778b099ea Mon Sep 17 00:00:00 2001 From: Dicken Date: Fri, 29 May 2026 10:52:26 +0200 Subject: [PATCH] Schnellzugriff Mobile: Pfeile nur wenn wischbar, overflow:hidden, Seitenindikatoren --- frontend/src/App.jsx | 190 ++++++++++++++++++++++++++++--------------- 1 file changed, 125 insertions(+), 65 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 8719ccf..f2fab86 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -435,6 +435,112 @@ function BottomNav({ active, setActive, user, onLogout, updateInfo, onUpdateClic // ── Dashboard Widgets ───────────────────────────────────────────────────────── +// ── QuickLinks Carousel (Mobile) ───────────────────────────────────────────── +function QuickLinksCarousel({ links }) { + const iconW = 58; const gap = 6; + const containerW = window.innerWidth - 28; + const perRow = Math.max(3, Math.floor((containerW + gap) / (iconW + gap))); + const pageSize = perRow * 2; + const pageCount = Math.ceil(links.length / pageSize); + + const [page, setPage] = useState(0); + const scrollRef = useRef(null); + + // Sync scroll position → page indicator + const onScroll = () => { + if (!scrollRef.current) return; + const p = Math.round(scrollRef.current.scrollLeft / containerW); + setPage(p); + }; + + const canLeft = page > 0; + const canRight = page < pageCount - 1; + + const scrollTo = (p) => { + scrollRef.current?.scrollTo({ left: p * containerW, behavior:'smooth' }); + }; + + if (pageCount <= 1) return ( +
+ {links.map(l => )} +
+ ); + + return ( +
+ {/* Scroll container – overflow hidden so nothing peeks */} +
+ {Array.from({length: pageCount}, (_,pi) => ( +
+ {links.slice(pi*pageSize, (pi+1)*pageSize).map(l => )} +
+ ))} +
+ + {/* Left arrow */} + {canLeft && ( + + )} + + {/* Right arrow */} + {canRight && ( + + )} + + {/* Page dots */} + {pageCount > 1 && ( +
+ {Array.from({length:pageCount}, (_,i) => ( +
scrollTo(i)} style={{ + width: i===page ? 14 : 5, height:5, borderRadius:3, cursor:'pointer', + background: i===page ? '#4ecdc4' : 'rgba(255,255,255,0.2)', + transition:'all 0.2s', + }}/> + ))} +
+ )} +
+ ); +} + +function QuickLinkIcon({ l }) { + return ( + + {l.icon && l.icon.startsWith('http') + ? e.target.style.display='none'}/> + : {l.icon}} + {l.title} + + ); +} + function QuickLinks({ toast, mobile }) { const { confirm, ConfirmDialog } = useConfirm(); const [links, setLinks] = useState([]); @@ -485,71 +591,25 @@ function QuickLinks({ toast, mobile }) { {/* Link-Grid */} {links.length === 0 && !editMode ?
Links können unter Einstellungen → Dashboard hinzugefügt werden.
- : mobile ? (() => { - // Mobile: max 2 Zeilen, dann horizontal scrollbar - // Berechne Icons pro Zeile anhand der Viewport-Breite - const iconW = 58 + 6; // minWidth + gap - const containerW = window.innerWidth - 28 - 28; // padding links+rechts (S.card=14px*2) - const perRow = Math.max(3, Math.floor(containerW / iconW)); - const maxVisible = perRow * 2; - const needsScroll = links.length > maxVisible; - const pages = needsScroll - ? Math.ceil(links.length / maxVisible) - : 1; - // Gruppen zu je maxVisible Icons - const groups = []; - for (let i = 0; i < links.length; i += maxVisible) groups.push(links.slice(i, i + maxVisible)); - return ( -
- {groups.map((group, gi) => ( -
- {group.map(l => ( -
- - {l.icon && l.icon.startsWith('http') - ? e.target.style.display='none'}/> - : {l.icon}} - {l.title} - -
- ))} -
- ))} -
- ); - })() - :
- {links.map(l => ( -
- - {l.icon && l.icon.startsWith('http') - ? e.target.style.display='none'}/> - : {l.icon}} - {l.title} - -
- ))} -
+ : mobile + ? + :
+ {links.map(l => ( +
+ + {l.icon && l.icon.startsWith('http') + ? e.target.style.display='none'}/> + : {l.icon}} + {l.title} + +
+ ))} +
} {/* Formular */}