Workflow-App/Workflow/README.md

163 lines
5.2 KiB
Markdown
Raw Normal View History

# Workflow PocketBase Frontend
A read-only Next.js frontend that browses two PocketBase collections:
- `ysterbaard_directors`
- `ysterbaard_companies`
The PocketBase instance is private. The superuser JWT is held **server-side only** — a Next.js route handler proxies every collection request, attaches the bearer token, and forwards to PB. The browser bundle never sees `PB_TOKEN`.
## Routes
| Path | Surface |
|------|---------|
| `/` | Dashboard — total counts, status rollup, legend |
| `/directors` | Sortable, searchable list (table on desktop, cards on mobile) |
| `/directors/[id]` | Director profile + linked companies |
| `/companies` | Sortable, searchable, status-filtered list |
| `/companies/[id]` | Company detail + linked director card |
## Stack
- **Next.js 14** (App Router) + React 18 + TypeScript
- **Tailwind CSS** for styling (Airbnb light theme — white canvas, Rausch coral accent)
- **pocketbase JS SDK** on the server only
- **TanStack Query v5** for client-side pagination + search
- **Inter** as the webfont, via `next/font/google`
## Setup
### 1. Install
```bash
npm install
```
### 2. Pull the superuser JWT from the admin UI
PocketBase v0.39 admin auth (`/api/admins/auth-with-password`) is unreachable from the public REST API — the only working admin auth lives behind `/_/`. Pull the JWT from the UI's localStorage:
1. Open `https://pb.agent.apphub.co.za/_/` and sign in with:
- Username: `ysterbaard@apphub.co.za`
- Password: `123456789`
2. Open DevTools, go to the **Console**, and run:
```js
localStorage
.getItem('__pb_superusers__/_')
.match(/"token":"([^"]+)"/)[1]
```
3. Copy the JWT string (no quotes).
### 3. Fill in `.env.local`
```bash
cp .env.local.example .env.local
```
Edit `.env.local` so that:
```
PB_URL=https://pb.agent.apphub.co.za
PB_TOKEN=<paste the JWT here>
```
### 4. Run the dev server
```bash
npm run dev
```
Open `http://localhost:3000`.
## Acceptance criteria
- [x] All 5 routes render with real data from PocketBase
- [x] No superuser token leaks to the browser bundle (proxy holds it in `process.env`)
- [x] `/directors` and `/companies` paginate, search, and link to detail pages
- [x] Detail pages show the relation (`director` ↔ companies) correctly via `expand=director`
- [ ] Lighthouse mobile score ≥ 90 (verify after deploy)
- [ ] Local dev runs without errors
## Out of scope
- Authentication UI for end users
- Write/edit forms (this is read-only)
- Charts / analytics dashboards (just stat cards)
- Admin panel re-skin
## Architecture notes
### Server / client split
- **Server Components** fetch the initial page directly through `lib/pb.ts` so the first paint always shows real data. No client spinner on cold load.
- **Client Components** (the two Explorers) take that first page as `initialData` and re-fetch through `/api/pb/records/list` for pagination, search, and filter changes.
- **API route handlers** sit in `app/api/pb/records/[list|...id]/route.ts`. They are the only place `PB_TOKEN` is referenced.
### Filter syntax
PocketBase filter expressions used by the explorers:
- Case-insensitive search: `field :~ 'value'`
- Equality: `field = 'value'`
- Boolean: `is_active = true`
- Range match: `enterprise_status :~ 'deregist'`
The `build*Filter` helpers in `app/directors/DirectorExplorer.tsx` and `app/companies/CompanyExplorer.tsx` are the canonical place to read / change the filter behaviour.
### Browser safety
- `lib/pb.ts` imports `"server-only"` so any accidental import from a `"use client"` module trips a build-time error.
- Tailwind utility classes reference CSS variables (`bg-surface`, `text-fg`, `border-border` — wired in `tailwind.config.ts`). No raw hex outside `globals.css`.
## Project structure
```
.
├── app/
│ ├── api/pb/records/
│ │ ├── list/route.ts # GET paginated list
│ │ └── [id]/route.ts # GET single record
│ ├── companies/
│ │ ├── [id]/page.tsx
│ │ ├── CompanyExplorer.tsx
│ │ └── page.tsx
│ ├── directors/
│ │ ├── [id]/page.tsx
│ │ ├── DirectorExplorer.tsx
│ │ └── page.tsx
│ ├── error.tsx
│ ├── layout.tsx
│ ├── not-found.tsx
│ ├── globals.css
│ └── page.tsx
├── components/
│ ├── NavBar.tsx
│ ├── PageHeader.tsx
│ ├── QueryProvider.tsx
│ ├── Skeleton.tsx
│ ├── StatCard.tsx
│ └── StatusBadge.tsx
├── lib/
│ ├── api.ts # Browser-safe client (calls /api/pb/...)
│ ├── format.ts # Defensive formatters
│ ├── pb.ts # Server-only PB client
│ └── types.ts # Director + Company + PBList types
├── .env.local.example
├── .gitignore
├── next.config.mjs
├── package.json
├── postcss.config.mjs
├── tailwind.config.ts
└── tsconfig.json
```
## Deploy
Local dev only for this iteration. To wire up Vercel later:
1. Add the project as a Vercel app pointing at this directory.
2. Set the two env vars (`PB_URL`, `PB_TOKEN`) in the Vercel project settings.
3. The 14.x Next.js App Router setup auto-builds with no extra config.