@wix/himalaya-cli 0.941.0 → 0.943.0

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.
Files changed (26) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/bookings-v2/src/index.d.ts +10 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/wix-data/src/index.d.ts +50 -3
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-data.mjs +16 -2
  4. package/dist/cli.mjs +6 -1
  5. package/guides/sdk-reference.json +45 -21
  6. package/package.json +2 -2
  7. package/templates/beauty-salon/tier5-src/wix-spaces-collections/index.ts +60 -12
  8. package/templates/branded-lite/dev/index.ts +224 -14
  9. package/templates/branded-lite/tier5-src/himi-branded-lite-badges/index.ts +11 -8
  10. package/templates/branded-lite/tier5-src/himi-branded-lite-coupons/index.ts +17 -6
  11. package/templates/branded-lite/tier5-src/himi-branded-lite-donations/index.ts +11 -8
  12. package/templates/branded-lite/tier5-src/himi-branded-lite-forms/index.ts +11 -10
  13. package/templates/branded-lite/tier5-src/himi-branded-lite-galleries/index.ts +12 -9
  14. package/templates/branded-lite/tier5-src/himi-branded-lite-giftcards/index.ts +11 -8
  15. package/templates/branded-lite/tier5-src/himi-branded-lite-inbox/index.ts +11 -8
  16. package/templates/branded-lite/tier5-src/himi-branded-lite-invoices/index.ts +11 -8
  17. package/templates/branded-lite/tier5-src/himi-branded-lite-loyalty/index.ts +11 -8
  18. package/templates/branded-lite/tier5-src/himi-branded-lite-notifications/index.ts +13 -8
  19. package/templates/branded-lite/tier5-src/himi-branded-lite-notifsettings/index.ts +11 -8
  20. package/templates/branded-lite/tier5-src/himi-branded-lite-reservations/index.ts +11 -8
  21. package/templates/branded-lite/tier5-src/himi-branded-lite-reviews/index.ts +11 -8
  22. package/templates/branded-lite/tier5-src/himi-branded-lite-videos/index.ts +12 -9
  23. package/templates/branded-lite/tier5-src/wix-spaces-collections/index.ts +60 -12
  24. package/templates/gym-fitness/tier5-src/wix-spaces-collections/index.ts +60 -12
  25. package/templates/portfolio-creative/tier5-src/wix-spaces-collections/index.ts +60 -12
  26. package/templates/retail-store/tier5-src/wix-spaces-collections/index.ts +60 -12
@@ -27533,7 +27533,22 @@ const SCREENS = runtimeSetting({
27533
27533
  }
27534
27534
  },
27535
27535
  "modifiers": {
27536
- "hiddenPath": "$service:himiBrandedCoupons.notMock"
27536
+ "hiddenPath": "$service:himiBrandedCoupons.notMockEmpty"
27537
+ }
27538
+ },
27539
+ {
27540
+ "id": "himi_coupons.unavailable_banner",
27541
+ "body": {
27542
+ "package": "himalaya",
27543
+ "type": "Banner",
27544
+ "props": {
27545
+ "severity": "warning",
27546
+ "title": "Sample content",
27547
+ "message": "Sample content — this site's offers couldn't be loaded."
27548
+ }
27549
+ },
27550
+ "modifiers": {
27551
+ "hiddenPath": "$service:himiBrandedCoupons.notMockUnavailable"
27537
27552
  }
27538
27553
  },
27539
27554
  {
@@ -29751,7 +29766,22 @@ const SCREENS = runtimeSetting({
29751
29766
  }
29752
29767
  },
29753
29768
  "modifiers": {
29754
- "hiddenPath": "$service:himiBrandedNotifications.notMock"
29769
+ "hiddenPath": "$service:himiBrandedNotifications.notMockEmpty"
29770
+ }
29771
+ },
29772
+ {
29773
+ "id": "himi_notifications.unavailable_banner",
29774
+ "body": {
29775
+ "package": "himalaya",
29776
+ "type": "Banner",
29777
+ "props": {
29778
+ "severity": "warning",
29779
+ "title": "Sample content",
29780
+ "message": "Sample content — your notifications couldn't be loaded."
29781
+ }
29782
+ },
29783
+ "modifiers": {
29784
+ "hiddenPath": "$service:himiBrandedNotifications.notMockUnavailable"
29755
29785
  }
29756
29786
  },
