/* ===== Page views ===== */ /* ---------- Dashboard home ---------- */ function DashboardView({ nav, favs, toggleFav }) { const total = window.SECTIONS.length; const catCount = window.CATEGORIES.length; const myDownloads = window.getMyDownloads ? window.getMyDownloads() : 0; const [tab, setTab] = useState('recent'); const recent = window.SECTIONS.slice() .sort((a, b) => new Date(b.added) - new Date(a.added)).slice(0, 6); const popular = window.SECTIONS.slice() .sort((a, b) => b.popularity - a.popularity).slice(0, 6); const topCats = window.CATEGORIES.slice() .sort((a, b) => window.catCount(b.id) - window.catCount(a.id)).slice(0, 6); const feed = tab === 'recent' ? recent : popular; const openCat = (c) => nav({ view: 'category', catId: c.id }); const openSec = (s) => nav({ view: 'section', sectionId: s.id }); const spark = [40, 62, 34, 74, 52, 90, 64]; return (
{/* KPI row */}
Live library
{total}
Sections Available
{spark.map((h, i) => )}
{catCount}
Categories
{myDownloads}
Your Downloads
HTML & React exports
{favs.length}
Favorites
{/* Browse by Category (left) + tabbed feed (right) */}

Browse by Category

{topCats.map(c => )}
{feed.map((s, i) => )}
); } /* ---------- Browse / library ---------- */ function BrowseView({ nav, favs, toggleFav, search, route }) { const [cats, setCats] = useState(route.catId ? [route.catId] : []); const [fw, setFw] = useState('all'); const [sort, setSort] = useState(route.sort || 'popular'); let list = window.SECTIONS.filter(s => { if (cats.length && !cats.includes(s.category)) return false; if (fw !== 'all' && !s.frameworks.includes(fw)) return false; if (search) { const q = search.toLowerCase(); const hay = (s.name + ' ' + s.tags.join(' ') + ' ' + window.catById(s.category).label).toLowerCase(); if (!hay.includes(q)) return false; } return true; }); list = list.sort((a, b) => sort === 'new' ? new Date(b.added) - new Date(a.added) : sort === 'downloads' ? b.downloads - a.downloads : b.popularity - a.popularity); return (
Library

Browse all sections

{list.length} {list.length === 1 ? 'result' : 'results'}{search ? ' for “' + search + '”' : ''}
{['all', 'html', 'react'].map(f => )}
{cats.length > 0 && (
{cats.map(id => { const c = window.catById(id); return ( ); })}
)} {list.length === 0 ? :
{list.map(s => nav({ view: 'section', sectionId: sec.id })} />)}
}
); } /* ---------- Category detail ---------- */ function CategoryView({ nav, favs, toggleFav, route }) { const cat = window.catById(route.catId); const list = window.SECTIONS.filter(s => s.category === cat.id).sort((a, b) => b.popularity - a.popularity); return (

{cat.label}

{cat.blurb} · {list.length} sections

{list.map(s => nav({ view: 'section', sectionId: sec.id })} />)}
); } /* ---------- Collections ---------- */ function CollectionsView({ nav, favs, toggleFav }) { return (
Curated

Collections

Hand-picked bundles ready to assemble into full pages.

{window.COLLECTIONS.map(col => { const items = col.items.map(window.sectionById).filter(Boolean); return (

{col.name}

{col.desc} · {items.length} sections

{items.map(s => nav({ view: 'section', sectionId: sec.id })} />)}
); })}
); } /* ---------- Favorites ---------- */ function FavoritesView({ nav, favs, toggleFav }) { const list = favs.map(window.sectionById).filter(Boolean); return (
Saved

Your favorites

{list.length} saved {list.length === 1 ? 'section' : 'sections'}.

{list.length === 0 ? :
{list.map(s => nav({ view: 'section', sectionId: sec.id })} />)}
}
); } /* ---------- Section detail ---------- */ function SectionView({ nav, favs, toggleFav, route, notify, refresh }) { const section = window.sectionById(route.sectionId); const cat = window.catById(section.category); const isCustom = window.SectionStore.isCustom(section.id); const isEdited = window.SectionStore.isEdited(section.id); const [confirmDel, setConfirmDel] = useState(false); const [device, setDevice] = useState('desktop'); const widths = { desktop: 1280, tablet: 834, mobile: 390 }; const isFav = favs.includes(section.id); const related = window.SECTIONS.filter(s => s.category === cat.id && s.id !== section.id).slice(0, 3); useEffect(() => { const el = document.querySelector('.content'); if (el) el.scrollTop = 0; }, [route.sectionId]); return (

{section.name}

{cat.label} · {section.downloads.toLocaleString()} downloads · Added {window.timeAgo(section.added)} {section.pro && Pro} {isCustom && Custom} {isEdited && Edited}
{confirmDel ?
Delete this section?
: <> {isEdited && } }
{[['desktop', 'desktop'], ['tablet', 'device'], ['mobile', 'device']].map(([d, ic]) => )}
sectionly.app/preview/{section.id}
{widths[device]}px
{related.length > 0 && <>

More in {cat.label}

{related.map(s => nav({ view: 'section', sectionId: sec.id })} />)}
}
); } /* ---------- Empty state ---------- */ function EmptyState({ heart }) { return (

{heart ? 'No favorites yet' : 'No sections found'}

{heart ? 'Tap the heart on any section to save it here.' : 'Try a different search or category filter.'}

); } Object.assign(window, { DashboardView, BrowseView, CategoryView, CollectionsView, FavoritesView, SectionView, EmptyState });