feat(projects): Project Overview cockpit UI + CRM nav entry

- ProjectsListPage: searchable list + inline create, under CRM → Overview.
- ProjectCockpitPage: editable header, milestone timeline, and one dated
  feed merging emails (with sent-HTML preview modal + resend/cancel/retry/
  send-now actions), quotes, contracts, invoices, galleries and hours.
- Routes /admin/clients/projects(/:id) gated by RequireFeature flag=projects.
- ClientsLayout 'Overview' nav entry (top), gated on flags.projects.
- en + de i18n for the projects namespace + book-to-project label.
This commit is contained in:
Luca
2026-06-06 13:25:38 +02:00
parent 0175007abc
commit 81553aa0e3
6 changed files with 585 additions and 1 deletions
+8
View File
@@ -43,6 +43,8 @@ import { HoursLoggingPage } from './pages/admin/clients/HoursLoggingPage';
const CalendarPage = lazy(() => import('./pages/admin/clients/CalendarPage').then((m) => ({ default: m.CalendarPage })));
import { QuoteResponsePage } from './pages/public/QuoteResponsePage';
import { ContractResponsePage } from './pages/public/ContractResponsePage';
import { ProjectsListPage } from './pages/admin/projects/ProjectsListPage';
import { ProjectCockpitPage } from './pages/admin/projects/ProjectCockpitPage';
import { ContractsListPage } from './pages/admin/contracts/ContractsListPage';
import { ContractEditorPage } from './pages/admin/contracts/ContractEditorPage';
import { ContractDetailPage } from './pages/admin/contracts/ContractDetailPage';
@@ -202,6 +204,12 @@ function App() {
<Route path="quotes/:id" element={<QuoteDetailPage />} />
<Route path="quotes/:id/edit" element={<QuoteEditorPage />} />
</Route>
{/* Project Overview (CRM) — admin-only grouping
layer above events, gated by `projects`. */}
<Route element={<RequireFeature flag="projects" />}>
<Route path="projects" element={<ProjectsListPage />} />
<Route path="projects/:id" element={<ProjectCockpitPage />} />
</Route>
{/* Bills / invoices (CRM) — gated by `bills`. */}
<Route element={<RequireFeature flag="bills" />}>
<Route path="bills" element={<BillsListPage />} />