29757
29787
  {
@@ -31913,7 +31943,22 @@ const SCREENS = runtimeSetting({
31913
31943
  }
31914
31944
  },
31915
31945
  "modifiers": {
31916
- "hiddenPath": "$service:himiBrandedLoyalty.notMock"
31946
+ "hiddenPath": "$service:himiBrandedLoyalty.notMockEmpty"
31947
+ }
31948
+ },
31949
+ {
31950
+ "id": "himi_loyalty.unavailable_banner",
31951
+ "body": {
31952
+ "package": "himalaya",
31953
+ "type": "Banner",
31954
+ "props": {
31955
+ "severity": "warning",
31956
+ "title": "Sample content",
31957
+ "message": "Sample content — the rewards program couldn't be loaded."
31958
+ }
31959
+ },
31960
+ "modifiers": {
31961
+ "hiddenPath": "$service:himiBrandedLoyalty.notMockUnavailable"
31917
31962
  }
31918
31963
  },
31919
31964
  {
@@ -34154,7 +34199,22 @@ const SCREENS = runtimeSetting({
34154
34199
  }
34155
34200
  },
34156
34201
  "modifiers": {
34157
- "hiddenPath": "$service:himiBrandedReviews.notMock"
34202
+ "hiddenPath": "$service:himiBrandedReviews.notMockEmpty"
34203
+ }
34204
+ },
34205
+ {
34206
+ "id": "himi_reviews.unavailable_banner",
34207
+ "body": {
34208
+ "package": "himalaya",
34209
+ "type": "Banner",
34210
+ "props": {
34211
+ "severity": "warning",
34212
+ "title": "Sample content",
34213
+ "message": "Sample content — this business's reviews couldn't be loaded."
34214
+ }
34215
+ },
34216
+ "modifiers": {
34217
+ "hiddenPath": "$service:himiBrandedReviews.notMockUnavailable"
34158
34218
  }
34159
34219
  },
34160
34220
  {
@@ -39102,7 +39162,22 @@ const SCREENS = runtimeSetting({
39102
39162
  }
39103
39163
  },
39104
39164
  "modifiers": {
39105
- "hiddenPath": "$service:himiBrandedReservations.notMock"
39165
+ "hiddenPath": "$service:himiBrandedReservations.notMockEmpty"
39166
+ }
39167
+ },
39168
+ {
39169
+ "id": "himi_reservations.unavailable_banner",
39170
+ "body": {
39171
+ "package": "himalaya",
39172
+ "type": "Banner",
39173
+ "props": {
39174
+ "severity": "warning",
39175
+ "title": "Sample content",
39176
+ "message": "Sample content — your reservations couldn't be loaded."
39177
+ }
39178
+ },
39179
+ "modifiers": {
39180
+ "hiddenPath": "$service:himiBrandedReservations.notMockUnavailable"
39106
39181
  }
39107
39182
  },
39108
39183
  {
@@ -39241,7 +39316,22 @@ const SCREENS = runtimeSetting({
39241
39316
  }
39242
39317
  },
39243
39318
  "modifiers": {
39244
- "hiddenPath": "$service:himiBrandedInvoices.notMock"
39319
+ "hiddenPath": "$service:himiBrandedInvoices.notMockEmpty"
39320
+ }
39321
+ },
39322
+ {
39323
+ "id": "himi_invoices.unavailable_banner",
39324
+ "body": {
39325
+ "package": "himalaya",
39326
+ "type": "Banner",
39327
+ "props": {
39328
+ "severity": "warning",
39329
+ "title": "Sample content",
39330
+ "message": "Sample content — your invoices couldn't be loaded."
39331
+ }
39332
+ },
39333
+ "modifiers": {
39334
+ "hiddenPath": "$service:himiBrandedInvoices.notMockUnavailable"
39245
39335
  }
39246
39336
  },
