kaafil-react-uikit 0.12.0 → 0.13.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 (55) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/dist/admin/index.cjs +363 -381
  3. package/dist/admin/index.cjs.map +1 -1
  4. package/dist/admin/index.js +6 -24
  5. package/dist/admin/index.js.map +1 -1
  6. package/dist/chunk-5QFW5GL4.cjs +24 -0
  7. package/dist/chunk-5QFW5GL4.cjs.map +1 -0
  8. package/dist/{chunk-5ORJRFXZ.cjs → chunk-64AFXHOF.cjs} +6 -4
  9. package/dist/chunk-64AFXHOF.cjs.map +1 -0
  10. package/dist/{chunk-YJJ4DI42.js → chunk-AKJLIH5A.js} +6 -4
  11. package/dist/chunk-AKJLIH5A.js.map +1 -0
  12. package/dist/{chunk-ZKLX6YRT.js → chunk-BT2ZX3JY.js} +5 -5
  13. package/dist/{chunk-ZKLX6YRT.js.map → chunk-BT2ZX3JY.js.map} +1 -1
  14. package/dist/{chunk-U6IE2UYL.js → chunk-CJLQ2Z4Q.js} +3 -3
  15. package/dist/{chunk-U6IE2UYL.js.map → chunk-CJLQ2Z4Q.js.map} +1 -1
  16. package/dist/{chunk-F2ENMVT7.js → chunk-DXDSCQLC.js} +3 -3
  17. package/dist/{chunk-F2ENMVT7.js.map → chunk-DXDSCQLC.js.map} +1 -1
  18. package/dist/{chunk-ARXY3ZA7.cjs → chunk-GD5UU4G6.cjs} +85 -85
  19. package/dist/{chunk-ARXY3ZA7.cjs.map → chunk-GD5UU4G6.cjs.map} +1 -1
  20. package/dist/{chunk-RCWSMWQD.js → chunk-IAKK2CKB.js} +3 -3
  21. package/dist/{chunk-RCWSMWQD.js.map → chunk-IAKK2CKB.js.map} +1 -1
  22. package/dist/chunk-JOUTGBUJ.js +22 -0
  23. package/dist/chunk-JOUTGBUJ.js.map +1 -0
  24. package/dist/{chunk-KJSQLVBR.cjs → chunk-JY2C4S3J.cjs} +55 -55
  25. package/dist/{chunk-KJSQLVBR.cjs.map → chunk-JY2C4S3J.cjs.map} +1 -1
  26. package/dist/chunk-KFOCETDW.cjs +12 -0
  27. package/dist/{chunk-YKBA4WQJ.cjs.map → chunk-KFOCETDW.cjs.map} +1 -1
  28. package/dist/{chunk-T5JYKERY.cjs → chunk-LSOV3FJL.cjs} +12 -12
  29. package/dist/{chunk-T5JYKERY.cjs.map → chunk-LSOV3FJL.cjs.map} +1 -1
  30. package/dist/{chunk-XGPX7TYV.js → chunk-LW2YB7VC.js} +3 -3
  31. package/dist/{chunk-XGPX7TYV.js.map → chunk-LW2YB7VC.js.map} +1 -1
  32. package/dist/{chunk-6QSHORU3.cjs → chunk-MLVS5KS6.cjs} +17 -17
  33. package/dist/{chunk-6QSHORU3.cjs.map → chunk-MLVS5KS6.cjs.map} +1 -1
  34. package/dist/{chunk-XWU5MCY3.cjs → chunk-TCVXLZ4H.cjs} +9 -9
  35. package/dist/{chunk-XWU5MCY3.cjs.map → chunk-TCVXLZ4H.cjs.map} +1 -1
  36. package/dist/{chunk-LJO2FGFD.js → chunk-TFFHYZMZ.js} +5 -5
  37. package/dist/{chunk-LJO2FGFD.js.map → chunk-TFFHYZMZ.js.map} +1 -1
  38. package/dist/{chunk-VHBGE4BY.cjs → chunk-XNZU6ZLX.cjs} +4 -4
  39. package/dist/{chunk-VHBGE4BY.cjs.map → chunk-XNZU6ZLX.cjs.map} +1 -1
  40. package/dist/{chunk-LOLQNRIK.js → chunk-YSJXNKCU.js} +3 -3
  41. package/dist/{chunk-LOLQNRIK.js.map → chunk-YSJXNKCU.js.map} +1 -1
  42. package/dist/core/index.cjs +107 -107
  43. package/dist/core/index.js +10 -10
  44. package/dist/manager/index.cjs +273 -298
  45. package/dist/manager/index.cjs.map +1 -1
  46. package/dist/manager/index.d.cts +46 -2
  47. package/dist/manager/index.d.ts +46 -2
  48. package/dist/manager/index.js +21 -46
  49. package/dist/manager/index.js.map +1 -1
  50. package/dist/traveller/index.cjs +35 -35
  51. package/dist/traveller/index.js +5 -5
  52. package/package.json +14 -14
  53. package/dist/chunk-5ORJRFXZ.cjs.map +0 -1
  54. package/dist/chunk-YJJ4DI42.js.map +0 -1
  55. package/dist/chunk-YKBA4WQJ.cjs +0 -12
