feat(projects): gate Project Overview behind a projects feature flag + cockpit email actions
- Migration 120 seeds the projects flag (default OFF), idempotent. - Backend feature-flags whitelist + DEFAULT_FLAGS + clients derivation. - adminProjects routes 403 PROJECTS_DISABLED when the flag is off. - projectService email actions (resend/cancel/retry/send-now) + routes. - Frontend flag type, DEFAULT_FLAGS, Features tab card (en+de).
This commit is contained in:
@@ -45,6 +45,10 @@ export const DEFAULT_FLAGS: FeatureFlags = {
|
||||
// Settings → Features once they've reviewed the seeded block
|
||||
// library with their lawyer.
|
||||
contracts: false,
|
||||
// Projects (migration 120). Admin-only grouping layer above events +
|
||||
// the Project Overview cockpit. Off by default — admin opts in under
|
||||
// Settings → Features once they want the CRM → Overview area.
|
||||
projects: false,
|
||||
};
|
||||
|
||||
export const FEATURE_FLAGS_QUERY_KEY = ['feature-flags'] as const;
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
Briefcase,
|
||||
Wrench,
|
||||
Calculator,
|
||||
FolderKanban,
|
||||
} from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Card } from '../../../components/common';
|
||||
@@ -291,6 +292,20 @@ export const FeaturesTab: React.FC = () => {
|
||||
enabled={staged.hoursLogging}
|
||||
onToggle={(next) => setFlag('hoursLogging', next)}
|
||||
/>
|
||||
|
||||
<FeatureCard
|
||||
icon={FolderKanban}
|
||||
title={t('settings.features.projects.title', 'Projects')}
|
||||
description={t(
|
||||
'settings.features.projects.description',
|
||||
'Admin-only grouping layer above events. Bundle several events under one project and open a 360° Project Overview cockpit — milestone timeline plus a dated feed of every email (with the actual sent preview + resend/cancel/retry actions), quote, contract, invoice, gallery and logged hour. Adds a "book to project" control when logging hours. Customers never see projects.',
|
||||
)}
|
||||
status="new"
|
||||
statusLabel={statusLabel('new')}
|
||||
sidebarLabel={t('settings.features.projects.sidebar', 'Overview')}
|
||||
enabled={staged.projects}
|
||||
onToggle={(next) => setFlag('projects', next)}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
{/* Insights & Access */}
|
||||
|
||||
@@ -1666,6 +1666,11 @@
|
||||
"title": "Stundenerfassung",
|
||||
"description": "Zeiterfassung pro Kunde. Admin erfasst Datum + Start-/Endzeit + optionalen Satz-Override + Notiz. Kunden im Monatsmodus akkumulieren Stunden automatisch in den laufenden Monatsentwurf; Kunden pro Anlass sehen eine Schaltfläche „Entwurfsrechnung erstellen“, die eine eigenständige Entwurfsrechnung mit einer Zeile pro Eintrag erzeugt. Unabhängig von Rechnungen — Stunden erfassen, noch bevor die volle Abrechnungsoberfläche aktiviert ist.",
|
||||
"sidebar": "Stunden"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projekte",
|
||||
"description": "Nur-Admin-Gruppierungsebene über Events. Bündle mehrere Events unter einem Projekt und öffne ein 360°-Projektübersichts-Cockpit — Meilenstein-Zeitleiste plus ein datierter Verlauf aller E-Mails (mit der tatsächlich gesendeten Vorschau + Erneut-senden/Abbrechen/Wiederholen-Aktionen), Angebote, Verträge, Rechnungen, Galerien und erfassten Stunden. Fügt beim Erfassen von Stunden eine „Auf Projekt buchen“-Option hinzu. Kunden sehen Projekte nie.",
|
||||
"sidebar": "Übersicht"
|
||||
}
|
||||
},
|
||||
"customerSurface": {
|
||||
|
||||
@@ -1224,6 +1224,11 @@
|
||||
"title": "Hours logging",
|
||||
"description": "Per-customer time tracking. Admin logs date + start/end times + optional rate override + note. Monthly-mode customers auto-accumulate hours into the running monthly draft; per-event customers see a \"Create draft invoice\" button that mints a standalone draft invoice with one line per entry. Independent of Bills — log hours even before turning the full billing surface on.",
|
||||
"sidebar": "Hours"
|
||||
},
|
||||
"projects": {
|
||||
"title": "Projects",
|
||||
"description": "Admin-only grouping layer above events. Bundle several events under one project and open a 360° Project Overview cockpit — milestone timeline plus a dated feed of every email (with the actual sent preview + resend/cancel/retry actions), quote, contract, invoice, gallery and logged hour. Adds a \"book to project\" control when logging hours. Customers never see projects.",
|
||||
"sidebar": "Overview"
|
||||
}
|
||||
},
|
||||
"customerSurface": {
|
||||
|
||||
@@ -41,7 +41,11 @@ export type FeatureKey =
|
||||
// upload. Independent of quotes / bills — contracts can be sent on
|
||||
// their own. Seeded block bodies are examples only; admins must
|
||||
// have their lawyer review before sending. See docs/crm-disclaimers.md.
|
||||
| 'contracts';
|
||||
| 'contracts'
|
||||
// Projects (migration 120). Admin-only grouping layer above events with the
|
||||
// 360° Project Overview cockpit + the "book to project" hours control. Off
|
||||
// by default; gates the CRM → Overview area entirely.
|
||||
| 'projects';
|
||||
|
||||
export type FeatureFlags = Record<FeatureKey, boolean>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user