39247
39337
  {
@@ -41400,7 +41490,22 @@ const SCREENS = runtimeSetting({
41400
41490
  }
41401
41491
  },
41402
41492
  "modifiers": {
41403
- "hiddenPath": "$service:himiBrandedBadges.notMock"
41493
+ "hiddenPath": "$service:himiBrandedBadges.notMockEmpty"
41494
+ }
41495
+ },
41496
+ {
41497
+ "id": "himi_badges.unavailable_banner",
41498
+ "body": {
41499
+ "package": "himalaya",
41500
+ "type": "Banner",
41501
+ "props": {
41502
+ "severity": "warning",
41503
+ "title": "Sample content",
41504
+ "message": "Sample content — this community's badges couldn't be loaded."
41505
+ }
41506
+ },
41507
+ "modifiers": {
41508
+ "hiddenPath": "$service:himiBrandedBadges.notMockUnavailable"
41404
41509
  }
41405
41510
  },
41406
41511
  {
@@ -43641,7 +43746,22 @@ const SCREENS = runtimeSetting({
43641
43746
  }
43642
43747
  },
43643
43748
  "modifiers": {
43644
- "hiddenPath": "$service:himiBrandedNotifSettings.notMock"
43749
+ "hiddenPath": "$service:himiBrandedNotifSettings.notMockEmpty"
43750
+ }
43751
+ },
43752
+ {
43753
+ "id": "himi_notif_settings.unavailable_banner",
43754
+ "body": {
43755
+ "package": "himalaya",
43756
+ "type": "Banner",
43757
+ "props": {
43758
+ "severity": "warning",
43759
+ "title": "Sample content",
43760
+ "message": "Sample content — your notification settings couldn't be loaded."
43761
+ }
43762
+ },
43763
+ "modifiers": {
43764
+ "hiddenPath": "$service:himiBrandedNotifSettings.notMockUnavailable"
43645
43765
  }
43646
43766
  },
43647
43767
  {
@@ -55810,7 +55930,22 @@ const SCREENS = runtimeSetting({
55810
55930
  }
55811
55931
  },
55812
55932
  "modifiers": {
55813
- "hiddenPath": "$service:himiBrandedDonations.notMock"
55933
+ "hiddenPath": "$service:himiBrandedDonations.notMockEmpty"
55934
+ }
55935
+ },
55936
+ {
55937
+ "id": "himi_donations.unavailable_banner",
55938
+ "body": {
55939
+ "package": "himalaya",
55940
+ "type": "Banner",
55941
+ "props": {
55942
+ "severity": "warning",
55943
+ "title": "Sample content",
55944
+ "message": "Sample content — this site's donation campaigns couldn't be loaded."
55945
+ }
55946
+ },
55947
+ "modifiers": {
55948
+ "hiddenPath": "$service:himiBrandedDonations.notMockUnavailable"
55814
55949
  }
55815
55950
  },
55816
55951
  {
@@ -58051,7 +58186,22 @@ const SCREENS = runtimeSetting({
58051
58186
  }
58052
58187
  },
58053
58188
  "modifiers": {
58054
- "hiddenPath": "$service:himiBrandedGiftCards.notMock"
58189
+ "hiddenPath": "$service:himiBrandedGiftCards.notMockEmpty"
58190
+ }
58191
+ },
58192
+ {
58193
+ "id": "himi_gift_cards.unavailable_banner",
58194
+ "body": {
58195
+ "package": "himalaya",
58196
+ "type": "Banner",
58197
+ "props": {
58198
+ "severity": "warning",
58199
+ "title": "Sample content",
58200
+ "message": "Sample content — your gift cards couldn't be loaded."
58201
+ }
58202
+ },
58203
+ "modifiers": {
58204
+ "hiddenPath": "$service:himiBrandedGiftCards.notMockUnavailable"
58055
58205
  }
58056
58206
  },
