feat(customers): customer portal (#354) on top of feature-flags reorg
Implements the recurring-customer login surface from the-luap/picpeak#354 plugged into the maintainer's new feature-flag infrastructure (PR #443) instead of a parallel toggle. * New `customerPortal` feature flag (foundation flag for the not-yet-built calendar/quotes/bills/messaging customer surfaces). Defaults FALSE on fresh installs, TRUE on existing installs (events > 0) via migration 095 so live customer accounts don't disappear mid-deployment. * Foundation schema: customer_accounts, customer_invitations, event_customer_assignments, customer_password_resets, plus RBAC permissions customers.view / .create / .delete granted to super_admin + admin system roles. * Backend: /api/admin/customers (invite, list, search, assign, deactivate, reset password) + /api/customer/auth/* + /api/customer/* (login, dashboard, accept-invite, reset). Customer JWT bypass minted via /api/customer/events/:slug/access-token so existing gallery middleware stays untouched. * Frontend: /customer/* route tree gated by RequireFeature flag customerPortal, with login / dashboard / accept-invite / reset pages and a customer-side sidebar layout. /admin/customers and /admin/customers/:id gated identically. * Settings → Features grows a "Customers" section with a Customer portal card. The maintainer's Features tab stays the single source of truth — no parallel Advanced features tab. * CustomerAccountPicker on event create/edit forms hides itself when the flag is off; backend ignores customer_account_ids in that case instead of erroring the whole event save. Translations: en + de hand-translated. nl/pt/ru fall through to en — flagged here as needing native review. Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
Receipt,
|
||||
BarChart3,
|
||||
Users,
|
||||
UserCog,
|
||||
} from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Card } from '../../../components/common';
|
||||
@@ -107,6 +108,26 @@ export const FeaturesTab: React.FC = () => {
|
||||
/>
|
||||
</Section>
|
||||
|
||||
{/* Customer accounts (#354) — recurring customer logins. The
|
||||
calendar / quotes / bills / messaging cards below are
|
||||
customer-side surfaces; they only render in the customer
|
||||
dashboard when this is on. */}
|
||||
<Section title={t('settings.features.sections.customers', 'Customers')}>
|
||||
<FeatureCard
|
||||
icon={UserCog}
|
||||
title={t('settings.features.customerPortal.title', 'Customer portal')}
|
||||
description={t(
|
||||
'settings.features.customerPortal.description',
|
||||
'Persistent customer logins. Recurring clients see all their assigned galleries from one place — no per-event passwords. Foundation for Calendar / Quotes / Bills (which only render in the customer dashboard when this is on).',
|
||||
)}
|
||||
status="beta"
|
||||
statusLabel={statusLabel('beta')}
|
||||
sidebarLabel={t('navigation.customers', 'Customers')}
|
||||
enabled={staged.customerPortal}
|
||||
onToggle={(next) => setFlag('customerPortal', next)}
|
||||
/>
|
||||
</Section>
|
||||
|
||||
{/* Communication */}
|
||||
<Section title={t('settings.features.sections.communication', 'Communication')}>
|
||||
<FeatureCard
|
||||
|
||||
Reference in New Issue
Block a user