Commit graph

21 commits

Author SHA1 Message Date
ed3c6de272 Compliance snapshot redesign: BizPortal AR summary + SARS placeholder; CIPC address labels; Math.abs amount fix 2026-08-27 21:18:22 +02:00
Ysterbaard
a79145f0d2 Fix: clearing a field in the edit modal did not persist
The modal's submit handler wrapped every optional field with
"if (value.trim()) fields.x = value.trim()". When the user
deleted the content of a field, the value was empty, the guard
returned false, and the field was OMITTED from the PATCH entirely.
PB then left the existing value in place.

Symptom: edit a field, delete its content, save. The DB still
has the old value.

Fix: always send every field. Empty string ("") clears a value
in PocketBase (verified end-to-end). Required-field validation
(surname, first_names, enterprise_no, enterprise_name) still
guards against empty required values up-front.

Also fixed the modal's React Query invalidation to target the
list pages' actual keys (["companies"], ["directors"]) in
addition to the incorrect ["pb-list"] key. This makes the
list page refetch after save.

Same fix applied to DeleteConfirmModal for consistency.
2026-08-19 12:04:58 +02:00
Ysterbaard
1fecf02214 Add pre-send validation gate + idempotent sign-back to appointment flow
PB: 3 new fields on ysterbaard_director_appointments
  - proceed_anyway (bool) — true if user proceeded with missing emails
  - missing_emails (text) — comma-separated keys
  - missing_emails_detail (text) — JSON per-recipient validation

App:
  - POST /api/appointments: builds recipient report (initial +
    distro); returns 422 + report if proceed_anyway is missing
    and any recipient is missing/invalid. preview=1 returns the
    report without sending.
  - PATCH /api/appointments/[id]: tightened idempotency guard to
    also short-circuit on signature_received (not just
    mail_sent_to_all). Prevents double-send on double-click.
  - DirectorAppointmentTab: two-step modal — "Validate recipients"
    surfaces the report (status dots + per-recipient email),
    then Send / Proceed anyway / Fix records first. New
    "company_email" gap surfaced before any email leaves.
  - lib/format.ts: isValidEmail() shared helper.

End-to-end tested: 422 enforces server-side, preview returns
the report, double-PATCH signs only once.
2026-08-18 21:29:08 +02:00
Ysterbaard
9bd35898a2 Add onboarding form fields to companies + directors (visual + editable)
PB: 15 fields on ysterbaard_companies (financial_year_end_month,
authorised_shares, structured physical/postal address, company_cell_phone,
public_officer_name, company_secretary_name), 11 fields on
ysterbaard_directors (date_of_birth, structured residential/postal address).

App: types widened in lib/types.ts. EditEntityModal rebuilt with full
address sections (line 1, line 2, town/city, SA province dropdown,
postal code), DOB, company-level fields, financial year end month,
authorised shares, public officer, company secretary.

View pages: structured address blocks now show labeled fields
(line 1, line 2, town/city, province, postal code) on both
/companies/[id] and /directors/[id].
2026-08-18 12:25:06 +02:00
Dave
37d94f4241 Add company_email to EditEntityModal company form 2026-08-17 20:08:33 +02:00
Dave
c349998fa1 feat: Task Kanban UI + Python task worker
Adds the visible front-end and the worker back-end for the agent
task system. The PocketBase schema, API routes, and ToastProvider
were already in the previous commit; this commit completes the
picture.

UI
- app/tasks/{page,KanbanBoard,TaskCard,CardModal,TaskDetail,api,columns}
  Full Kanban with six columns (Backlog, Ready, In Progress,
  Blocked, Done, Failed), drag-and-drop between columns, quick-add
  chips, type/priority filters, task detail panel with retry/cancel/
  delete, 5s polling, transition toasts.
- components/NavBar.tsx: 'Tasks' link in primary nav.
- app/bizportal-2/BizPortal2Explorer.tsx: 'Send to Kanban' button
  on the result view — dispatches the current search to the agent
  queue as a 'ready' task.

Back-end
- scripts/task_worker.py: PocketBase polling worker with two
  lanes. Deterministic handles bizportal_search/reserve, pdf_generate,
  email_send. Custom lane writes to /tmp/agent_inbox/ for the
  LLM agent to pick up. Atomic claim via PB filter, auto-retry up
  to 3x, structured log on each task.
- scripts/bizportal_service.py: bugfix — _is_logged_in was using
  a non-CSS selector so session-recovery was a no-op. Also made
  the login flow re-runnable mid-session (handles BizPortal's
  ~20-minute session timeout transparently).
- scripts/init_pb_schema.py: duration_ms no longer capped at 0.

