@powerhousedao/service-offering 1.0.0-dev.20 → 1.0.0-dev.22

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.
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../document-models/service-offering/v1/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM7D,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,YAAY,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,0BAA0B,GAAG,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,YAAY,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;IAC9C,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;IAC7C,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1D,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC3D;AAyLD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,aAAa,GACvB,cAAc,CAsGhB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../document-models/service-offering/v1/src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9D,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM7D,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,YAAY,CAAC;IACpC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,iBAAiB,EAAE,0BAA0B,GAAG,IAAI,CAAC;CACtD;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,YAAY,CAAC;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;IAC9C,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;IAC7C,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,MAAM,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1D,0BAA0B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CAC3D;AA0LD,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,sBAAsB,EAC7B,SAAS,EAAE,aAAa,GACvB,cAAc,CAsGhB"}
@@ -45,9 +45,10 @@ function resolveGroupPricing(group, tier, effectiveCycle, globalCurrency) {
45
45
  // Monthly base
46
46
  const monthlyOption = pricing.find((p) => p.billingCycle === "MONTHLY");
47
47
  const monthlyBase = monthlyOption?.amount ?? 0;
48
- // Price for effective cycle
48
+ // Price for effective cycle — amounts represent monthly rates,
49
+ // so multiply by months to get the total for the billing period
49
50
  const cycleOption = pricing.find((p) => p.billingCycle === effectiveCycle);
50
- const cycleAmount = cycleOption?.amount ?? monthlyBase * (months || 1);
51
+ const cycleAmount = (cycleOption?.amount ?? monthlyBase) * (months || 1);
51
52
  let discount = null;
52
53
  let recurringAmount = cycleAmount;
53
54
  // Check for discount on the cycle option itself
@@ -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;AAuF1E,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,2CAgkB/B"}
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;AAuF1E,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"}
@@ -62,11 +62,23 @@ export function ResourceTemplateSelector({ document, dispatch, }) {
62
62
  const localTemplateIds = useMemo(() => new Set((localTemplates ?? []).map((t) => t.header.id)), [localTemplates]);
63
63
  // Fetch remote templates (filtered to exclude locals)
64
64
  const { templates: remoteTemplates, isLoading: isLoadingRemote } = useRemoteResourceTemplates(localTemplateIds);
65
- // Normalize and merge local + remote templates
65
+ // Normalize, merge, and deduplicate local + remote templates
66
66
  const allTemplates = useMemo(() => {
67
- const normalized = (localTemplates ?? []).map(normalizeLocalTemplate);
67
+ const seen = new Set();
68
+ const normalized = [];
69
+ // Local templates take priority
70
+ for (const doc of localTemplates ?? []) {
71
+ if (!seen.has(doc.header.id)) {
72
+ seen.add(doc.header.id);
73
+ normalized.push(normalizeLocalTemplate(doc));
74
+ }
75
+ }
76
+ // Add remote templates only if not already present
68
77
  for (const remote of remoteTemplates) {
69
- normalized.push(normalizeRemoteTemplate(remote));
78
+ if (!seen.has(remote.id)) {
79
+ seen.add(remote.id);
80
+ normalized.push(normalizeRemoteTemplate(remote));
81
+ }
70
82
  }
71
83
  return normalized;
72
84
  }, [localTemplates, remoteTemplates]);
@@ -304,7 +316,7 @@ function TemplateCard({ template, isSelected, isRecommended, onSelect, }) {
304
316
  : undefined, children: [isRecommended && !isSelected && (_jsxs("div", { className: "absolute -top-px right-10 flex items-center gap-1 py-1.5 px-3 text-[0.625rem] font-bold uppercase tracking-[0.04em] text-white rounded-b-lg z-[5]", style: {
305
317
  background: "linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",
306
318
  boxShadow: "0 2px 8px rgba(245, 158, 11, 0.4)",
307
- }, children: [_jsx("svg", { className: "w-3 h-3 fill-current stroke-current", 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"] })), template.isRemote && (_jsxs("div", { className: `absolute top-2.5 right-2.5 flex items-center gap-1 py-1 px-2.5 text-[0.625rem] font-bold uppercase tracking-[0.04em] rounded-full z-[4] ${template.operatorName
319
+ }, children: [_jsx("svg", { className: "w-3 h-3 fill-current stroke-current", 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"] })), !template.isRemote && (_jsxs("div", { className: "absolute top-2.5 right-2.5 flex items-center gap-1 py-1 px-2.5 text-[0.625rem] font-bold uppercase tracking-[0.04em] rounded-full z-[4] text-emerald-600 bg-emerald-50", style: { backdropFilter: "blur(8px)" }, children: [_jsx("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" }) }), "This Drive"] })), template.isRemote && (_jsxs("div", { className: `absolute top-2.5 right-2.5 flex items-center gap-1 py-1 px-2.5 text-[0.625rem] font-bold uppercase tracking-[0.04em] rounded-full z-[4] ${template.operatorName
308
320
  ? "normal-case font-semibold text-teal-500 bg-teal-100"
309
321
  : "text-[#7c5cff] bg-[#f4f1ff]"}`, style: { backdropFilter: "blur(8px)" }, children: [_jsx("svg", { className: "w-3 h-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: template.operatorName ? (_jsxs(_Fragment, { children: [_jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }), _jsx("circle", { cx: "12", cy: "7", r: "4" })] })) : (_jsxs(_Fragment, { children: [_jsx("path", { d: "M2 15c6.667-6 13.333 0 20-6" }), _jsx("path", { d: "M9 22c1.798-1.998 2.54-3.995 2.807-5.993" }), _jsx("path", { d: "M15 2c-1.798 1.998-2.54 3.995-2.807 5.993" })] })) }), template.operatorName ?? "Remote"] })), _jsxs("div", { className: "relative h-[100px]", children: [globalState.thumbnailUrl ? (_jsx("div", { className: "w-full h-full bg-cover bg-center bg-[#f0f2f7]", style: { backgroundImage: `url(${globalState.thumbnailUrl})` } })) : (_jsx("div", { className: "w-full h-full flex items-center justify-center text-[#8792a8]", style: {
310
322
  background: "linear-gradient(135deg, #f0f2f7 0%, #e4e8f0 100%)",
@@ -628,7 +628,7 @@ export function ServiceCatalog({ document, dispatch }) {
628
628
  }
629
629
  }, className: "cursor-pointer w-4 h-4" }), _jsx("span", { children: label })] }, value))) })] })), editGroupType === "recurring" &&
630
630
  editGroupPricingMode === "TIER_DEPENDENT" &&
631
- tiers.length > 0 && (_jsxs(_Fragment, { children: [_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
631
+ tiers.length > 0 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex gap-0 border-b border-slate-200 mb-3 overflow-x-auto sticky top-0 bg-white z-10", 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
632
632
  ? "text-violet-700 border-b-violet-600 font-semibold"
633
633
  : "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.isCustomPricing &&
634
634
  editTierPrices[tier.id] &&
@@ -1 +1 @@
1
- {"version":3,"file":"useRemoteResourceTemplates.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/hooks/useRemoteResourceTemplates.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,UAAU,gCAAgC;IACxC,8CAA8C;IAC9C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,gCAAgC,CAqClC"}
1
+ {"version":3,"file":"useRemoteResourceTemplates.d.ts","sourceRoot":"","sources":["../../../../editors/service-offering-editor/hooks/useRemoteResourceTemplates.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,4BAA4B,CAAC;AAEpC,UAAU,gCAAgC;IACxC,8CAA8C;IAC9C,SAAS,EAAE,sBAAsB,EAAE,CAAC;IACpC,+CAA+C;IAC/C,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,gCAAgC,CA+ClC"}
@@ -18,7 +18,17 @@ export function useRemoteResourceTemplates(localTemplateIds) {
18
18
  try {
19
19
  const templates = await fetchAllRemoteResourceTemplates();
20
20
  hasFetchedRef.current = true;
21
- setAllTemplates(templates);
21
+ // Deduplicate by ID — findDocuments can return the same document
22
+ // multiple times when it is referenced from multiple drives
23
+ const seen = new Set();
24
+ const unique = [];
25
+ for (const t of templates) {
26
+ if (!seen.has(t.id)) {
27
+ seen.add(t.id);
28
+ unique.push(t);
29
+ }
30
+ }
31
+ setAllTemplates(unique);
22
32
  }
23
33
  catch {
24
34
  // Silently fail — remote data is a fallback
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.20",
4
+ "version": "1.0.0-dev.22",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
7
7
  "type": "git",