@aranova/tracking-react 1.4.1 → 1.6.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.
package/dist/index.mjs CHANGED
@@ -722,7 +722,14 @@ function parseBookingOption(value) {
722
722
  if (!value || typeof value !== "object") return [];
723
723
  const o = value;
724
724
  if (typeof o.key !== "string" || !o.key || typeof o.label !== "string") return [];
725
- return [{ key: o.key, label: o.label }];
725
+ return [
726
+ {
727
+ key: o.key,
728
+ label: o.label,
729
+ group: typeof o.group === "string" && o.group ? o.group : null,
730
+ description: typeof o.description === "string" && o.description ? o.description : null
731
+ }
732
+ ];
726
733
  }
727
734
  function parseIntegrations(value) {
728
735
  if (!value || typeof value !== "object") return {};
@@ -1449,7 +1456,12 @@ function getBookingIntegration(integrations) {
1449
1456
  timezone: booking.timezone,
1450
1457
  configVersion: booking.config_version,
1451
1458
  rules,
1452
- options: booking.options.map((option) => ({ key: option.key, label: option.label })),
1459
+ options: booking.options.map((option) => ({
1460
+ key: option.key,
1461
+ label: option.label,
1462
+ group: option.group,
1463
+ description: option.description
1464
+ })),
1453
1465
  mode: booking.mode ?? "live"
1454
1466
  };
1455
1467
  }
@@ -1529,6 +1541,15 @@ function nationalDigits(phone) {
1529
1541
  const parsed = parsePhone(phone);
1530
1542
  return (parsed.isValid ? parsed.national : phone).replace(/\D/g, "");
1531
1543
  }
1544
+ function groupBookingOptions(options) {
1545
+ const groups = /* @__PURE__ */ new Map();
1546
+ for (const option of options) {
1547
+ const members = groups.get(option.group);
1548
+ if (members) members.push(option);
1549
+ else groups.set(option.group, [option]);
1550
+ }
1551
+ return [...groups].map(([group, members]) => ({ group, options: members }));
1552
+ }
1532
1553
 
1533
1554
  // ../tracking-core/src/events/semantics.ts
1534
1555
  var EVENT_SEMANTICS = {
@@ -1712,7 +1733,7 @@ function outcomeOf(body) {
1712
1733
  if (body.status === "pending") return { status: "pending", id: body.id, mode };
1713
1734
  return { status: "failed", id: body.id, fallbackUrl: body.fallback_url, mode };
1714
1735
  }
1715
- function formSubmitPayload(input, formId, labels) {
1736
+ function formSubmitPayload(input, formSubmit, labels) {
1716
1737
  const vehicle = input.vehicle ? `${input.vehicle.year} ${input.vehicle.make} ${input.vehicle.model}` : "";
1717
1738
  const field = (name, type, label, value) => ({
1718
1739
  name,
@@ -1720,32 +1741,31 @@ function formSubmitPayload(input, formId, labels) {
1720
1741
  label,
1721
1742
  value
1722
1743
  });
1744
+ const fields = [
1745
+ field("first_name", "text", "First name", input.firstName),
1746
+ field("last_name", "text", "Last name", input.lastName),
1747
+ // E.164 on the wire: it keys the customer and enhanced-conversion matching.
1748
+ field("phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
1749
+ field("email", "email", "Email", input.email ?? ""),
1750
+ field(
1751
+ "service",
1752
+ "select",
1753
+ "Service",
1754
+ input.services.map((key) => labels.get(key) ?? key).join(", ")
1755
+ ),
1756
+ field("vehicle", "text", "Vehicle", vehicle),
1757
+ field(
1758
+ "start",
1759
+ "text",
1760
+ "Requested time",
1761
+ `${input.startDate} ${String(input.startHour).padStart(2, "0")}:00`
1762
+ ),
1763
+ field("note", "textarea", "Notes", input.notes ?? "")
1764
+ ];
1765
+ const reported = new Set(fields.map((item) => item.name));
1766
+ const extra = (formSubmit.extraFields ?? []).filter((item) => !reported.has(item.name));
1723
1767
  return {
1724
- form: {
1725
- id: formId,
1726
- action: "/tracking/bookings",
1727
- fields: [
1728
- field("first_name", "text", "First name", input.firstName),
1729
- field("last_name", "text", "Last name", input.lastName),
1730
- // E.164 on the wire: it keys the customer and enhanced-conversion matching.
1731
- field("phone", "tel", "Phone", toE164(input.phone) ?? input.phone),
1732
- field("email", "email", "Email", input.email ?? ""),
1733
- field(
1734
- "service",
1735
- "select",
1736
- "Service",
1737
- input.services.map((key) => labels.get(key) ?? key).join(", ")
1738
- ),
1739
- field("vehicle", "text", "Vehicle", vehicle),
1740
- field(
1741
- "start",
1742
- "text",
1743
- "Requested time",
1744
- `${input.startDate} ${String(input.startHour).padStart(2, "0")}:00`
1745
- ),
1746
- field("note", "textarea", "Notes", input.notes ?? "")
1747
- ]
1748
- },
1768
+ form: { id: formSubmit.formId, action: "/tracking/bookings", fields: [...fields, ...extra] },
1749
1769
  page: { path: typeof window === "undefined" ? "/" : window.location.pathname }
1750
1770
  };
1751
1771
  }
@@ -1833,7 +1853,7 @@ function createSalesBookingsClient(config, firing) {
1833
1853
  return failedBeforeSend(input);
1834
1854
  }
1835
1855
  return {
1836
- async submit(input, { attemptKey, formSubmit, simulate }) {
1856
+ async submit(input, { attemptKey, formSubmit, simulate, onPending }) {
1837
1857
  registerCapability("booking_integration");
1838
1858
  const runtime = runtimeOf(firing);
1839
1859
  warnOnSetupMismatch(runtime);
@@ -1844,10 +1864,7 @@ function createSalesBookingsClient(config, firing) {
1844
1864
  if (formSubmit && !submittedForms.has(attemptKey)) {
1845
1865
  submittedForms.add(attemptKey);
1846
1866
  const labels = new Map(booking.options.map((option) => [option.key, option.label]));
1847
- formSubmit.tracking.trackEvent(
1848
- "form_submit",
1849
- formSubmitPayload(input, formSubmit.formId, labels)
1850
- );
1867
+ formSubmit.tracking.trackEvent("form_submit", formSubmitPayload(input, formSubmit, labels));
1851
1868
  }
1852
1869
  const body = {
1853
1870
  idempotency_key: attemptKey,
@@ -1881,10 +1898,9 @@ function createSalesBookingsClient(config, firing) {
1881
1898
  return rejected(error, input, attemptKey, runtime);
1882
1899
  }
1883
1900
  const outcome = outcomeOf(response);
1884
- return withHandoff(
1885
- outcome.status === "pending" ? await poll(outcome.id, outcome.mode) : outcome,
1886
- input
1887
- );
1901
+ if (outcome.status !== "pending") return withHandoff(outcome, input);
1902
+ onPending?.(outcome);
1903
+ return withHandoff(await poll(outcome.id, outcome.mode), input);
1888
1904
  },
1889
1905
  async status(id) {
1890
1906
  return outcomeOf(
@@ -2445,6 +2461,7 @@ export {
2445
2461
  getConsentState,
2446
2462
  getEventSemantics,
2447
2463
  getTrackingConfigRuntime,
2464
+ groupBookingOptions,
2448
2465
  newBookingAttemptKey,
2449
2466
  onConsentChange,
2450
2467
  optIn,