W0 web foundation: Vite + React SPA under /app/, sync-pull ledger, auth, tokens, shared components
Build Kvitt images / build (push) Failing after 1h14m5s
Build Kvitt images / build (push) Failing after 1h14m5s
web/ is the browser client's scaffold: Vite 8, React 19, TypeScript 5.9 strict, React Router 7 (basename /app, every fixed route with a lazy placeholder page), TanStack Query 5 (refetch on focus and every 60 s), openapi-typescript types generated from contracts/openapi.yaml with openapi-fetch. Reads go through GET /sync (no REST reads exist for the ledger, SPEC §7): useLedger() pulls from cursor 0 and then incrementally, restarting on a new epoch or cursor_ahead. Login pairs the browser as "Web · <browser>" with an invite code (E-3); every call sends the SPEC §14.3.1 headers, a 401 signs out. kvitt-domain's split, balances, allocation and settlement rules are ported to web/src/lib and pass every case of contracts/test-vectors. Design tokens from design-spec §2 in tokens.css (light-dark()), Material Symbols Rounded (Apache-2.0) as generated inline SVG, sv/en catalogs generated from docs/ux/strings.csv plus web-strings.csv. Gate: cd web && npm run check. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import { PlaceholderPage } from '../../app/PlaceholderPage';
|
||||
import { paths } from '../../app/routes';
|
||||
import { useI18n } from '../../i18n/useI18n';
|
||||
|
||||
/** S-5 Account detail, /app/accounts/:id. */
|
||||
export default function AccountDetailPage() {
|
||||
const { t } = useI18n();
|
||||
return <PlaceholderPage title={t('web_account_detail_title')} back={paths.home} />;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { useParams } from 'react-router';
|
||||
import { PlaceholderPage } from '../../app/PlaceholderPage';
|
||||
import { paths } from '../../app/routes';
|
||||
import { useI18n } from '../../i18n/useI18n';
|
||||
|
||||
/** S-6 Account editor: /app/accounts/new and /app/accounts/:id/edit. */
|
||||
export default function AccountEditorPage() {
|
||||
const { t } = useI18n();
|
||||
const { id } = useParams();
|
||||
return id === undefined ? (
|
||||
<PlaceholderPage title={t('account_editor_new')} back={paths.home} />
|
||||
) : (
|
||||
<PlaceholderPage title={t('account_editor_edit')} back={paths.account(id)} />
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { RouteObject } from 'react-router';
|
||||
import { lazyPage } from '../../app/lazyPage';
|
||||
|
||||
/** Routes of W1's accounts, relative to /app (inside the shell). */
|
||||
export const accountsRoutes: RouteObject[] = [
|
||||
{ path: 'accounts/new', ...lazyPage(() => import('./AccountEditorPage')) },
|
||||
{ path: 'accounts/:id', ...lazyPage(() => import('./AccountDetailPage')) },
|
||||
{ path: 'accounts/:id/edit', ...lazyPage(() => import('./AccountEditorPage')) },
|
||||
];
|
||||
Reference in New Issue
Block a user