58057
58207
  {
@@ -60292,7 +60442,22 @@ const SCREENS = runtimeSetting({
60292
60442
  }
60293
60443
  },
60294
60444
  "modifiers": {
60295
- "hiddenPath": "$service:himiBrandedVideos.notMock"
60445
+ "hiddenPath": "$service:himiBrandedVideos.notMockEmpty"
60446
+ }
60447
+ },
60448
+ {
60449
+ "id": "himi_videos.unavailable_banner",
60450
+ "body": {
60451
+ "package": "himalaya",
60452
+ "type": "Banner",
60453
+ "props": {
60454
+ "severity": "warning",
60455
+ "title": "Sample content",
60456
+ "message": "Sample content — this site's video channels couldn't be loaded."
60457
+ }
60458
+ },
60459
+ "modifiers": {
60460
+ "hiddenPath": "$service:himiBrandedVideos.notMockUnavailable"
60296
60461
  }
60297
60462
  },
60298
60463
  {
@@ -65307,7 +65472,22 @@ const SCREENS = runtimeSetting({
65307
65472
  }
65308
65473
  },
65309
65474
  "modifiers": {
65310
- "hiddenPath": "$service:himiBrandedForms.notMock"
65475
+ "hiddenPath": "$service:himiBrandedForms.notMockEmpty"
65476
+ }
65477
+ },
65478
+ {
65479
+ "id": "himi_forms.unavailable_banner",
65480
+ "body": {
65481
+ "package": "himalaya",
65482
+ "type": "Banner",
65483
+ "props": {
65484
+ "severity": "warning",
65485
+ "title": "Sample content",
65486
+ "message": "Sample content — this site's forms couldn't be loaded."
65487
+ }
65488
+ },
65489
+ "modifiers": {
65490
+ "hiddenPath": "$service:himiBrandedForms.notMockUnavailable"
65311
65491
  }
65312
65492
  },
65313
65493
  {
@@ -67452,7 +67632,22 @@ const SCREENS = runtimeSetting({
67452
67632
  }
67453
67633
  },
67454
67634
  "modifiers": {
67455
- "hiddenPath": "$service:himiBrandedGalleries.notMock"
67635
+ "hiddenPath": "$service:himiBrandedGalleries.notMockEmpty"
67636
+ }
67637
+ },
67638
+ {
67639
+ "id": "himi_galleries.unavailable_banner",
67640
+ "body": {
67641
+ "package": "himalaya",
67642
+ "type": "Banner",
67643
+ "props": {
67644
+ "severity": "warning",
67645
+ "title": "Sample content",
67646
+ "message": "Sample content — this site's galleries couldn't be loaded."
67647
+ }
67648
+ },
67649
+ "modifiers": {
67650
+ "hiddenPath": "$service:himiBrandedGalleries.notMockUnavailable"
67456
67651
  }
67457
67652
  },
67458
67653
  {
@@ -69969,7 +70164,22 @@ const SCREENS = runtimeSetting({
69969
70164
  }
69970
70165
  },
69971
70166
  "modifiers": {
69972
- "hiddenPath": "$service:himiBrandedInbox.notMock"
70167
+ "hiddenPath": "$service:himiBrandedInbox.notMockEmpty"
70168
+ }
70169
+ },
70170
+ {
70171
+ "id": "himi_inbox.unavailable_banner",
70172
+ "body": {
70173
+ "package": "himalaya",
70174
+ "type": "Banner",
70175
+ "props": {
70176
+ "severity": "warning",
70177
+ "title": "Sample content",
70178
+ "message": "Sample content — your messages couldn't be loaded."
70179
+ }
70180
+ },
70181
+ "modifiers": {
70182
+ "hiddenPath": "$service:himiBrandedInbox.notMockUnavailable"
69973
70183
  }
69974
70184
  },
