@powerhousedao/contributor-billing 0.1.41 → 0.1.42
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/document-models.d.ts.map +1 -1
- package/dist/document-models/document-models.js +2 -0
- package/dist/document-models/resource-template/gen/document-model.js +25 -25
- package/dist/document-models/resource-template/gen/reducer.d.ts +1 -1
- package/dist/document-models/resource-template/gen/reducer.d.ts.map +1 -1
- package/dist/document-models/resource-template/hooks.d.ts +1 -1
- package/dist/document-models/resource-template/hooks.d.ts.map +1 -1
- package/dist/document-models/resource-template/module.d.ts +1 -1
- package/dist/document-models/resource-template/module.d.ts.map +1 -1
- package/dist/document-models/resource-template/reducers/audience-management.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/audience-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/audience-management.js +17 -0
- package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts +59 -0
- package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/facet-preset-management.js +52 -0
- package/dist/document-models/resource-template/reducers/facet-targeting.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/facet-targeting.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/facet-targeting.js +47 -0
- package/dist/document-models/resource-template/reducers/option-group-management.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/option-group-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/option-group-management.js +44 -0
- package/dist/document-models/resource-template/reducers/service-category-management.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/service-category-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/service-category-management.js +10 -0
- package/dist/document-models/resource-template/reducers/service-management.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/service-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/service-management.js +71 -0
- package/dist/document-models/resource-template/reducers/template-management.d.ts +3 -0
- package/dist/document-models/resource-template/reducers/template-management.d.ts.map +1 -0
- package/dist/document-models/resource-template/reducers/template-management.js +32 -0
- package/dist/document-models/resource-template/src/reducers/audience-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/audience-management.js +1 -1
- package/dist/document-models/resource-template/src/reducers/facet-targeting.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/facet-targeting.js +1 -1
- package/dist/document-models/resource-template/src/reducers/option-group-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/option-group-management.js +1 -1
- package/dist/document-models/resource-template/src/reducers/service-category-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/service-category-management.js +1 -1
- package/dist/document-models/resource-template/src/reducers/service-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/service-management.js +1 -1
- package/dist/document-models/resource-template/src/reducers/template-management.d.ts.map +1 -1
- package/dist/document-models/resource-template/src/reducers/template-management.js +1 -1
- package/dist/document-models/service-offering/gen/document-model.js +5 -5
- package/dist/document-models/service-offering/gen/document-schema.d.ts.map +1 -1
- package/dist/document-models/service-offering/gen/reducer.d.ts +1 -1
- package/dist/document-models/service-offering/gen/reducer.d.ts.map +1 -1
- package/dist/document-models/service-offering/gen/schema/types.d.ts +3 -0
- package/dist/document-models/service-offering/gen/schema/types.d.ts.map +1 -1
- package/dist/document-models/service-offering/gen/schema/zod.d.ts.map +1 -1
- package/dist/document-models/service-offering/gen/schema/zod.js +3 -0
- package/dist/document-models/service-offering/src/reducers/option-group-management.d.ts.map +1 -1
- package/dist/document-models/service-offering/src/reducers/option-group-management.js +11 -8
- package/dist/document-models/service-offering/src/reducers/service-management.d.ts.map +1 -1
- package/dist/document-models/service-offering/src/reducers/service-management.js +20 -12
- package/dist/document-models/service-offering/src/reducers/tier-management.d.ts.map +1 -1
- package/dist/document-models/service-offering/src/reducers/tier-management.js +21 -19
- package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts +1 -1
- package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts.map +1 -1
- package/dist/editors/resource-template-editor/components/FacetTargeting.js +526 -19
- package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts +1 -1
- package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts.map +1 -1
- package/dist/editors/resource-template-editor/components/TemplateInfo.js +302 -2
- package/dist/editors/resource-template-editor/editor.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/EditName.js +1 -1
- package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts +10 -0
- package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts.map +1 -0
- package/dist/editors/service-offering-editor/components/OfferingProgress.js +240 -0
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.js +111 -4
- package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ServiceCatalog.js +318 -1
- package/dist/editors/service-offering-editor/components/ServicesList.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/ServicesList.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/ServicesList.js +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TheMatrix.js +548 -13
- package/dist/editors/service-offering-editor/components/TierDefinition.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/TierDefinition.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/components/TierDefinition.js +406 -4
- package/dist/editors/service-offering-editor/components/TiersList.d.ts +1 -1
- package/dist/editors/service-offering-editor/components/TiersList.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/editor.d.ts.map +1 -1
- package/dist/editors/service-offering-editor/editor.js +2 -2
- package/dist/powerhouse.manifest.json +18 -0
- package/dist/subgraphs/index.d.ts +1 -0
- package/dist/subgraphs/index.d.ts.map +1 -1
- package/dist/subgraphs/index.js +1 -0
- package/dist/subgraphs/resource-template/index.d.ts +11 -0
- package/dist/subgraphs/resource-template/index.d.ts.map +1 -0
- package/dist/subgraphs/resource-template/index.js +11 -0
- package/dist/subgraphs/resource-template/resolvers.d.ts +3 -0
- package/dist/subgraphs/resource-template/resolvers.d.ts.map +1 -0
- package/dist/subgraphs/resource-template/resolvers.js +312 -0
- package/dist/subgraphs/resource-template/schema.d.ts +3 -0
- package/dist/subgraphs/resource-template/schema.d.ts.map +1 -0
- package/dist/subgraphs/resource-template/schema.js +262 -0
- package/dist/subgraphs/service-offering/resolvers.d.ts.map +1 -1
- package/dist/subgraphs/service-offering/resolvers.js +24 -0
- package/dist/subgraphs/service-offering/schema.d.ts.map +1 -1
- package/dist/subgraphs/service-offering/schema.js +21 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
|
|
2
|
-
import type { ServiceOfferingDocument, ServiceOfferingAction } from "
|
|
2
|
+
import type { ServiceOfferingDocument, ServiceOfferingAction } from "@powerhousedao/contributor-billing/document-models/service-offering";
|
|
3
3
|
interface ResourceTemplateSelectorProps {
|
|
4
4
|
document: ServiceOfferingDocument;
|
|
5
5
|
dispatch: DocumentDispatch<ServiceOfferingAction>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceTemplateSelector.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ResourceTemplateSelector.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,
|
|
1
|
+
{"version":3,"file":"ResourceTemplateSelector.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ResourceTemplateSelector.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACtB,MAAM,qEAAqE,CAAC;AAe7E,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,2CAoO/B"}
|
|
@@ -47,17 +47,34 @@ export function ResourceTemplateSelector({ document, dispatch, }) {
|
|
|
47
47
|
}, []);
|
|
48
48
|
const activeTemplates = filteredTemplates.filter((t) => t.state.global.status === "ACTIVE");
|
|
49
49
|
const otherTemplates = filteredTemplates.filter((t) => t.state.global.status !== "ACTIVE");
|
|
50
|
+
// Determine recommended template (Social Proof / Authority Bias)
|
|
51
|
+
// The most complete active template is recommended
|
|
52
|
+
const recommendedTemplateId = useMemo(() => {
|
|
53
|
+
if (!activeTemplates || activeTemplates.length === 0)
|
|
54
|
+
return null;
|
|
55
|
+
// Score templates by completeness (more services, facets, audiences = better)
|
|
56
|
+
const scored = activeTemplates.map((t) => ({
|
|
57
|
+
id: t.header.id,
|
|
58
|
+
score: t.state.global.services.length * 3 + // Services weighted highest
|
|
59
|
+
t.state.global.facetTargets.length * 2 +
|
|
60
|
+
t.state.global.targetAudiences.length +
|
|
61
|
+
(t.state.global.description ? 2 : 0) +
|
|
62
|
+
(t.state.global.thumbnailUrl ? 1 : 0),
|
|
63
|
+
}));
|
|
64
|
+
const best = scored.sort((a, b) => b.score - a.score)[0];
|
|
65
|
+
return best?.id || null;
|
|
66
|
+
}, [activeTemplates]);
|
|
50
67
|
// If a template is selected and user is not changing, show the detail view with facet selection
|
|
51
68
|
if (selectedTemplate && !showingSelector) {
|
|
52
69
|
return (_jsxs(_Fragment, { children: [_jsx("style", { children: styles }), _jsx("div", { className: "rts-container", children: _jsx(TemplateDetailView, { template: selectedTemplate, offeringDocument: document, dispatch: dispatch, onChangeTemplate: handleChangeTemplate }) })] }));
|
|
53
70
|
}
|
|
54
|
-
return (_jsxs(_Fragment, { children: [_jsx("style", { children: styles }), _jsxs("div", { className: "rts-container", children: [_jsxs("div", { className: "rts-header", children: [_jsx("div", { className: "rts-header__icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" }) }) }), _jsxs("div", { className: "rts-header__text", children: [_jsx("h2", { className: "rts-header__title", children: "Select Resource Template" }), _jsx("p", { className: "rts-header__subtitle", children: "Choose a resource template to base this service offering on. The template defines the product configuration, target audiences, and available services." })] })] }), _jsxs("div", { className: "rts-search", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: [_jsx("circle", { cx: "11", cy: "11", r: "8", strokeWidth: "2" }), _jsx("path", { d: "M21 21l-4.35-4.35", strokeWidth: "2" })] }), _jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search resource templates...", className: "rts-search__input" }), searchQuery && (_jsx("button", { type: "button", onClick: () => setSearchQuery(""), className: "rts-search__clear", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) }))] }), _jsx("div", { className: "rts-templates", children: !templates || templates.length === 0 ? (_jsxs("div", { className: "rts-empty", children: [_jsx("div", { className: "rts-empty__icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: _jsx("path", { d: "M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" }) }) }), _jsx("h3", { className: "rts-empty__title", children: "No Resource Templates Found" }), _jsx("p", { className: "rts-empty__desc", children: "Create a Resource Template first to define the base configuration for your service offering." })] })) : filteredTemplates.length === 0 ? (_jsx("div", { className: "rts-empty rts-empty--search", children: _jsxs("p", { className: "rts-empty__desc", children: ["No templates match \"", searchQuery, "\""] }) })) : (_jsxs(_Fragment, { children: [activeTemplates.length > 0 && (_jsxs("div", { className: "rts-section", children: [_jsxs("h3", { className: "rts-section__title", children: [_jsx("span", { className: "rts-section__dot rts-section__dot--active" }), "Active Templates"] }), _jsx("div", { className: "rts-grid", children: activeTemplates.map((template) => (_jsx(TemplateCard, { template: template, isSelected: currentTemplateId === template.header.id, onSelect: () => handleSelectTemplate(template) }, template.header.id))) })] })), otherTemplates.length > 0 && (_jsxs("div", { className: "rts-section", children: [_jsxs("h3", { className: "rts-section__title", children: [_jsx("span", { className: "rts-section__dot" }), "Other Templates"] }), _jsx("div", { className: "rts-grid", children: otherTemplates.map((template) => (_jsx(TemplateCard, { template: template, isSelected: currentTemplateId === template.header.id, onSelect: () => handleSelectTemplate(template) }, template.header.id))) })] }))] })) })] })] }));
|
|
71
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: styles }), _jsxs("div", { className: "rts-container", children: [_jsxs("div", { className: "rts-header", children: [_jsx("div", { className: "rts-header__icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" }) }) }), _jsxs("div", { className: "rts-header__text", children: [_jsx("h2", { className: "rts-header__title", children: "Select Resource Template" }), _jsx("p", { className: "rts-header__subtitle", children: "Choose a resource template to base this service offering on. The template defines the product configuration, target audiences, and available services." })] })] }), _jsxs("div", { className: "rts-search", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: [_jsx("circle", { cx: "11", cy: "11", r: "8", strokeWidth: "2" }), _jsx("path", { d: "M21 21l-4.35-4.35", strokeWidth: "2" })] }), _jsx("input", { type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search resource templates...", className: "rts-search__input" }), searchQuery && (_jsx("button", { type: "button", onClick: () => setSearchQuery(""), className: "rts-search__clear", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M18 6L6 18M6 6l12 12", strokeWidth: "2" }) }) }))] }), _jsx("div", { className: "rts-templates", children: !templates || templates.length === 0 ? (_jsxs("div", { className: "rts-empty", children: [_jsx("div", { className: "rts-empty__icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: _jsx("path", { d: "M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m6.75 12H9m1.5-12H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" }) }) }), _jsx("h3", { className: "rts-empty__title", children: "No Resource Templates Found" }), _jsx("p", { className: "rts-empty__desc", children: "Create a Resource Template first to define the base configuration for your service offering." })] })) : filteredTemplates.length === 0 ? (_jsx("div", { className: "rts-empty rts-empty--search", children: _jsxs("p", { className: "rts-empty__desc", children: ["No templates match \"", searchQuery, "\""] }) })) : (_jsxs(_Fragment, { children: [activeTemplates.length > 0 && (_jsxs("div", { className: "rts-section", children: [_jsxs("h3", { className: "rts-section__title", children: [_jsx("span", { className: "rts-section__dot rts-section__dot--active" }), "Active Templates"] }), _jsx("div", { className: "rts-grid", children: activeTemplates.map((template) => (_jsx(TemplateCard, { template: template, isSelected: currentTemplateId === template.header.id, isRecommended: template.header.id === recommendedTemplateId, onSelect: () => handleSelectTemplate(template) }, template.header.id))) })] })), otherTemplates.length > 0 && (_jsxs("div", { className: "rts-section", children: [_jsxs("h3", { className: "rts-section__title", children: [_jsx("span", { className: "rts-section__dot" }), "Other Templates"] }), _jsx("div", { className: "rts-grid", children: otherTemplates.map((template) => (_jsx(TemplateCard, { template: template, isSelected: currentTemplateId === template.header.id, onSelect: () => handleSelectTemplate(template) }, template.header.id))) })] }))] })) })] })] }));
|
|
55
72
|
}
|
|
56
|
-
function TemplateCard({ template, isSelected, onSelect }) {
|
|
73
|
+
function TemplateCard({ template, isSelected, isRecommended, onSelect, }) {
|
|
57
74
|
const { state } = template;
|
|
58
75
|
const globalState = state.global;
|
|
59
76
|
const statusStyle = getStatusStyle(globalState.status);
|
|
60
|
-
return (_jsxs("button", { type: "button", onClick: onSelect, className: `rts-card ${isSelected ? "rts-card--selected" : ""}`, children: [_jsxs("div", { className: "rts-card__header", children: [globalState.thumbnailUrl ? (_jsx("div", { className: "rts-card__thumb", style: { backgroundImage: `url(${globalState.thumbnailUrl})` } })) : (_jsx("div", { className: "rts-card__thumb rts-card__thumb--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" })] }) })), _jsxs("span", { className: "rts-card__status", style: {
|
|
77
|
+
return (_jsxs("button", { type: "button", onClick: onSelect, className: `rts-card ${isSelected ? "rts-card--selected" : ""} ${isRecommended ? "rts-card--recommended" : ""}`, children: [isRecommended && !isSelected && (_jsxs("div", { className: "rts-card__recommended", children: [_jsx("svg", { 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" }) }), "Recommended"] })), _jsxs("div", { className: "rts-card__header", children: [globalState.thumbnailUrl ? (_jsx("div", { className: "rts-card__thumb", style: { backgroundImage: `url(${globalState.thumbnailUrl})` } })) : (_jsx("div", { className: "rts-card__thumb rts-card__thumb--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" })] }) })), _jsxs("span", { className: "rts-card__status", style: {
|
|
61
78
|
backgroundColor: statusStyle.bg,
|
|
62
79
|
color: statusStyle.text,
|
|
63
80
|
}, children: [_jsx("span", { className: "rts-card__status-dot", style: { backgroundColor: statusStyle.dot } }), globalState.status.replace("_", " ")] })] }), _jsxs("div", { className: "rts-card__body", children: [_jsx("h4", { className: "rts-card__title", children: globalState.title || "Untitled" }), _jsx("p", { className: "rts-card__summary", children: globalState.summary || "No summary provided" }), _jsxs("div", { className: "rts-card__meta", children: [globalState.targetAudiences.length > 0 && (_jsxs("span", { className: "rts-card__tag", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: [_jsx("path", { d: "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2", strokeWidth: "2" }), _jsx("circle", { cx: "9", cy: "7", r: "4", strokeWidth: "2" }), _jsx("path", { d: "M23 21v-2a4 4 0 0 0-3-3.87", strokeWidth: "2" }), _jsx("path", { d: "M16 3.13a4 4 0 0 1 0 7.75", strokeWidth: "2" })] }), globalState.targetAudiences.length] })), globalState.services.length > 0 && (_jsxs("span", { className: "rts-card__tag", children: [_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: [_jsx("path", { d: "M12 2L2 7l10 5 10-5-10-5z", strokeWidth: "2" }), _jsx("path", { d: "M2 17l10 5 10-5", strokeWidth: "2" }), _jsx("path", { d: "M2 12l10 5 10-5", strokeWidth: "2" })] }), globalState.services.length] })), globalState.facetTargets.length > 0 && (_jsxs("span", { className: "rts-card__tag", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M3 6h18M7 12h10M10 18h4", strokeWidth: "2" }) }), globalState.facetTargets.length] }))] })] }), isSelected && (_jsx("div", { className: "rts-card__check", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M5 12l5 5L20 7", strokeWidth: "2.5" }) }) }))] }));
|
|
@@ -103,6 +120,13 @@ function TemplateDetailView({ template, offeringDocument, dispatch, onChangeTemp
|
|
|
103
120
|
}));
|
|
104
121
|
}
|
|
105
122
|
}, [offeringFacetTargets, dispatch]);
|
|
123
|
+
// Calculate facet completion progress (Goal-Gradient Effect)
|
|
124
|
+
const facetProgress = useMemo(() => {
|
|
125
|
+
const totalOptions = globalState.facetTargets.reduce((sum, facet) => sum + facet.selectedOptions.length, 0);
|
|
126
|
+
const selectedOptions = offeringFacetTargets.reduce((sum, facet) => sum + facet.selectedOptions.length, 0);
|
|
127
|
+
const percent = totalOptions > 0 ? Math.round((selectedOptions / totalOptions) * 100) : 0;
|
|
128
|
+
return { total: totalOptions, selected: selectedOptions, percent };
|
|
129
|
+
}, [globalState.facetTargets, offeringFacetTargets]);
|
|
106
130
|
return (_jsxs("div", { className: "rtd-container", children: [_jsx("div", { className: "rtd-selected-header", children: _jsxs("div", { className: "rtd-selected-header__info", children: [_jsxs("span", { className: "rtd-selected-header__badge", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }), "Selected Template"] }), _jsxs("button", { type: "button", onClick: onChangeTemplate, className: "rtd-selected-header__change", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" }) }), "Change Template"] })] }) }), _jsxs("section", { className: "rtd-hero", children: [_jsx("div", { className: "rtd-hero__thumbnail-area", children: _jsxs("div", { className: "rtd-hero__thumbnail", style: {
|
|
107
131
|
backgroundImage: globalState.thumbnailUrl
|
|
108
132
|
? `url(${globalState.thumbnailUrl})`
|
|
@@ -116,7 +140,7 @@ function TemplateDetailView({ template, offeringDocument, dispatch, onChangeTemp
|
|
|
116
140
|
borderColor: `${audience.color}40`,
|
|
117
141
|
color: audience.color,
|
|
118
142
|
}
|
|
119
|
-
: undefined, children: audience.label }, audience.id))) })), _jsx("p", { className: "rtd-hero__summary", children: globalState.summary || "No summary provided" })] })] }), globalState.description && (_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-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" }) }) }), _jsx("div", { children: _jsx("h3", { className: "rtd-card__title", children: "Description" }) })] }), _jsx("p", { className: "rtd-card__text", children: globalState.description })] })), _jsxs("div", { className: "rtd-grid", children: [_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-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: "rtd-card__title", children: "Formation & Setup" }), _jsx("p", { className: "rtd-card__subtitle", children: "One-time setup services" })] })] }), globalState.setupServices.length > 0 ? (_jsx("div", { className: "rtd-services", children: globalState.setupServices.map((service, index) => (_jsxs("div", { className: "rtd-service", children: [_jsx("span", { className: "rtd-service__bullet" }), _jsx("span", { className: "rtd-service__text", children: service })] }, index))) })) : (_jsx("p", { className: "rtd-card__empty", children: "No setup services defined" }))] }), _jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-card__icon--amber", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 8v4l3 3" }), _jsx("circle", { cx: "12", cy: "12", r: "9" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "rtd-card__title", children: "Recurring Services" }), _jsx("p", { className: "rtd-card__subtitle", children: "Ongoing services included" })] })] }), globalState.recurringServices.length > 0 ? (_jsx("div", { className: "rtd-services", children: globalState.recurringServices.map((service, index) => (_jsxs("div", { className: "rtd-service", children: [_jsx("span", { className: "rtd-service__bullet rtd-service__bullet--recurring" }), _jsx("span", { className: "rtd-service__text", children: service })] }, index))) })) : (_jsx("p", { className: "rtd-card__empty", children: "No recurring services defined" }))] })] }), globalState.facetTargets.length > 0 && (_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-card__icon--sky", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M3 6h18M7 12h10M10 18h4" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "rtd-card__title", children: "Facet Targeting" }), _jsx("p", { className: "rtd-card__subtitle", children: "Select which facet options apply to this offering" })] })] }), _jsx("div", { className: "rtd-facets", children: globalState.facetTargets.map((facet) => (_jsxs("div", { className: "rtd-facet rtd-facet--selectable", children: [_jsx("span", { className: "rtd-facet__label", children: facet.categoryLabel }), _jsx("div", { className: "rtd-facet__options", children: facet.selectedOptions.map((option) => {
|
|
143
|
+
: undefined, children: audience.label }, audience.id))) })), _jsx("p", { className: "rtd-hero__summary", children: globalState.summary || "No summary provided" })] })] }), globalState.description && (_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-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" }) }) }), _jsx("div", { children: _jsx("h3", { className: "rtd-card__title", children: "Description" }) })] }), _jsx("p", { className: "rtd-card__text", children: globalState.description })] })), _jsxs("div", { className: "rtd-grid", children: [_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-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: "rtd-card__title", children: "Formation & Setup" }), _jsx("p", { className: "rtd-card__subtitle", children: "One-time setup services" })] })] }), globalState.setupServices.length > 0 ? (_jsx("div", { className: "rtd-services", children: globalState.setupServices.map((service, index) => (_jsxs("div", { className: "rtd-service", children: [_jsx("span", { className: "rtd-service__bullet" }), _jsx("span", { className: "rtd-service__text", children: service })] }, index))) })) : (_jsx("p", { className: "rtd-card__empty", children: "No setup services defined" }))] }), _jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-card__icon--amber", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M12 8v4l3 3" }), _jsx("circle", { cx: "12", cy: "12", r: "9" })] }) }), _jsxs("div", { children: [_jsx("h3", { className: "rtd-card__title", children: "Recurring Services" }), _jsx("p", { className: "rtd-card__subtitle", children: "Ongoing services included" })] })] }), globalState.recurringServices.length > 0 ? (_jsx("div", { className: "rtd-services", children: globalState.recurringServices.map((service, index) => (_jsxs("div", { className: "rtd-service", children: [_jsx("span", { className: "rtd-service__bullet rtd-service__bullet--recurring" }), _jsx("span", { className: "rtd-service__text", children: service })] }, index))) })) : (_jsx("p", { className: "rtd-card__empty", children: "No recurring services defined" }))] })] }), globalState.facetTargets.length > 0 && (_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header rtd-card__header--with-progress", children: [_jsxs("div", { className: "rtd-card__header-left", children: [_jsx("div", { className: "rtd-card__icon rtd-card__icon--sky", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M3 6h18M7 12h10M10 18h4" }) }) }), _jsxs("div", { children: [_jsx("h3", { className: "rtd-card__title", children: "Facet Targeting" }), _jsx("p", { className: "rtd-card__subtitle", children: "Select which facet options apply to this offering" })] })] }), _jsxs("div", { className: "rtd-facet-progress", children: [_jsx("div", { className: "rtd-facet-progress__bar", children: _jsx("div", { className: "rtd-facet-progress__fill", style: { width: `${facetProgress.percent}%` } }) }), _jsxs("span", { className: "rtd-facet-progress__text", children: [facetProgress.selected, " of ", facetProgress.total, " selected", facetProgress.percent === 100 && (_jsx("span", { className: "rtd-facet-progress__complete", children: " \u2713" }))] })] })] }), _jsx("div", { className: "rtd-facets", children: globalState.facetTargets.map((facet) => (_jsxs("div", { className: "rtd-facet rtd-facet--selectable", children: [_jsx("span", { className: "rtd-facet__label", children: facet.categoryLabel }), _jsx("div", { className: "rtd-facet__options", children: facet.selectedOptions.map((option) => {
|
|
120
144
|
const selected = isOptionSelected(facet.categoryKey, option);
|
|
121
145
|
return (_jsxs("button", { type: "button", className: `rtd-facet__option rtd-facet__option--toggle ${selected ? "rtd-facet__option--selected" : ""}`, onClick: () => handleToggleFacetOption(facet.categoryKey, facet.categoryLabel, option), children: [_jsx("span", { className: "rtd-facet__checkbox", children: selected && (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", children: _jsx("path", { d: "M5 12l5 5L20 7" }) })) }), option.replace(/-/g, " ")] }, option));
|
|
122
146
|
}) })] }, facet.id))) })] })), globalState.services.length > 0 && (_jsxs("section", { className: "rtd-card", children: [_jsxs("div", { className: "rtd-card__header", children: [_jsx("div", { className: "rtd-card__icon rtd-card__icon--teal", 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: "rtd-card__title", children: "Services Defined" }), _jsxs("p", { className: "rtd-card__subtitle", children: [globalState.services.length, " service", globalState.services.length !== 1 ? "s" : "", " available"] })] })] }), _jsx("div", { className: "rtd-services-list", children: globalState.services.map((service) => (_jsxs("div", { className: "rtd-service-item", children: [_jsxs("div", { className: "rtd-service-item__main", children: [_jsx("span", { className: "rtd-service-item__title", children: service.title }), service.isSetupFormation && (_jsx("span", { className: "rtd-service-item__badge", children: "Setup" }))] }), service.description && (_jsx("p", { className: "rtd-service-item__desc", children: service.description }))] }, service.id))) })] })), _jsxs("section", { className: "rtd-metadata", children: [globalState.operatorId && (_jsxs("div", { className: "rtd-meta-field", children: [_jsx("span", { className: "rtd-meta-field__label", children: "Operator ID" }), _jsx("span", { className: "rtd-meta-field__value rtd-meta-field__value--mono", children: globalState.operatorId })] })), globalState.infoLink && (_jsxs("div", { className: "rtd-meta-field", children: [_jsx("span", { className: "rtd-meta-field__label", children: "More Info" }), _jsxs("a", { href: globalState.infoLink, target: "_blank", rel: "noopener noreferrer", className: "rtd-meta-field__link", children: [globalState.infoLink, _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }), _jsx("polyline", { points: "15 3 21 3 21 9" }), _jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })] })] })] }))] })] }));
|
|
@@ -473,6 +497,43 @@ const styles = `
|
|
|
473
497
|
height: 16px;
|
|
474
498
|
}
|
|
475
499
|
|
|
500
|
+
/* Recommended Badge - Social Proof */
|
|
501
|
+
.rts-card--recommended {
|
|
502
|
+
border-color: var(--rts-amber);
|
|
503
|
+
box-shadow: 0 0 0 1px var(--rts-amber), 0 4px 16px rgba(245, 158, 11, 0.15);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.rts-card--recommended:hover {
|
|
507
|
+
border-color: var(--rts-amber);
|
|
508
|
+
box-shadow: 0 0 0 1px var(--rts-amber), 0 6px 20px rgba(245, 158, 11, 0.2);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.rts-card__recommended {
|
|
512
|
+
position: absolute;
|
|
513
|
+
top: -1px;
|
|
514
|
+
right: 40px;
|
|
515
|
+
display: flex;
|
|
516
|
+
align-items: center;
|
|
517
|
+
gap: 4px;
|
|
518
|
+
padding: 6px 12px;
|
|
519
|
+
font-size: 0.625rem;
|
|
520
|
+
font-weight: 700;
|
|
521
|
+
text-transform: uppercase;
|
|
522
|
+
letter-spacing: 0.04em;
|
|
523
|
+
color: white;
|
|
524
|
+
background: linear-gradient(135deg, var(--rts-amber) 0%, #d97706 100%);
|
|
525
|
+
border-radius: 0 0 8px 8px;
|
|
526
|
+
box-shadow: 0 2px 8px rgba(245, 158, 11, 0.4);
|
|
527
|
+
z-index: 5;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.rts-card__recommended svg {
|
|
531
|
+
width: 12px;
|
|
532
|
+
height: 12px;
|
|
533
|
+
fill: currentColor;
|
|
534
|
+
stroke: currentColor;
|
|
535
|
+
}
|
|
536
|
+
|
|
476
537
|
/* Empty State */
|
|
477
538
|
.rts-empty {
|
|
478
539
|
padding: 48px;
|
|
@@ -702,6 +763,52 @@ const styles = `
|
|
|
702
763
|
margin-bottom: 16px;
|
|
703
764
|
}
|
|
704
765
|
|
|
766
|
+
.rtd-card__header--with-progress {
|
|
767
|
+
flex-wrap: wrap;
|
|
768
|
+
justify-content: space-between;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
.rtd-card__header-left {
|
|
772
|
+
display: flex;
|
|
773
|
+
align-items: flex-start;
|
|
774
|
+
gap: 14px;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/* Goal-Gradient Progress Bar for Facet Selection */
|
|
778
|
+
.rtd-facet-progress {
|
|
779
|
+
display: flex;
|
|
780
|
+
flex-direction: column;
|
|
781
|
+
align-items: flex-end;
|
|
782
|
+
gap: 6px;
|
|
783
|
+
min-width: 140px;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
.rtd-facet-progress__bar {
|
|
787
|
+
width: 100%;
|
|
788
|
+
height: 6px;
|
|
789
|
+
background: var(--rts-border-light);
|
|
790
|
+
border-radius: 100px;
|
|
791
|
+
overflow: hidden;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
.rtd-facet-progress__fill {
|
|
795
|
+
height: 100%;
|
|
796
|
+
background: linear-gradient(90deg, var(--rts-sky), var(--rts-emerald));
|
|
797
|
+
border-radius: 100px;
|
|
798
|
+
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
.rtd-facet-progress__text {
|
|
802
|
+
font-size: 0.6875rem;
|
|
803
|
+
color: var(--rts-ink-muted);
|
|
804
|
+
font-weight: 500;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
.rtd-facet-progress__complete {
|
|
808
|
+
color: var(--rts-emerald);
|
|
809
|
+
font-weight: 600;
|
|
810
|
+
}
|
|
811
|
+
|
|
705
812
|
.rtd-card__icon {
|
|
706
813
|
width: 40px;
|
|
707
814
|
height: 40px;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
|
|
2
|
-
import type { ServiceOfferingDocument, ServiceOfferingAction } from "
|
|
2
|
+
import type { ServiceOfferingDocument, ServiceOfferingAction } from "@powerhousedao/contributor-billing/document-models/service-offering";
|
|
3
3
|
interface ScopeAndFacetsProps {
|
|
4
4
|
document: ServiceOfferingDocument;
|
|
5
5
|
dispatch: DocumentDispatch<ServiceOfferingAction>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScopeAndFacets.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ScopeAndFacets.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,
|
|
1
|
+
{"version":3,"file":"ScopeAndFacets.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ScopeAndFacets.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,qEAAqE,CAAC;AAe7E,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAgED,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,mBAAmB,2CA8sBzE"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
|
|
3
|
-
import type { ServiceOfferingDocument, ServiceOfferingAction } from "
|
|
3
|
+
import type { ServiceOfferingDocument, ServiceOfferingAction } from "@powerhousedao/contributor-billing/document-models/service-offering";
|
|
4
4
|
export interface GroupMetadata {
|
|
5
5
|
isSetupFormation: boolean;
|
|
6
6
|
setupFee: number | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceCatalog.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServiceCatalog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAGtB,MAAM,
|
|
1
|
+
{"version":3,"file":"ServiceCatalog.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServiceCatalog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAGtB,MAAM,qEAAqE,CAAC;AA0I7E,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAC9B,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CACpD,CAAC;CACH;AAED,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,gBAAgB,GACjB,EAAE,mBAAmB,2CA+6BrB"}
|
|
@@ -2,6 +2,118 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import React, { useState, useMemo, useEffect } from "react";
|
|
3
3
|
import { generateId } from "document-model/core";
|
|
4
4
|
import { addService, updateService, deleteService, addOptionGroup, updateOptionGroup, deleteOptionGroup, addServiceLevel, removeServiceLevel, } from "../../../document-models/service-offering/gen/creators.js";
|
|
5
|
+
const SERVICE_TEMPLATES = {
|
|
6
|
+
"Setup & Formation": [
|
|
7
|
+
{
|
|
8
|
+
title: "Entity Formation",
|
|
9
|
+
description: "Legal entity registration and setup",
|
|
10
|
+
category: "setup",
|
|
11
|
+
icon: "🏛️",
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
title: "Registered Agent",
|
|
15
|
+
description: "Registered agent designation for one year",
|
|
16
|
+
category: "setup",
|
|
17
|
+
icon: "📋",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
title: "Operating Agreement",
|
|
21
|
+
description: "Custom operating agreement drafting",
|
|
22
|
+
category: "setup",
|
|
23
|
+
icon: "📄",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
title: "EIN Application",
|
|
27
|
+
description: "Federal tax ID number application",
|
|
28
|
+
category: "setup",
|
|
29
|
+
icon: "🔢",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
title: "Banking Resolution",
|
|
33
|
+
description: "Corporate banking resolution documents",
|
|
34
|
+
category: "setup",
|
|
35
|
+
icon: "🏦",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
"Compliance & Governance": [
|
|
39
|
+
{
|
|
40
|
+
title: "Annual Compliance Review",
|
|
41
|
+
description: "Yearly compliance status check and filings",
|
|
42
|
+
category: "recurring",
|
|
43
|
+
icon: "✓",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
title: "Board Meeting Minutes",
|
|
47
|
+
description: "Professional minute-taking for board meetings",
|
|
48
|
+
category: "recurring",
|
|
49
|
+
icon: "📝",
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
title: "Regulatory Filing Support",
|
|
53
|
+
description: "Assistance with regulatory submissions",
|
|
54
|
+
category: "recurring",
|
|
55
|
+
icon: "📊",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
title: "Corporate Record Maintenance",
|
|
59
|
+
description: "Ongoing corporate record keeping",
|
|
60
|
+
category: "recurring",
|
|
61
|
+
icon: "🗂️",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
"Accounting & Finance": [
|
|
65
|
+
{
|
|
66
|
+
title: "Bookkeeping",
|
|
67
|
+
description: "Monthly transaction recording and reconciliation",
|
|
68
|
+
category: "recurring",
|
|
69
|
+
icon: "📚",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
title: "Financial Reporting",
|
|
73
|
+
description: "Monthly/quarterly financial statements",
|
|
74
|
+
category: "recurring",
|
|
75
|
+
icon: "📈",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
title: "Tax Preparation",
|
|
79
|
+
description: "Annual tax return preparation and filing",
|
|
80
|
+
category: "recurring",
|
|
81
|
+
icon: "💰",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "Payroll Processing",
|
|
85
|
+
description: "Employee payroll and tax withholding",
|
|
86
|
+
category: "recurring",
|
|
87
|
+
icon: "💳",
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
"Advisory & Support": [
|
|
91
|
+
{
|
|
92
|
+
title: "Dedicated Account Manager",
|
|
93
|
+
description: "Single point of contact for all services",
|
|
94
|
+
category: "addon",
|
|
95
|
+
icon: "👤",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
title: "Priority Support",
|
|
99
|
+
description: "24/7 priority support line access",
|
|
100
|
+
category: "addon",
|
|
101
|
+
icon: "⭐",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
title: "Strategic Consulting",
|
|
105
|
+
description: "Quarterly strategic review sessions",
|
|
106
|
+
category: "addon",
|
|
107
|
+
icon: "🎯",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
title: "Legal Document Review",
|
|
111
|
+
description: "Contract and agreement review services",
|
|
112
|
+
category: "addon",
|
|
113
|
+
icon: "⚖️",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
5
117
|
export function ServiceCatalog({ document, dispatch, groupMetadata, setGroupMetadata, }) {
|
|
6
118
|
const { state } = document;
|
|
7
119
|
const services = state.global.services ?? [];
|
|
@@ -21,6 +133,8 @@ export function ServiceCatalog({ document, dispatch, groupMetadata, setGroupMeta
|
|
|
21
133
|
const [editGroupName, setEditGroupName] = useState("");
|
|
22
134
|
const [editGroupType, setEditGroupType] = useState("recurring");
|
|
23
135
|
const [editGroupSetupFee, setEditGroupSetupFee] = useState("");
|
|
136
|
+
// Service templates quick-add state
|
|
137
|
+
const [showServiceTemplates, setShowServiceTemplates] = useState(false);
|
|
24
138
|
// Initialize metadata from existing services in groups when optionGroups change
|
|
25
139
|
useEffect(() => {
|
|
26
140
|
const metadata = {};
|
|
@@ -170,6 +284,34 @@ export function ServiceCatalog({ document, dispatch, groupMetadata, setGroupMeta
|
|
|
170
284
|
setSelectedTierIds(new Set());
|
|
171
285
|
setIsAddingService(false);
|
|
172
286
|
};
|
|
287
|
+
// Quick-add service from template (reduces activation energy)
|
|
288
|
+
const handleAddFromTemplate = (template) => {
|
|
289
|
+
if (!selectedGroupId)
|
|
290
|
+
return;
|
|
291
|
+
const serviceId = generateId();
|
|
292
|
+
const now = new Date().toISOString();
|
|
293
|
+
const isSetupFormation = groupMetadata[selectedGroupId]?.isSetupFormation ?? false;
|
|
294
|
+
dispatch(addService({
|
|
295
|
+
id: serviceId,
|
|
296
|
+
title: template.title,
|
|
297
|
+
description: template.description,
|
|
298
|
+
isSetupFormation,
|
|
299
|
+
optionGroupId: selectedGroupId,
|
|
300
|
+
lastModified: now,
|
|
301
|
+
}));
|
|
302
|
+
// Auto-include in all tiers for convenience (can be changed later)
|
|
303
|
+
tiers.forEach((tier) => {
|
|
304
|
+
dispatch(addServiceLevel({
|
|
305
|
+
serviceLevelId: generateId(),
|
|
306
|
+
serviceId,
|
|
307
|
+
tierId: tier.id,
|
|
308
|
+
level: "INCLUDED",
|
|
309
|
+
optionGroupId: selectedGroupId,
|
|
310
|
+
lastModified: now,
|
|
311
|
+
}));
|
|
312
|
+
});
|
|
313
|
+
setShowServiceTemplates(false);
|
|
314
|
+
};
|
|
173
315
|
const handleUpdateService = (service, updates) => {
|
|
174
316
|
dispatch(updateService({
|
|
175
317
|
id: service.id,
|
|
@@ -265,7 +407,13 @@ export function ServiceCatalog({ document, dispatch, groupMetadata, setGroupMeta
|
|
|
265
407
|
setNewGroupName("");
|
|
266
408
|
setNewGroupType("recurring");
|
|
267
409
|
setNewGroupSetupFee("");
|
|
268
|
-
}, className: "catalog__btn catalog__btn--secondary", children: "Cancel" })] })] })), _jsxs("div", { className: "catalog__groups", children: [setupGroups.length > 0 && (_jsx(GroupSection, { title: "Setup & Formation", color: "amber", groups: setupGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), regularGroups.length > 0 && (_jsx(GroupSection, { title: "Recurring Services", color: "emerald", groups: regularGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), addonGroups.length > 0 && (_jsx(GroupSection, { title: "Optional Add-ons", color: "violet", groups: addonGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), ungroupedServices.length > 0 && (_jsx("div", { className: "catalog__section", children: _jsxs("button", { onClick: () => setSelectedGroupId(null), className: `catalog__ungrouped-btn ${selectedGroupId === null ? "catalog__ungrouped-btn--active" : ""}`, children: [_jsx("span", { className: "catalog__ungrouped-name", children: "Ungrouped Services" }), _jsxs("span", { className: "catalog__ungrouped-count", children: [ungroupedServices.length, " services"] })] }) })), optionGroups.length === 0 && ungroupedServices.length === 0 && (_jsxs("div", { className: "catalog__empty", children: [_jsx("p", { className: "catalog__empty-title", children: "No service groups yet" }), _jsx("p", { className: "catalog__empty-text", children: "Click + to create a group" })] }))] })] }), _jsxs("main", { className: "catalog__main", children: [_jsxs("div", { className: "catalog__main-header", children: [_jsxs("div", { className: "catalog__main-info", children: [_jsx("h2", { className: "catalog__main-title", children: selectedGroup?.name || "Ungrouped Services" }), _jsx("p", { className: "catalog__main-subtitle", children: selectedGroupMeta?.isSetupFormation ? (_jsxs("span", { className: "catalog__main-meta", children: [_jsx("span", { className: "catalog__badge catalog__badge--amber", children: "Setup & Formation" }), selectedGroupMeta.setupFee && (_jsxs("span", { className: "catalog__fee-display", children: ["$", selectedGroupMeta.setupFee, " one-time fee"] }))] })) : selectedGroup?.isAddOn ? ("Optional add-on group") : selectedGroup ? ("Included in subscription") : ("Services not assigned to any group") })] }), selectedGroupId && (_jsxs("button", { onClick: () =>
|
|
410
|
+
}, className: "catalog__btn catalog__btn--secondary", children: "Cancel" })] })] })), _jsxs("div", { className: "catalog__groups", children: [setupGroups.length > 0 && (_jsx(GroupSection, { title: "Setup & Formation", color: "amber", groups: setupGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), regularGroups.length > 0 && (_jsx(GroupSection, { title: "Recurring Services", color: "emerald", groups: regularGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), addonGroups.length > 0 && (_jsx(GroupSection, { title: "Optional Add-ons", color: "violet", groups: addonGroups, selectedGroupId: selectedGroupId, groupMetadata: groupMetadata, getServicesForGroup: getServicesForGroup, onSelect: setSelectedGroupId, onEdit: handleOpenEditGroup, onDelete: handleDeleteGroup })), ungroupedServices.length > 0 && (_jsx("div", { className: "catalog__section", children: _jsxs("button", { onClick: () => setSelectedGroupId(null), className: `catalog__ungrouped-btn ${selectedGroupId === null ? "catalog__ungrouped-btn--active" : ""}`, children: [_jsx("span", { className: "catalog__ungrouped-name", children: "Ungrouped Services" }), _jsxs("span", { className: "catalog__ungrouped-count", children: [ungroupedServices.length, " services"] })] }) })), optionGroups.length === 0 && ungroupedServices.length === 0 && (_jsxs("div", { className: "catalog__empty", children: [_jsx("p", { className: "catalog__empty-title", children: "No service groups yet" }), _jsx("p", { className: "catalog__empty-text", children: "Click + to create a group" })] }))] })] }), _jsxs("main", { className: "catalog__main", children: [_jsxs("div", { className: "catalog__main-header", children: [_jsxs("div", { className: "catalog__main-info", children: [_jsx("h2", { className: "catalog__main-title", children: selectedGroup?.name || "Ungrouped Services" }), _jsx("p", { className: "catalog__main-subtitle", children: selectedGroupMeta?.isSetupFormation ? (_jsxs("span", { className: "catalog__main-meta", children: [_jsx("span", { className: "catalog__badge catalog__badge--amber", children: "Setup & Formation" }), selectedGroupMeta.setupFee && (_jsxs("span", { className: "catalog__fee-display", children: ["$", selectedGroupMeta.setupFee, " one-time fee"] }))] })) : selectedGroup?.isAddOn ? ("Optional add-on group") : selectedGroup ? ("Included in subscription") : ("Services not assigned to any group") })] }), selectedGroupId && (_jsxs("div", { className: "catalog__header-actions", children: [_jsxs("button", { onClick: () => setShowServiceTemplates(!showServiceTemplates), className: "catalog__btn catalog__btn--secondary", title: "Quick-add from templates", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z" }) }), "Templates"] }), _jsxs("button", { onClick: () => setIsAddingService(true), className: "catalog__btn catalog__btn--primary", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 4v16m8-8H4" }) }), "Add Service"] })] }))] }), showServiceTemplates && selectedGroupId && (_jsxs("div", { className: "catalog__templates-panel", children: [_jsxs("div", { className: "catalog__templates-header", children: [_jsx("h3", { className: "catalog__templates-title", children: "Quick Add from Templates" }), _jsx("button", { onClick: () => setShowServiceTemplates(false), className: "catalog__templates-close", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("p", { className: "catalog__templates-hint", children: "Click any template to instantly add it to this group. Services will be included in all tiers by default." }), _jsx("div", { className: "catalog__templates-grid", children: Object.entries(SERVICE_TEMPLATES).map(([category, templates]) => (_jsxs("div", { className: "catalog__template-category", children: [_jsx("h4", { className: "catalog__template-category-title", children: category }), _jsx("div", { className: "catalog__template-items", children: templates.map((template, idx) => {
|
|
411
|
+
// Check if service already exists
|
|
412
|
+
const alreadyExists = services.some((s) => s.title.toLowerCase() ===
|
|
413
|
+
template.title.toLowerCase());
|
|
414
|
+
return (_jsxs("button", { onClick: () => !alreadyExists &&
|
|
415
|
+
handleAddFromTemplate(template), disabled: alreadyExists, className: `catalog__template-item ${alreadyExists ? "catalog__template-item--exists" : ""}`, children: [_jsx("span", { className: "catalog__template-icon", children: template.icon }), _jsxs("div", { className: "catalog__template-info", children: [_jsx("span", { className: "catalog__template-name", children: template.title }), _jsx("span", { className: "catalog__template-desc", children: template.description })] }), alreadyExists && (_jsx("span", { className: "catalog__template-badge", children: "Added" }))] }, idx));
|
|
416
|
+
}) })] }, category))) })] })), !selectedGroupId && (_jsxs("div", { className: "catalog__notice catalog__notice--info", 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: "M12 16v-4m0-4h.01" })] }), _jsx("p", { children: "Select a service group from the sidebar to add services. Services must belong to a group to be properly managed." })] })), isAddingService && selectedGroupId && (_jsxs("div", { className: "catalog__add-service-form", children: [_jsxs("div", { className: "catalog__field", children: [_jsx("label", { className: "catalog__label", children: "Service Name" }), _jsx("input", { type: "text", value: newService.title, onChange: (e) => setNewService({ ...newService, title: e.target.value }), placeholder: "Enter service name...", className: "catalog__input", autoFocus: true })] }), _jsxs("div", { className: "catalog__field", children: [_jsx("label", { className: "catalog__label", children: "Description" }), _jsx("textarea", { value: newService.description, onChange: (e) => setNewService({
|
|
269
417
|
...newService,
|
|
270
418
|
description: e.target.value,
|
|
271
419
|
}), placeholder: "Enter description...", rows: 2, className: "catalog__textarea" })] }), tiers.length > 0 && (_jsxs("div", { className: "catalog__field", children: [_jsx("label", { className: "catalog__label", children: "Include in Tiers" }), _jsx("div", { className: "catalog__tier-grid", children: tiers.map((tier) => {
|
|
@@ -1376,4 +1524,173 @@ const styles = `
|
|
|
1376
1524
|
flex-direction: column;
|
|
1377
1525
|
gap: 8px;
|
|
1378
1526
|
}
|
|
1527
|
+
|
|
1528
|
+
/* Header Actions */
|
|
1529
|
+
.catalog__header-actions {
|
|
1530
|
+
display: flex;
|
|
1531
|
+
gap: 8px;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/* Service Templates Panel */
|
|
1535
|
+
.catalog__templates-panel {
|
|
1536
|
+
background: linear-gradient(135deg, var(--so-violet-50) 0%, var(--so-slate-50) 100%);
|
|
1537
|
+
border: 1px solid var(--so-violet-200);
|
|
1538
|
+
border-radius: var(--so-radius-lg);
|
|
1539
|
+
padding: 20px;
|
|
1540
|
+
margin-bottom: 24px;
|
|
1541
|
+
animation: so-scale-in var(--so-transition-fast) ease-out;
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
.catalog__templates-header {
|
|
1545
|
+
display: flex;
|
|
1546
|
+
align-items: center;
|
|
1547
|
+
justify-content: space-between;
|
|
1548
|
+
margin-bottom: 8px;
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
.catalog__templates-title {
|
|
1552
|
+
font-size: 1rem;
|
|
1553
|
+
font-weight: 600;
|
|
1554
|
+
color: var(--so-slate-800);
|
|
1555
|
+
margin: 0;
|
|
1556
|
+
display: flex;
|
|
1557
|
+
align-items: center;
|
|
1558
|
+
gap: 8px;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
.catalog__templates-title::before {
|
|
1562
|
+
content: "⚡";
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
.catalog__templates-close {
|
|
1566
|
+
width: 28px;
|
|
1567
|
+
height: 28px;
|
|
1568
|
+
border-radius: var(--so-radius-sm);
|
|
1569
|
+
background: transparent;
|
|
1570
|
+
border: none;
|
|
1571
|
+
color: var(--so-slate-400);
|
|
1572
|
+
cursor: pointer;
|
|
1573
|
+
display: flex;
|
|
1574
|
+
align-items: center;
|
|
1575
|
+
justify-content: center;
|
|
1576
|
+
transition: all var(--so-transition-fast);
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
.catalog__templates-close:hover {
|
|
1580
|
+
background: white;
|
|
1581
|
+
color: var(--so-slate-600);
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
.catalog__templates-close svg {
|
|
1585
|
+
width: 16px;
|
|
1586
|
+
height: 16px;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
.catalog__templates-hint {
|
|
1590
|
+
font-size: 0.8125rem;
|
|
1591
|
+
color: var(--so-slate-500);
|
|
1592
|
+
margin: 0 0 16px;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
.catalog__templates-grid {
|
|
1596
|
+
display: grid;
|
|
1597
|
+
grid-template-columns: repeat(2, 1fr);
|
|
1598
|
+
gap: 16px;
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
.catalog__template-category {
|
|
1602
|
+
display: flex;
|
|
1603
|
+
flex-direction: column;
|
|
1604
|
+
gap: 8px;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
.catalog__template-category-title {
|
|
1608
|
+
font-size: 0.6875rem;
|
|
1609
|
+
font-weight: 700;
|
|
1610
|
+
text-transform: uppercase;
|
|
1611
|
+
letter-spacing: 0.06em;
|
|
1612
|
+
color: var(--so-slate-500);
|
|
1613
|
+
margin: 0;
|
|
1614
|
+
padding-left: 4px;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
.catalog__template-items {
|
|
1618
|
+
display: flex;
|
|
1619
|
+
flex-direction: column;
|
|
1620
|
+
gap: 4px;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
.catalog__template-item {
|
|
1624
|
+
display: flex;
|
|
1625
|
+
align-items: center;
|
|
1626
|
+
gap: 10px;
|
|
1627
|
+
padding: 10px 12px;
|
|
1628
|
+
background: white;
|
|
1629
|
+
border: 1px solid var(--so-slate-200);
|
|
1630
|
+
border-radius: var(--so-radius-md);
|
|
1631
|
+
cursor: pointer;
|
|
1632
|
+
text-align: left;
|
|
1633
|
+
transition: all var(--so-transition-fast);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
.catalog__template-item:hover:not(:disabled) {
|
|
1637
|
+
border-color: var(--so-violet-300);
|
|
1638
|
+
background: white;
|
|
1639
|
+
box-shadow: 0 2px 8px rgba(124, 58, 237, 0.1);
|
|
1640
|
+
transform: translateX(2px);
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
.catalog__template-item:active:not(:disabled) {
|
|
1644
|
+
transform: translateX(0);
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
.catalog__template-item--exists {
|
|
1648
|
+
opacity: 0.6;
|
|
1649
|
+
cursor: not-allowed;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
.catalog__template-icon {
|
|
1653
|
+
font-size: 1.25rem;
|
|
1654
|
+
flex-shrink: 0;
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
.catalog__template-info {
|
|
1658
|
+
flex: 1;
|
|
1659
|
+
min-width: 0;
|
|
1660
|
+
display: flex;
|
|
1661
|
+
flex-direction: column;
|
|
1662
|
+
gap: 2px;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
.catalog__template-name {
|
|
1666
|
+
font-size: 0.8125rem;
|
|
1667
|
+
font-weight: 500;
|
|
1668
|
+
color: var(--so-slate-800);
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
.catalog__template-desc {
|
|
1672
|
+
font-size: 0.6875rem;
|
|
1673
|
+
color: var(--so-slate-500);
|
|
1674
|
+
white-space: nowrap;
|
|
1675
|
+
overflow: hidden;
|
|
1676
|
+
text-overflow: ellipsis;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
.catalog__template-badge {
|
|
1680
|
+
padding: 2px 8px;
|
|
1681
|
+
font-size: 0.5625rem;
|
|
1682
|
+
font-weight: 700;
|
|
1683
|
+
text-transform: uppercase;
|
|
1684
|
+
letter-spacing: 0.04em;
|
|
1685
|
+
background: var(--so-emerald-100);
|
|
1686
|
+
color: var(--so-emerald-700);
|
|
1687
|
+
border-radius: 4px;
|
|
1688
|
+
flex-shrink: 0;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
@media (max-width: 900px) {
|
|
1692
|
+
.catalog__templates-grid {
|
|
1693
|
+
grid-template-columns: 1fr;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1379
1696
|
`;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
|
|
2
|
-
import type { ServiceOfferingDocument, ServiceOfferingAction } from "
|
|
2
|
+
import type { ServiceOfferingDocument, ServiceOfferingAction } from "@powerhousedao/contributor-billing/document-models/service-offering";
|
|
3
3
|
interface ServicesListProps {
|
|
4
4
|
document: ServiceOfferingDocument;
|
|
5
5
|
dispatch: DocumentDispatch<ServiceOfferingAction>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServicesList.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServicesList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,
|
|
1
|
+
{"version":3,"file":"ServicesList.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/components/ServicesList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,qEAAqE,CAAC;AAS7E,UAAU,iBAAiB;IACzB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAC;CACnD;AAED,wBAAgB,YAAY,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,iBAAiB,2CA8QrE"}
|