@powerhousedao/service-offering 1.0.0-dev.22 → 1.0.0-dev.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/document-models/resource-template/v1/actions.d.ts +1 -0
- package/dist/document-models/resource-template/v1/actions.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/document-model.js +174 -163
- package/dist/document-models/resource-template/v1/gen/document-schema.d.ts +6 -0
- package/dist/document-models/resource-template/v1/gen/document-schema.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/ph-factories.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/ph-factories.js +2 -0
- package/dist/document-models/resource-template/v1/gen/reducer.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/reducer.js +6 -1
- package/dist/document-models/resource-template/v1/gen/schema/types.d.ts +7 -0
- package/dist/document-models/resource-template/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/schema/zod.d.ts +2 -1
- package/dist/document-models/resource-template/v1/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/schema/zod.js +9 -0
- package/dist/document-models/resource-template/v1/gen/template-management/actions.d.ts +6 -2
- package/dist/document-models/resource-template/v1/gen/template-management/actions.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/template-management/creators.d.ts +3 -2
- package/dist/document-models/resource-template/v1/gen/template-management/creators.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/template-management/creators.js +2 -1
- package/dist/document-models/resource-template/v1/gen/template-management/operations.d.ts +2 -1
- package/dist/document-models/resource-template/v1/gen/template-management/operations.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/utils.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/gen/utils.js +2 -0
- package/dist/document-models/resource-template/v1/src/reducers/template-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/v1/src/reducers/template-management.js +7 -0
- package/dist/document-models/resource-template/v1/tests/template-management.test.js +11 -1
- package/dist/document-models/service-offering/v1/actions.d.ts +1 -0
- package/dist/document-models/service-offering/v1/actions.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/document-model.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/document-model.js +31 -5
- package/dist/document-models/service-offering/v1/gen/reducer.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/reducer.js +6 -1
- package/dist/document-models/service-offering/v1/gen/schema/types.d.ts +7 -0
- package/dist/document-models/service-offering/v1/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/schema/zod.d.ts +2 -1
- package/dist/document-models/service-offering/v1/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/schema/zod.js +9 -0
- package/dist/document-models/service-offering/v1/gen/tiers/actions.d.ts +6 -2
- package/dist/document-models/service-offering/v1/gen/tiers/actions.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/tiers/creators.d.ts +3 -2
- package/dist/document-models/service-offering/v1/gen/tiers/creators.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/tiers/creators.js +2 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.d.ts +13 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/gen/tiers/error.js +13 -0
- package/dist/document-models/service-offering/v1/gen/tiers/operations.d.ts +2 -1
- package/dist/document-models/service-offering/v1/gen/tiers/operations.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/tiers.d.ts.map +1 -1
- package/dist/document-models/service-offering/v1/src/reducers/tiers.js +24 -1
- package/dist/document-models/service-offering/v1/tests/tiers.test.js +11 -1
- package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts.map +1 -1
- package/dist/editors/resource-template-editor/components/TemplateInfo.js +45 -3
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.js +2 -0
- package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ServiceCatalog.js +4 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.js +9 -5
- package/dist/editors/service-offering-editor/components/TierDefinition.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TierDefinition.js +25 -5
- package/dist/style.css +25 -0
- package/dist/subgraphs/resources-services/resolvers.js +4 -0
- package/dist/subgraphs/resources-services/schema.d.ts.map +1 -1
- package/dist/subgraphs/resources-services/schema.js +4 -0
- package/package.json +15 -15
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect, useRef } from "react";
|
|
3
3
|
import { generateId } from "document-model/core";
|
|
4
|
-
import { updateTemplateInfo, updateTemplateStatus, setOperator, addTargetAudience, removeTargetAudience, setSetupServices, setRecurringServices, addFaq, updateFaq, deleteFaq, reorderFaqs, addContentSection, updateContentSection, deleteContentSection, reorderContentSections, } from "../../../document-models/resource-template/v1/gen/creators.js";
|
|
4
|
+
import { updateTemplateInfo, updateTemplateStatus, setOperator, setWeight, addTargetAudience, removeTargetAudience, setSetupServices, setRecurringServices, addFaq, updateFaq, deleteFaq, reorderFaqs, addContentSection, updateContentSection, deleteContentSection, reorderContentSections, } from "../../../document-models/resource-template/v1/gen/creators.js";
|
|
5
5
|
import { MarkdownEditor } from "./markdown-editor.js";
|
|
6
6
|
const STATUS_OPTIONS = [
|
|
7
7
|
{ value: "DRAFT", label: "Draft", color: "slate" },
|
|
@@ -85,6 +85,7 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
85
85
|
const globalState = state.global;
|
|
86
86
|
const [formData, setFormData] = useState({
|
|
87
87
|
title: globalState.title || "",
|
|
88
|
+
subtitle: globalState.subtitle || "",
|
|
88
89
|
summary: globalState.summary || "",
|
|
89
90
|
description: globalState.description || "",
|
|
90
91
|
operatorId: globalState.operatorId || "",
|
|
@@ -114,6 +115,7 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
114
115
|
useEffect(() => {
|
|
115
116
|
setFormData({
|
|
116
117
|
title: globalState.title || "",
|
|
118
|
+
subtitle: globalState.subtitle || "",
|
|
117
119
|
summary: globalState.summary || "",
|
|
118
120
|
description: globalState.description || "",
|
|
119
121
|
operatorId: globalState.operatorId || "",
|
|
@@ -123,6 +125,7 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
123
125
|
});
|
|
124
126
|
}, [
|
|
125
127
|
globalState.title,
|
|
128
|
+
globalState.subtitle,
|
|
126
129
|
globalState.summary,
|
|
127
130
|
globalState.description,
|
|
128
131
|
globalState.operatorId,
|
|
@@ -156,6 +159,10 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
156
159
|
changes.infoLink = formData.infoLink || null;
|
|
157
160
|
hasChanges = true;
|
|
158
161
|
}
|
|
162
|
+
if (formData.subtitle !== (globalState.subtitle || "")) {
|
|
163
|
+
changes.subtitle = formData.subtitle || null;
|
|
164
|
+
hasChanges = true;
|
|
165
|
+
}
|
|
159
166
|
if (hasChanges) {
|
|
160
167
|
dispatch(updateTemplateInfo({
|
|
161
168
|
...changes,
|
|
@@ -420,7 +427,12 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
420
427
|
backgroundImage: formData.thumbnailUrl
|
|
421
428
|
? `url(${formData.thumbnailUrl})`
|
|
422
429
|
: undefined,
|
|
423
|
-
}, children: [!formData.thumbnailUrl && (_jsxs("div", { className: "template-editor__thumbnail-placeholder", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), _jsx("path", { d: "M21 15l-5-5L5 21" })] }), _jsx("span", { children: "Add Thumbnail" })] })), formData.thumbnailUrl && (_jsx("div", { className: `template-editor__status-badge template-editor__status-badge--${currentStatus?.color}`, children: currentStatus?.label }))] }), _jsx("div", { className: "template-editor__thumbnail-input", children: _jsx("input", { type: "text", value: formData.thumbnailUrl, onChange: (e) => handleFieldChange("thumbnailUrl", e.target.value), onBlur: handleInfoBlur, placeholder: "https://example.com/image.jpg", className: "template-editor__input template-editor__input--sm" }) })] }), _jsxs("div", { className: "template-editor__identity", children: [_jsxs("div", { className: "template-editor__title-row", children: [_jsx("input", { type: "text", value: formData.title, onChange: (e) => handleFieldChange("title", e.target.value), onBlur: handleInfoBlur, className: "template-editor__title-input", placeholder: "Product Title" }), _jsxs("div", { className: "template-editor__status-select", children: [_jsx("select", { value: formData.status, onChange: (e) => handleStatusChange(e.target.value), className: "template-editor__select", "data-status": currentStatus?.color, children: STATUS_OPTIONS.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) }), _jsx("span", { className: `template-editor__status-indicator template-editor__status-indicator--${currentStatus?.color}` })] })] }),
|
|
430
|
+
}, children: [!formData.thumbnailUrl && (_jsxs("div", { className: "template-editor__thumbnail-placeholder", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [_jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }), _jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), _jsx("path", { d: "M21 15l-5-5L5 21" })] }), _jsx("span", { children: "Add Thumbnail" })] })), formData.thumbnailUrl && (_jsx("div", { className: `template-editor__status-badge template-editor__status-badge--${currentStatus?.color}`, children: currentStatus?.label }))] }), _jsx("div", { className: "template-editor__thumbnail-input", children: _jsx("input", { type: "text", value: formData.thumbnailUrl, onChange: (e) => handleFieldChange("thumbnailUrl", e.target.value), onBlur: handleInfoBlur, placeholder: "https://example.com/image.jpg", className: "template-editor__input template-editor__input--sm" }) })] }), _jsxs("div", { className: "template-editor__identity", children: [_jsxs("div", { className: "template-editor__title-row", children: [_jsx("input", { type: "text", value: formData.title, onChange: (e) => handleFieldChange("title", e.target.value), onBlur: handleInfoBlur, className: "template-editor__title-input", placeholder: "Product Title" }), _jsxs("div", { className: "template-editor__status-select", children: [_jsx("select", { value: formData.status, onChange: (e) => handleStatusChange(e.target.value), className: "template-editor__select", "data-status": currentStatus?.color, children: STATUS_OPTIONS.map((option) => (_jsx("option", { value: option.value, children: option.label }, option.value))) }), _jsx("span", { className: `template-editor__status-indicator template-editor__status-indicator--${currentStatus?.color}` })] })] }), _jsx("input", { type: "text", value: formData.subtitle, onChange: (e) => handleFieldChange("subtitle", e.target.value), onBlur: handleInfoBlur, className: "template-editor__title-input", placeholder: "Subtitle / Tagline", style: {
|
|
431
|
+
fontSize: "0.95rem",
|
|
432
|
+
fontWeight: 400,
|
|
433
|
+
color: "var(--rt-slate-600, #475569)",
|
|
434
|
+
marginTop: "-4px",
|
|
435
|
+
} }), _jsxs("div", { className: "template-editor__audiences", children: [globalState.targetAudiences.map((audience) => (_jsxs("span", { className: "template-editor__audience-tag", style: audience.color
|
|
424
436
|
? {
|
|
425
437
|
backgroundColor: `${audience.color}15`,
|
|
426
438
|
borderColor: `${audience.color}40`,
|
|
@@ -431,7 +443,37 @@ export function TemplateInfo({ document, dispatch }) {
|
|
|
431
443
|
handleAddAudience(newAudienceLabel);
|
|
432
444
|
if (e.key === "Escape")
|
|
433
445
|
setShowAudienceInput(false);
|
|
434
|
-
}, placeholder: "Audience name...", className: "template-editor__audience-input", autoFocus: true }), _jsx("button", { type: "button", onClick: () => handleAddAudience(newAudienceLabel), className: "template-editor__audience-add-btn", children: "Add" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowAudienceInput(true), className: "template-editor__add-audience-btn", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add Audience"] }))] }), availablePresets.length > 0 && (_jsxs("div", { className: "template-editor__audience-presets", children: [_jsx("span", { className: "template-editor__presets-label", children: "Quick add:" }), availablePresets.slice(0, 4).map((preset) => (_jsx("button", { type: "button", onClick: () => handleAddAudience(preset.label, preset.color), className: "template-editor__preset-btn", style: { color: preset.color }, children: preset.label }, preset.label)))] })), _jsx("textarea", { value: formData.summary, onChange: (e) => handleFieldChange("summary", e.target.value), onBlur: handleInfoBlur, className: "template-editor__summary", placeholder: "Brief summary of your product...", rows: 2 })
|
|
446
|
+
}, placeholder: "Audience name...", className: "template-editor__audience-input", autoFocus: true }), _jsx("button", { type: "button", onClick: () => handleAddAudience(newAudienceLabel), className: "template-editor__audience-add-btn", children: "Add" })] })) : (_jsxs("button", { type: "button", onClick: () => setShowAudienceInput(true), className: "template-editor__add-audience-btn", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add Audience"] }))] }), availablePresets.length > 0 && (_jsxs("div", { className: "template-editor__audience-presets", children: [_jsx("span", { className: "template-editor__presets-label", children: "Quick add:" }), availablePresets.slice(0, 4).map((preset) => (_jsx("button", { type: "button", onClick: () => handleAddAudience(preset.label, preset.color), className: "template-editor__preset-btn", style: { color: preset.color }, children: preset.label }, preset.label)))] })), _jsx("textarea", { value: formData.summary, onChange: (e) => handleFieldChange("summary", e.target.value), onBlur: handleInfoBlur, className: "template-editor__summary", placeholder: "Brief summary of your product...", rows: 2 }), _jsxs("div", { style: {
|
|
447
|
+
display: "flex",
|
|
448
|
+
alignItems: "center",
|
|
449
|
+
gap: "8px",
|
|
450
|
+
marginTop: "8px",
|
|
451
|
+
}, children: [_jsx("label", { style: {
|
|
452
|
+
fontSize: "0.75rem",
|
|
453
|
+
fontWeight: 600,
|
|
454
|
+
textTransform: "uppercase",
|
|
455
|
+
letterSpacing: "0.05em",
|
|
456
|
+
color: "var(--rt-slate-500, #64748b)",
|
|
457
|
+
whiteSpace: "nowrap",
|
|
458
|
+
}, children: "Sort Weight" }), _jsx("input", { type: "number", value: globalState.weight ?? "", onChange: (e) => {
|
|
459
|
+
const val = e.target.value === "" ? null : parseInt(e.target.value, 10);
|
|
460
|
+
dispatch(setWeight({
|
|
461
|
+
weight: Number.isNaN(val) ? null : val,
|
|
462
|
+
lastModified: new Date().toISOString(),
|
|
463
|
+
}));
|
|
464
|
+
}, placeholder: "\u2014", style: {
|
|
465
|
+
width: "72px",
|
|
466
|
+
padding: "4px 8px",
|
|
467
|
+
fontSize: "0.8125rem",
|
|
468
|
+
border: "1px solid var(--rt-slate-200, #e2e8f0)",
|
|
469
|
+
borderRadius: "6px",
|
|
470
|
+
outline: "none",
|
|
471
|
+
textAlign: "center",
|
|
472
|
+
fontFamily: "var(--rt-font-mono, monospace)",
|
|
473
|
+
} }), _jsx("span", { style: {
|
|
474
|
+
fontSize: "0.6875rem",
|
|
475
|
+
color: "var(--rt-slate-400, #94a3b8)",
|
|
476
|
+
}, children: "Lower = higher priority" })] })] })] }), _jsxs("section", { className: "template-editor__card template-editor__card--full", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--violet", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M4 6h16M4 12h16M4 18h10" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Description" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Detailed description of your product" })] })] }), _jsx(MarkdownEditor, { label: "", height: 350, value: formData.description, onChange: (value) => handleFieldChange("description", value), onBlur: handleInfoBlur })] }), _jsxs("section", { className: "template-editor__card template-editor__card--full", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--indigo", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M4 6h16M4 10h16M4 14h10M4 18h6" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Expandable Content Sections" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Add long-form article content with expandable titles" })] })] }), _jsx("div", { className: "template-editor__sections-list", children: sortedSections.map((section, index) => (_jsx("div", { className: `template-editor__section-item ${editingSectionId === section.id ? "template-editor__section-item--editing" : ""}`, children: editingSectionId === section.id ? (_jsxs("div", { className: "template-editor__section-edit-form", children: [_jsx("input", { type: "text", value: editingSectionTitle, onChange: (e) => setEditingSectionTitle(e.target.value), className: "template-editor__section-edit-title", placeholder: "Section title", autoFocus: true }), _jsx("textarea", { value: editingSectionContent, onChange: (e) => setEditingSectionContent(e.target.value), className: "template-editor__section-edit-content", placeholder: "Section content...", rows: 6 }), _jsxs("div", { className: "template-editor__section-edit-actions", children: [_jsx("button", { type: "button", onClick: handleSaveSectionEdit, className: "template-editor__section-save-btn", children: "Save" }), _jsx("button", { type: "button", onClick: handleCancelSectionEdit, className: "template-editor__section-cancel-btn", children: "Cancel" })] })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "template-editor__section-reorder", children: [_jsx("button", { type: "button", onClick: () => handleMoveSection(index, "up"), className: "template-editor__section-reorder-btn", disabled: index === 0, title: "Move up", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M18 15l-6-6-6 6" }) }) }), _jsx("button", { type: "button", onClick: () => handleMoveSection(index, "down"), className: "template-editor__section-reorder-btn", disabled: index === sortedSections.length - 1, title: "Move down", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M6 9l6 6 6-6" }) }) })] }), _jsx("button", { type: "button", onClick: () => toggleSectionExpanded(section.id), className: "template-editor__section-toggle", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: `template-editor__section-chevron ${expandedSections.has(section.id) ? "template-editor__section-chevron--expanded" : ""}`, children: _jsx("path", { d: "M6 9l6 6 6-6" }) }) }), _jsxs("div", { className: "template-editor__section-main", children: [_jsxs("div", { className: "template-editor__section-header", onClick: () => toggleSectionExpanded(section.id), children: [_jsx("span", { className: "template-editor__section-title", children: section.title }), _jsx("span", { className: "template-editor__section-preview", children: section.content.length > 80
|
|
435
477
|
? `${section.content.substring(0, 80)}...`
|
|
436
478
|
: section.content })] }), expandedSections.has(section.id) && (_jsx("div", { className: "template-editor__section-content", children: section.content }))] }), _jsxs("div", { className: "template-editor__section-actions", children: [_jsx("button", { type: "button", onClick: () => handleStartEditSection(section), className: "template-editor__section-action-btn", title: "Edit section", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), _jsx("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })] }) }), _jsx("button", { type: "button", onClick: () => handleDeleteContentSection(section.id), className: "template-editor__section-action-btn template-editor__section-action-btn--delete", title: "Delete section", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2" }) }) })] })] })) }, section.id))) }), _jsxs("div", { className: "template-editor__section-add-form", children: [_jsx("input", { type: "text", value: newSectionTitle, onChange: (e) => setNewSectionTitle(e.target.value), placeholder: "New section title...", className: "template-editor__section-new-title" }), _jsx("textarea", { value: newSectionContent, onChange: (e) => setNewSectionContent(e.target.value), placeholder: "Section content (long-form article content)...", className: "template-editor__section-new-content", rows: 4 }), (newSectionTitle || newSectionContent) && (_jsxs("button", { type: "button", onClick: handleAddContentSection, className: "template-editor__section-add-btn", disabled: !newSectionTitle.trim() || !newSectionContent.trim(), children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add Section"] }))] })] }), _jsxs("section", { className: "template-editor__card template-editor__card--full", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--sky", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3" }), _jsx("path", { d: "M12 17h.01" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Frequently Asked Questions" }), _jsx("p", { className: "template-editor__card-subtitle", children: "Common questions and answers about this product" })] })] }), _jsx("div", { className: "template-editor__faq-list", children: sortedFaqs.map((faq, index) => (_jsx("div", { className: `template-editor__faq-item ${editingFaqId === faq.id ? "template-editor__faq-item--editing" : ""}`, children: editingFaqId === faq.id ? (_jsxs("div", { className: "template-editor__faq-edit-form", children: [_jsx("input", { type: "text", value: editingFaqQuestion, onChange: (e) => setEditingFaqQuestion(e.target.value), className: "template-editor__faq-edit-question", placeholder: "Question", autoFocus: true }), _jsx("textarea", { value: editingFaqAnswer, onChange: (e) => setEditingFaqAnswer(e.target.value), className: "template-editor__faq-edit-answer", placeholder: "Answer", rows: 3 }), _jsxs("div", { className: "template-editor__faq-edit-actions", children: [_jsx("button", { type: "button", onClick: handleSaveFaqEdit, className: "template-editor__faq-save-btn", children: "Save" }), _jsx("button", { type: "button", onClick: handleCancelFaqEdit, className: "template-editor__faq-cancel-btn", children: "Cancel" })] })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { className: "template-editor__faq-reorder", children: [_jsx("button", { type: "button", onClick: () => handleMoveFaq(index, "up"), className: "template-editor__faq-reorder-btn", disabled: index === 0, title: "Move up", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M18 15l-6-6-6 6" }) }) }), _jsx("button", { type: "button", onClick: () => handleMoveFaq(index, "down"), className: "template-editor__faq-reorder-btn", disabled: index === sortedFaqs.length - 1, title: "Move down", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M6 9l6 6 6-6" }) }) })] }), _jsx("div", { className: "template-editor__faq-number", children: index + 1 }), _jsxs("div", { className: "template-editor__faq-content", children: [_jsx("div", { className: "template-editor__faq-question", children: faq.question }), _jsx("div", { className: "template-editor__faq-answer", children: faq.answer })] }), _jsxs("div", { className: "template-editor__faq-actions", children: [_jsx("button", { type: "button", onClick: () => handleStartEditFaq(faq), className: "template-editor__faq-action-btn", title: "Edit FAQ", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" }), _jsx("path", { d: "M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" })] }) }), _jsx("button", { type: "button", onClick: () => handleDeleteFaq(faq.id), className: "template-editor__faq-action-btn template-editor__faq-action-btn--delete", title: "Delete FAQ", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6M8 6V4a2 2 0 012-2h4a2 2 0 012 2v2" }) }) })] })] })) }, faq.id))) }), _jsxs("div", { className: "template-editor__faq-add-form", children: [_jsx("input", { type: "text", value: newFaqQuestion, onChange: (e) => setNewFaqQuestion(e.target.value), placeholder: "New question...", className: "template-editor__faq-new-question" }), _jsx("textarea", { value: newFaqAnswer, onChange: (e) => setNewFaqAnswer(e.target.value), placeholder: "Answer to the question...", className: "template-editor__faq-new-answer", rows: 2 }), (newFaqQuestion || newFaqAnswer) && (_jsxs("button", { type: "button", onClick: handleAddFaq, className: "template-editor__faq-add-btn", disabled: !newFaqQuestion.trim() || !newFaqAnswer.trim(), children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 5v14M5 12h14", strokeWidth: "2" }) }), "Add FAQ"] }))] })] }), _jsxs("div", { className: "template-editor__section-divider", children: [_jsxs("div", { className: "template-editor__section-badge", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }), _jsx("path", { d: "M2 17l10 5 10-5" }), _jsx("path", { d: "M2 12l10 5 10-5" })] }), "Services Information"] }), _jsx("div", { className: "template-editor__section-divider-line" })] }), _jsxs("div", { className: "template-editor__grid", children: [_jsxs("section", { className: "template-editor__card", children: [_jsxs("div", { className: "template-editor__card-header", children: [_jsx("div", { className: "template-editor__card-icon template-editor__card-icon--emerald", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z" }), _jsx("path", { d: "M2 17l10 5 10-5" }), _jsx("path", { d: "M2 12l10 5 10-5" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "template-editor__card-title", children: "Formation & Setup" }), _jsx("p", { className: "template-editor__card-subtitle", children: "One-time setup services" })] }), _jsxs("button", { type: "button", onClick: () => setShowSetupTemplates(!showSetupTemplates), className: `template-editor__templates-toggle ${showSetupTemplates ? "template-editor__templates-toggle--active" : ""}`, children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 4h6v6H4zM14 4h6v6h-6zM4 14h6v6H4zM14 14h6v6h-6z" }) }), "Templates"] })] }), showSetupTemplates && (_jsx("div", { className: "template-editor__templates-panel", children: Object.entries(SETUP_SERVICE_TEMPLATES).map(([category, templates]) => (_jsxs("div", { className: "template-editor__template-category", children: [_jsx("span", { className: "template-editor__template-category-label", children: category }), _jsx("div", { className: "template-editor__template-items", children: templates.map((template) => {
|
|
437
479
|
const isAdded = globalState.setupServices.includes(template.title);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceTemplateSelector.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ResourceTemplateSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,kEAAkE,CAAC;
|
|
1
|
+
{"version":3,"file":"ResourceTemplateSelector.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ResourceTemplateSelector.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,kEAAkE,CAAC;AAyF1E,UAAU,6BAA6B;IACrC,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,QAAQ,GACT,EAAE,6BAA6B,2CA0kB/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceCatalog.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServiceCatalog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAMtB,MAAM,kEAAkE,CAAC;AAgH1E,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"ServiceCatalog.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServiceCatalog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAMtB,MAAM,kEAAkE,CAAC;AAgH1E,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA8lEzE"}
|
|
@@ -724,11 +724,14 @@ export function ServiceCatalog({ document, dispatch }) {
|
|
|
724
724
|
}), placeholder: "0", step: "0.1", min: "0", max: "100", className: "flex-1 py-1.5 px-2 pr-1 border-none text-sm text-slate-700 bg-transparent outline-none min-w-0 placeholder:text-slate-400", style: fontMono }), _jsx("span", { className: "px-3 py-2.5 pl-2 text-sm font-medium text-slate-400 bg-slate-50 whitespace-nowrap select-none", children: "%" })] })] })] })), effective !== null && discountPct > 0 && (_jsxs("div", { className: "flex items-center gap-2 mt-1.5 px-2.5 py-1.5 bg-emerald-50 rounded-md", children: [_jsx("span", { className: "text-[0.8125rem] text-emerald-600", children: "\u2192" }), _jsx("span", { className: "text-sm font-bold text-emerald-700", style: fontMono, children: formatPrice(effective, "USD") }), savingsPct > 0 && (_jsxs("span", { className: "ml-auto text-[0.6875rem] font-bold text-emerald-600 bg-emerald-100 px-2 py-0.5 rounded-full", style: fontMono, children: [savingsPct, "% off"] }))] }))] }, cycle));
|
|
725
725
|
}) })] }))] })), editGroupType === "setup" && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("span", { className: "text-[0.6875rem] font-semibold uppercase tracking-[0.05em] text-slate-500", children: "One-time Fee" }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "text-sm text-slate-500", children: "$" }), _jsx("input", { type: "number", value: editGroupPrice, onChange: (e) => setEditGroupPrice(e.target.value), placeholder: "0", className: "flex-1 px-2.5 py-2 text-sm text-slate-800 bg-white border-[1.5px] border-slate-200 rounded-md focus:outline-none focus:border-violet-500 focus:shadow-[0_0_0_2px_rgb(237,233,254)]", style: fontSans, step: "0.01" })] })] }), tiers.length > 0 && parseFloat(editGroupPrice) > 0 && (_jsxs("div", { className: "flex flex-col gap-2.5", children: [_jsx("span", { className: "text-[0.6875rem] font-semibold uppercase tracking-[0.05em] text-slate-500", children: "Setup Fee Discounts by Tier & Billing Cycle" }), _jsx("div", { className: "flex gap-0 border-b border-slate-200 mb-3 overflow-x-auto", children: tiers.map((tier) => (_jsxs("button", { onClick: () => setEditTierTab(tier.id), className: `flex items-center gap-1.5 px-3 py-2 text-xs font-medium bg-none border-none border-b-2 cursor-pointer whitespace-nowrap transition-all duration-150 ${editTierTab === tier.id
|
|
726
726
|
? "text-violet-700 border-b-violet-600 font-semibold"
|
|
727
|
-
: "text-slate-500 border-b-transparent hover:text-slate-700 hover:bg-slate-50"} ${tier.isCustomPricing ? "italic" : ""}`, style: fontSans, children: [tier.name, tier.isCustomPricing && (_jsx("span", { className: "text-[0.5625rem] font-semibold uppercase tracking-[0.04em] text-amber-600 bg-amber-50 px-[5px] py-px rounded-full", children: "Custom" }))] }, tier.id))) }), editTierTab &&
|
|
727
|
+
: "text-slate-500 border-b-transparent hover:text-slate-700 hover:bg-slate-50"} ${tier.isCustomPricing ? "italic" : ""}`, style: fontSans, children: [tier.name, tier.excludeFromSetupFee && (_jsx("span", { className: "text-[0.5625rem] font-semibold uppercase tracking-[0.04em] text-teal-600 bg-teal-50 px-[5px] py-px rounded-full", children: "No Fee" })), tier.isCustomPricing && (_jsx("span", { className: "text-[0.5625rem] font-semibold uppercase tracking-[0.04em] text-amber-600 bg-amber-50 px-[5px] py-px rounded-full", children: "Custom" }))] }, tier.id))) }), editTierTab &&
|
|
728
728
|
(() => {
|
|
729
729
|
const activeTier = tiers.find((t) => t.id === editTierTab);
|
|
730
730
|
if (!activeTier)
|
|
731
731
|
return null;
|
|
732
|
+
if (activeTier.excludeFromSetupFee) {
|
|
733
|
+
return (_jsxs("div", { className: "flex items-center gap-2 p-3 bg-teal-50 border border-dashed border-teal-300 rounded-md text-xs text-teal-700 italic", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", width: "16", height: "16", children: _jsx("path", { d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), _jsx("span", { children: "No setup fee \u2014 this tier is excluded from setup fees." })] }));
|
|
734
|
+
}
|
|
732
735
|
if (activeTier.isCustomPricing) {
|
|
733
736
|
return (_jsxs("div", { className: "flex items-center gap-2 p-3 bg-slate-50 border border-dashed border-slate-300 rounded-md text-xs text-slate-500 italic", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", width: "16", height: "16", children: _jsx("path", { d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), _jsx("span", { children: "Custom pricing tier \u2014 discounts negotiated per customer." })] }));
|
|
734
737
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheMatrix.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/TheMatrix.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAS3B,MAAM,kEAAkE,CAAC;AA2B1E,UAAU,cAAc;IACtB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAgDD,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"TheMatrix.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/TheMatrix.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAS3B,MAAM,kEAAkE,CAAC;AA2B1E,UAAU,cAAc;IACtB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAgDD,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,cAAc,2CAq8E/D"}
|
|
@@ -867,7 +867,9 @@ export function TheMatrix({ document, dispatch }) {
|
|
|
867
867
|
}
|
|
868
868
|
: {}),
|
|
869
869
|
}, children: idx === selectedTierIdx
|
|
870
|
-
?
|
|
870
|
+
? tier.excludeFromSetupFee
|
|
871
|
+
? "No setup fee"
|
|
872
|
+
: `${formatPrice(ab.setupCost, ab.setupCostCurrency || "USD")} one-time`
|
|
871
873
|
: null }, tier.id)))] }, `addon-setup-${ab.optionGroupId}`))), (() => {
|
|
872
874
|
const setupBds = tierBreakdowns[selectedTierIdx]?.setupGroupBreakdowns ?? [];
|
|
873
875
|
const totalSetupBase = setupBds.reduce((sum, s) => sum +
|
|
@@ -885,9 +887,11 @@ export function TheMatrix({ document, dispatch }) {
|
|
|
885
887
|
}
|
|
886
888
|
: {}),
|
|
887
889
|
}, children: idx === selectedTierIdx
|
|
888
|
-
?
|
|
889
|
-
?
|
|
890
|
-
:
|
|
890
|
+
? tier.excludeFromSetupFee
|
|
891
|
+
? "No setup fee"
|
|
892
|
+
: hasDiscount
|
|
893
|
+
? `${formatPrice(totalSetupEffective, "USD")} one-time`
|
|
894
|
+
: `${formatPrice(totalSetupBase, "USD")} one-time`
|
|
891
895
|
: null }, tier.id)))] }));
|
|
892
896
|
})()] }) }) })] }), selectedCell && (_jsx(ServiceLevelDetailPanel, { serviceId: selectedCell.serviceId, tierId: selectedCell.tierId, services: services, tiers: tiers, optionGroups: optionGroups, dispatch: dispatch, onClose: () => setSelectedCell(null) })), addServiceModal && (_jsx("div", { className: "fixed inset-0 bg-slate-900/75 backdrop-blur-sm flex items-center justify-center z-[100]", style: { animation: "modal-backdrop 0.2s ease-out" }, children: _jsxs("div", { className: "bg-white rounded-xl p-6 max-h-[85vh] overflow-y-auto", style: {
|
|
893
897
|
width: "min(32rem, calc(100vw - 2rem))",
|
|
@@ -1129,7 +1133,7 @@ function ServiceGroupSection({ group, services, tiers, isSetupFormation, isOptio
|
|
|
1129
1133
|
}
|
|
1130
1134
|
const curr = group.currency || "USD";
|
|
1131
1135
|
const hasDiscount = effectivePrice !== basePrice;
|
|
1132
|
-
return (_jsxs("tr", { className: "bg-slate-50 [&>td]:py-2.5 [&>td]:px-4 [&>td]:font-semibold [&>td]:text-slate-700 [&>td]:border-b [&>td]:border-slate-200 [&>td:first-child]:sticky [&>td:first-child]:left-0 [&>td:first-child]:z-10 [&>td:first-child]:bg-slate-50", children: [_jsx("td", { children: "TOTAL SETUP FEE" }), _jsx("td", { colSpan: tiers.length, style: { textAlign: "center" }, children: hasDiscount ? (_jsxs(_Fragment, { children: [_jsx("span", { style: {
|
|
1136
|
+
return (_jsxs("tr", { className: "bg-slate-50 [&>td]:py-2.5 [&>td]:px-4 [&>td]:font-semibold [&>td]:text-slate-700 [&>td]:border-b [&>td]:border-slate-200 [&>td:first-child]:sticky [&>td:first-child]:left-0 [&>td:first-child]:z-10 [&>td:first-child]:bg-slate-50", children: [_jsx("td", { children: "TOTAL SETUP FEE" }), _jsx("td", { colSpan: tiers.length, style: { textAlign: "center" }, children: selectedTier?.excludeFromSetupFee ? (_jsx("span", { className: "text-slate-400 italic", children: "No setup fee for this tier" })) : hasDiscount ? (_jsxs(_Fragment, { children: [_jsx("span", { style: {
|
|
1133
1137
|
textDecoration: "line-through",
|
|
1134
1138
|
opacity: 0.5,
|
|
1135
1139
|
marginRight: 6,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TierDefinition.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/TierDefinition.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAItB,MAAM,kEAAkE,CAAC;
|
|
1
|
+
{"version":3,"file":"TierDefinition.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/TierDefinition.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAItB,MAAM,kEAAkE,CAAC;AAY1E,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AA6ED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CAiYzE"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useMemo, useState, useCallback } from "react";
|
|
3
3
|
import { generateId } from "document-model/core";
|
|
4
|
-
import { addTier, updateTier, deleteTier, setAvailableBillingCycles, } from "../../../document-models/service-offering/v1/gen/creators.js";
|
|
4
|
+
import { addTier, updateTier, deleteTier, setAvailableBillingCycles, reorderTiers, } from "../../../document-models/service-offering/v1/gen/creators.js";
|
|
5
5
|
import { calculateTierRecurringPrice, formatPrice } from "./pricing-utils.js";
|
|
6
6
|
import { InfoIcon } from "./InfoIcon.js";
|
|
7
7
|
import { ConfirmDialog } from "./ConfirmDialog.js";
|
|
@@ -119,6 +119,20 @@ export function TierDefinition({ document, dispatch }) {
|
|
|
119
119
|
}));
|
|
120
120
|
});
|
|
121
121
|
};
|
|
122
|
+
const handleMoveTier = useCallback((tierIndex, direction) => {
|
|
123
|
+
const newIndex = direction === "left" ? tierIndex - 1 : tierIndex + 1;
|
|
124
|
+
if (newIndex < 0 || newIndex >= tiers.length)
|
|
125
|
+
return;
|
|
126
|
+
const reordered = tiers.map((t) => t.id);
|
|
127
|
+
[reordered[tierIndex], reordered[newIndex]] = [
|
|
128
|
+
reordered[newIndex],
|
|
129
|
+
reordered[tierIndex],
|
|
130
|
+
];
|
|
131
|
+
dispatch(reorderTiers({
|
|
132
|
+
tierIds: reordered,
|
|
133
|
+
lastModified: new Date().toISOString(),
|
|
134
|
+
}));
|
|
135
|
+
}, [tiers, dispatch]);
|
|
122
136
|
const getTierAccent = (index) => TIER_ACCENTS[index % TIER_ACCENTS.length];
|
|
123
137
|
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col gap-6", children: [tiers.length === 0 && (_jsxs("div", { className: "rounded-xl p-6 mb-6 border border-violet-100", style: {
|
|
124
138
|
background: "linear-gradient(135deg, rgb(245 243 255) 0%, rgb(240 249 255) 100%)",
|
|
@@ -149,7 +163,7 @@ export function TierDefinition({ document, dispatch }) {
|
|
|
149
163
|
lastModified: new Date().toISOString(),
|
|
150
164
|
}));
|
|
151
165
|
}, children: opt.label }, opt.value));
|
|
152
|
-
}) }), (state.global.availableBillingCycles ?? []).length === 0 && (_jsx("div", { className: "text-[0.6875rem] text-rose-600 py-1.5 px-2.5 bg-rose-50 rounded-md mt-2", children: "Select at least one billing cycle to enable pricing" }))] }), _jsxs("div", { className: "so-scrollbar-h flex flex-nowrap gap-6 overflow-x-auto overflow-y-visible pb-4", style: { scrollBehavior: "smooth", WebkitOverflowScrolling: "touch" }, children: [tiers.map((tier, index) => (_jsx(TierCard, { tier: tier, accent: getTierAccent(index), dispatch: dispatch, onDelete: () => handleDeleteTier(tier.id), isRecommended: tier.mostPopular, regularGroups: regularGroups }, tier.id))), isAddingTier ? (_jsxs("div", { className: "w-80 bg-white border-2 border-violet-200 rounded-xl p-6", style: { animation: "tier-slide-up 0.2s ease-out" }, children: [_jsx("h3", { className: "text-base font-bold text-slate-900 mb-5", style: { fontFamily: fontSans }, children: "New Subscription Tier" }), _jsxs("div", { className: "mb-4", children: [_jsx("label", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-500 mb-1.5", style: { fontFamily: fontMono }, children: "Tier Name" }), _jsx("input", { type: "text", value: newTier.name, onChange: (e) => setNewTier({ ...newTier, name: e.target.value }), placeholder: "e.g., Basic, Professional", className: "w-full text-base font-semibold text-slate-900 bg-white border border-slate-200 rounded-[10px] py-2.5 px-3.5 outline-none transition-all duration-150 focus:border-violet-400 focus:shadow-[0_0_0_3px_rgb(237_233_254)] placeholder:font-normal placeholder:text-slate-400", style: { fontFamily: fontSans }, autoFocus: true })] }), _jsxs("label", { className: "flex items-center gap-2.5 mb-4 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: newTier.isCustomPricing, onChange: (e) => setNewTier({
|
|
166
|
+
}) }), (state.global.availableBillingCycles ?? []).length === 0 && (_jsx("div", { className: "text-[0.6875rem] text-rose-600 py-1.5 px-2.5 bg-rose-50 rounded-md mt-2", children: "Select at least one billing cycle to enable pricing" }))] }), _jsxs("div", { className: "so-scrollbar-h flex flex-nowrap gap-6 overflow-x-auto overflow-y-visible pb-4", style: { scrollBehavior: "smooth", WebkitOverflowScrolling: "touch" }, children: [tiers.map((tier, index) => (_jsx(TierCard, { tier: tier, accent: getTierAccent(index), dispatch: dispatch, onDelete: () => handleDeleteTier(tier.id), isRecommended: tier.mostPopular, regularGroups: regularGroups, onMoveLeft: () => handleMoveTier(index, "left"), onMoveRight: () => handleMoveTier(index, "right"), isFirst: index === 0, isLast: index === tiers.length - 1 }, tier.id))), isAddingTier ? (_jsxs("div", { className: "w-80 bg-white border-2 border-violet-200 rounded-xl p-6", style: { animation: "tier-slide-up 0.2s ease-out" }, children: [_jsx("h3", { className: "text-base font-bold text-slate-900 mb-5", style: { fontFamily: fontSans }, children: "New Subscription Tier" }), _jsxs("div", { className: "mb-4", children: [_jsx("label", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-500 mb-1.5", style: { fontFamily: fontMono }, children: "Tier Name" }), _jsx("input", { type: "text", value: newTier.name, onChange: (e) => setNewTier({ ...newTier, name: e.target.value }), placeholder: "e.g., Basic, Professional", className: "w-full text-base font-semibold text-slate-900 bg-white border border-slate-200 rounded-[10px] py-2.5 px-3.5 outline-none transition-all duration-150 focus:border-violet-400 focus:shadow-[0_0_0_3px_rgb(237_233_254)] placeholder:font-normal placeholder:text-slate-400", style: { fontFamily: fontSans }, autoFocus: true })] }), _jsxs("label", { className: "flex items-center gap-2.5 mb-4 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: newTier.isCustomPricing, onChange: (e) => setNewTier({
|
|
153
167
|
...newTier,
|
|
154
168
|
isCustomPricing: e.target.checked,
|
|
155
169
|
}), className: "w-[1.125rem] h-[1.125rem] cursor-pointer", style: { accentColor: "#f59e0b" } }), _jsx("span", { className: "text-[0.8125rem] text-slate-600", children: "Custom Pricing (price varies per client)" })] }), _jsxs("div", { className: "flex gap-2.5 mt-5", children: [_jsx("button", { onClick: handleAddTier, disabled: !newTier.name.trim(), className: "flex-1 py-2.5 px-4 text-sm font-semibold rounded-[10px] cursor-pointer transition-all duration-150 bg-violet-600 text-white border-none hover:enabled:bg-violet-700 disabled:bg-slate-200 disabled:text-slate-400 disabled:cursor-not-allowed", style: { fontFamily: fontSans }, children: "Create Tier" }), _jsx("button", { onClick: () => {
|
|
@@ -161,7 +175,7 @@ export function TierDefinition({ document, dispatch }) {
|
|
|
161
175
|
});
|
|
162
176
|
}, className: "flex-1 py-2.5 px-4 text-sm font-semibold rounded-[10px] cursor-pointer transition-all duration-150 bg-slate-100 text-slate-700 border-none hover:bg-slate-200", style: { fontFamily: fontSans }, children: "Cancel" })] })] })) : (_jsxs("button", { onClick: () => setIsAddingTier(true), className: "group w-80 min-h-[280px] bg-white border-2 border-dashed border-slate-200 rounded-xl flex flex-col items-center justify-center gap-3 cursor-pointer transition-all duration-200 hover:border-violet-300 hover:bg-violet-50", children: [_jsx("div", { className: "w-14 h-14 rounded-full bg-slate-100 flex items-center justify-center transition-all duration-200 group-hover:bg-violet-100", children: _jsx("svg", { className: "w-6 h-6 text-slate-400 transition-all duration-150 group-hover:text-violet-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) }) }), _jsx("span", { className: "text-[0.9375rem] font-semibold text-slate-500 transition-all duration-150 group-hover:text-violet-600", style: { fontFamily: fontSans }, children: "Add Subscription Tier" })] }))] }), _jsxs("div", { className: "flex items-start gap-3.5 p-4 px-5 bg-amber-50 border border-amber-200 rounded-xl", children: [_jsx("svg", { className: "shrink-0 w-5 h-5 text-amber-600 mt-0.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-semibold text-amber-800 mb-1", style: { fontFamily: fontSans }, children: "Pricing is managed at the option group level" }), _jsx("p", { className: "text-[0.8125rem] text-amber-700 leading-relaxed", children: "Billing cycles and pricing are configured per option group in the Service Catalog. Setup fees, recurring prices, and billing cycles apply to all tiers within each group." })] })] })] }), pendingDeleteTierId && (_jsx(ConfirmDialog, { title: "Delete this tier?", message: "This will remove the tier and all its pricing configuration. This action cannot be undone.", confirmLabel: "Delete Tier", variant: "danger", onConfirm: confirmDeleteTier, onCancel: () => setPendingDeleteTierId(null) }))] }));
|
|
163
177
|
}
|
|
164
|
-
const TierCard = memo(function TierCard({ tier, accent, dispatch, onDelete, isRecommended, regularGroups, }) {
|
|
178
|
+
const TierCard = memo(function TierCard({ tier, accent, dispatch, onDelete, isRecommended, regularGroups, onMoveLeft, onMoveRight, isFirst, isLast, }) {
|
|
165
179
|
const [localName, setLocalName] = useState(tier.name);
|
|
166
180
|
const [localDescription, setLocalDescription] = useState(tier.description || "");
|
|
167
181
|
const isCustomPricing = tier.isCustomPricing ?? false;
|
|
@@ -204,7 +218,13 @@ const TierCard = memo(function TierCard({ tier, accent, dispatch, onDelete, isRe
|
|
|
204
218
|
mostPopular: true,
|
|
205
219
|
lastModified: new Date().toISOString(),
|
|
206
220
|
}));
|
|
207
|
-
}, children: [_jsx("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) }), "Set as Popular"] })), _jsx("div", { className: "h-1 w-full", style: { background: accent.color } }), _jsxs("div", { className: "so-scrollbar-v p-6 overflow-y-auto flex-1", children: [_jsxs("div", { className: "flex items-start justify-between mb-5", children: [_jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-400 mb-1.5", style: { fontFamily: fontMono }, children: "Tier Name" }), _jsx("input", { type: "text", value: localName, onChange: (e) => setLocalName(e.target.value), onBlur: handleNameBlur, className: "w-full text-[1.375rem] font-bold text-slate-900 bg-transparent border-none border-b-2 border-b-transparent pb-1 pl-0 transition-all duration-150 outline-none hover:border-b-slate-200 focus:border-b-violet-500", style: { fontFamily: fontSans } })] }), _jsx("button", { onClick: onDelete, className: "p-1.5 text-slate-400 bg-transparent border-none rounded-md cursor-pointer transition-all duration-150 hover:text-rose-500 hover:bg-rose-50", children: _jsx("svg", { width: "20", height: "20", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), isCustomPricing && (_jsxs("div", { className: "flex items-center gap-2 py-3 px-4 bg-amber-50 border border-amber-200 rounded-[10px] mb-4", children: [_jsx("svg", { className: "w-5 h-5 text-amber-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "block text-[0.8125rem] font-semibold text-amber-800", children: "Custom Pricing" }), _jsx("span", { className: "text-[0.6875rem] text-amber-600", children: "Price varies per client" })] })] })),
|
|
221
|
+
}, children: [_jsx("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) }), "Set as Popular"] })), _jsx("div", { className: "h-1 w-full", style: { background: accent.color } }), _jsxs("div", { className: "so-scrollbar-v p-6 overflow-y-auto flex-1", children: [_jsxs("div", { className: "flex items-start justify-between mb-5", children: [_jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-400 mb-1.5", style: { fontFamily: fontMono }, children: "Tier Name" }), _jsx("input", { type: "text", value: localName, onChange: (e) => setLocalName(e.target.value), onBlur: handleNameBlur, className: "w-full text-[1.375rem] font-bold text-slate-900 bg-transparent border-none border-b-2 border-b-transparent pb-1 pl-0 transition-all duration-150 outline-none hover:border-b-slate-200 focus:border-b-violet-500", style: { fontFamily: fontSans } })] }), _jsx("button", { onClick: onDelete, className: "p-1.5 text-slate-400 bg-transparent border-none rounded-md cursor-pointer transition-all duration-150 hover:text-rose-500 hover:bg-rose-50", children: _jsx("svg", { width: "20", height: "20", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), isCustomPricing && (_jsxs("div", { className: "flex items-center gap-2 py-3 px-4 bg-amber-50 border border-amber-200 rounded-[10px] mb-4", children: [_jsx("svg", { className: "w-5 h-5 text-amber-600", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("span", { className: "block text-[0.8125rem] font-semibold text-amber-800", children: "Custom Pricing" }), _jsx("span", { className: "text-[0.6875rem] text-amber-600", children: "Price varies per client" })] })] })), _jsxs("label", { className: "flex items-center gap-2.5 mb-4 cursor-pointer", children: [_jsx("input", { type: "checkbox", checked: tier.excludeFromSetupFee ?? false, onChange: (e) => {
|
|
222
|
+
dispatch(updateTier({
|
|
223
|
+
id: tier.id,
|
|
224
|
+
excludeFromSetupFee: e.target.checked,
|
|
225
|
+
lastModified: new Date().toISOString(),
|
|
226
|
+
}));
|
|
227
|
+
}, className: "w-[1.125rem] h-[1.125rem] cursor-pointer", style: { accentColor: "#0d9488" } }), _jsx("span", { className: "text-[0.8125rem] text-slate-600", children: "Exclude from setup fee" })] }), !isCustomPricing && (_jsxs("div", { className: "mb-4", children: [_jsx("div", { className: "mb-1.5", children: _jsxs("span", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-400 mb-1.5", style: { fontFamily: fontMono }, children: ["Recurring Price", _jsx(InfoIcon, { content: "This price is automatically calculated from the services and pricing configured in the Service Catalog. It is read-only \u2014 to change it, adjust pricing in your option groups." })] }) }), _jsxs("div", { className: "flex items-center gap-2 py-3.5 px-4 bg-slate-50 rounded-[10px] border border-slate-100", children: [_jsx("span", { children: "$" }), _jsx("span", { className: "text-[1.375rem] font-semibold text-emerald-700", style: { fontFamily: fontMono }, children: formatPrice(calculatedPrice.monthlyTotal).replace("$", "") }), _jsx("span", { className: "text-sm text-emerald-600 font-medium", children: "/mo" })] }), calculatedPrice.groupBreakdown.length > 0 && (_jsxs("div", { className: "mt-2 py-2 px-2.5 bg-slate-50 rounded-md border border-slate-100", children: [_jsxs("span", { className: "block text-[0.625rem] font-medium text-slate-500 uppercase tracking-wide mb-1.5", children: ["Sum of ", calculatedPrice.groupBreakdown.length, " service group", calculatedPrice.groupBreakdown.length !== 1 ? "s" : ""] }), calculatedPrice.groupBreakdown.map((g) => (_jsxs("div", { className: "flex items-center justify-between py-[0.1875rem]", children: [_jsxs("span", { className: `flex items-center gap-1 text-xs ${g.hasPrice ? "text-slate-600" : "text-amber-600"}`, children: [!g.hasPrice && (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", className: "w-3 h-3 text-amber-500", children: _jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" }) })), g.groupName] }), _jsx("span", { className: `text-xs font-medium ${g.hasPrice ? "text-slate-700" : "text-amber-500 italic"}`, style: { fontFamily: fontMono }, children: g.hasPrice ? formatPrice(g.monthlyAmount) : "$0" })] }, g.groupId)))] })), calculatedPrice.missingPriceGroups.length > 0 && (_jsxs("div", { className: "flex items-center gap-1.5 mt-2 py-1.5 px-2 text-[0.6875rem] text-amber-700 bg-amber-50 border border-amber-200 rounded-md", children: [_jsx("svg", { className: "shrink-0 w-3.5 h-3.5 text-amber-500", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }), _jsxs("span", { children: [calculatedPrice.missingPriceGroups.length, " group", calculatedPrice.missingPriceGroups.length !== 1
|
|
208
228
|
? "s"
|
|
209
|
-
: "", " ", "without pricing (counted as $0)"] })] }))] })), _jsxs("div", { className: "mt-4", children: [_jsx("span", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-400 mb-1.5", style: { fontFamily: fontMono }, children: "Description" }), _jsx("textarea", { value: localDescription, onChange: (e) => setLocalDescription(e.target.value), onBlur: handleDescriptionBlur, placeholder: "Add a description...", rows: 2, className: "w-full text-[0.8125rem] text-slate-600 bg-slate-50 border border-slate-200 rounded-[10px] p-3 resize-none outline-none transition-all duration-150 focus:border-violet-400 focus:shadow-[0_0_0_3px_rgb(237_233_254)] placeholder:text-slate-400", style: { fontFamily: fontSans } })] })] }), _jsxs("div", { className: "flex items-center
|
|
229
|
+
: "", " ", "without pricing (counted as $0)"] })] }))] })), _jsxs("div", { className: "mt-4", children: [_jsx("span", { className: "block text-[0.625rem] font-medium uppercase tracking-widest text-slate-400 mb-1.5", style: { fontFamily: fontMono }, children: "Description" }), _jsx("textarea", { value: localDescription, onChange: (e) => setLocalDescription(e.target.value), onBlur: handleDescriptionBlur, placeholder: "Add a description...", rows: 2, className: "w-full text-[0.8125rem] text-slate-600 bg-slate-50 border border-slate-200 rounded-[10px] p-3 resize-none outline-none transition-all duration-150 focus:border-violet-400 focus:shadow-[0_0_0_3px_rgb(237_233_254)] placeholder:text-slate-400", style: { fontFamily: fontSans } })] })] }), _jsxs("div", { className: "flex items-center justify-between py-3 px-6 bg-slate-50 border-t border-slate-100", children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: onMoveLeft, disabled: isFirst, className: "p-1.5 rounded-md border-none cursor-pointer transition-all duration-150 bg-transparent text-slate-400 hover:enabled:text-violet-600 hover:enabled:bg-violet-50 disabled:opacity-30 disabled:cursor-not-allowed", title: "Move left", children: _jsx("svg", { width: "16", height: "16", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) }) }), _jsx("button", { onClick: onMoveRight, disabled: isLast, className: "p-1.5 rounded-md border-none cursor-pointer transition-all duration-150 bg-transparent text-slate-400 hover:enabled:text-violet-600 hover:enabled:bg-violet-50 disabled:opacity-30 disabled:cursor-not-allowed", title: "Move right", children: _jsx("svg", { width: "16", height: "16", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) })] }), _jsx("span", { className: "text-[0.6875rem] text-slate-400", children: "Matrix view for service levels" })] })] }));
|
|
210
230
|
});
|
package/dist/style.css
CHANGED
|
@@ -30,8 +30,12 @@
|
|
|
30
30
|
--color-emerald-600: oklch(59.6% 0.145 163.225);
|
|
31
31
|
--color-emerald-700: oklch(50.8% 0.118 165.612);
|
|
32
32
|
--color-emerald-800: oklch(43.2% 0.095 166.913);
|
|
33
|
+
--color-teal-50: oklch(98.4% 0.014 180.72);
|
|
33
34
|
--color-teal-100: oklch(95.3% 0.051 180.801);
|
|
35
|
+
--color-teal-300: oklch(85.5% 0.138 181.071);
|
|
34
36
|
--color-teal-500: oklch(70.4% 0.14 182.503);
|
|
37
|
+
--color-teal-600: oklch(60% 0.118 184.704);
|
|
38
|
+
--color-teal-700: oklch(51.1% 0.096 186.391);
|
|
35
39
|
--color-sky-50: oklch(97.7% 0.013 236.62);
|
|
36
40
|
--color-sky-100: oklch(95.1% 0.026 236.824);
|
|
37
41
|
--color-sky-200: oklch(90.1% 0.058 230.902);
|
|
@@ -1126,6 +1130,9 @@
|
|
|
1126
1130
|
.border-slate-400 {
|
|
1127
1131
|
border-color: var(--color-slate-400);
|
|
1128
1132
|
}
|
|
1133
|
+
.border-teal-300 {
|
|
1134
|
+
border-color: var(--color-teal-300);
|
|
1135
|
+
}
|
|
1129
1136
|
.border-teal-500 {
|
|
1130
1137
|
border-color: var(--color-teal-500);
|
|
1131
1138
|
}
|
|
@@ -1309,6 +1316,9 @@
|
|
|
1309
1316
|
background-color: color-mix(in oklab, var(--color-slate-900) 75%, transparent);
|
|
1310
1317
|
}
|
|
1311
1318
|
}
|
|
1319
|
+
.bg-teal-50 {
|
|
1320
|
+
background-color: var(--color-teal-50);
|
|
1321
|
+
}
|
|
1312
1322
|
.bg-teal-100 {
|
|
1313
1323
|
background-color: var(--color-teal-100);
|
|
1314
1324
|
}
|
|
@@ -1862,6 +1872,12 @@
|
|
|
1862
1872
|
.text-teal-500 {
|
|
1863
1873
|
color: var(--color-teal-500);
|
|
1864
1874
|
}
|
|
1875
|
+
.text-teal-600 {
|
|
1876
|
+
color: var(--color-teal-600);
|
|
1877
|
+
}
|
|
1878
|
+
.text-teal-700 {
|
|
1879
|
+
color: var(--color-teal-700);
|
|
1880
|
+
}
|
|
1865
1881
|
.text-violet-500 {
|
|
1866
1882
|
color: var(--color-violet-500);
|
|
1867
1883
|
}
|
|
@@ -2845,6 +2861,15 @@
|
|
|
2845
2861
|
}
|
|
2846
2862
|
}
|
|
2847
2863
|
}
|
|
2864
|
+
.hover\:enabled\:bg-violet-50 {
|
|
2865
|
+
&:hover {
|
|
2866
|
+
@media (hover: hover) {
|
|
2867
|
+
&:enabled {
|
|
2868
|
+
background-color: var(--color-violet-50);
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2848
2873
|
.hover\:enabled\:bg-violet-100 {
|
|
2849
2874
|
&:hover {
|
|
2850
2875
|
@media (hover: hover) {
|
|
@@ -503,6 +503,8 @@ function mapResourceTemplateState(state, doc) {
|
|
|
503
503
|
content: section.content,
|
|
504
504
|
displayOrder: section.displayOrder,
|
|
505
505
|
})),
|
|
506
|
+
weight: state.weight ?? null,
|
|
507
|
+
subtitle: state.subtitle || null,
|
|
506
508
|
};
|
|
507
509
|
}
|
|
508
510
|
/**
|
|
@@ -588,6 +590,8 @@ function mapServiceOfferingState(state, doc) {
|
|
|
588
590
|
name: tier.name,
|
|
589
591
|
description: tier.description || null,
|
|
590
592
|
isCustomPricing: tier.isCustomPricing,
|
|
593
|
+
mostPopular: tier.mostPopular,
|
|
594
|
+
excludeFromSetupFee: tier.excludeFromSetupFee ?? false,
|
|
591
595
|
pricingMode: tier.pricingMode || null,
|
|
592
596
|
pricing: {
|
|
593
597
|
amount: tier.pricing?.amount ?? null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../subgraphs/resources-services/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,eAAO,MAAM,MAAM,EAAE,YA0VpB,CAAC"}
|
|
@@ -83,6 +83,8 @@ export const schema = gql `
|
|
|
83
83
|
optionGroups: [RSOptionGroup!]!
|
|
84
84
|
faqFields: [RSFaqField!]
|
|
85
85
|
contentSections: [RSContentSection!]!
|
|
86
|
+
weight: Int
|
|
87
|
+
subtitle: String
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
enum RSTemplateStatus {
|
|
@@ -241,9 +243,11 @@ export const schema = gql `
|
|
|
241
243
|
pricingMode: RSTierPricingMode
|
|
242
244
|
pricing: RSServicePricing!
|
|
243
245
|
defaultBillingCycle: RSBillingCycle
|
|
246
|
+
mostPopular: Boolean!
|
|
244
247
|
billingCycleDiscounts: [RSBillingCycleDiscount!]!
|
|
245
248
|
serviceLevels: [RSServiceLevelBinding!]!
|
|
246
249
|
usageLimits: [RSServiceUsageLimit!]!
|
|
250
|
+
excludeFromSetupFee: Boolean!
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
type RSServicePricing {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/service-offering",
|
|
3
3
|
"description": "service offering document models",
|
|
4
|
-
"version": "1.0.0-dev.
|
|
4
|
+
"version": "1.0.0-dev.24",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -76,13 +76,13 @@
|
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
78
|
"@electric-sql/pglite": "0.3.15",
|
|
79
|
-
"@powerhousedao/builder-tools": "6.0.0-dev.
|
|
80
|
-
"@powerhousedao/common": "6.0.0-dev.
|
|
81
|
-
"@powerhousedao/design-system": "6.0.0-dev.
|
|
79
|
+
"@powerhousedao/builder-tools": "6.0.0-dev.105",
|
|
80
|
+
"@powerhousedao/common": "6.0.0-dev.105",
|
|
81
|
+
"@powerhousedao/design-system": "6.0.0-dev.105",
|
|
82
82
|
"@powerhousedao/document-engineering": "1.40.1",
|
|
83
|
-
"@powerhousedao/vetra": "6.0.0-dev.
|
|
83
|
+
"@powerhousedao/vetra": "6.0.0-dev.105",
|
|
84
84
|
"@uiw/react-md-editor": "^4.0.11",
|
|
85
|
-
"document-model": "6.0.0-dev.
|
|
85
|
+
"document-model": "6.0.0-dev.105",
|
|
86
86
|
"graphql": "16.12.0",
|
|
87
87
|
"graphql-tag": "^2.12.6",
|
|
88
88
|
"lucide-react": "^0.577.0",
|
|
@@ -91,22 +91,22 @@
|
|
|
91
91
|
},
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@eslint/js": "^9.38.0",
|
|
94
|
+
"@powerhousedao/analytics-engine-core": "6.0.0-dev.105",
|
|
95
|
+
"@powerhousedao/config": "6.0.0-dev.105",
|
|
96
|
+
"@powerhousedao/connect": "6.0.0-dev.105",
|
|
97
|
+
"@powerhousedao/ph-cli": "6.0.0-dev.105",
|
|
98
|
+
"@powerhousedao/reactor-api": "6.0.0-dev.105",
|
|
99
|
+
"@powerhousedao/reactor-browser": "6.0.0-dev.105",
|
|
100
|
+
"@powerhousedao/reactor-local": "6.0.0-dev.105",
|
|
101
|
+
"@powerhousedao/switchboard": "6.0.0-dev.105",
|
|
94
102
|
"@semantic-release/changelog": "^6.0.3",
|
|
95
103
|
"@semantic-release/git": "^10.0.1",
|
|
96
|
-
"@powerhousedao/analytics-engine-core": "6.0.0-dev.104",
|
|
97
|
-
"@powerhousedao/config": "6.0.0-dev.104",
|
|
98
|
-
"@powerhousedao/connect": "6.0.0-dev.104",
|
|
99
|
-
"@powerhousedao/ph-cli": "6.0.0-dev.104",
|
|
100
|
-
"@powerhousedao/reactor-api": "6.0.0-dev.104",
|
|
101
|
-
"@powerhousedao/reactor-browser": "6.0.0-dev.104",
|
|
102
|
-
"@powerhousedao/reactor-local": "6.0.0-dev.104",
|
|
103
|
-
"@powerhousedao/switchboard": "6.0.0-dev.104",
|
|
104
104
|
"@tailwindcss/cli": "^4.1.4",
|
|
105
105
|
"@testing-library/react": "^16.3.0",
|
|
106
106
|
"@types/node": "^24.9.2",
|
|
107
107
|
"@types/react": "^19.2.3",
|
|
108
108
|
"@vitejs/plugin-react": "^5.1.0",
|
|
109
|
-
"document-drive": "6.0.0-dev.
|
|
109
|
+
"document-drive": "6.0.0-dev.105",
|
|
110
110
|
"eslint": "^9.38.0",
|
|
111
111
|
"eslint-config-prettier": "^10.1.8",
|
|
112
112
|
"eslint-plugin-prettier": "^5.5.4",
|