Verified end-to-end:
- CK search via worker: 1 company, 3 directors, ~10s
- ID search via worker: 4 companies, 7 total directors, ~34s
- Auto-retry + status transitions + toast fires
2026-08-17 18:57:02 +02:00
Dave
2fb979b98a Director appointment acceptance — full feature
- DirectorAppointmentTab: table + 'Acceptance Letter' modal with company/director dropdowns
- GET/POST /api/appointments: create record, generate HTML letter, convert to PDF via LibreOffice, email to director via himalaya SMTP
- PATCH /api/appointments/[id]: save signature PNG, embed in signed letter PDF, mail to all company directors
- GET /api/appointments/sign/[token]: public token lookup
- /sign/[token]/page.tsx: public signature canvas (mouse + touch)
- ysterbaard_director_appointments PB collection (requires manual schema setup)
- Section 3 'Director Appointment' now active in ResolutionExplorer
- NEXT_PUBLIC_APP_URL added to .env.local
2026-08-17 18:39:14 +02:00
Dave
da504c45a0 wip: registration wizard, address splits, document panel, appointments
Uncommitted work in progress at the point of starting the Kanban
project. Captures:
- Registration wizard refactor + multi-step routing
- structured physical/postal address fields on companies and directors
- appointments flow (sign + verify)
- document type manager + upload/panel for companies and directors
- status actions, approve button, action/dropdown buttons
- step2 review page

tsconfig.tsbuildinfo is now ignored (build artefact).
2026-08-17 18:33:56 +02:00
Dave
7c3847fbb0 feat: BizPortal 2.0 — Python Playwright sidecar
Replaces the brittle agent-driven /api/bizportal/search queue with a
deterministic Python FastAPI service that drives BizPortal via a real
headless Chromium. The old flow is untouched.

What this adds:
- scripts/bizportal_service.py — FastAPI + Playwright service with
  /search, /reserve, /health endpoints. Persistent login session
  via storage_state.json. Locator-based selectors (vs eval JS).
- app/bizportal-2/ — new /bizportal-2 page, synchronous fetch
  (no polling), shows round-trip duration, mirrors the existing
  bulk-add + link UX.
- app/api/bizportal-2/{search,reserve,health}/route.ts — thin
  proxies to the Python sidecar.
- scripts/README.md, .env.example, .gitignore, requirements.txt.
- .gitignore: ignore tsconfig.tsbuildinfo (build artefact).

Wiring:
- components/NavBar.tsx: 'BizPortal 2.0' nav entry with TEST badge.
- app/bizportal/page.tsx: 'Try BizPortal 2.0' action link in
  header so the new option is discoverable from the existing page.

Run: cd scripts && source .venv/bin/activate && uvicorn
bizportal_service:app --port 7001
2026-08-17 18:33:36 +02:00
Dave
c1b98a6eca feat: split company physical and postal addresses into structured fields 2026-08-14 21:00:14 +02:00
Dave
4c0a256d63 feat: split director residential and postal addresses into structured fields 2026-08-14 20:49:44 +02:00
Dave
c8fcddfbf1 feat: print to PDF button on registration detail view 2026-08-14 19:51:59 +02:00
Dave
5cedaf714c feat: add BizPortal tab + name-already-approved flow + registrations improvements 2026-08-14 18:08:51 +02:00
Dave
c5ee550795 feat: Revert button also in name_approved section 2026-08-11 21:07:48 +02:00
Dave
567972bd19 fix: Revert button also in bizportal_in_progress section 2026-08-11 21:07:00 +02:00
Dave
d05a2440db feat: Revert to Step 1 (New Names) button — clears CIPC fields on rejection 2026-08-11 20:59:46 +02:00
Dave
59c460a3d6 feat: Check Mail button on Step 2 + check-cipc-mail API route 2026-08-11 18:33:03 +02:00
SJCoetz
45e017c7c3 Add 'View all →' shortcut to Registrations page in Resolutions tab 2026-07-30 18:24:23 +02:00
SJCoetz
2d06ca27d6 Use type=tel for all ID number fields to trigger numeric keypad on mobile 2026-07-30 17:53:41 +02:00
SJCoetz
adead9148f Add native Share button to registration link dialog 2026-07-30 16:38:05 +02:00
SJCoetz
bb97fef453 feat: initialize full ysterbaard frontend application
Add complete production-ready Ysterbaard PocketBase registry browser frontend:
- Next.js 14 App Router with TypeScript, Tailwind CSS, and TanStack React Query
- Secure server-side PocketBase API proxy to avoid exposing superuser tokens
- Read-only directors and companies registry browse pages with search, filtering, and pagination
- Client onboarding workflow for creating and managing client submissions
- Docker container configuration for easy deployment
- All supporting UI components, utility functions, and configuration files
2026-07-23 19:10:47 +02:00