@@ -267,6 +267,41 @@ interface ManagerItinerarySectionProps {
267
267
  */
268
268
  declare function ManagerItinerarySection(props: ManagerItinerarySectionProps): ReactNode;
269
269
 
270
+ /**
271
+ * The ONE place a free-text `Traveller.dietary` value becomes a bucket.
272
+ *
273
+ * ── WHY THIS EXISTS ──
274
+ * `kaafil-engine`'s `Traveller.dietary` is a free-text `String?` the partner CRM
275
+ * supplies verbatim (the engine's own published example is `"Vegetarian, no
276
+ * nuts"`). Three copies of this function previously lived in three families,
277
+ * each testing raw EXACT EQUALITY against `V|VEG|VEGETARIAN` /
278
+ * `NV|NON-VEG|NONVEG|NON_VEG` / `J|JAIN` and returning `null` for anything else.
279
+ *
280
+ * Case was handled; nothing else was. `"Pure veg"`, `"Vegetarian, no nuts"`,
281
+ * `"Vegan"`, `"Halal"` and `"Non veg"` (space, no hyphen) all fell to `null`,
282
+ * which the UI rendered identically to "nothing recorded". A trip with twelve
283
+ * vegetarians spelled several ways showed a "Veg 4 / 20" stat card, and the
284
+ * kitchen ordered four meals — and the filter chips silently hid the other
285
+ * eight rather than offering a bucket they could appear in.
286
+ *
287
+ * ── THE RULE ──
288
+ * `null` is returned ONLY when there is genuinely no value (null, or blank after
289
+ * trimming). Every other input lands in a bucket, so a count over the buckets
290
+ * always sums to the roster. That is the property the old version lacked and the
291
+ * reason `OTHER` exists at all.
292
+ *
293
+ * ── WHY `VEGAN` IS `OTHER` AND NOT `V` ──
294
+ * Folding it into `V` would report a vegan as served by the vegetarian meal and
295
+ * remove the only signal that anything further is needed. `OTHER` keeps them
296
+ * counted, visible and distinct. The same argument covers `HALAL` and every
297
+ * allergy note. `OTHER` means "recorded, and not one of the three the badge
298
+ * knows" — never "unknown".
299
+ *
300
+ * Callers should still render the RAW string alongside the bucket: `"Vegetarian,
301
+ * no nuts"` buckets as `V`, and the nut allergy lives only in the raw text.
302
+ */
303
+ type DietBucket = 'V' | 'NV' | 'J' | 'OTHER';
304
+
270
305
  interface TripBookingGroupCardProps {
271
306
  readonly group: ManifestBookingGroup;
272
307
  readonly onCollect: (groupId: string) => void;
@@ -331,7 +366,7 @@ interface ManagerManifestSectionProps {
331
366
  };
332
367
  readonly style?: KaafilTokenOverrides;
333
368
  }
334
- type ManifestDiet = 'V' | 'NV' | 'J';
369
+ type ManifestDiet = DietBucket;
335
370
  /** `BookingStatus` (`kaafil-engine`'s real Prisma enum) — never a free
336
371
  * string; the DTO widens it to `z.string()` on the wire, but this composite
337
372
  * only ever recognizes these three real values. */
@@ -732,7 +767,16 @@ interface ManagerSyncCenterSectionProps {
732
767
 
733
768
  declare function ManagerSyncCenterSection({ tripRef, getEntityLabel, onResolved, style, }: ManagerSyncCenterSectionProps): ReactNode;
734
769
 
735
- type TravellerDiet = 'V' | 'NV' | 'J';
770
+ /**
771
+ * The bucket a free-text `Traveller.dietary` value lands in.
772
+ *
773
+ * One shared implementation in `core/internal/normalizeDiet.ts`, not a local
774
+ * copy: three copies of this rule existed and all three dropped `"Pure veg"`
775
+ * and `"Vegan"` to `null`, which rendered as "nothing recorded". See that
776
+ * file's header.
777
+ */
778
+ type TravellerDiet = DietBucket;
779
+
736
780
  interface DietaryRow {
737
781
  readonly key: string;
738
782
  readonly labelKey: string;
@@ -267,6 +267,41 @@ interface ManagerItinerarySectionProps {
267
267
  */
268
268
  declare function ManagerItinerarySection(props: ManagerItinerarySectionProps): ReactNode;
269
269
 
270
+ /**
271
+ * The ONE place a free-text `Traveller.dietary` value becomes a bucket.
272
+ *
273
+ * ── WHY THIS EXISTS ──
274
+ * `kaafil-engine`'s `Traveller.dietary` is a free-text `String?` the partner CRM
275
+ * supplies verbatim (the engine's own published example is `"Vegetarian, no
276
+ * nuts"`). Three copies of this function previously lived in three families,
277
+ * each testing raw EXACT EQUALITY against `V|VEG|VEGETARIAN` /
278
+ * `NV|NON-VEG|NONVEG|NON_VEG` / `J|JAIN` and returning `null` for anything else.
279
+ *
280
+ * Case was handled; nothing else was. `"Pure veg"`, `"Vegetarian, no nuts"`,
281
+ * `"Vegan"`, `"Halal"` and `"Non veg"` (space, no hyphen) all fell to `null`,
282
+ * which the UI rendered identically to "nothing recorded". A trip with twelve
283
+ * vegetarians spelled several ways showed a "Veg 4 / 20" stat card, and the
284
+ * kitchen ordered four meals — and the filter chips silently hid the other
285
+ * eight rather than offering a bucket they could appear in.
286
+ *
287
+ * ── THE RULE ──
288
+ * `null` is returned ONLY when there is genuinely no value (null, or blank after
289
+ * trimming). Every other input lands in a bucket, so a count over the buckets
290
+ * always sums to the roster. That is the property the old version lacked and the
291
+ * reason `OTHER` exists at all.
292
+ *
293
+ * ── WHY `VEGAN` IS `OTHER` AND NOT `V` ──
294
+ * Folding it into `V` would report a vegan as served by the vegetarian meal and
295
+ * remove the only signal that anything further is needed. `OTHER` keeps them
296
+ * counted, visible and distinct. The same argument covers `HALAL` and every
297
+ * allergy note. `OTHER` means "recorded, and not one of the three the badge
298
+ * knows" — never "unknown".
299
+ *
300
+ * Callers should still render the RAW string alongside the bucket: `"Vegetarian,
301
+ * no nuts"` buckets as `V`, and the nut allergy lives only in the raw text.
302
+ */
303
+ type DietBucket = 'V' | 'NV' | 'J' | 'OTHER';
304
+
270
305
  interface TripBookingGroupCardProps {
271
306
  readonly group: ManifestBookingGroup;
272
307
  readonly onCollect: (groupId: string) => void;
@@ -331,7 +366,7 @@ interface ManagerManifestSectionProps {
331
366
  };
332
367
  readonly style?: KaafilTokenOverrides;
333
368
  }
334
- type ManifestDiet = 'V' | 'NV' | 'J';
369
+ type ManifestDiet = DietBucket;
335
370
  /** `BookingStatus` (`kaafil-engine`'s real Prisma enum) — never a free
336
371
  * string; the DTO widens it to `z.string()` on the wire, but this composite
337
372
  * only ever recognizes these three real values. */
@@ -732,7 +767,16 @@ interface ManagerSyncCenterSectionProps {
732
767
 
733
768
  declare function ManagerSyncCenterSection({ tripRef, getEntityLabel, onResolved, style, }: ManagerSyncCenterSectionProps): ReactNode;
734
769
 
735
- type TravellerDiet = 'V' | 'NV' | 'J';
770
+ /**
771
+ * The bucket a free-text `Traveller.dietary` value lands in.
772
+ *
773
+ * One shared implementation in `core/internal/normalizeDiet.ts`, not a local
774
+ * copy: three copies of this rule existed and all three dropped `"Pure veg"`
775
+ * and `"Vegan"` to `null`, which rendered as "nothing recorded". See that
776
+ * file's header.
777
+ */
778
+ type TravellerDiet = DietBucket;
779
+
736
780
  interface DietaryRow {
737
781
  readonly key: string;
738
782
  readonly labelKey: string;
@@ -1,9 +1,10 @@
1
- import { useManagerMe, useConflicts, useNotifications } from '../chunk-U6IE2UYL.js';
2
- import { FORM_FIELD_KIND_SINGLE_BOOLEAN, useChecklists, useManagers, useCloseout, useFiles, useFloat, useForms, useParties, useItinerary, useVendors, useExpenses, useCollections, useManagerToday, usePickups, useRooming, useTravellerProfile, useSeating } from '../chunk-XGPX7TYV.js';
3
- import { useOfflineEngine } from '../chunk-RCWSMWQD.js';
4
- import { OfflineFallbackScreen } from '../chunk-LOLQNRIK.js';
5
- export { BootErrorScreen, LockedTripScreen, NotFoundScreen, OfflineFallbackScreen, SessionExpiredScreen } from '../chunk-LOLQNRIK.js';
6
- import { createRegistry, useKaafilChrome, useSession, tokenStyle, useOutboxStatus, useOfflineEvent, useKaafilBrand } from '../chunk-YJJ4DI42.js';
1
+ import { useManagerMe, useConflicts, useNotifications } from '../chunk-CJLQ2Z4Q.js';
2
+ import { normalizeDiet } from '../chunk-JOUTGBUJ.js';
3
+ import { FORM_FIELD_KIND_SINGLE_BOOLEAN, useChecklists, useManagers, useCloseout, useFiles, useFloat, useForms, useParties, useItinerary, useVendors, useExpenses, useCollections, useManagerToday, usePickups, useRooming, useTravellerProfile, useSeating } from '../chunk-LW2YB7VC.js';
4
+ import { useOfflineEngine } from '../chunk-IAKK2CKB.js';
5
+ import { OfflineFallbackScreen } from '../chunk-YSJXNKCU.js';
6
+ export { BootErrorScreen, LockedTripScreen, NotFoundScreen, OfflineFallbackScreen, SessionExpiredScreen } from '../chunk-YSJXNKCU.js';
7
+ import { createRegistry, useKaafilChrome, useSession, tokenStyle, useOutboxStatus, useOfflineEvent, useKaafilBrand } from '../chunk-AKJLIH5A.js';
7
8
  import { useState, useRef, useEffect, useMemo, useId } from 'react';
8
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
10
 
@@ -4118,22 +4119,6 @@ var RECOGNIZED_BOOKING_STATUS = /* @__PURE__ */ new Set([
4118
4119
  function normalizeBookingStatus(raw) {
4119
4120
  return RECOGNIZED_BOOKING_STATUS.has(raw) ? raw : "TENTATIVE";
4120
4121
  }
4121
- function normalizeDiet(raw) {
4122
- if (raw === null) {
4123
- return null;
4124
- }
4125
- const upper = raw.trim().toUpperCase();
4126
- if (upper === "V" || upper === "VEG" || upper === "VEGETARIAN") {
4127
- return "V";
4128
- }
4129
- if (upper === "NV" || upper === "NON-VEG" || upper === "NONVEG" || upper === "NON_VEG") {
4130
- return "NV";
4131
- }
4132
- if (upper === "J" || upper === "JAIN") {
4133
- return "J";
4134
- }
4135
- return null;
4136
- }
4137
4122
  function toManifestTravellers(roster) {
4138
4123
  return roster.map((row) => ({
4139
4124
  travellerId: row.traveller.travellerId,
@@ -4358,11 +4343,12 @@ function CloseIcon5(props) {
4358
4343
  }
4359
4344
  );
4360
4345
  }
4361
- var DIET_OPTIONS = ["V", "NV", "J"];
4346
+ var DIET_OPTIONS = ["V", "NV", "J", "OTHER"];
4362
4347
  var DIET_LABEL_KEY = {
4363
4348
  V: "chrome.managerTrip.manifest.traveller.diet.v",
4364
4349
  NV: "chrome.managerTrip.manifest.traveller.diet.nv",
4365
- J: "chrome.managerTrip.manifest.traveller.diet.j"
4350
+ J: "chrome.managerTrip.manifest.traveller.diet.j",
4351
+ OTHER: "chrome.managerTrip.manifest.traveller.diet.other"
4366
4352
  };
4367
4353
  var BALANCE_OPTIONS = ["due", "settled"];
4368
4354
  var BALANCE_LABEL_KEY = {
@@ -4551,7 +4537,8 @@ function TripManifestStats({ stats }) {
4551
4537
  var DIET_LABEL_KEY2 = {
4552
4538
  V: "chrome.managerTrip.manifest.traveller.diet.v",
4553
4539
  NV: "chrome.managerTrip.manifest.traveller.diet.nv",
4554
- J: "chrome.managerTrip.manifest.traveller.diet.j"
4540
+ J: "chrome.managerTrip.manifest.traveller.diet.j",
4541
+ OTHER: "chrome.managerTrip.manifest.traveller.diet.other"
4555
4542
  };
4556
4543
  var STATUS_LABEL_KEY3 = {
4557
4544
  TENTATIVE: "chrome.managerTrip.manifest.traveller.status.tentative",
@@ -4635,7 +4622,8 @@ function ReadyManagerManifestSection({
4635
4622
  diet: {
4636
4623
  V: travellers.filter((row) => row.diet === "V").length,
4637
4624
  NV: travellers.filter((row) => row.diet === "NV").length,
4638
- J: travellers.filter((row) => row.diet === "J").length
4625
+ J: travellers.filter((row) => row.diet === "J").length,
4626
+ OTHER: travellers.filter((row) => row.diet === "OTHER").length
4639
4627
  },
4640
4628
  balance: {
4641
4629
  due: travellers.filter((row) => row.dueMinor > 0).length,
@@ -9222,7 +9210,6 @@ function UnassignedPoolSection({
9222
9210
  children: [
9223
9211
  /* @__PURE__ */ jsx("span", { className: "kf-manager-rooming__pool-avatar", children: traveller.glyph }),
9224
9212
  /* @__PURE__ */ jsx("span", { className: "kf-manager-rooming__pool-name", children: traveller.fullName }),
9225
- traveller.dietary !== null ? /* @__PURE__ */ jsx("span", { className: "kf-manager-rooming__pill", "data-tone": "soft", children: traveller.dietary }) : null,
9226
9213
  traveller.medicalFlag ? /* @__PURE__ */ jsx("span", { className: "kf-manager-rooming__pill", "data-tone": "warn", children: t("chrome.managerTrip.rooming.pool.medical") }) : null
9227
9214
  ]
9228
9215
  },
@@ -9988,30 +9975,17 @@ function ManagerSyncCenterSection({
9988
9975
  }
9989
9976
 
9990
9977
  // src/manager/composite/office/ManagerTravellerProfileSection/internal/deriveTravellerProfile.ts
9991
- function normalizeDiet2(raw) {
9992
- if (raw === null) {
9993
- return null;
9994
- }
9995
- const upper = raw.trim().toUpperCase();
9996
- if (upper === "V" || upper === "VEG" || upper === "VEGETARIAN") {
9997
- return "V";
9998
- }
9999
- if (upper === "NV" || upper === "NON-VEG" || upper === "NONVEG" || upper === "NON_VEG") {
10000
- return "NV";
10001
- }
10002
- if (upper === "J" || upper === "JAIN") {
10003
- return "J";
10004
- }
10005
- return null;
10006
- }
10007
9978
  function deriveDietaryRows(dietary, mealPreference, dietaryReqs, allergies, medicalFlag, medicalNotes) {
10008
9979
  const rows = [];
10009
- const diet = normalizeDiet2(dietary);
9980
+ const diet = normalizeDiet(dietary);
10010
9981
  if (mealPreference !== null || diet !== null) {
10011
9982
  rows.push({
10012
9983
  key: "meal",
10013
9984
  labelKey: "chrome.managerTraveller.dietary.meal",
10014
- value: mealPreference ?? "",
9985
+ // The RAW string when the CRM sent no separate meal preference. The bucket
9986
+ // is a badge and necessarily lossy — `"Vegetarian, no nuts"` buckets as
9987
+ // `V` — so dropping the text left the nut allergy on screen NOWHERE.
9988
+ value: mealPreference ?? dietary ?? "",
10015
9989
  diet,
10016
9990
  isAlert: false
10017
9991
  });
@@ -10357,7 +10331,8 @@ function TravellerContactRow({ fullName, phone }) {
10357
10331
  var DIET_LABEL_KEY3 = {
10358
10332
  V: "chrome.managerTraveller.dietary.diet.v",
10359
10333
  NV: "chrome.managerTraveller.dietary.diet.nv",
10360
- J: "chrome.managerTraveller.dietary.diet.j"
10334
+ J: "chrome.managerTraveller.dietary.diet.j",
10335
+ OTHER: "chrome.managerTraveller.dietary.diet.other"
10361
10336
  };
10362
10337
  function TravellerDietaryCard({ rows }) {
10363
10338
  const { t } = useKaafilChrome();