Chronicle Visualizer app page
Imported React file from app/page.jsx.
Source file
app/page.jsx
React176 lines
"use client";import { useMemo, useState } from "react";const projects = ["all", "hyphenomenon", "rps-etsy", "family-shapes", "tmora", "shopify", "codex-skills"];const frames = Array.from({ length: 72 }).map((_, index) => {const hour = 12 - Math.floor(index / 12);const minute = 55 - ((index * 5) % 60);const project = projects[(index % (projects.length - 1)) + 1];const status = index % 9 === 0 ? "quarantine" : index % 4 === 0 ? "candidate" : "private";return {id: `frame-${index + 1}`,time: `${Math.max(7, hour)}:${String(Math.max(0, minute)).padStart(2, "0")} ${hour >= 12 ? "PM" : "AM"}`,group: hour >= 11 ? "June 4, 2026 - Midday Capture" : "June 4, 2026 - Morning Capture",project,status,summary: project === "tmora"? "Inferred TMORA print-production context. Raw screen content stays private until reviewed.": `Inferred ${project} work context. Publication requires redaction review and source-safe summary text.`};});const statusLabels = {private: "raw private",candidate: "redaction candidate",quarantine: "quarantined"};export default function Home() {const [project, setProject] = useState("all");const [query, setQuery] = useState("");const [selected, setSelected] = useState(frames[7]);const visibleFrames = useMemo(() => {const normalized = query.trim().toLowerCase();return frames.filter((frame) => {const projectMatch = project === "all" || frame.project === project;const text = `${frame.project} ${frame.status} ${frame.summary}`.toLowerCase();return projectMatch && (!normalized || text.includes(normalized));});}, [project, query]);const groups = useMemo(() => {return visibleFrames.reduce((acc, frame) => {acc[frame.group] ||= [];acc[frame.group].push(frame);return acc;}, {});}, [visibleFrames]);return (<main className="viewer-shell"><aside className="side-nav" aria-label="Chronicle viewer sections"><a className="brand" href="/"><span className="brand-mark" aria-hidden="true" />Chronicle</a><nav><a className="active" href="/">Timeline</a><a href="/docs">Docs</a><a href="/projects">Projects</a></nav><div className="storage-note"><strong>Raw archive</strong><span>Private object storage planned. Git is for source and reviewed public derivatives.</span></div></aside><section className="timeline-app"><header className="app-toolbar"><div><h1>Visual Timeline</h1><p>Public app scaffold using synthetic/redacted placeholders. Raw captures are not loaded here.</p></div><div className="toolbar-controls"><label className="app-search"><span>Search</span><inputvalue={query}onChange={(event) => setQuery(event.target.value)}placeholder="project, redaction status, summary"/></label><button type="button">Archive setup</button><button type="button">Redaction queue</button></div></header><section className="filter-row" aria-label="Project filters">{projects.map((item) => (<buttonclassName={project === item ? "selected" : ""}key={item}onClick={() => setProject(item)}type="button">{item === "all" ? "All projects" : item}</button>))}</section><div className="viewer-content"><section className="timeline-canvas" aria-label="Chronicle visual timeline">{Object.entries(groups).map(([group, items]) => (<section className="frame-group" key={group}><header><h2>{group}</h2><span>{items.length} frames</span></header><div className="frame-grid">{items.map((frame, index) => (<buttonclassName={`frame-card ${frame.status} ${selected?.id === frame.id ? "is-selected" : ""}`}key={frame.id}onClick={() => setSelected(frame)}type="button"><span className="synthetic-screen"><span className="screen-bar" /><span className="screen-line short" /><span className="screen-line" /><span className={index % 5 === 0 ? "redaction-block wide" : "redaction-block"} /></span><span className="frame-time">{frame.time}</span><span className="frame-project">{frame.project}</span></button>))}</div></section>))}</section><aside className="detail-panel" aria-label="Selected frame details"><div className="date-rail" aria-label="Date scrubber"><a href="#june-4" className="active">Jun 4</a><a href="#summaries">Summaries</a><a href="#archive">Archive</a></div>{selected ? (<article className="inspector"><div className={`status-pill ${selected.status}`}>{statusLabels[selected.status]}</div><h2>{selected.time}</h2><p>{selected.summary}</p><dl><div><dt>Project label</dt><dd>{selected.project} <span>inferred</span></dd></div><div><dt>Source visibility</dt><dd>private raw frame</dd></div><div><dt>Publication state</dt><dd>{selected.status === "candidate" ? "needs review" : "not public"}</dd></div></dl><section className="policy-box"><h3>Publication boundary</h3><p>This app must publish only reviewed redacted derivatives. Raw screenshots, OCR,local paths, and private summaries stay outside git and public deploys.</p></section></article>) : null}</aside></div></section></main>);}