feat(branding): Customer dashboard header toggles in Branding page

Adds back the "Show logo" / "Show company name" toggles for the
customer dashboard, scoped to /customer/* surfaces only. Lives as a
dedicated card at the bottom of Settings → Branding, gated by the
customerPortal feature flag so admins who haven't enabled the portal
don't see it.

* Backend: restored GET/PUT /admin/settings/customer-surface
  endpoints, whitelisted only to the two branding keys
  (customer_show_logo, customer_show_company_name). The
  calendar/quotes/bills feature globals that used to live on this
  endpoint are now driven by the Features tab (feature_flags table).
* customerAccountsService.getCustomerSurfaceGlobals() reads from
  app_settings again so /api/customer/auth/session honours the
  toggles in its branding payload.
* New CustomerDashboardBrandingCard component with its own save
  flow — separate from the main BrandingPage payload so flipping a
  toggle doesn't replay the full branding mutation.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
Luca
2026-05-11 01:52:27 +02:00
co-authored by Claude Opus 4.6
parent da08a5828a
commit b252cb67eb
6 changed files with 314 additions and 10 deletions
+23 -10
View File
@@ -761,23 +761,36 @@ async function isCustomerPortalEnabled() {
}
/**
* Customer-surface global feature toggles. The customer-portal feature
* flag (read above) is the master switch; calendar / quotes / bills are
* locked behind their own maintainer-side flags (Settings → Features)
* but those surfaces aren't yet built — return false so the customer
* dashboard doesn't render placeholder tabs.
* Customer-surface global toggles. Branding visibility (logo /
* company name in the customer dashboard header) lives in
* app_settings under setting_type='customer_surface' and is edited
* from the Branding page (Customer dashboard card, gated by the
* customerPortal feature flag).
*
* Branding visibility (logo / company name) is no longer per-instance
* configurable on the customer surface — the customer layout always
* shows the configured brand to keep parity with /admin.
* Calendar / Quotes / Bills feature globals are intentionally OFF
* here — those surfaces are now governed by the maintainer's
* feature_flags table (Settings → Features), not by app_settings.
*
* Returns sane defaults when the keys aren't present so an install
* missing migration 092 doesn't crash — branding defaults ON to
* match the visual state before the toggle existed.
*/
async function getCustomerSurfaceGlobals() {
const rows = await db('app_settings').where('setting_type', 'customer_surface').select('setting_key', 'setting_value');
const map = {};
for (const r of rows) {
let v = r.setting_value;
if (typeof v === 'string') {
try { v = JSON.parse(v); } catch { /* leave as-is */ }
}
map[r.setting_key] = v;
}
return {
calendarEnabled: false,
quotesEnabled: false,
billsEnabled: false,
showLogo: true,
showCompanyName: true,
showLogo: map.customer_show_logo !== false, // default true
showCompanyName: map.customer_show_company_name !== false, // default true
};
}