pi-kiosk-shared 2.1.41 → 2.1.43

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 (53) hide show
  1. package/dist/analyticsApiTypes.d.ts +28 -0
  2. package/dist/analyticsApiTypes.d.ts.map +1 -0
  3. package/dist/analyticsApiTypes.js +29 -0
  4. package/dist/analyticsApiTypes.js.map +1 -0
  5. package/dist/analyticsConsentAllowlist.d.ts +4 -0
  6. package/dist/analyticsConsentAllowlist.d.ts.map +1 -0
  7. package/dist/analyticsConsentAllowlist.js +23 -0
  8. package/dist/analyticsConsentAllowlist.js.map +1 -0
  9. package/dist/analyticsDevLog.d.ts +2 -0
  10. package/dist/analyticsDevLog.d.ts.map +1 -0
  11. package/dist/analyticsDevLog.js +15 -0
  12. package/dist/analyticsDevLog.js.map +1 -0
  13. package/dist/analyticsEmitterManifest.d.ts +22 -0
  14. package/dist/analyticsEmitterManifest.d.ts.map +1 -0
  15. package/dist/analyticsEmitterManifest.js +68 -0
  16. package/dist/analyticsEmitterManifest.js.map +1 -0
  17. package/dist/analyticsEventDescriptions.js +71 -71
  18. package/dist/analyticsEventDescriptions.js.map +1 -1
  19. package/dist/api.d.ts +5 -2
  20. package/dist/api.d.ts.map +1 -1
  21. package/dist/api.js +5 -3
  22. package/dist/api.js.map +1 -1
  23. package/dist/auditEventCodes.d.ts +1 -1
  24. package/dist/auditEventCodes.d.ts.map +1 -1
  25. package/dist/auditEventCodes.js +1 -0
  26. package/dist/auditEventCodes.js.map +1 -1
  27. package/dist/auditEventDescriptions.d.ts +1 -1
  28. package/dist/auditEventDescriptions.d.ts.map +1 -1
  29. package/dist/auditEventDescriptions.js +85 -81
  30. package/dist/auditEventDescriptions.js.map +1 -1
  31. package/dist/auditEventLabels.d.ts +1 -1
  32. package/dist/auditEventLabels.d.ts.map +1 -1
  33. package/dist/auditEventLabels.js +163 -13
  34. package/dist/auditEventLabels.js.map +1 -1
  35. package/dist/auditMetadataDisplayFields.d.ts.map +1 -1
  36. package/dist/auditMetadataDisplayFields.js +0 -2
  37. package/dist/auditMetadataDisplayFields.js.map +1 -1
  38. package/dist/crossTab/CrossTabBus.d.ts +20 -0
  39. package/dist/crossTab/CrossTabBus.d.ts.map +1 -0
  40. package/dist/crossTab/CrossTabBus.js +115 -0
  41. package/dist/crossTab/CrossTabBus.js.map +1 -0
  42. package/dist/crossTab/index.d.ts +38 -0
  43. package/dist/crossTab/index.d.ts.map +1 -0
  44. package/dist/crossTab/index.js +8 -0
  45. package/dist/crossTab/index.js.map +1 -0
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/kiosk/kioskPublicConfig.d.ts +6 -0
  51. package/dist/kiosk/kioskPublicConfig.d.ts.map +1 -1
  52. package/dist/kiosk/kioskPublicConfig.js.map +1 -1
  53. package/package.json +31 -1
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Analytics API response shapes — tenant-scoped sessions controller envelope.
3
+ *
4
+ * POST /api/{tenant}/v1/analytics/sessions returns:
5
+ * { success: true, data: { session: { sessionId, ... }, created } }
6
+ */
7
+ export interface AnalyticsStartSessionData {
8
+ readonly session: {
9
+ readonly sessionId: string;
10
+ readonly id?: number;
11
+ readonly tenantId?: number;
12
+ readonly kioskId?: number | null;
13
+ readonly deviceId?: number | null;
14
+ readonly startedAt?: string;
15
+ readonly completed?: boolean;
16
+ readonly abandoned?: boolean;
17
+ };
18
+ readonly created: boolean;
19
+ }
20
+ export interface ParsedAnalyticsStartSession {
21
+ readonly sessionId: string;
22
+ readonly created: boolean;
23
+ }
24
+ /**
25
+ * Parse nested session start payload. No flat `sessionId` fallback.
26
+ */
27
+ export declare function parseAnalyticsStartSessionData(data: unknown): ParsedAnalyticsStartSession;
28
+ //# sourceMappingURL=analyticsApiTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsApiTypes.d.ts","sourceRoot":"","sources":["../src/analyticsApiTypes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,OAAO,GACZ,2BAA2B,CAkB7B"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Analytics API response shapes — tenant-scoped sessions controller envelope.
3
+ *
4
+ * POST /api/{tenant}/v1/analytics/sessions returns:
5
+ * { success: true, data: { session: { sessionId, ... }, created } }
6
+ */
7
+ /**
8
+ * Parse nested session start payload. No flat `sessionId` fallback.
9
+ */
10
+ export function parseAnalyticsStartSessionData(data) {
11
+ if (typeof data !== 'object' || data === null) {
12
+ throw new Error('analytics_start_session_invalid_shape');
13
+ }
14
+ const record = data;
15
+ const session = record.session;
16
+ if (typeof session !== 'object' || session === null) {
17
+ throw new Error('analytics_start_session_missing_session');
18
+ }
19
+ const sessionRecord = session;
20
+ const sessionId = sessionRecord.sessionId;
21
+ if (typeof sessionId !== 'string' || sessionId.length < 8) {
22
+ throw new Error('analytics_start_session_missing_session_id');
23
+ }
24
+ return {
25
+ sessionId,
26
+ created: record.created === true,
27
+ };
28
+ }
29
+ //# sourceMappingURL=analyticsApiTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsApiTypes.js","sourceRoot":"","sources":["../src/analyticsApiTypes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAqBH;;GAEG;AACH,MAAM,UAAU,8BAA8B,CAC5C,IAAa;IAEb,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,MAAM,GAAG,IAA+B,CAAC;IAC/C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,MAAM,aAAa,GAAG,OAAkC,CAAC;IACzD,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC;IAC1C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IACD,OAAO;QACL,SAAS;QACT,OAAO,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const ANALYTICS_EVENTS_ALLOWED_WITHOUT_CONSENT: readonly ["session_started", "session_completed", "session_abandoned", "error_shown", "auth_flow_started", "identity_completed", "login_success", "account_created", "payment_started", "payment_qr_generated", "payment_submitted", "payment_confirmed", "payment_failed", "receipt_opened", "retail_order_paid", "donation_completed"];
2
+ export type AnalyticsEventAllowedWithoutConsent = (typeof ANALYTICS_EVENTS_ALLOWED_WITHOUT_CONSENT)[number];
3
+ export declare function isAnalyticsEventAllowedWithoutConsent(eventName: string): boolean;
4
+ //# sourceMappingURL=analyticsConsentAllowlist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsConsentAllowlist.d.ts","sourceRoot":"","sources":["../src/analyticsConsentAllowlist.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,wCAAwC,0UAiBH,CAAC;AAEnD,MAAM,MAAM,mCAAmC,GAC7C,CAAC,OAAO,wCAAwC,CAAC,CAAC,MAAM,CAAC,CAAC;AAI5D,wBAAgB,qCAAqC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEhF"}
@@ -0,0 +1,23 @@
1
+ export const ANALYTICS_EVENTS_ALLOWED_WITHOUT_CONSENT = [
2
+ 'session_started',
3
+ 'session_completed',
4
+ 'session_abandoned',
5
+ 'error_shown',
6
+ 'auth_flow_started',
7
+ 'identity_completed',
8
+ 'login_success',
9
+ 'account_created',
10
+ 'payment_started',
11
+ 'payment_qr_generated',
12
+ 'payment_submitted',
13
+ 'payment_confirmed',
14
+ 'payment_failed',
15
+ 'receipt_opened',
16
+ 'retail_order_paid',
17
+ 'donation_completed',
18
+ ];
19
+ const ALLOWED_SET = new Set(ANALYTICS_EVENTS_ALLOWED_WITHOUT_CONSENT);
20
+ export function isAnalyticsEventAllowedWithoutConsent(eventName) {
21
+ return ALLOWED_SET.has(eventName);
22
+ }
23
+ //# sourceMappingURL=analyticsConsentAllowlist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsConsentAllowlist.js","sourceRoot":"","sources":["../src/analyticsConsentAllowlist.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,MAAM,wCAAwC,GAAG;IACtD,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;IACnB,aAAa;IACb,mBAAmB;IACnB,oBAAoB;IACpB,eAAe;IACf,iBAAiB;IACjB,iBAAiB;IACjB,sBAAsB;IACtB,mBAAmB;IACnB,mBAAmB;IACnB,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,oBAAoB;CAC4B,CAAC;AAKnD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAS,wCAAwC,CAAC,CAAC;AAE9E,MAAM,UAAU,qCAAqC,CAAC,SAAiB;IACrE,OAAO,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function logAnalyticsDevError(context: string, details: Record<string, unknown>): void;
2
+ //# sourceMappingURL=analyticsDevLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsDevLog.d.ts","sourceRoot":"","sources":["../src/analyticsDevLog.ts"],"names":[],"mappings":"AAQA,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,IAAI,CAMN"}
@@ -0,0 +1,15 @@
1
+ /** Dev/non-prod structured analytics error logging (plan P0.4). */
2
+ function isProductionRuntime() {
3
+ if (typeof process !== 'undefined' && process.env?.['NODE_ENV'] === 'production') {
4
+ return true;
5
+ }
6
+ return false;
7
+ }
8
+ export function logAnalyticsDevError(context, details) {
9
+ if (isProductionRuntime()) {
10
+ console.warn(`[analytics] ${context}`, details);
11
+ return;
12
+ }
13
+ console.error(`[analytics] ${context}`, details);
14
+ }
15
+ //# sourceMappingURL=analyticsDevLog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsDevLog.js","sourceRoot":"","sources":["../src/analyticsDevLog.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,SAAS,mBAAmB;IAC1B,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE,CAAC;QACjF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,OAAgC;IAEhC,IAAI,mBAAmB,EAAE,EAAE,CAAC;QAC1B,OAAO,CAAC,IAAI,CAAC,eAAe,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,eAAe,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Static emitter matrix for shipped analytics journeys (plan P0.3).
3
+ * CI drift tests ensure every `eventName` is in the v1 catalog and that
4
+ * required FE cells map to known orchestration surfaces.
5
+ */
6
+ import { type AnalyticsEventName } from './analyticsEvents.js';
7
+ export type AnalyticsEmitterSurface = 'kiosk' | 'customer' | 'server';
8
+ export type AnalyticsEmitterLayer = 'FE' | 'BE';
9
+ export interface AnalyticsEmitterManifestCell {
10
+ readonly eventName: AnalyticsEventName;
11
+ readonly surface: AnalyticsEmitterSurface;
12
+ readonly layer: AnalyticsEmitterLayer;
13
+ readonly required: boolean;
14
+ /** Allowlisted path fragment or server use-case name. */
15
+ readonly reference: string;
16
+ }
17
+ /** Shipped journeys only — kiosk retail/donation, customer shop/checkout, server payment/session. */
18
+ export declare const ANALYTICS_EMITTER_MANIFEST: readonly AnalyticsEmitterManifestCell[];
19
+ /** Repo-relative paths for CI grep wiring tests (G3). */
20
+ export declare const ANALYTICS_EMITTER_FE_REFERENCE_PATHS: Readonly<Record<string, string>>;
21
+ export declare function validateAnalyticsEmitterManifest(): string[];
22
+ //# sourceMappingURL=analyticsEmitterManifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsEmitterManifest.d.ts","sourceRoot":"","sources":["../src/analyticsEmitterManifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAyB,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAEtF,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AACtE,MAAM,MAAM,qBAAqB,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,uBAAuB,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,qGAAqG;AACrG,eAAO,MAAM,0BAA0B,EAAE,SAAS,4BAA4B,EAoBpE,CAAC;AAWX,yDAAyD;AACzD,eAAO,MAAM,oCAAoC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOjF,CAAC;AASF,wBAAgB,gCAAgC,IAAI,MAAM,EAAE,CAiB3D"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Static emitter matrix for shipped analytics journeys (plan P0.3).
3
+ * CI drift tests ensure every `eventName` is in the v1 catalog and that
4
+ * required FE cells map to known orchestration surfaces.
5
+ */
6
+ import { ANALYTICS_EVENT_NAMES } from './analyticsEvents.js';
7
+ /** Shipped journeys only — kiosk retail/donation, customer shop/checkout, server payment/session. */
8
+ export const ANALYTICS_EMITTER_MANIFEST = [
9
+ { eventName: 'session_started', surface: 'server', layer: 'BE', required: true, reference: 'StartAnalyticsSessionUseCase' },
10
+ { eventName: 'session_completed', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
11
+ { eventName: 'session_completed', surface: 'customer', layer: 'FE', required: true, reference: 'QrPaymentView' },
12
+ { eventName: 'session_abandoned', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
13
+ { eventName: 'screen_viewed', surface: 'customer', layer: 'FE', required: true, reference: 'shopAnalyticsMetadata' },
14
+ { eventName: 'screen_viewed', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
15
+ { eventName: 'catalog_interaction', surface: 'customer', layer: 'FE', required: true, reference: 'ShopScreen' },
16
+ { eventName: 'catalog_interaction', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
17
+ { eventName: 'product_added', surface: 'customer', layer: 'FE', required: true, reference: 'ShopScreen' },
18
+ { eventName: 'product_added', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
19
+ { eventName: 'cart_viewed', surface: 'customer', layer: 'FE', required: true, reference: 'ShopScreen' },
20
+ { eventName: 'checkout_started', surface: 'customer', layer: 'FE', required: true, reference: 'ShopScreen' },
21
+ { eventName: 'checkout_started', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
22
+ { eventName: 'payment_started', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
23
+ { eventName: 'payment_started', surface: 'customer', layer: 'FE', required: true, reference: 'PhoneFirstProductJourney' },
24
+ { eventName: 'payment_qr_generated', surface: 'server', layer: 'BE', required: true, reference: 'CreateQRPaymentUseCase' },
25
+ { eventName: 'payment_confirmed', surface: 'server', layer: 'BE', required: true, reference: 'CompletePaymentTransactionUseCase' },
26
+ { eventName: 'donation_started', surface: 'customer', layer: 'FE', required: true, reference: 'PhoneFirstDonationJourney' },
27
+ { eventName: 'kiosk_wakeup', surface: 'kiosk', layer: 'FE', required: true, reference: 'useKioskOrchestration' },
28
+ ];
29
+ const ALLOWED_FE_REFERENCES = new Set([
30
+ 'ShopScreen',
31
+ 'shopAnalyticsMetadata',
32
+ 'useKioskOrchestration',
33
+ 'QrPaymentView',
34
+ 'PhoneFirstProductJourney',
35
+ 'PhoneFirstDonationJourney',
36
+ ]);
37
+ /** Repo-relative paths for CI grep wiring tests (G3). */
38
+ export const ANALYTICS_EMITTER_FE_REFERENCE_PATHS = {
39
+ shopAnalyticsMetadata: 'rpapp-customer/src/features/shop/shopAnalyticsMetadata.ts',
40
+ ShopScreen: 'rpapp-customer/src/features/shop/ShopScreen.tsx',
41
+ useKioskOrchestration: 'rpapp-kiosk/src/features/kiosk/hooks/useKioskOrchestration.ts',
42
+ QrPaymentView: 'rpapp-customer/src/features/checkout/QrPaymentView.tsx',
43
+ PhoneFirstProductJourney: 'rpapp-customer/src/features/journeys/PhoneFirstProductJourney.tsx',
44
+ PhoneFirstDonationJourney: 'rpapp-customer/src/features/journeys/PhoneFirstDonationJourney.tsx',
45
+ };
46
+ const ALLOWED_BE_REFERENCES = new Set([
47
+ 'StartAnalyticsSessionUseCase',
48
+ 'CreateQRPaymentUseCase',
49
+ 'CompletePaymentTransactionUseCase',
50
+ 'CreatePostKioskAnalyticsChildSessionUseCase',
51
+ ]);
52
+ export function validateAnalyticsEmitterManifest() {
53
+ const errors = [];
54
+ const catalog = new Set(ANALYTICS_EVENT_NAMES);
55
+ for (const cell of ANALYTICS_EMITTER_MANIFEST) {
56
+ if (!catalog.has(cell.eventName)) {
57
+ errors.push(`manifest event not in catalog: ${cell.eventName}`);
58
+ }
59
+ if (cell.layer === 'FE' && !ALLOWED_FE_REFERENCES.has(cell.reference)) {
60
+ errors.push(`unknown FE reference for ${cell.eventName}: ${cell.reference}`);
61
+ }
62
+ if (cell.layer === 'BE' && !ALLOWED_BE_REFERENCES.has(cell.reference)) {
63
+ errors.push(`unknown BE reference for ${cell.eventName}: ${cell.reference}`);
64
+ }
65
+ }
66
+ return errors;
67
+ }
68
+ //# sourceMappingURL=analyticsEmitterManifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyticsEmitterManifest.js","sourceRoot":"","sources":["../src/analyticsEmitterManifest.ts"],"names":[],"mappings":"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"}
@@ -1,151 +1,151 @@
1
1
  import { ANALYTICS_DONATION_EVENTS, ANALYTICS_EVENT_NAMES, ANALYTICS_KIOSK_EVENTS, ANALYTICS_RETAIL_EVENTS, ANALYTICS_UNIVERSAL_EVENTS, } from './analyticsEvents.js';
2
- /** Operator-facing analytics event descriptions (cs + en), 1–3 sentences each. */
2
+ /** Plain-language analytics descriptions for operators (cs + en), 1–3 short sentences. */
3
3
  const UNIVERSAL_DESCRIPTIONS = {
4
4
  [ANALYTICS_UNIVERSAL_EVENTS.SESSION_STARTED]: {
5
- en: 'Recorded once when the backend accepts a new analytics session (POST …/analytics/sessions via StartAnalyticsSessionUseCase). This is the only server emitter of the “Session started” event. One ingest row per tenant + client sessionId; repeats are deduplicated. It is not the dashboard funnel metricSessions started” that column comes from the sessions table, not a count of this event. Scoped to the tenant; timestamps stored in UTC; OPERATIONAL telemetry only.',
6
- cs: 'Zaznamená se jednou, kdy backend přijme novou analytickou relaci (POST …/analytics/sessions přes StartAnalyticsSessionUseCase). Jediný serverový emitent události „Relace zahájena“. Jedna řádka ingestu na tenant + client sessionId; opakování se deduplikují. Není to metrika Zahájené relace“ ve funnelu — ta vychází ze sloupce sessions, ne z počtu tohoto eventu. V rozsahu tenanta; čas UTC; pouze OPERATIONAL telemetrie.',
5
+ en: 'Counts when a new customer visit starts on the kiosk or phone app. One count per new visit doing the same thing again in the same visit does not add another. This is not the same as thesessions started” number on some charts, which is calculated differently.',
6
+ cs: 'Počítá se, když na kiosku nebo v aplikaci začne nová návštěva zákazníka. Jednou za každou novou návštěvu opakování ve stejné návštěvě nepřidá další. Není totéž jako číslozahájených relací“ na některých grafech, které se počítá jinak.',
7
7
  },
8
8
  [ANALYTICS_UNIVERSAL_EVENTS.SESSION_COMPLETED]: {
9
- en: 'Recorded when a session is closed with outcome completed (CloseAnalyticsSessionUseCase), including after a successful payment completion path. One row per closed session under normal idempotency. Not the same as payment_confirmed or retail_order_paid/donation_completed — those are separate commerce events. Tenant-scoped; UTC occurredAt; does not by itself drive GMV rollups.',
10
- cs: 'Zaznamená se při uzavření relace s výsledkem completed (CloseAnalyticsSessionUseCase), včetně po úspěšné platbě. Obvykle jedna řádka na uzavřenou relaci. Není totéž co payment_confirmed ani retail_order_paid/donation_completed. V rozsahu tenanta; čas UTC; samo o sobě neřídí GMV v rollupech.',
9
+ en: 'Counts when a visit ends in a normal, finished way often after a successful payment. Usually one per finished visit. Not the same as “payment went through” or “order paid” — those are counted separately.',
10
+ cs: 'Počítá se, když návštěva skončí normálně často po úspěšné platbě. Obvykle jednou za každou dokončenou návštěvu. Není totéž jako „platba prošla“ nebo „objednávka zaplacena“ to se počítá zvlášť.',
11
11
  },
12
12
  [ANALYTICS_UNIVERSAL_EVENTS.SESSION_ABANDONED]: {
13
- en: 'Recorded when a session ends without completion: explicit abandon API, tab_close/route_leave beacons, payment cancel mapped to abandon (§2.6), or AnalyticsSessionTimeoutWorker. One occurrence per abandon close per session in typical flows. Not payment_failed (that is explicit cancel while payment is terminal/uninitiated). Not a “bounce” on kiosk_wakeup alone. Tenant + sessionId scoped; UTC dates in explore filters apply to occurredAt, not local kiosk clock.',
14
- cs: 'Zaznamená se, když relace skončí bez dokončení: abandon API, beacon tab_close/route_leave, mapování cancel na abandon (§2.6) nebo timeout worker. Typicky jedna událost na abandon uzavření relace. Není payment_failed (explicitní zrušení u terminální platby). Není „bounce“ jen po kiosk_wakeup. Rozsah tenant + sessionId; filtry explore používají UTC occurredAt.',
13
+ en: 'Counts when someone leaves without finishing closed tab, walked away, timed out, or cancelled in a way that ends the visit. One count per time that happens for a visit. Not the same as “payment failed” when they only cancel a payment step.',
14
+ cs: 'Počítá se, když někdo odejde bez dokončení zavře stránku, odejde od kiosku, vyprší čas, nebo zruší tak, že návštěva skončí. Jednou za každý takový konec návštěvy. Není totéž jako „platba selhala“, když zruší jen krok platby.',
15
15
  },
16
16
  [ANALYTICS_UNIVERSAL_EVENTS.SCREEN_VIEWED]: {
17
- en: 'Recorded when the kiosk or customer PWA shows a screen (client emit on mount or route enter). Each navigation or re-entry to the same screen is a separate row — multiple per session are expected. Counts as one occurrence per ingest row in Explore (raw COUNT(*)). Not a session start/end, not a payment outcome, and not deduplicated across tenants. Optional metadata: screen_name / screen, previous_screen_name, payment_method. OPERATIONAL only; UTC storage.',
18
- cs: 'Zaznamená se při zobrazení obrazovky na kiosku nebo v PWA zákazníka (klient při mountu nebo vstupu na route). Každá navigace nebo opětovný vstup = samostatná řádka — v relaci jich bývá více. V Explore jedna occurrence = jeden ingest řádek (COUNT(*)). Není začátek/konec relace ani výsledek platby. Volitelná metadata: screen_name / screen, previous_screen_name. Pouze OPERATIONAL; UTC.',
17
+ en: 'Counts each time a screen is shown on the kiosk or customer app home, cart, payment, and so on. Every time they open or return to a screen adds one. Not a new visit, not a payment result.',
18
+ cs: 'Počítá se pokaždé, když se na kiosku nebo v aplikaci zobrazí obrazovka úvod, košík, platba atd. Každé otevření nebo návrat na obrazovku přidá jednu. Není nová návštěva ani výsledek platby.',
19
19
  },
20
20
  [ANALYTICS_UNIVERSAL_EVENTS.CTA_CLICKED]: {
21
- en: 'Recorded when the user taps a primary call-to-action (client emit). One row per click emit; rapid double-taps can produce two rows. Not a screen_viewed (navigation) or payment_started. Tenant-scoped; may include element_id / cta_label metadata. Explore counts rows, not unique users.',
22
- cs: 'Zaznamená se po klepnutí na hlavní CTA (klient). Jedna řádka na emit; dvojité klepnutí může dát dvě řádky. Není screen_viewed ani payment_started. Rozsah tenant; metadata element_id / cta_label. Explore počítá řádky, ne unikátní uživatele.',
21
+ en: 'Counts when someone taps a main action button (for example “Continue” or “Pay”). One count per tap tapping twice quickly can mean two. Not the same as just changing screen or starting payment.',
22
+ cs: 'Počítá se, když někdo klepne na hlavní tlačítko (např. „Pokračovat“ nebo „Zaplatit“). Jednou za každé klepnutí — rychlé dvojité klepnutí může být dvakrát. Není jen změna obrazovky ani začátek platby.',
23
23
  },
24
24
  [ANALYTICS_UNIVERSAL_EVENTS.BACK_CLICKED]: {
25
- en: 'Recorded when the user uses an in-flow back control (client emit). One occurrence per back action emitted. Not session_abandoned unless the abandon/close API or beacon also fires. Tenant-scoped OPERATIONAL telemetry.',
26
- cs: 'Zaznamená se při použití zpět v průběhu (klient). Jedna occurrence na emit zpět. Není session_abandoned, pokud se zároveň nevolá abandon/close API nebo beacon. OPERATIONAL telemetrie v rozsahu tenanta.',
25
+ en: 'Counts when someone uses the Back control in the flow. One count per back press. Leaving the whole visit is counted separately as “visit abandoned”, not here.',
26
+ cs: 'Počítá se, když někdo v průběhu použije Zpět. Jednou za každé stisknutí. Úplné opuštění návštěvy se počítá zvlášť jako „návštěva opuštěna“, ne tady.',
27
27
  },
28
28
  [ANALYTICS_UNIVERSAL_EVENTS.ERROR_SHOWN]: {
29
- en: 'Recorded when the UI surfaces an error state to the user (client emit from kiosk orchestration and similar). One row per error presentation emit; the same underlying fault shown twice yields two rows. Not server exception logs or ingest rejections. May carry error_code / message metadata. Not counted in payment_failed unless cancel mapping applies separately.',
30
- cs: 'Zaznamená se, kdy UI zobrazí chybu uživateli (klient, např. orchestrace kiosku). Jedna řádka na emit zobrazení; opakované zobrazení = více řádků. Nejsou to serverové logy ani ingest rejections. Metadata error_code / message. Není payment_failed, pokud cancel mapování neproběhne zvlášť.',
29
+ en: 'Counts when an error message is shown to the customer on screen. One count each time the message appears showing it again adds another. Not the same as a failed payment unless they also cancel the payment.',
30
+ cs: 'Počítá se, když se zákazníkovi na obrazovce ukáže chybová hláška. Jednou za každé zobrazení opětovné ukázání přidá další. Není totéž jako neúspěšná platba, pokud platbu zároveň nezruší.',
31
31
  },
32
32
  [ANALYTICS_UNIVERSAL_EVENTS.AUTH_FLOW_STARTED]: {
33
- en: 'Recorded when the customer begins login or registration (client emit). One row per started auth attempt emit. Not login_success or account_created until those steps complete. Tenant-scoped; optional auth_method metadata.',
34
- cs: 'Zaznamená se na začátku přihlášení nebo registrace (klient). Jedna řádka na emit zahájení auth. Není login_success ani account_created do dokončení kroku. Rozsah tenant; volitelné auth_method.',
33
+ en: 'Counts when someone starts logging in or signing up. One count per time they begin that process. Success or new account is counted with different events.',
34
+ cs: 'Počítá se, když někdo začne přihlašování nebo registraci. Jednou za každý začátek. Úspěch nebo nový účet se počítá jinými událostmi.',
35
35
  },
36
36
  [ANALYTICS_UNIVERSAL_EVENTS.IDENTITY_COMPLETED]: {
37
- en: 'Recorded when the user finishes an identity capture step (e.g. phone/email verification) in the journey (client emit). One occurrence per completed identity step emit. Not login_success and not payment identity checks on the server alone.',
38
- cs: 'Zaznamená se po dokončení kroku identity (např. ověření telefonu/e-mailu) v journey (klient). Jedna occurrence na emit dokončeného kroku. Není login_success ani samotná serverová kontrola u platby.',
37
+ en: 'Counts when someone finishes a step like confirming phone or email in the journey. One count per completed step. Not the same as “logged in” or “account created”.',
38
+ cs: 'Počítá se, když někdo dokončí krok jako potvrzení telefonu nebo e-mailu. Jednou za každý dokončený krok. Není totéž jako „přihlášen“ nebo „účet vytvořen“.',
39
39
  },
40
40
  [ANALYTICS_UNIVERSAL_EVENTS.LOGIN_SUCCESS]: {
41
- en: 'Recorded when authentication succeeds (client and/or server with idempotency on tenantId + customerId). At most one stable row per customer per tenant under server idempotency keys. Not account_created for brand-new registrations. OPERATIONAL; not marketing consent profiling.',
42
- cs: 'Zaznamená se po úspěšném přihlášení (klient a/nebo server s idempotencí tenantId + customerId). Při serverové idempotenci nejvýše jedna stabilní řádka na zákazníka a tenant. Není account_created u nové registrace. OPERATIONAL; ne marketingový profil.',
41
+ en: 'Counts when login succeeds. Usually one per customer per shop when the system remembers them repeats may be ignored. Not the same as creating a brand-new account.',
42
+ cs: 'Počítá se po úspěšném přihlášení. Obvykle jednou na zákazníka a provozovnu, když si systém pamatuje opakování mohou být ignorována. Není totéž jako založení úplně nového účtu.',
43
43
  },
44
44
  [ANALYTICS_UNIVERSAL_EVENTS.ACCOUNT_CREATED]: {
45
- en: 'Recorded when a new customer account is created in the auth flow (client and/or server; idempotent per tenantId + customerId). One canonical row per new account under server keys. Not login_success for returning users. Tenant-scoped OPERATIONAL event.',
46
- cs: 'Zaznamená se při vytvoření nového účtu v auth flow (klient a/nebo server; idempotentní per tenantId + customerId). Jedna kanonická řádka na nový účet. Není login_success pro vracející se uživatele. OPERATIONAL v rozsahu tenanta.',
45
+ en: 'Counts when a new customer account is created. One count per new account. Returning customers who only log in are not counted here.',
46
+ cs: 'Počítá se při vytvoření nového zákaznického účtu. Jednou za každý nový účet. Zákazníci, kteří se jen přihlásí, se sem nepočítají.',
47
47
  },
48
48
  [ANALYTICS_UNIVERSAL_EVENTS.PAYMENT_STARTED]: {
49
- en: 'Recorded when a payment attempt begins — client emit first (with clientEventId), then server merge/insert from CreateQRPayment / CreateGatewayPayment (Option A merge port may UPDATE the same row with paymentId). One logical attempt per paymentId after merge; duplicate client+server rows collapse when merge succeeds. Not payment_confirmed or QR generation alone. Included in funnel “payment started” session flags, not raw event sum for sessions started.',
50
- cs: 'Zaznamená se na začátku pokusu o platbu — nejdřív klient (clientEventId), pak server merge/insert z CreateQRPayment / CreateGatewayPayment (Option A může UPDATE stejné řádky paymentId). Po merge jeden logický pokus na paymentId. Není payment_confirmed ani samotné vygenerování QR. Ve funnelu flag relací s payment started, ne součet pro sessions started.',
49
+ en: 'Counts when a payment attempt begins — customer chose to pay and the system started handling it. One count per payment try (retries may merge into one). Not the same as payment finished or QR code shown alone.',
50
+ cs: 'Počítá se, když začne pokus o platbu — zákazník zvolil zaplatit a systém to začal řešit. Jednou za pokus (opakování se mohou sloučit). Není totéž jako dokončená platba nebo jen zobrazení QR kódu.',
51
51
  },
52
52
  [ANALYTICS_UNIVERSAL_EVENTS.PAYMENT_QR_GENERATED]: {
53
- en: 'Recorded by the server when a QR payment payload is created (CreateQRPaymentUseCase). One idempotent row per tenant + paymentId. Not emitted by the kiosk UI alone. Precedes or accompanies payment_submitted on the QR path. OPERATIONAL server telemetry.',
54
- cs: 'Zaznamená server při vytvoření QR platby (CreateQRPaymentUseCase). Jedna idempotentní řádka na tenant + paymentId. NEemituje samotné UI kiosku. Na QR cestě předchází nebo doprovází payment_submitted. Serverová OPERATIONAL telemetrie.',
53
+ en: 'Counts when the system creates a QR code for paying by phone banking. One count per payment that gets a QR. The customer tapping “pay” on screen is counted separately.',
54
+ cs: 'Počítá se, když systém vytvoří QR kód pro platbu přes bankovní aplikaci. Jednou za platbu s QR. Klepnutí zákazníka na „zaplatit“ na obrazovce se počítá zvlášť.',
55
55
  },
56
56
  [ANALYTICS_UNIVERSAL_EVENTS.PAYMENT_SUBMITTED]: {
57
- en: 'Recorded by the server when the QR (or gateway) payment is submitted for provider processing after generation. Idempotent per payment attempt on the server. Not “user pressed pay” on the client (that is closer to payment_started / checkout_started). Not payment_confirmed until the transaction completes.',
58
- cs: 'Zaznamená server, když je QR (nebo gateway) platba odeslána poskytovateli po vygenerování. Idempotentní na serveru per pokus. Není klepnutí Zaplatit na klientovi (payment_started / checkout_started). Není payment_confirmed do dokončení transakce.',
57
+ en: 'Counts when the payment is sent to the bank or card provider to process. One count per payment sent. Not the same as money already received that is “payment confirmed”.',
58
+ cs: 'Počítá se, když se platba odešle bance nebo platební bráně ke zpracování. Jednou za odeslanou platbu. Není totéž jako peníze dorazily to je „platba potvrzena“.',
59
59
  },
60
60
  [ANALYTICS_UNIVERSAL_EVENTS.PAYMENT_CONFIRMED]: {
61
- en: 'Recorded only on the server when CompletePaymentTransactionUseCase moves the transaction to COMPLETED (best-effort emit). One idempotent row per tenant + paymentId; metadata may include amount_cents. Not a client-side “thank you” screen view. Not the same row as retail_order_paid or donation_completed — those fire as companion events in the same completion handler. Explore “occurrences” are raw event rows; dashboard GMV uses commerce rollups / TenantCommerceFact, not a sum of this event alone. UTC occurredAt; tenant-scoped.',
62
- cs: 'Zaznamená pouze server při přechodu transakce do COMPLETED v CompletePaymentTransactionUseCase (best-effort). Jedna idempotentní řádka na tenant + paymentId; metadata může mít amount_cents. Není zobrazení děkovné obrazovky na klientovi. Není totéž co retail_order_paid nebo donation_completed — ty jdou jako doprovodné eventy ve stejném handleru. Occurrences v Explore = řádky eventů; GMV na dashboardu z commerce rollupů, ne ze součtu tohoto eventu. UTC; rozsah tenant.',
61
+ en: 'Counts when the system marks a payment as successfully received. One count per successful payment. Revenue totals on dashboards use money reports, not just adding up this number.',
62
+ cs: 'Počítá se, když systém označí platbu jako úspěšně přijatou. Jednou za každou úspěšnou platbu. Součty tržeb na přehledech vycházejí z finančních reportů, ne jen ze sečtení tohoto čísla.',
63
63
  },
64
64
  [ANALYTICS_UNIVERSAL_EVENTS.PAYMENT_FAILED]: {
65
- en: 'Recorded on the server when CancelIntent maps to payment_failed (explicit_cancel while the payment is already terminal or was never successfully initiated §2.6). Idempotent per tenant + paymentId + failureReason (e.g. cancelled). Not tab_close or route_leave (those map to session_abandoned). Not a provider timeout unless the cancel path emits it. Distinct from error_shown UI events. Tenant-scoped; counts as one Explore occurrence per matching ingest row.',
66
- cs: 'Zaznamená server, když CancelIntent mapuje na payment_failed (explicit_cancel u terminální nebo nezahájené platby §2.6). Idempotentní per tenant + paymentId + failureReason (např. cancelled). Není tab_close ani route_leave (session_abandoned). Není timeout poskytovatele, pokud cancel neemituje. Odlišné od error_shown v UI. Rozsah tenant; v Explore jedna occurrence = jeden ingest řádek.',
65
+ en: 'Counts when a payment is cancelled or fails in a way the system records as failed for example customer cancels at the terminal. One count per failed payment attempt. Closing the browser without paying is usually “visit abandoned”, not this.',
66
+ cs: 'Počítá se, když je platba zrušena nebo selže tak, že ji systém eviduje jako neúspěšnou např. zrušení u terminálu. Jednou za neúspěšný pokus. Zavření prohlížeče bez placení je obvykle „návštěva opuštěna“, ne toto.',
67
67
  },
68
68
  [ANALYTICS_UNIVERSAL_EVENTS.RECEIPT_OPENED]: {
69
- en: 'Recorded when the user opens or requests a receipt view (client emit). One row per open action. Not payment_confirmed and not email delivery success on the server. Optional receipt_format metadata. OPERATIONAL client telemetry per session.',
70
- cs: 'Zaznamená se při otevření nebo zobrazení účtenky (klient). Jedna řádka na akci otevření. Není payment_confirmed ani úspěšné odeslání e-mailu na serveru. Volitelné receipt_format. OPERATIONAL telemetrie relace.',
69
+ en: 'Counts when the customer opens or views a receipt on screen. One count per time they open it. Not the same as payment succeeding or an email receipt being sent.',
70
+ cs: 'Počítá se, když zákazník otevře nebo zobrazí účtenku na obrazovce. Jednou za každé otevření. Není totéž jako úspěšná platba nebo odeslání účtenky e-mailem.',
71
71
  },
72
72
  };
73
73
  const RETAIL_DESCRIPTIONS = {
74
74
  [ANALYTICS_RETAIL_EVENTS.CATALOG_INTERACTION]: {
75
- en: 'Recorded when the shopper interacts with the product catalog (browse, category tap, product detail) on kiosk or mobile shop (client emit). One row per emitted interaction. Not product_added until the item enters the cart. Used in funnel “catalog” session flags. RETAIL flow; tenant-scoped.',
76
- cs: 'Zaznamená se při interakci s katalogem (prohlížení, kategorie, detail) na kiosku nebo mobilním shopu (klient). Jedna řádka na emit. Není product_added dokud položka není v košíku. Ve funnelu flag relací s katalogem. Flow RETAIL; rozsah tenant.',
75
+ en: 'Counts when someone browses products opens categories or product details in the shop. One count per browsing action recorded. Adding to cart is a different event.',
76
+ cs: 'Počítá se, když někdo prohlíží produkty otevře kategorie nebo detail v obchodě. Jednou za zaznamenanou interakci. Přidání do košíku je jiná událost.',
77
77
  },
78
78
  [ANALYTICS_RETAIL_EVENTS.PRODUCT_ADDED]: {
79
- en: 'Recorded when a product is added to the cart (client emit). One occurrence per add emit; quantity changes may emit again depending on UI. Not checkout_started or payment_started. Drives funnel “product added” session metrics. Optional product_id / quantity metadata.',
80
- cs: 'Zaznamená se při přidání produktu do košíku (klient). Jedna occurrence na emit přidání. Změna množství může emitovat znovu dle UI. Není checkout_started ani payment_started. Řídí funnel „product added“. Volitelná metadata product_id / quantity.',
79
+ en: 'Counts when a product is put into the shopping cart. One count per add (changing quantity may count again). Not checkout or payment yet.',
80
+ cs: 'Počítá se, když se produkt vloží do košíku. Jednou za přidání (změna množství může počítat znovu). Ještě není pokladna ani platba.',
81
81
  },
82
82
  [ANALYTICS_RETAIL_EVENTS.PRODUCT_REMOVED]: {
83
- en: 'Recorded when a line item is removed from the cart (client emit). One row per removal emit. Not retail_order_abandoned (that signals leaving the whole order). RETAIL flow only in catalog v1.',
84
- cs: 'Zaznamená se při odebrání položky z košíku (klient). Jedna řádka na emit odebrání. Není retail_order_abandoned (opuštění celé objednávky). Ve v1 katalogu pouze flow RETAIL.',
83
+ en: 'Counts when a product is removed from the cart. One count per removal. Leaving the whole order without paying is counted elsewhere.',
84
+ cs: 'Počítá se, když se produkt odebere z košíku. Jednou za odebrání. Opuštění celé objednávky bez platby se počítá jinde.',
85
85
  },
86
86
  [ANALYTICS_RETAIL_EVENTS.CART_VIEWED]: {
87
- en: 'Recorded when the cart screen is shown or refreshed for review (client emit). One emit per cart view action; revisiting the cart adds another row. Not cart_item_count truth for revenue rollups use commerce facts. Funnel “cart viewed” session flag source.',
88
- cs: 'Zaznamená se při zobrazení nebo obnovení obrazovky košíku (klient). Jedna řádka na emit zobrazení; návrat na košík přidá další. Počet položek zde není zdroj pravdy GMV rollupy používají commerce fakta. Zdroj funnel flagu „cart viewed“.',
87
+ en: 'Counts when the cart screen is opened to review items. One count each time they open the cart opening it again adds another. Sales money uses payment data, not this count alone.',
88
+ cs: 'Počítá se, když se otevře obrazovka košíku ke kontrole položek. Jednou za každé otevření návrat na košík přidá další. Tržby vycházejí z plateb, ne jen z tohoto počtu.',
89
89
  },
90
90
  [ANALYTICS_RETAIL_EVENTS.CHECKOUT_STARTED]: {
91
- en: 'Recorded when the user enters checkout from the cart (client emit, e.g. Pay on kiosk). One row per checkout entry emit. Precedes payment_started on the payment path. Not payment_confirmed. May include cart totals in metadata for diagnostics only.',
92
- cs: 'Zaznamená se při vstupu do checkoutu z košíku (klient, např. Zaplatit na kiosku). Jedna řádka na emit vstupu. Předchází payment_started na platební cestě. Není payment_confirmed. Metadata s celky košíku jen pro diagnostiku.',
91
+ en: 'Counts when the customer moves from the cart to the payment step (for example taps Pay). One count per time they enter checkout. Payment finishing is counted separately.',
92
+ cs: 'Počítá se, když zákazník přejde z košíku k platbě (např. klepne Zaplatit). Jednou za vstup do pokladny. Dokončení platby se počítá zvlášť.',
93
93
  },
94
94
  [ANALYTICS_RETAIL_EVENTS.RETAIL_ORDER_PAID]: {
95
- en: 'Recorded on the server alongside payment_confirmed when the completed transaction purpose is retail (CompletePaymentTransactionUseCase). One idempotent row per tenant + transactionId. Companion to payment_confirmed, not a substitute. GMV dashboards use commerce rollups, not a raw count of this event.',
96
- cs: 'Zaznamená server spolu s payment_confirmed u dokončené retail transakce (CompletePaymentTransactionUseCase). Jedna idempotentní řádka na tenant + transactionId. Doprovod k payment_confirmed. GMV dashboardy z commerce rollupů, ne z počtu tohoto eventu.',
95
+ en: 'Counts when a shop purchase payment is completed successfully. One count per paid order. Works together with “payment confirmed” dashboards use money totals, not only this row count.',
96
+ cs: 'Počítá se, když je nákup v obchodě úspěšně zaplacen. Jednou za zaplacenou objednávku. Jde ruku v ruce s „platba potvrzena“ přehledy používají součty peněz, ne jen tento počet řádků.',
97
97
  },
98
98
  [ANALYTICS_RETAIL_EVENTS.RETAIL_ORDER_ABANDONED]: {
99
- en: 'Recorded when the shopper leaves a retail order without paying (client emit on abandon paths). Server idempotency per tenant + sessionId + eventName. Not session_abandoned unless the session close API also runs. Not product_removed for a single line.',
100
- cs: 'Zaznamená se, když zákazník opustí retail objednávku bez platby (klient na abandon cestách). Serverová idempotence per tenant + sessionId + eventName. Není session_abandoned, pokud se nevolá close relace. Není product_removed jedné položky.',
99
+ en: 'Counts when someone leaves a shop order without paying. One count per abandoned order attempt. Not removing one item from the cart.',
100
+ cs: 'Počítá se, když někdo opustí objednávku v obchodě bez zaplacení. Jednou za opuštěný pokus. Není odebrání jedné položky z košíku.',
101
101
  },
102
102
  };
103
103
  const DONATION_DESCRIPTIONS = {
104
104
  [ANALYTICS_DONATION_EVENTS.DONATION_STARTED]: {
105
- en: 'Recorded when a donation payment intent is formed (client emit, e.g. kiosk donation-intent). One row per intent emit for that step. Not donation_completed (server, after pay). DONATION flow; may include project/amount metadata.',
106
- cs: 'Zaznamená se při vzniku intentu daru (klient, např. kiosk donation-intent). Jedna řádka na emit kroku. Není donation_completed (server po zaplacení). Flow DONATION; metadata projekt/částka.',
105
+ en: 'Counts when someone starts the donation flow and chooses to give. One count per start of that flow. A finished donation is counted separately after payment.',
106
+ cs: 'Počítá se, když někdo začne darovat a zvolí dát peníze. Jednou za začátek tohoto kroku. Dokončený dar se počítá zvlášť po zaplacení.',
107
107
  },
108
108
  [ANALYTICS_DONATION_EVENTS.DONATION_AMOUNT_SELECTED]: {
109
- en: 'Recorded when the donor picks a preset amount chip (client emit). One occurrence per selection emit; choosing another preset emits again. Not donation_custom_amount_entered. Often followed by screen_viewed on the next step.',
110
- cs: 'Zaznamená se při výběru přednastavené částky (klient). Jedna occurrence na emit; jiná předvolba = další řádka. Není donation_custom_amount_entered. Často následuje screen_viewed dalšího kroku.',
109
+ en: 'Counts when someone picks a preset donation amount (a chip on screen). One count per pick choosing another amount adds another. Typing a custom amount is a different event.',
110
+ cs: 'Počítá se, když někdo vybere přednastavenou částku daru (tlačítko na obrazovce). Jednou za výběr jiná částka přidá další. Vlastní částka je jiná událost.',
111
111
  },
112
112
  [ANALYTICS_DONATION_EVENTS.DONATION_CUSTOM_AMOUNT_ENTERED]: {
113
- en: 'Recorded when the donor enters a custom amount instead of a preset (client emit). Mutually exclusive with donation_amount_selected for the same amount step. One row per custom entry submit.',
114
- cs: 'Zaznamená se při zadání vlastní částky místo předvolby (klient). Vylučuje donation_amount_selected pro stejný krok. Jedna řádka na odeslání vlastní částky.',
113
+ en: 'Counts when someone types their own donation amount instead of a preset. One count when they confirm that amount. Preset chip clicks are not counted here.',
114
+ cs: 'Počítá se, když někdo napíše vlastní částku daru místo předvolby. Jednou při potvrzení částky. Klepnutí na předvolbu se sem nepočítá.',
115
115
  },
116
116
  [ANALYTICS_DONATION_EVENTS.DONATION_PROJECT_SELECTED]: {
117
- en: 'Recorded when the donor selects a beneficiary project (client emit). One row per project selection. Not donation_completed until payment succeeds on the server.',
118
- cs: 'Zaznamená se při výběru projektu příjemce (klient). Jedna řádka na výběr. Není donation_completed do úspěšné platby na serveru.',
117
+ en: 'Counts when someone chooses which project or cause receives the donation. One count per project choice. Paying the donation is counted later.',
118
+ cs: 'Počítá se, když někdo vybere, který projekt nebo účel dar dostane. Jednou za výběr projektu. Samotná platba daru se počítá později.',
119
119
  },
120
120
  [ANALYTICS_DONATION_EVENTS.DONATION_IMPACT_OPENED]: {
121
- en: 'Recorded when the donor opens impact or story content for a project (client emit). One occurrence per open action. Informational only — not a payment or completion signal.',
122
- cs: 'Zaznamená se při otevření informace o dopadu příběhu projektu (klient). Jedna occurrence na otevření. Pouze informativnínení platba ani dokončení.',
121
+ en: 'Counts when someone opens extra information about the project’s impact or story. One count per open. Just reading — not paying yet.',
122
+ cs: 'Počítá se, když někdo otevře doplňující informace o dopadu nebo příběhu projektu. Jednou za otevření. Jen čteníještě bez platby.',
123
123
  },
124
124
  [ANALYTICS_DONATION_EVENTS.DONATION_TAX_RECEIPT_SELECTED]: {
125
- en: 'Recorded when the donor toggles tax-receipt preference (client emit). One row per toggle emit; flipping the switch again adds another row. Not legal receipt issuance on the server.',
126
- cs: 'Zaznamená se při přepnutí preference daňového dokladu (klient). Jedna řádka na emit přepnutí. Není vystavení dokladu na serveru.',
125
+ en: 'Counts when someone turns the tax receipt option on or off. One count per change. Does not mean a receipt was already issued.',
126
+ cs: 'Počítá se, když někdo zapne nebo vypne volbu daňového dokladu. Jednou za změnu. Neznamená, že doklad byl vystaven.',
127
127
  },
128
128
  [ANALYTICS_DONATION_EVENTS.RECURRING_DONATION_SELECTED]: {
129
- en: 'Recorded when the donor selects a recurring donation option (client emit). One occurrence per selection emit. Does not create a subscription by itself operational telemetry only in v1.',
130
- cs: 'Zaznamená se při výběru opakovaného daru (klient). Jedna occurrence na emit. Nesamostatně zakládá předplatné ve v1 jen OPERATIONAL telemetrie.',
129
+ en: 'Counts when someone chooses a repeating (monthly) donation option on screen. One count per choice. It does not by itself start a subscription in this report.',
130
+ cs: 'Počítá se, když někdo na obrazovce zvolí opakovaný (měsíční) dar. Jednou za volbu. Samo o sobě tím v tomto reportu nevzniká předplatné.',
131
131
  },
132
132
  [ANALYTICS_DONATION_EVENTS.DONATION_COMPLETED]: {
133
- en: 'Recorded on the server with payment_confirmed when the completed transaction is a donation (CompletePaymentTransactionUseCase). One idempotent row per tenant + transactionId. Not the client thank-you screen alone. Pair with payment_confirmed for money truth in rollups.',
134
- cs: 'Zaznamená server s payment_confirmed u dokončeného daru (CompletePaymentTransactionUseCase). Jedna idempotentní řádka na tenant + transactionId. Není jen děkovná obrazovka klienta. K payment_confirmed pro peněžní pravdu v rollupech.',
133
+ en: 'Counts when a donation payment is completed successfully. One count per paid donation. Shown together with payment success in the system.',
134
+ cs: 'Počítá se, když je dar úspěšně zaplacen. Jednou za zaplacený dar. V systému jde ruku v ruce s úspěšnou platbou.',
135
135
  },
136
136
  [ANALYTICS_DONATION_EVENTS.DONATION_ABANDONED]: {
137
- en: 'Recorded when the donor exits the donation flow without completing payment (client emit). Idempotent server key per tenant + sessionId. Not donation_completed and not payment_failed unless cancel mapping applies to an in-flight payment.',
138
- cs: 'Zaznamená se při opuštění darovacího flow bez platby (klient). Serverová idempotence per tenant + sessionId. Není donation_completed ani payment_failed, pokud cancel neemituje u rozjeté platby.',
137
+ en: 'Counts when someone leaves the donation flow without paying. One count per time they abandon. Not the same as a failed card payment unless they cancel an active payment.',
138
+ cs: 'Počítá se, když někdo opustí darování bez zaplacení. Jednou za každé opuštění. Není totéž jako neúspěšná platba kartou, pokud nezruší rozjetou platbu.',
139
139
  },
140
140
  };
141
141
  const KIOSK_DESCRIPTIONS = {
142
142
  [ANALYTICS_KIOSK_EVENTS.KIOSK_WAKEUP]: {
143
- en: 'Recorded on physical kiosk idle wake (touch) or programmatic donation boot telemetry (client emit). One row per wake emit; first mount may include configVersion/projectCount. Not session_started the session API may follow separately. KIOSK platform; included in kiosk performance rollups (wakeup counts). OPERATIONAL only.',
144
- cs: 'Zaznamená se při probuzení kiosku z idle (dotyk) nebo při boot telemetrii darovacího kiosku (klient). Jedna řádka na probuzení; první mount může mít configVersion/projectCount. Není session_started — relace může následovat API zvlášť. Platforma KIOSK; počítá se v rollup výkonu kiosku. Pouze OPERATIONAL.',
143
+ en: 'Counts when the kiosk wakes up from the idle attract screen because someone touched it or it starts up. One count per wake-up. Starting a full customer visit may be counted separately.',
144
+ cs: 'Počítá se, když se kiosk probudí z úvodní obrazovky po dotyku nebo při startu. Jednou za probuzení. Zahájení celé návštěvy zákazníka se může počítat zvlášť.',
145
145
  },
146
146
  [ANALYTICS_KIOSK_EVENTS.KIOSK_TIMEOUT]: {
147
- en: 'Recorded when the kiosk idle timer fires and resets the attract loop (client emit). One occurrence per timeout cycle with required idle_time_ms and last_screen_name. Not session_abandoned unless the abandon beacon also runs. May include cart snapshot metadata; tenant + kiosk scoped.',
148
- cs: 'Zaznamená se při vypršení idle timeru kiosku a návratu do attract loop (klient). Jedna occurrence na cyklus s idle_time_ms a last_screen_name. Není session_abandoned, pokud neběží i abandon beacon. Může nést snapshot košíku; rozsah tenant + kiosk.',
147
+ en: 'Counts when the kiosk sits unused too long and returns to the attract screen by itself. One count per timeout. Someone walking away mid-order may also count as visit abandoned.',
148
+ cs: 'Počítá se, když kiosk dlouho nikdo nepoužívá a sám se vrátí na úvodní obrazovku. Jednou za vypršení času. Odejití uprostřed objednávky může být také „návštěva opuštěna“.',
149
149
  },
150
150
  };
151
151
  function buildAnalyticsEventDescriptions() {