mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 03:05:32 +02:00
feat(ui): rewrite frontend in React with Vite
- Scaffold Vite+React project in frontend/ (bun, react 18, @vitejs/plugin-react) - vite.config.js outputs to crates/archivr-server/static/ directly - src/utils.js: formatBytes, valueText, formatTimestamp, SOURCE_ICONS, sourceIconSvg - src/api.js: typed fetch wrappers for all API endpoints - App.jsx: full state management, archive switching, debounced search, tag filter, view routing, capture dialog orchestration - components/Topbar.jsx: archive switcher, nav, capture button - components/CaptureDialog.jsx: native <dialog> ref with showModal/close, Escape key support, locator validation - components/EntriesView.jsx + EntryRow.jsx: flex table with source icons, type pills, keyboard selection - components/ContextRail.jsx: parallel detail+tags fetch, stale-race guard via selectSeqRef, inline tag assign/remove - components/RunsView.jsx: runs kept as <table> (matches original) - components/AdminView.jsx: mounted archives list - components/TagsView.jsx: recursive tag tree with active state - Remove old app.js; styles.css moved to frontend/src/ (Vite bundles it)
This commit is contained in:
parent
b895d6331c
commit
4458f17b13
22 changed files with 1035 additions and 591 deletions
20
frontend/src/components/Topbar.jsx
Normal file
20
frontend/src/components/Topbar.jsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export default function Topbar({ archives, archiveId, onArchiveChange, view, onViewChange, onCaptureClick }) {
|
||||
return (
|
||||
<header className="topbar">
|
||||
<div className="brand">Archivr</div>
|
||||
<select className="archive-switcher" aria-label="Select archive"
|
||||
value={archiveId ?? ''} onChange={e => onArchiveChange(e.target.value)}>
|
||||
{archives.map(a => <option key={a.id} value={a.id}>{a.label}</option>)}
|
||||
</select>
|
||||
<nav className="nav" aria-label="Primary">
|
||||
{['archive', 'runs', 'admin', 'tags'].map(name => (
|
||||
<button key={name} className={`nav-link${view === name ? ' is-active' : ''}`}
|
||||
onClick={() => onViewChange(name)}>
|
||||
{name.charAt(0).toUpperCase() + name.slice(1)}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
<button className="capture-button" onClick={onCaptureClick}>+ Capture</button>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue