From 136bc73216d676bcdb1e56cbaf920929a8ca1e4f Mon Sep 17 00:00:00 2001 From: Mayur Shinde Date: Tue, 9 Jun 2026 23:10:59 +0530 Subject: [PATCH] package content fully tenant-editable and versioned in the admin --- .../estimateWizard/EstimateWizardAdmin.jsx | 130 ++++++++++++++---- .../estimateWizard/data/tenantConfig.js | 28 ++++ 2 files changed, 134 insertions(+), 24 deletions(-) diff --git a/src/modules/estimateWizard/EstimateWizardAdmin.jsx b/src/modules/estimateWizard/EstimateWizardAdmin.jsx index d68dba5..e0825e5 100644 --- a/src/modules/estimateWizard/EstimateWizardAdmin.jsx +++ b/src/modules/estimateWizard/EstimateWizardAdmin.jsx @@ -8,9 +8,9 @@ */ import React, { useMemo, useState } from 'react'; import { toast } from 'sonner'; -import { Save, RotateCcw, Power, Sparkles, ShieldCheck, BarChart3 } from 'lucide-react'; +import { Save, RotateCcw, Power, Sparkles, ShieldCheck, BarChart3, Package, History } from 'lucide-react'; import { - getTenantConfig, loadConfigOverrides, saveConfigOverrides, resetConfigOverrides, + getTenantConfig, loadConfigOverrides, publishConfigOverrides, resetConfigOverrides, } from './data/tenantConfig'; import { loadSubmissions } from './api/crmHandoff'; @@ -31,9 +31,16 @@ const Toggle = ({ label, desc, checked, onChange, icon: Icon }) => ( const numInput = 'w-full rounded-lg border border-zinc-200 dark:border-white/10 bg-white dark:bg-zinc-900 px-2.5 py-1.5 text-sm text-zinc-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-amber-500'; +const textInput = numInput; +const areaInput = numInput + ' min-h-[64px] resize-y leading-relaxed'; + const EstimateWizardAdmin = () => { const initial = useMemo(() => getTenantConfig(), []); const [cfg, setCfg] = useState(initial); + const [versionInfo, setVersionInfo] = useState(() => { + const o = loadConfigOverrides(); + return { version: initial.version, versionedAt: o.versionedAt || null, history: o.versionHistory || [] }; + }); const submissions = useMemo(() => loadSubmissions(), []); const analytics = useMemo(() => { @@ -49,6 +56,8 @@ const EstimateWizardAdmin = () => { ...c, packages: c.packages.map((p) => (p.type === type ? { ...p, [field]: value } : p)), })); + // Included scope is edited as one item per line. + const setScope = (type, text) => setPkg(type, 'scope', text.split('\n').map((s) => s.trim()).filter(Boolean)); const setDiscount = (type, value) => setCfg((c) => ({ ...c, discountScenarios: { ...c.discountScenarios, [type]: { ...c.discountScenarios[type], base: value } }, @@ -64,17 +73,31 @@ const EstimateWizardAdmin = () => { conservativeMode: cfg.conservativeMode, branding: cfg.branding, discountScenarios: cfg.discountScenarios, + // Full Good/Better/Best content is tenant-controlled (spec §4/§14). packages: cfg.packages.map((p) => ({ - type: p.type, pricePerSquare: p.pricePerSquare, serviceLifeYears: p.serviceLifeYears, + type: p.type, + name: p.name, + category: p.category, + warrantyLabel: p.warrantyLabel, + hailResistance: p.hailResistance, + position: p.position, + fit: p.fit, + scope: p.scope, + pricePerSquare: p.pricePerSquare, + serviceLifeYears: p.serviceLifeYears, })), }; - saveConfigOverrides(overrides); - toast.success('Estimate Wizard settings saved'); + const saved = publishConfigOverrides(overrides); // bumps version + history + setVersionInfo({ version: saved.version, versionedAt: saved.versionedAt, history: saved.versionHistory }); + setCfg((c) => ({ ...c, version: saved.version })); + toast.success(`Published ${saved.version}`); }; const handleReset = () => { resetConfigOverrides(); - setCfg(getTenantConfig()); + const fresh = getTenantConfig(); + setCfg(fresh); + setVersionInfo({ version: fresh.version, versionedAt: null, history: [] }); toast.message('Reset to defaults'); }; @@ -88,15 +111,25 @@ const EstimateWizardAdmin = () => { Estimate Wizard — Admin

- Tenant controls for pricing, discounts, AI, branding, and analytics. + Tenant controls for package content, pricing, discounts, AI, branding, and analytics.

+
+ + {versionInfo.version} + + {versionInfo.versionedAt && ( + + published {new Date(versionInfo.versionedAt).toLocaleString()} + + )} +
@@ -108,25 +141,52 @@ const EstimateWizardAdmin = () => { setFlag('conservativeMode', v)} /> - {/* Package pricing */} + {/* Good / Better / Best content — fully tenant-controlled (spec §4/§14) */}
-

Packages, pricing & discounts

-
+

+ Good / Better / Best content +

+

+ Every customer-facing field is editable here — nothing is hard-coded. Saving publishes a new version. +

+
{cfg.packages.map((p) => ( -
-
-
{PKG_LABEL[p.type]}
-
{p.name}
+
+
{PKG_LABEL[p.type]}
+
+ + + + + +