Files
leocrm/.a0/briefings/T07b_continuation_briefing.md
leocrm-bot 700b7a71ad T07b: frontend feature pages — companies + contacts + settings + audit + dashboard + search
- 11 new feature pages (CompaniesList/Detail/Form, ContactsList/Detail/Form,
  SettingsProfile/Roles/Users, AuditLog, GlobalSearchResults)
- 3 page updates (Dashboard with StatCard+ActivityFeed, Settings with tree nav+Outlet,
  TopBar with SearchDropdown)
- 13 new routes in routes/index.tsx
- i18n updates (de.json + en.json) with companies/contacts/settings/audit/search keys
- 12 new test files + 2 existing test fixes (TopBar, AppShell)
- 7 shared components (DataGrid, Tabs, SearchDropdown, CsvImportDialog, StatCard,
  ActivityFeed, UnsavedChangesGuard)
- 16 new API hooks in hooks.ts
- Verification: 141 tests pass, build succeeds, tsc --noEmit clean
2026-06-29 11:01:39 +02:00

5.9 KiB

T07b Continuation — Frontend Feature Pages (Part 2)

Project Root

/a0/usr/workdir/dev-projects/leocrm

Frontend Directory

/a0/usr/workdir/dev-projects/leocrm/frontend/

What's Already Done (DO NOT recreate)

API Hooks (src/api/hooks.ts — 432 lines, modified)

16 new hooks already added: useCompany, useCreateCompany, useUpdateCompany, useDeleteCompany, useContact, useCreateContact, useUpdateContact, useDeleteContact, useCompanyExport, useCompanyImport, useAuditLog, useGlobalSearch, plus CRUD for users.

Shared Components (src/components/shared/ — all exist)

  • Tabs.tsx (2055 bytes) — Tab navigation component
  • StatCard.tsx (1107 bytes) — Dashboard stat card
  • ActivityFeed.tsx (1372 bytes) — Activity feed list
  • DataGrid.tsx (6067 bytes) — TanStack Table wrapper with search/sort/pagination
  • SearchDropdown.tsx (6275 bytes) — Debounced search dropdown with highlighting
  • CsvImportDialog.tsx (5429 bytes) — CSV upload + preview dialog
  • UnsavedChangesGuard.tsx (821 bytes) — useBlocker-based unsaved changes warning

Dependencies

What Remains (ALL of this must be created)

1. Feature Pages (src/pages/)

Companies:

  • CompaniesList.tsx — Use DataGrid component, search/filter/sort/pagination, CSV import (CsvImportDialog) + export buttons, empty state with create button (AC 1, 4, 5, 20)
  • CompanyDetail.tsx — Tabs: overview, contacts, files, activity (AC 2)
  • CompanyForm.tsx — RHF + Zod, validate name required, unsaved changes guard (AC 3, 22)

Contacts:

  • ContactsList.tsx — Use DataGrid, loading skeleton rows, empty state (AC 6, 21)
  • ContactDetail.tsx — Tabs: overview, companies, files, activity (AC 7)
  • ContactForm.tsx — RHF + Zod, validate first_name/last_name/email, multi-company assignment (AC 8, 9)

Settings:

  • SettingsProfile.tsx — Update name, email, password, avatar (AC 11)
  • SettingsRoles.tsx — Create role, assign permissions, save (AC 12)
  • SettingsUsers.tsx — List users, invite user, change role, deactivate (AC 13)

Other:

  • AuditLog.tsx — Filterable table (date, user, action, entity). Call useAuditLog hook. Handle 404 gracefully with empty state (AC 14)
  • GlobalSearchResults.tsx — Filters (entity type, date), highlight matched terms. Call useGlobalSearch hook (AC 17, 18)

2. Page Updates

  • Dashboard.tsx — Replace placeholder with stat cards (StatCard component) + recent activity feed (ActivityFeed component) (AC 15)
  • Settings.tsx — Add tree navigation (Profile, Roles, Users, System). Render child routes (AC 10)
  • TopBar.tsx — Add SearchDropdown in topbar for global search (AC 16)

3. Routes (src/routes/index.tsx)

Add these routes:

/companies              → CompaniesList
/companies/:id          → CompanyDetail
/companies/new          → CompanyForm
/companies/:id/edit     → CompanyForm
/contacts               → ContactsList
/contacts/:id           → ContactDetail
/contacts/new           → ContactForm
/contacts/:id/edit      → ContactForm
/audit-log              → AuditLog
/search                 → GlobalSearchResults
/settings/profile       → SettingsProfile
/settings/roles         → SettingsRoles
/settings/users         → SettingsUsers

4. i18n Updates (src/i18n/locales/de.json + en.json)

Add translation keys for all new pages: companies, contacts, settings, audit_log, search, dashboard sections.

5. Tests (src/tests/)

Create test files:

  • companies/CompaniesList.test.tsx
  • companies/CompanyDetail.test.tsx
  • companies/CompanyForm.test.tsx
  • contacts/ContactsList.test.tsx
  • contacts/ContactDetail.test.tsx
  • contacts/ContactForm.test.tsx
  • settings/SettingsProfile.test.tsx
  • settings/SettingsRoles.test.tsx
  • settings/SettingsUsers.test.tsx
  • dashboard/Dashboard.test.tsx
  • search/GlobalSearch.test.tsx
  • AuditLog.test.tsx

6. Verification

Run these commands and report results:

cd /a0/usr/workdir/dev-projects/leocrm/frontend
npx vitest run src/__tests__/ --reporter=verbose
npm run build
npx tsc --noEmit

Tech Stack

  • React 18 + Vite + TypeScript
  • TanStack Query v5 (hooks in src/api/hooks.ts)
  • Zustand (stores in src/store/)
  • react-i18next (de/en locales)
  • React Hook Form + Zod
  • Tailwind CSS
  • Vitest + @testing-library/react
  • @tanstack/react-table v8

Existing UI Components (src/components/ui/)

Avatar, Badge, Button, Card, ConfirmDialog, EmptyState, Input, Modal, Pagination, Select, Skeleton, Table, Toast

Existing Layout (src/components/layout/)

AppShell, Sidebar, TopBar

API Client (src/api/client.ts)

Axios instance with interceptors. Base URL: http://localhost:8000. Auth via session cookie.

Backend API Endpoints

GET/POST/PATCH/DELETE /api/v1/companies
GET /api/v1/companies/{id}            # includes contacts[]
GET /api/v1/companies/export?format=csv
POST /api/v1/companies/import          # CSV upload
GET/POST/PATCH/DELETE /api/v1/contacts
GET /api/v1/contacts/{id}             # includes companies[]
GET/POST/PATCH/DELETE /api/v1/users
GET /api/v1/users/{id}
GET /api/v1/notifications
GET /api/v1/plugins
GET /health

Note: No /api/v1/audit endpoint exists yet. useAuditLog hook may 404 — handle gracefully. Note: No dedicated search endpoint. useGlobalSearch calls useCompanies + useContacts with search param.

Company Schema

name: str (required, 1-100 chars)
account_number: str | None (max 40)
industry: str | None (max 50)
phone: str | None (max 30)
email: str | None (max 255)
website: str | None (max 500)
description: str | None

Rules

  • TypeScript only, no .js files
  • No Lorem Ipsum — use real German/English content
  • Reuse existing UI components, don't recreate them
  • Keep responses under 50 lines — reference files by path
  • Use real content, not placeholder text
  • All 23 acceptance criteria must be covered
  • Test files must use @testing-library/react with vitest