69975
70185
  {
@@ -13,7 +13,11 @@ interface Row { id: string; title: string; subtitle: string }
13
13
  interface S {
14
14
  status: "loading" | "ready";
15
15
  badges: Row[]; emptyText: string;
16
- isMock: boolean; notMock: boolean; mockBanner: string;
16
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
17
+ * shows only when the site really has none, and the unavailable one only when the
18
+ * query failed. A failed query must never render the sentence that claims the
19
+ * customer has no content. */
20
+ notMockEmpty: boolean; notMockUnavailable: boolean;
17
21
  }
18
22
 
19
23
  function norm(b: WixBadge): Row {
@@ -21,7 +25,6 @@ function norm(b: WixBadge): Row {
21
25
  return { id: b.id || b.slug || "badge", title, subtitle: (b.description || "").trim() };
22
26
  }
23
27
 
24
- const MOCK_BANNER = "Sample content — this community has no badges yet.";
25
28
  const MOCK: Row[] = [
26
29
  { id: "sample-founder", title: "Founding Member", subtitle: "One of the first to join the community." },
27
30
  { id: "sample-top", title: "Top Contributor", subtitle: "Recognized for consistently helpful posts." },
@@ -29,21 +32,21 @@ const MOCK: Row[] = [
29
32
  { id: "sample-vip", title: "VIP", subtitle: "A valued long-standing customer." },
30
33
  ];
31
34
 
32
- function mockState(s: S): S {
33
- return { ...s, status: "ready", badges: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
35
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
36
+ return { ...s, status: "ready", badges: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable"};
34
37
  }
35
38
 
36
39
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedBadges", {
37
- state: { status: "loading", badges: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
40
+ state: { status: "loading", badges: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
38
41
  actions: {
39
42
  load: async (s) => {
40
43
  try {
41
44
  const r = await queryBadges({ query: { cursorPaging: { limit: 50 } } });
42
45
  const badges = (r.badges ?? []).map(norm);
43
- if (badges.length) return { ...s, status: "ready", badges, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
44
- return mockState(s);
46
+ if (badges.length) return { ...s, status: "ready", badges, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
47
+ return mockState(s, "empty");
45
48
  } catch {
46
- return mockState(s);
49
+ return mockState(s, "unavailable");
47
50
  }
48
51
  },
49
52
  },
@@ -11,7 +11,11 @@ interface Row { id: string; name: string; subtitle: string }
11
11
  interface S {
12
12
  status: "loading" | "ready";
13
13
  coupons: Row[]; emptyText: string;
14
- isMock: boolean; notMock: boolean; mockBanner: string;
14
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
15
+ * shows only when the site really has none, and the unavailable one only when the
16
+ * query failed. A failed query must never render the sentence that claims the
17
+ * customer has no content. */
18
+ notMockEmpty: boolean; notMockUnavailable: boolean;
15
19
  }
16
20
 
17
21
  function norm(c: WixCoupon): Row {
@@ -19,7 +23,6 @@ function norm(c: WixCoupon): Row {
19
23
  return { id: cc.id || cc.code || "coupon", name: cc.name || cc.code || "Coupon", subtitle: cc.code ? `Code: ${cc.code}` : "" };
20
24
  }
21
25
 
22
- const MOCK_BANNER = "Sample content — your site has no coupons yet.";
23
26
  const MOCK: Row[] = [
24
27
  { id: "sample-welcome15", name: "Welcome — 15% off your first order", subtitle: "Code: WELCOME15 · ends Aug 31" },
25
28
  { id: "sample-freeship", name: "Free shipping", subtitle: "Code: FREESHIP · orders over $50" },
@@ -27,17 +30,25 @@ const MOCK: Row[] = [
27
30
  { id: "sample-loyal10", name: "Loyalty reward — $10 off", subtitle: "Code: LOYAL10 · members only" },
28
31
  ];
29
32
 
33
+ /** The sample fallback, shared by both arms so neither can drift from the other — this
34
+ * worker inlined it twice, which is how a rename reached the constants and missed the
35
+ * uses. */
36
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
37
+ return { ...s, status: "ready", coupons: MOCK, emptyText: "", isMock: true, notMock: false,
38
+ notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable" };
39
+ }
40
+
30
41
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedCoupons", {
31
- state: { status: "loading", coupons: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
42
+ state: { status: "loading", coupons: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
32
43
  actions: {
33
44
  load: async (s) => {
34
45
  try {
35
46
  const r = await queryCoupons({ paging: { limit: 30 } } as never);
36
47
  const coupons = (((r as unknown as { coupons?: WixCoupon[] }).coupons) ?? []).map(norm);
37
- if (coupons.length) return { ...s, status: "ready", coupons, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
38
- return { ...s, status: "ready", coupons: MOCK, emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
48
+ if (coupons.length) return { ...s, status: "ready", coupons, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
49
+ return mockState(s, "empty");
39
50
  } catch {
40
- return { ...s, status: "ready", coupons: MOCK, emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
51
+ return mockState(s, "unavailable");
41
52
  }
42
53
  },
43
54
  },
@@ -11,7 +11,11 @@ interface Row { id: string; title: string; subtitle: string }
11
11
  interface S {
12
12
  status: "loading" | "ready";
13
13
  campaigns: Row[]; emptyText: string;
14
- isMock: boolean; notMock: boolean; mockBanner: string;
14
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
15
+ * shows only when the site really has none, and the unavailable one only when the
16
+ * query failed. A failed query must never render the sentence that claims the
17
+ * customer has no content. */
18
+ notMockEmpty: boolean; notMockUnavailable: boolean;
15
19
  }
16
20
 
17
21
  const STATUS_LABEL: Record<string, string> = {
@@ -30,28 +34,27 @@ function norm(c: WixDonationCampaign): Row {
30
34
  return { id: c.id || "campaign", title: (c.name || "Campaign").trim() || "Campaign", subtitle: subtitleFor(c) };
31
35
  }
32
36
 
33
- const MOCK_BANNER = "Sample content — this site has no donation campaigns yet.";
34
37
  const MOCK: Row[] = [
35
38
  { id: "sample-reef", title: "Save the Coral Reef", subtitle: "Goal: $10,000 · Active" },
36
39
  { id: "sample-school", title: "Build a Village School", subtitle: "Goal: $25,000 · Active" },
37
40
  { id: "sample-relief", title: "Winter Relief Fund", subtitle: "Goal: $5,000 · Goal reached" },
38
41
  ];
39
42
 
40
- function mockState(s: S): S {
41
- return { ...s, status: "ready", campaigns: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
43
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
44
+ return { ...s, status: "ready", campaigns: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable"};
42
45
  }
43
46
 
44
47
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedDonations", {
45
- state: { status: "loading", campaigns: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
48
+ state: { status: "loading", campaigns: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
46
49
  actions: {
47
50
  load: async (s) => {
48
51
  try {
49
52
  const r = await queryDonationCampaigns({ query: { cursorPaging: { limit: 20 } } });
50
53
  const campaigns = (r.donationCampaigns ?? []).filter((c) => c.archived !== true).map(norm);
51
- if (campaigns.length) return { ...s, status: "ready", campaigns, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
52
- return mockState(s);
54
+ if (campaigns.length) return { ...s, status: "ready", campaigns, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
55
+ return mockState(s, "empty");
53
56
  } catch {
54
- return mockState(s);
57
+ return mockState(s, "unavailable");
55
58
  }
56
59
  },
57
60
  },
@@ -8,14 +8,17 @@
8
8
  // there would state "this site has none yet", which the app never established.
9
9
  // Real forms always win the moment any exist.
10
10
  import { defineService } from "../_shared/collection-service.js";
11
- import { copyParam } from "../_shared/himi-copy.js";
12
11
  import { queryForms, type WixForm } from "@himalaya/wix-forms";
13
12
 
14
13
  interface Row { id: string; title: string; subtitle: string }
15
14
  interface S {
16
15
  status: "loading" | "ready" | "error";
17
16
  forms: Row[]; emptyText: string;
18
- isMock: boolean; notMock: boolean; mockBanner: string;
17
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
18
+ * shows only when the site really has none, and the unavailable one only when the
19
+ * query failed. A failed query must never render the sentence that claims the
20
+ * customer has no content. */
21
+ notMockEmpty: boolean; notMockUnavailable: boolean;
19
22
  }
20
23
 
21
24
  const STATUS_LABEL: Record<string, string> = { PUBLISHED: "Published", DRAFT: "Draft" };
@@ -41,32 +44,30 @@ function norm(f: WixForm): Row {
41
44
  * which keeps these verticals showing labelled sample content rather than a blank screen.
42
45
  * So what was wrong was never the samples — it was claiming to know something the app had
43
46
  * not established. */
44
- const MOCK_BANNER_EMPTY = "Sample content — this site has no forms yet.";
45
- const MOCK_BANNER_UNAVAILABLE = "Sample content — this site's forms couldn't be loaded.";
46
47
  const MOCK: Row[] = [
47
48
  { id: "sample-contact", title: "Contact Us", subtitle: "4 fields · Published" },
48
49
  { id: "sample-subscribe", title: "Newsletter Signup", subtitle: "2 fields · Published" },
49
50
  { id: "sample-feedback", title: "Feedback", subtitle: "5 fields · Published" },
50
51
  ];
51
52
 
52
- function mockState(s: S, banner: string): S {
53
- return { ...s, status: "ready", forms: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: banner };
53
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
54
+ return { ...s, status: "ready", forms: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable"};
54
55
  }
55
56
 
56
57
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedForms", {
57
- state: { status: "loading", forms: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
58
+ state: { status: "loading", forms: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
58
59
  actions: {
59
60
  load: async (s) => {
60
61
  try {
61
62
  const r = await queryForms({ filter: { namespace: FORMS_NAMESPACE }, paging: { limit: 50 } });
62
63
  const forms = (r.forms ?? []).map(norm);
63
- if (forms.length) return { ...s, status: "ready", forms, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
64
- return mockState(s, copyParam("forms.emptyBanner", MOCK_BANNER_EMPTY));
64
+ if (forms.length) return { ...s, status: "ready", forms, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
65
+ return mockState(s, "empty");
65
66
  } catch {
66
67
  // The samples still render — a blank screen helps nobody and this vertical
67
68
  // deliberately ships a fallback — but the banner no longer asserts the site is
68
69
  // empty, because a failed query established no such thing.
69
- return mockState(s, copyParam("forms.unavailableBanner", MOCK_BANNER_UNAVAILABLE));
70
+ return mockState(s, "unavailable");
70
71
  }
71
72
  },
72
73
  },
@@ -25,7 +25,11 @@ interface Row { id: string; title: string; subtitle: string }
25
25
  interface S {
26
26
  status: "loading" | "ready";
27
27
  galleries: Row[]; emptyText: string;
28
- isMock: boolean; notMock: boolean; mockBanner: string;
28
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
29
+ * shows only when the site really has none, and the unavailable one only when the
30
+ * query failed. A failed query must never render the sentence that claims the
31
+ * customer has no content. */
32
+ notMockEmpty: boolean; notMockUnavailable: boolean;
29
33
  }
30
34
 
31
35
  function norm(g: RawGallery, i: number): Row {
@@ -35,24 +39,23 @@ function norm(g: RawGallery, i: number): Row {
35
39
  return { id: g.id || `gallery-${i}`, title, subtitle };
36
40
  }
37
41
 
38
- const MOCK_BANNER = "Sample content — this site has no galleries yet.";
39
42
  const MOCK: Row[] = [
40
43
  { id: "sample-work", title: "Our Work", subtitle: "24 photos" },
41
44
  { id: "sample-events", title: "Events", subtitle: "48 photos" },
42
45
  { id: "sample-team", title: "The Team", subtitle: "9 photos" },
43
46
  ];
44
47
 
45
- function mockState(s: S): S {
46
- return { ...s, status: "ready", galleries: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
48
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
49
+ return { ...s, status: "ready", galleries: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable"};
47
50
  }
48
51
 
49
52
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedGalleries", {
50
- state: { status: "loading", galleries: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
53
+ state: { status: "loading", galleries: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
51
54
  actions: {
52
55
  load: async (s) => {
53
56
  try {
54
57
  const api = wixApi();
55
- if (!api) return mockState(s);
58
+ if (!api) return mockState(s, "unavailable");
56
59
  const res = (await api.call("GET", GALLERIES_URL)) as
57
60
  { galleries?: RawGallery[] } | RawGallery[] | { data?: { galleries?: RawGallery[] } };
58
61
  // Accept {galleries:[...]}, a top-level array, or a {data:{galleries}} envelope.
@@ -61,10 +64,10 @@ const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedGalleri
61
64
  (Array.isArray(res) ? (res as RawGallery[]) : undefined) ??
62
65
  (res as { data?: { galleries?: RawGallery[] } })?.data?.galleries ?? [];
63
66
  const galleries = raw.map(norm);
64
- if (galleries.length) return { ...s, status: "ready", galleries, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
65
- return mockState(s);
67
+ if (galleries.length) return { ...s, status: "ready", galleries, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
68
+ return mockState(s, "empty");
66
69
  } catch {
67
- return mockState(s);
70
+ return mockState(s, "unavailable");
68
71
  }
69
72
  },
70
73
  },
@@ -11,7 +11,11 @@ interface Row { id: string; title: string; subtitle: string }
11
11
  interface S {
12
12
  status: "loading" | "ready";
13
13
  cards: Row[]; emptyText: string;
14
- isMock: boolean; notMock: boolean; mockBanner: string;
14
+ isMock: boolean; notMock: boolean; /** #2849 — hiddenWhen() hides on TRUE, so these are inverted: the empty-state banner
15
+ * shows only when the site really has none, and the unavailable one only when the
16
+ * query failed. A failed query must never render the sentence that claims the
17
+ * customer has no content. */
18
+ notMockEmpty: boolean; notMockUnavailable: boolean;
15
19
  }
16
20
 
17
21
  const CURRENCY_SYMBOL: Record<string, string> = { USD: "$", EUR: "€", GBP: "£", ILS: "₪", AUD: "A$", CAD: "C$" };
@@ -34,28 +38,27 @@ function norm(c: WixGiftCard): Row {
34
38
  return { id: c.id || c.code || "gift-card", title, subtitle };
35
39
  }
36
40
 
37
- const MOCK_BANNER = "Sample content — you have no gift cards yet.";
38
41
  const MOCK: Row[] = [
39
42
  { id: "sample-1", title: "Gift card ····4821", subtitle: "Balance $50.00" },
40
43
  { id: "sample-2", title: "Gift card ····9075", subtitle: "Balance $18.50" },
41
44
  { id: "sample-3", title: "Gift card ····3312", subtitle: "Balance $0.00" },
42
45
  ];
43
46
 
44
- function mockState(s: S): S {
45
- return { ...s, status: "ready", cards: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, mockBanner: MOCK_BANNER };
47
+ function mockState(s: S, reason: "empty" | "unavailable"): S {
48
+ return { ...s, status: "ready", cards: MOCK.map((r) => ({ ...r })), emptyText: "", isMock: true, notMock: false, notMockEmpty: reason !== "empty", notMockUnavailable: reason !== "unavailable"};
46
49
  }
47
50
 
48
51
  const svc = defineService<S, { load: (s: S) => Promise<S> }>("himiBrandedGiftCards", {
49
- state: { status: "loading", cards: [], emptyText: "", isMock: false, notMock: true, mockBanner: "" },
52
+ state: { status: "loading", cards: [], emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true},
50
53
  actions: {
51
54
  load: async (s) => {
52
55
  try {
53
56
  const r = await queryGiftCards({ query: { cursorPaging: { limit: 20 } } });
54
57
  const cards = (r.giftCards ?? []).map(norm);
55
- if (cards.length) return { ...s, status: "ready", cards, emptyText: "", isMock: false, notMock: true, mockBanner: "" };
56
- return mockState(s);
58
+ if (cards.length) return { ...s, status: "ready", cards, emptyText: "", isMock: false, notMock: true, notMockEmpty: true, notMockUnavailable: true};
59
+ return mockState(s, "empty");
57
60
  } catch {
58
- return mockState(s);
61
+ return mockState(s, "unavailable");
59
62
  }
60
63
  },
61
64
  },