From 6b7d8c4abae9b9726977a4dffe3c93ea27a597c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gjermund=20H=C3=B8s=C3=B8ien=20Wiggen?= Date: Sun, 7 Jun 2026 21:56:36 +0200 Subject: [PATCH] Fix next.config.ts API proxy, add web pages spec --- docs/web-pages-spec.md | 64 ++++++++++++++++++++++++++++++++++++++++++ web/next.config.ts | 9 +++++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 docs/web-pages-spec.md diff --git a/docs/web-pages-spec.md b/docs/web-pages-spec.md new file mode 100644 index 0000000..e76e825 --- /dev/null +++ b/docs/web-pages-spec.md @@ -0,0 +1,64 @@ +Create the Tessera frontend files in web/src/. The Next.js + shadcn/ui scaffold already exists. Only create TypeScript/TSX files — no bash commands needed. + +## Files to create (read existing scaffold files first to understand imports) + +### 1. web/src/lib/types.ts +Copy the types from the web spec (docs/web-spec.md lines 89-110). Add import for Lucide icons where needed. Create TypeScript interfaces for: Ticket, Queue, Transaction, Scrip, Template, Lifecycle, LifecycleDefinition, CustomField, CustomFieldValue, PreviewResult, PreparedScrip, UpdateResult, ScripResult. + +### 2. web/src/lib/api.ts +Fetch wrapper using the types. Base URL is '/api' (proxied by next.config.ts to backend). +Every function returns Promise<{ data: T | null; error: string | null }>. +Import types from './types'. +Implement all 15 functions from docs/web-spec.md lines 69-84. +Use try/catch with fetch. Parse JSON responses. Handle non-200 status codes. +Use backend URL path mapping: /api/tickets, /api/queues, /api/scrips, /api/custom-fields, /api/lifecycles. + +### 3. web/src/app/layout.tsx +Add dark mode. Import Inter from next/font/google. Set className="dark" on html element. +Import and use existing components: no shadcn components needed for layout. +Nav bar with gradient and blur. Content area with min-height. + +### 4. web/src/app/page.tsx (ticket list) +Full ticket list page with: +- State: tickets array, queues array, filters (queue_id, status), loading, error +- Fetch tickets + queues on mount with useEffect +- Filter bar: Select for queue (shadcn Select), Select for status, Filter button +- Table using shadcn Table component +- Badge for status (shadcn Badge) with colors: new=default, open=blue, in_progress=yellow, resolved=green, closed=gray +- Click row → useRouter router.push(`/tickets/${id}`) +- Empty state: "No tickets yet" +- "New Ticket" button → shadcn Dialog with form (subject input, queue select) +- Form uses useState for values, calls createTicket on submit +- Loading: "Loading tickets..." text +- Error: red text with error message + +### 5. web/src/app/tickets/[id]/page.tsx +Ticket detail page with: +- State: ticket, transactions, loading, error, selectedStatus, previewResult +- Back link using Link from next/link +- Ticket info: Card with subject, status badge, queue, dates, owner +- Status change: Select dropdown, "Preview" button (calls previewTicket, shows in Dialog), "Apply" button (calls updateTicket) +- Transaction timeline: Card with list of transactions. Each shows type badge (colored), field change, timestamp using date-fns formatDistanceToNow +- Custom fields: Card showing CF name:value pairs (from ticket.custom_fields) + +### 6. web/src/app/admin/page.tsx +Admin page with shadcn Tabs: Queues, Lifecycles, Scrips, Custom Fields. +Each tab: list table + "Add" button → Dialog with form. +Uses existing API functions from lib/api.ts. + +## Rules +- Use shadcn/ui components by importing from '@/components/ui/...' (e.g. '@/components/ui/button') +- Use lucide-react for icons (import from 'lucide-react') +- All state management with React useState/useEffect +- No external state libraries +- Proper TypeScript types everywhere +- Handle loading and error states +- Dark theme is automatic via the dark class on html +- Use Tailwind classes for spacing and layout +- Minimal styling needed — shadcn handles it + +## Verification +After creating all files: +1. Run `cd /home/gjermund/projects/tessera/web && nix-shell -p bun --run "bun run build"` to verify no compile errors +2. Fix any type errors +3. Commit after each file diff --git a/web/next.config.ts b/web/next.config.ts index e9ffa30..959768f 100644 --- a/web/next.config.ts +++ b/web/next.config.ts @@ -1,7 +1,14 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + async rewrites() { + return [ + { + source: '/api/:path*', + destination: 'http://127.0.0.1:9876/api/:path*', + }, + ]; + }, }; export default nextConfig;