feat(ui): scaffold vite + react 19 frontend
Replaces the CRA + React 16 + class-component frontend with the
shape from architecture/generic.md §4: vite + react + swc + ts,
served as static from nginx in prod, vite dev server in dev with
/api proxied to localhost:8080.
Layout:
ui/
package.json, vite.config.ts, tsconfig.{json,app,node}.json
index.html
src/
main.tsx — react root + react-query provider
App.tsx — header, filters, vertical timeline
App.css — dark backdrop, hot-pink links
api/client.ts — TS types mirroring moments-entities;
fetchEvents, fetchSources via /api/v1
components/
Filters.tsx — source toggles, count slider, date range
TimelineEntry.tsx — renders one TimelineItem with body
support for markdown, commits, links
lib/icon.tsx — TimelineIcon → react-bootstrap-icons map
+ colour per icon
Stack: react 19, @tanstack/react-query 5, react-bootstrap 2 (on
bootstrap 5), react-vertical-timeline-component 3, rc-slider 11
(<Slider range /> replaces the removed v8 Range), react-markdown 9.
Dev proxy: /api/* → http://localhost:8080/* (rewrite strips /api).
Backend stays location-agnostic at /v1; ingress prefix is added
by nginx (and the dev proxy) so the same fetch shape works in
both environments.
Verified: tsc -b clean, vite build clean (417 KB js / 245 KB css
gzip 128 / 33), vite dev server serves the index. NOT verified
visually in a browser — that's a `pnpm run dev` away on roosta
once the api is up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
56
ui/src/lib/icon.tsx
Normal file
56
ui/src/lib/icon.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import {
|
||||
ArrowLeftRight,
|
||||
ArrowUpCircle,
|
||||
ArrowsAngleContract,
|
||||
Bug,
|
||||
ChatLeft,
|
||||
CodeSquare,
|
||||
DashCircle,
|
||||
Diagram3,
|
||||
ExclamationCircle,
|
||||
PlusCircle,
|
||||
StarFill,
|
||||
Tag,
|
||||
Wrench,
|
||||
} from 'react-bootstrap-icons';
|
||||
import type { TimelineIcon } from '../api/client';
|
||||
|
||||
const map: Record<TimelineIcon, typeof Wrench> = {
|
||||
'git-push': ArrowUpCircle,
|
||||
'git-commit': CodeSquare,
|
||||
'git-merge': ArrowsAngleContract,
|
||||
'git-fork': Diagram3,
|
||||
'git-branch-create': PlusCircle,
|
||||
'git-branch-delete': DashCircle,
|
||||
'pull-request': ArrowLeftRight,
|
||||
issue: ExclamationCircle,
|
||||
comment: ChatLeft,
|
||||
star: StarFill,
|
||||
release: Tag,
|
||||
bug: Bug,
|
||||
generic: Wrench,
|
||||
};
|
||||
|
||||
const colors: Record<TimelineIcon, string> = {
|
||||
'git-push': '#2e7d32',
|
||||
'git-commit': '#1565c0',
|
||||
'git-merge': '#6a1b9a',
|
||||
'git-fork': '#1565c0',
|
||||
'git-branch-create': '#2e7d32',
|
||||
'git-branch-delete': '#c62828',
|
||||
'pull-request': '#1565c0',
|
||||
issue: '#ef6c00',
|
||||
comment: '#1565c0',
|
||||
star: '#f9a825',
|
||||
release: '#6a1b9a',
|
||||
bug: '#c62828',
|
||||
generic: '#546e7a',
|
||||
};
|
||||
|
||||
export function iconFor(name: TimelineIcon) {
|
||||
return map[name] ?? Wrench;
|
||||
}
|
||||
|
||||
export function colorFor(name: TimelineIcon) {
|
||||
return colors[name] ?? colors.generic;
|
||||
}
|
||||
Reference in New Issue
Block a user