@bash-app/bash-common 30.260.1 → 30.262.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 (79) hide show
  1. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.d.ts +2 -0
  2. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.d.ts.map +1 -0
  3. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.js +33 -0
  4. package/dist/__tests__/ticketBnplPaymentMethods.cashapp.test.js.map +1 -0
  5. package/dist/__tests__/ticketBnplPaymentMethods.test.d.ts +2 -0
  6. package/dist/__tests__/ticketBnplPaymentMethods.test.d.ts.map +1 -0
  7. package/dist/__tests__/ticketBnplPaymentMethods.test.js +46 -0
  8. package/dist/__tests__/ticketBnplPaymentMethods.test.js.map +1 -0
  9. package/dist/definitions.d.ts +6 -1
  10. package/dist/definitions.d.ts.map +1 -1
  11. package/dist/definitions.js.map +1 -1
  12. package/dist/index.d.ts +6 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +6 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/ticketBnplPaymentMethods.d.ts +32 -0
  17. package/dist/ticketBnplPaymentMethods.d.ts.map +1 -0
  18. package/dist/ticketBnplPaymentMethods.js +42 -0
  19. package/dist/ticketBnplPaymentMethods.js.map +1 -0
  20. package/dist/utils/__tests__/featuredDiscoveryGeo.test.d.ts +2 -0
  21. package/dist/utils/__tests__/featuredDiscoveryGeo.test.d.ts.map +1 -0
  22. package/dist/utils/__tests__/featuredDiscoveryGeo.test.js +98 -0
  23. package/dist/utils/__tests__/featuredDiscoveryGeo.test.js.map +1 -0
  24. package/dist/utils/__tests__/flyerUtils.test.js +7 -1
  25. package/dist/utils/__tests__/flyerUtils.test.js.map +1 -1
  26. package/dist/utils/__tests__/guestSurface.test.d.ts +2 -0
  27. package/dist/utils/__tests__/guestSurface.test.d.ts.map +1 -0
  28. package/dist/utils/__tests__/guestSurface.test.js +94 -0
  29. package/dist/utils/__tests__/guestSurface.test.js.map +1 -0
  30. package/dist/utils/__tests__/ticketTierSchedule.test.d.ts +2 -0
  31. package/dist/utils/__tests__/ticketTierSchedule.test.d.ts.map +1 -0
  32. package/dist/utils/__tests__/ticketTierSchedule.test.js +84 -0
  33. package/dist/utils/__tests__/ticketTierSchedule.test.js.map +1 -0
  34. package/dist/utils/featuredDiscoveryGeo.d.ts +30 -0
  35. package/dist/utils/featuredDiscoveryGeo.d.ts.map +1 -0
  36. package/dist/utils/featuredDiscoveryGeo.js +47 -0
  37. package/dist/utils/featuredDiscoveryGeo.js.map +1 -0
  38. package/dist/utils/flyerUtils.d.ts +5 -0
  39. package/dist/utils/flyerUtils.d.ts.map +1 -1
  40. package/dist/utils/flyerUtils.js +24 -0
  41. package/dist/utils/flyerUtils.js.map +1 -1
  42. package/dist/utils/guestSurface.d.ts +114 -0
  43. package/dist/utils/guestSurface.d.ts.map +1 -0
  44. package/dist/utils/guestSurface.js +164 -0
  45. package/dist/utils/guestSurface.js.map +1 -0
  46. package/dist/utils/promotionBlastUtils.d.ts +38 -0
  47. package/dist/utils/promotionBlastUtils.d.ts.map +1 -0
  48. package/dist/utils/promotionBlastUtils.js +88 -0
  49. package/dist/utils/promotionBlastUtils.js.map +1 -0
  50. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.d.ts +2 -0
  51. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.d.ts.map +1 -0
  52. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.js +65 -0
  53. package/dist/utils/service/__tests__/defaultOfferAmountUtils.test.js.map +1 -0
  54. package/dist/utils/service/defaultOfferAmountUtils.d.ts +32 -0
  55. package/dist/utils/service/defaultOfferAmountUtils.d.ts.map +1 -0
  56. package/dist/utils/service/defaultOfferAmountUtils.js +115 -0
  57. package/dist/utils/service/defaultOfferAmountUtils.js.map +1 -0
  58. package/dist/utils/ticketTierSchedule.d.ts +58 -0
  59. package/dist/utils/ticketTierSchedule.d.ts.map +1 -0
  60. package/dist/utils/ticketTierSchedule.js +279 -0
  61. package/dist/utils/ticketTierSchedule.js.map +1 -0
  62. package/package.json +5 -2
  63. package/prisma/schema.prisma +332 -1
  64. package/src/__tests__/ticketBnplPaymentMethods.cashapp.test.ts +45 -0
  65. package/src/__tests__/ticketBnplPaymentMethods.test.ts +66 -0
  66. package/src/definitions.ts +6 -1
  67. package/src/index.ts +6 -0
  68. package/src/ticketBnplPaymentMethods.ts +79 -0
  69. package/src/utils/__tests__/featuredDiscoveryGeo.test.ts +120 -0
  70. package/src/utils/__tests__/flyerUtils.test.ts +10 -0
  71. package/src/utils/__tests__/guestSurface.test.ts +128 -0
  72. package/src/utils/__tests__/ticketTierSchedule.test.ts +131 -0
  73. package/src/utils/featuredDiscoveryGeo.ts +75 -0
  74. package/src/utils/flyerUtils.ts +33 -0
  75. package/src/utils/guestSurface.ts +315 -0
  76. package/src/utils/promotionBlastUtils.ts +127 -0
  77. package/src/utils/service/__tests__/defaultOfferAmountUtils.test.ts +102 -0
  78. package/src/utils/service/defaultOfferAmountUtils.ts +170 -0
  79. package/src/utils/ticketTierSchedule.ts +387 -0
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Curated guest visibility — shared policy resolver for API + bash-app.
3
+ * Three layers compose: event teaser policy, per-guest visibility, viewer roster depth.
4
+ */
5
+ import type { PublicTeaserUser } from "../extendedSchemas.js";
6
+ export type AttendeeDisplayMode = "All" | "CountOnly" | "NetworkOnly" | "Hidden";
7
+ export type AttendeeVisibility = "Visible" | "Hidden" | "FeaturedPending" | "FeaturedInvited";
8
+ export type GuestListDepth = "None" | "Partial" | "Full";
9
+ export type { PublicTeaserUser };
10
+ export type NetworkOverlapPayload = {
11
+ connections: PublicTeaserUser[];
12
+ contacts: PublicTeaserUser[];
13
+ customLists: Array<{
14
+ listId: string;
15
+ listName: string;
16
+ users: PublicTeaserUser[];
17
+ }>;
18
+ };
19
+ export type GuestSurfacePayload = {
20
+ count: {
21
+ totalTickets: number;
22
+ visibleAttendees: number;
23
+ };
24
+ preview: PublicTeaserUser[];
25
+ featured: PublicTeaserUser[];
26
+ featuredHeadline: string | null;
27
+ network: NetworkOverlapPayload | null;
28
+ upsell: {
29
+ hasDeeperTiers: boolean;
30
+ cheapestTierName?: string;
31
+ } | null;
32
+ roster?: {
33
+ users: PublicTeaserUser[];
34
+ totalVisible: number;
35
+ hasMore: boolean;
36
+ cursor?: string;
37
+ };
38
+ viewer: {
39
+ rosterDepth: GuestListDepth;
40
+ isHost: boolean;
41
+ };
42
+ policy: {
43
+ effectiveMode: AttendeeDisplayMode;
44
+ };
45
+ /** Host-only: user IDs awaiting spotlight approval (guest-initiated) */
46
+ pendingFeaturedUserIds?: string[];
47
+ /** Host-only: user IDs with host-initiated featured invite pending accept */
48
+ pendingFeaturedInviteUserIds?: string[];
49
+ /** Viewer-only: pending featured invite for the authenticated viewer */
50
+ viewerFeaturedInvite?: {
51
+ bashEventId: string;
52
+ bashTitle: string;
53
+ hostName?: string;
54
+ } | null;
55
+ /** Host-only: per-guest visibility for roster management */
56
+ attendeeVisibilityByUserId?: Record<string, AttendeeVisibility>;
57
+ /** Event has public guest list enabled on bash detail */
58
+ attendeeListPublic?: boolean;
59
+ };
60
+ export type AttendeeRosterMeta = {
61
+ depth: GuestListDepth;
62
+ totalVisible?: number;
63
+ hasMore?: boolean;
64
+ cursor?: string;
65
+ };
66
+ export type EventModeInput = {
67
+ attendeeDisplayMode?: string | null;
68
+ showAttendees?: boolean | null;
69
+ };
70
+ export type GuestSurfacePolicyInput = {
71
+ eventMode: AttendeeDisplayMode;
72
+ isHost: boolean;
73
+ isAuthenticated: boolean;
74
+ viewerRosterDepth: GuestListDepth;
75
+ };
76
+ export type GuestSurfacePolicy = {
77
+ showCount: boolean;
78
+ showPreviewAvatars: boolean;
79
+ showFeatured: boolean;
80
+ showNetworkSlice: boolean;
81
+ rosterDepth: GuestListDepth;
82
+ previewLimit: number;
83
+ apiPreviewLimit: number;
84
+ effectiveMode: AttendeeDisplayMode;
85
+ };
86
+ /** Legacy showAttendees=false → Hidden; otherwise honour attendeeDisplayMode string. */
87
+ export declare function resolveEffectiveEventMode(event: EventModeInput): AttendeeDisplayMode;
88
+ export declare function compareGuestListDepth(a: GuestListDepth, b: GuestListDepth): number;
89
+ export declare function maxGuestListDepth(...depths: GuestListDepth[]): GuestListDepth;
90
+ /** Cap viewer tier depth by event mode for non-hosts. */
91
+ export declare function capRosterDepthForEventMode(viewerDepth: GuestListDepth, eventMode: AttendeeDisplayMode, isHost: boolean): GuestListDepth;
92
+ /** Whether the viewer may fetch the full host-style roster endpoint. */
93
+ export declare function viewerMayFetchFullRoster(input: {
94
+ isHost: boolean;
95
+ viewerRosterDepth: GuestListDepth;
96
+ }): boolean;
97
+ /** Public bash-detail teaser policy (Layer 1 + viewer depth cap). */
98
+ export declare function resolveGuestSurfacePolicy(input: GuestSurfacePolicyInput): GuestSurfacePolicy;
99
+ export type PreviewAttendeeRow = {
100
+ userId: string;
101
+ paidOn?: Date | string | null;
102
+ checkedInAt?: Date | string | null;
103
+ };
104
+ /** Featured first, then most recent activity, then stable userId. */
105
+ export declare function orderPreviewAttendeeIds(rows: PreviewAttendeeRow[], featuredUserIds: string[], limit: number): string[];
106
+ export declare function filterHiddenVisibilityUserIds(userIds: string[], visibilityByUserId: Map<string, AttendeeVisibility>, isHost: boolean): string[];
107
+ export declare function filterBlockedUserIds(userIds: string[], blockedIds: Set<string>): string[];
108
+ export declare function guestListDepthFromTierField(value: string | null | undefined): GuestListDepth;
109
+ export declare function computeUpsellFromTiers(tiers: Array<{
110
+ guestListDepth?: string | null;
111
+ title?: string | null;
112
+ price?: number | null;
113
+ }>, viewerDepth: GuestListDepth): GuestSurfacePayload["upsell"];
114
+ //# sourceMappingURL=guestSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guestSurface.d.ts","sourceRoot":"","sources":["../../src/utils/guestSurface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Curated guest visibility — shared policy resolver for API + bash-app.
3
+ * Three layers compose: event teaser policy, per-guest visibility, viewer roster depth.
4
+ */
5
+ const DEPTH_RANK = {
6
+ None: 0,
7
+ Partial: 1,
8
+ Full: 2,
9
+ };
10
+ /** Legacy showAttendees=false → Hidden; otherwise honour attendeeDisplayMode string. */
11
+ export function resolveEffectiveEventMode(event) {
12
+ const raw = event.attendeeDisplayMode;
13
+ if (raw === "CountOnly")
14
+ return "CountOnly";
15
+ if (raw === "NetworkOnly")
16
+ return "NetworkOnly";
17
+ if (raw === "Hidden")
18
+ return "Hidden";
19
+ if (event.showAttendees === false)
20
+ return "Hidden";
21
+ return "All";
22
+ }
23
+ export function compareGuestListDepth(a, b) {
24
+ return DEPTH_RANK[a] - DEPTH_RANK[b];
25
+ }
26
+ export function maxGuestListDepth(...depths) {
27
+ if (depths.length === 0)
28
+ return "None";
29
+ return depths.reduce((max, d) => compareGuestListDepth(d, max) > 0 ? d : max);
30
+ }
31
+ /** Cap viewer tier depth by event mode for non-hosts. */
32
+ export function capRosterDepthForEventMode(viewerDepth, eventMode, isHost) {
33
+ if (isHost)
34
+ return "Full";
35
+ if (eventMode === "Hidden")
36
+ return "None";
37
+ if (eventMode === "NetworkOnly")
38
+ return "None";
39
+ return viewerDepth;
40
+ }
41
+ /** Whether the viewer may fetch the full host-style roster endpoint. */
42
+ export function viewerMayFetchFullRoster(input) {
43
+ if (input.isHost)
44
+ return true;
45
+ return compareGuestListDepth(input.viewerRosterDepth, "Partial") >= 0;
46
+ }
47
+ /** Public bash-detail teaser policy (Layer 1 + viewer depth cap). */
48
+ export function resolveGuestSurfacePolicy(input) {
49
+ const { eventMode, isHost, isAuthenticated, viewerRosterDepth } = input;
50
+ const effectiveDepth = capRosterDepthForEventMode(viewerRosterDepth, eventMode, isHost);
51
+ if (eventMode === "Hidden" && !isHost) {
52
+ return {
53
+ showCount: false,
54
+ showPreviewAvatars: false,
55
+ showFeatured: false,
56
+ showNetworkSlice: false,
57
+ rosterDepth: "None",
58
+ previewLimit: 4,
59
+ apiPreviewLimit: 10,
60
+ effectiveMode: eventMode,
61
+ };
62
+ }
63
+ if (eventMode === "CountOnly" && !isHost) {
64
+ return {
65
+ showCount: true,
66
+ showPreviewAvatars: false,
67
+ showFeatured: false,
68
+ showNetworkSlice: isAuthenticated,
69
+ rosterDepth: effectiveDepth,
70
+ previewLimit: 4,
71
+ apiPreviewLimit: 10,
72
+ effectiveMode: eventMode,
73
+ };
74
+ }
75
+ const showCount = true;
76
+ const showPreviewAvatars = eventMode === "All" && !isHost
77
+ ? true
78
+ : eventMode === "All" && isHost
79
+ ? true
80
+ : false;
81
+ const showFeatured = (eventMode === "All" || isHost) && eventMode !== "CountOnly";
82
+ const showNetworkSlice = isAuthenticated &&
83
+ (eventMode === "All" ||
84
+ eventMode === "CountOnly" ||
85
+ eventMode === "NetworkOnly" ||
86
+ isHost);
87
+ return {
88
+ showCount,
89
+ showPreviewAvatars: showPreviewAvatars &&
90
+ eventMode !== "CountOnly" &&
91
+ eventMode !== "NetworkOnly",
92
+ showFeatured: showFeatured && eventMode !== "NetworkOnly",
93
+ showNetworkSlice,
94
+ rosterDepth: effectiveDepth,
95
+ previewLimit: 4,
96
+ apiPreviewLimit: 10,
97
+ effectiveMode: eventMode,
98
+ };
99
+ }
100
+ /** Featured first, then most recent activity, then stable userId. */
101
+ export function orderPreviewAttendeeIds(rows, featuredUserIds, limit) {
102
+ const featuredSet = new Set(featuredUserIds);
103
+ const byUser = new Map();
104
+ for (const row of rows) {
105
+ if (!row.userId)
106
+ continue;
107
+ const existing = byUser.get(row.userId);
108
+ if (!existing) {
109
+ byUser.set(row.userId, row);
110
+ continue;
111
+ }
112
+ const existingTs = activityTimestamp(existing);
113
+ const rowTs = activityTimestamp(row);
114
+ if (rowTs > existingTs)
115
+ byUser.set(row.userId, row);
116
+ }
117
+ const featuredOrdered = featuredUserIds.filter((id) => byUser.has(id));
118
+ const rest = [...byUser.entries()]
119
+ .filter(([id]) => !featuredSet.has(id))
120
+ .sort(([, a], [, b]) => {
121
+ const diff = activityTimestamp(b) - activityTimestamp(a);
122
+ if (diff !== 0)
123
+ return diff;
124
+ return a.userId.localeCompare(b.userId);
125
+ })
126
+ .map(([id]) => id);
127
+ return [...featuredOrdered, ...rest].slice(0, limit);
128
+ }
129
+ function activityTimestamp(row) {
130
+ const paid = row.paidOn != null ? new Date(row.paidOn).getTime() : 0;
131
+ const checked = row.checkedInAt != null
132
+ ? new Date(row.checkedInAt).getTime()
133
+ : 0;
134
+ return Math.max(paid, checked);
135
+ }
136
+ export function filterHiddenVisibilityUserIds(userIds, visibilityByUserId, isHost) {
137
+ if (isHost)
138
+ return userIds;
139
+ return userIds.filter((id) => {
140
+ const v = visibilityByUserId.get(id) ?? "Visible";
141
+ return v === "Visible" || v === "FeaturedPending";
142
+ // FeaturedInvited is hidden until the guest accepts
143
+ });
144
+ }
145
+ export function filterBlockedUserIds(userIds, blockedIds) {
146
+ return userIds.filter((id) => !blockedIds.has(id));
147
+ }
148
+ export function guestListDepthFromTierField(value) {
149
+ if (value === "Partial" || value === "Full")
150
+ return value;
151
+ return "None";
152
+ }
153
+ export function computeUpsellFromTiers(tiers, viewerDepth) {
154
+ const deeper = tiers.filter((t) => compareGuestListDepth(guestListDepthFromTierField(t.guestListDepth), "None") > 0);
155
+ if (deeper.length === 0 || compareGuestListDepth(viewerDepth, "Partial") >= 0) {
156
+ return null;
157
+ }
158
+ const sorted = [...deeper].sort((a, b) => (a.price ?? 0) - (b.price ?? 0));
159
+ return {
160
+ hasDeeperTiers: true,
161
+ cheapestTierName: sorted[0]?.title ?? undefined,
162
+ };
163
+ }
164
+ //# sourceMappingURL=guestSurface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guestSurface.js","sourceRoot":"","sources":["../../src/utils/guestSurface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Promotion Blast — on-site partner promos (time-boxed + geofence).
3
+ */
4
+ export type PromotionBlastPackageTierId = "starter" | "standard" | "premium";
5
+ export type PromotionBlastTriggerTypeId = "TIME_BOXED" | "GEOFENCE";
6
+ export interface PromotionBlastPackageTerms {
7
+ tierId: PromotionBlastPackageTierId;
8
+ maxBlasts: number;
9
+ maxPushRecipients?: number | null;
10
+ maxRadiusFeet: number;
11
+ allowedTriggerTypes: PromotionBlastTriggerTypeId[];
12
+ hostAccessFeeCents: number;
13
+ bashPlatformFeeCents: number;
14
+ templateId?: string | null;
15
+ }
16
+ /** Minutes before event start when partners may activate blasts. */
17
+ export declare const PROMOTION_BLAST_EVENT_WINDOW_BEFORE_MINUTES = 30;
18
+ /** Minutes after event end when partners may still activate. */
19
+ export declare const PROMOTION_BLAST_EVENT_WINDOW_AFTER_MINUTES = 30;
20
+ /** Max concurrently live partner promos per event. */
21
+ export declare const PROMOTION_BLAST_MAX_LIVE_PER_EVENT = 5;
22
+ /** Max promotional pushes per attendee per event (all partners). */
23
+ export declare const PROMOTION_BLAST_MAX_PUSHES_PER_USER_PER_EVENT = 3;
24
+ /** Min minutes between promo pushes to same user at same event. */
25
+ export declare const PROMOTION_BLAST_MIN_PUSH_INTERVAL_MINUTES = 15;
26
+ export declare const PROMOTION_BLAST_HEADLINE_MAX_LENGTH = 80;
27
+ export declare const PROMOTION_BLAST_BODY_MAX_LENGTH = 280;
28
+ export declare const PROMOTION_BLAST_CTA_MAX_LENGTH = 40;
29
+ export declare const PROMOTION_BLAST_DURATION_PRESETS_MINUTES: readonly [15, 30, 60];
30
+ export declare const PROMOTION_BLAST_RADIUS_PRESETS_FEET: readonly [100, 200, 500];
31
+ export declare const PROMOTION_BLAST_PACKAGES: Record<PromotionBlastPackageTierId, Omit<PromotionBlastPackageTerms, "hostAccessFeeCents" | "templateId">>;
32
+ export declare function promotionBlastPackageForTier(tierId: PromotionBlastPackageTierId, hostAccessFeeCents: number, templateId?: string | null): PromotionBlastPackageTerms;
33
+ export declare function promotionBlastPackageTotalCents(pkg: PromotionBlastPackageTerms): number;
34
+ export declare function promotionBlastPackageLabel(tierId: PromotionBlastPackageTierId): string;
35
+ export declare function isWithinPromotionBlastEventWindow(eventStart: Date, eventEnd: Date | null | undefined, now?: Date): boolean;
36
+ export declare function generatePromotionBlastConfirmationCode(): string;
37
+ export declare function promotionBlastDeepLinkPath(bashEventId: string, blastId: string): string;
38
+ //# sourceMappingURL=promotionBlastUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promotionBlastUtils.d.ts","sourceRoot":"","sources":["../../src/utils/promotionBlastUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,2BAA2B,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE7E,MAAM,MAAM,2BAA2B,GAAG,YAAY,GAAG,UAAU,CAAC;AAEpE,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,2BAA2B,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,2BAA2B,EAAE,CAAC;IACnD,kBAAkB,EAAE,MAAM,CAAC;IAC3B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,oEAAoE;AACpE,eAAO,MAAM,2CAA2C,KAAK,CAAC;AAE9D,gEAAgE;AAChE,eAAO,MAAM,0CAA0C,KAAK,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,oEAAoE;AACpE,eAAO,MAAM,6CAA6C,IAAI,CAAC;AAE/D,mEAAmE;AACnE,eAAO,MAAM,yCAAyC,KAAK,CAAC;AAE5D,eAAO,MAAM,mCAAmC,KAAK,CAAC;AACtD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AACnD,eAAO,MAAM,8BAA8B,KAAK,CAAC;AAEjD,eAAO,MAAM,wCAAwC,uBAAwB,CAAC;AAC9E,eAAO,MAAM,mCAAmC,0BAA2B,CAAC;AAE5E,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,2BAA2B,EAC3B,IAAI,CAAC,0BAA0B,EAAE,oBAAoB,GAAG,YAAY,CAAC,CA0BtE,CAAC;AAEF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,2BAA2B,EACnC,kBAAkB,EAAE,MAAM,EAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GACzB,0BAA0B,CAO5B;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,0BAA0B,GAAG,MAAM,CAEvF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,2BAA2B,GAAG,MAAM,CAWtF;AAED,wBAAgB,iCAAiC,CAC/C,UAAU,EAAE,IAAI,EAChB,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,SAAS,EACjC,GAAG,GAAE,IAAiB,GACrB,OAAO,CAQT;AAED,wBAAgB,sCAAsC,IAAI,MAAM,CAO/D;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvF"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Promotion Blast — on-site partner promos (time-boxed + geofence).
3
+ */
4
+ /** Minutes before event start when partners may activate blasts. */
5
+ export const PROMOTION_BLAST_EVENT_WINDOW_BEFORE_MINUTES = 30;
6
+ /** Minutes after event end when partners may still activate. */
7
+ export const PROMOTION_BLAST_EVENT_WINDOW_AFTER_MINUTES = 30;
8
+ /** Max concurrently live partner promos per event. */
9
+ export const PROMOTION_BLAST_MAX_LIVE_PER_EVENT = 5;
10
+ /** Max promotional pushes per attendee per event (all partners). */
11
+ export const PROMOTION_BLAST_MAX_PUSHES_PER_USER_PER_EVENT = 3;
12
+ /** Min minutes between promo pushes to same user at same event. */
13
+ export const PROMOTION_BLAST_MIN_PUSH_INTERVAL_MINUTES = 15;
14
+ export const PROMOTION_BLAST_HEADLINE_MAX_LENGTH = 80;
15
+ export const PROMOTION_BLAST_BODY_MAX_LENGTH = 280;
16
+ export const PROMOTION_BLAST_CTA_MAX_LENGTH = 40;
17
+ export const PROMOTION_BLAST_DURATION_PRESETS_MINUTES = [15, 30, 60];
18
+ export const PROMOTION_BLAST_RADIUS_PRESETS_FEET = [100, 200, 500];
19
+ export const PROMOTION_BLAST_PACKAGES = {
20
+ starter: {
21
+ tierId: "starter",
22
+ maxBlasts: 1,
23
+ maxPushRecipients: null,
24
+ maxRadiusFeet: 200,
25
+ allowedTriggerTypes: ["TIME_BOXED"],
26
+ bashPlatformFeeCents: 500,
27
+ },
28
+ standard: {
29
+ tierId: "standard",
30
+ maxBlasts: 3,
31
+ maxPushRecipients: null,
32
+ maxRadiusFeet: 500,
33
+ allowedTriggerTypes: ["TIME_BOXED", "GEOFENCE"],
34
+ bashPlatformFeeCents: 1200,
35
+ },
36
+ premium: {
37
+ tierId: "premium",
38
+ maxBlasts: 999,
39
+ maxPushRecipients: null,
40
+ maxRadiusFeet: 500,
41
+ allowedTriggerTypes: ["TIME_BOXED", "GEOFENCE"],
42
+ bashPlatformFeeCents: 2500,
43
+ },
44
+ };
45
+ export function promotionBlastPackageForTier(tierId, hostAccessFeeCents, templateId) {
46
+ const base = PROMOTION_BLAST_PACKAGES[tierId];
47
+ return {
48
+ ...base,
49
+ hostAccessFeeCents,
50
+ templateId: templateId ?? null,
51
+ };
52
+ }
53
+ export function promotionBlastPackageTotalCents(pkg) {
54
+ return pkg.hostAccessFeeCents + pkg.bashPlatformFeeCents;
55
+ }
56
+ export function promotionBlastPackageLabel(tierId) {
57
+ switch (tierId) {
58
+ case "starter":
59
+ return "Starter — 1 time-boxed blast";
60
+ case "standard":
61
+ return "Standard — 3 blasts + geofence";
62
+ case "premium":
63
+ return "Premium — unlimited blasts + geofence";
64
+ default:
65
+ return tierId;
66
+ }
67
+ }
68
+ export function isWithinPromotionBlastEventWindow(eventStart, eventEnd, now = new Date()) {
69
+ const windowStart = new Date(eventStart);
70
+ windowStart.setMinutes(windowStart.getMinutes() - PROMOTION_BLAST_EVENT_WINDOW_BEFORE_MINUTES);
71
+ const windowEnd = eventEnd
72
+ ? new Date(eventEnd)
73
+ : new Date(eventStart.getTime() + 4 * 60 * 60 * 1000);
74
+ windowEnd.setMinutes(windowEnd.getMinutes() + PROMOTION_BLAST_EVENT_WINDOW_AFTER_MINUTES);
75
+ return now >= windowStart && now <= windowEnd;
76
+ }
77
+ export function generatePromotionBlastConfirmationCode() {
78
+ const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
79
+ let code = "";
80
+ for (let i = 0; i < 6; i++) {
81
+ code += chars[Math.floor(Math.random() * chars.length)];
82
+ }
83
+ return code;
84
+ }
85
+ export function promotionBlastDeepLinkPath(bashEventId, blastId) {
86
+ return `/bash/${encodeURIComponent(bashEventId)}?tab=promotions&blast=${encodeURIComponent(blastId)}`;
87
+ }
88
+ //# sourceMappingURL=promotionBlastUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promotionBlastUtils.js","sourceRoot":"","sources":["../../src/utils/promotionBlastUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=defaultOfferAmountUtils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultOfferAmountUtils.test.d.ts","sourceRoot":"","sources":["../../../../src/utils/service/__tests__/defaultOfferAmountUtils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { calcLegacyRateEstimateCents, computeBashEventDurationHours, getDefaultOfferAmountCents, isBulkHostOfferEligible, } from "../defaultOfferAmountUtils.js";
2
+ describe("calcLegacyRateEstimateCents", () => {
3
+ it("uses flat rate when set", () => {
4
+ expect(calcLegacyRateEstimateCents({ flatRateCents: 50_000 }, 4)).toBe(50_000);
5
+ });
6
+ it("uses daily rate for 8+ hour events", () => {
7
+ expect(calcLegacyRateEstimateCents({ hourlyRateCents: 15_000, dailyRateCents: 50_000 }, 8)).toBe(50_000);
8
+ });
9
+ it("uses hourly × duration for shorter events", () => {
10
+ expect(calcLegacyRateEstimateCents({ hourlyRateCents: 15_000, dailyRateCents: 50_000 }, 4)).toBe(60_000);
11
+ });
12
+ });
13
+ describe("computeBashEventDurationHours", () => {
14
+ it("returns hours between start and end", () => {
15
+ expect(computeBashEventDurationHours("2026-06-01T18:00:00.000Z", "2026-06-01T22:00:00.000Z")).toBe(4);
16
+ });
17
+ it("defaults to 1 when dates missing", () => {
18
+ expect(computeBashEventDurationHours(null, null)).toBe(1);
19
+ });
20
+ });
21
+ describe("getDefaultOfferAmountCents", () => {
22
+ it("prefers unified HOURLY model with duration", () => {
23
+ expect(getDefaultOfferAmountCents({
24
+ service: {
25
+ entertainmentService: {
26
+ pricingModel: "HOURLY",
27
+ baseRateCents: 20_000,
28
+ },
29
+ },
30
+ durationHours: 3,
31
+ })).toBe(60_000);
32
+ });
33
+ it("falls back to legacy general rates", () => {
34
+ expect(getDefaultOfferAmountCents({
35
+ service: {
36
+ serviceRatesAssociation: {
37
+ serviceGeneralRates: { dailyRateCents: 75_000 },
38
+ },
39
+ },
40
+ durationHours: 10,
41
+ })).toBe(75_000);
42
+ });
43
+ it("computes PER_ATTENDEE from expected guests", () => {
44
+ expect(getDefaultOfferAmountCents({
45
+ service: {
46
+ eventService: {
47
+ pricingModel: "PER_ATTENDEE",
48
+ baseRateCents: 500,
49
+ },
50
+ },
51
+ durationHours: 4,
52
+ expectedAttendees: 100,
53
+ })).toBe(50_000);
54
+ });
55
+ });
56
+ describe("isBulkHostOfferEligible", () => {
57
+ it("rejects participation-fee services", () => {
58
+ expect(isBulkHostOfferEligible(50_000, true)).toBe(false);
59
+ });
60
+ it("requires a positive amount", () => {
61
+ expect(isBulkHostOfferEligible(0, false)).toBe(false);
62
+ expect(isBulkHostOfferEligible(25_000, false)).toBe(true);
63
+ });
64
+ });
65
+ //# sourceMappingURL=defaultOfferAmountUtils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultOfferAmountUtils.test.js","sourceRoot":"","sources":["../../../../src/utils/service/__tests__/defaultOfferAmountUtils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { type UnifiedPricingSourceCandidates } from "./unifiedPricingResolver.js";
2
+ import { SERVICE_DAILY_RATE_HOURS_MIN } from "./serviceRateUtils.js";
3
+ export { SERVICE_DAILY_RATE_HOURS_MIN };
4
+ export interface LegacyGeneralRatesShape {
5
+ flatRateCents?: number | null;
6
+ hourlyRateCents?: number | null;
7
+ dailyRateCents?: number | null;
8
+ }
9
+ export type DefaultOfferAmountServiceShape = UnifiedPricingSourceCandidates & {
10
+ serviceRatesAssociation?: {
11
+ serviceGeneralRates?: LegacyGeneralRatesShape | null;
12
+ } | null;
13
+ };
14
+ export interface DefaultOfferAmountParams {
15
+ service: DefaultOfferAmountServiceShape;
16
+ durationHours: number;
17
+ expectedAttendees?: number | null;
18
+ }
19
+ /** Event length in hours; defaults to 1 when dates are missing or invalid. */
20
+ export declare function computeBashEventDurationHours(startDateTime: Date | string | null | undefined, endDateTime: Date | string | null | undefined): number;
21
+ /** Legacy published-rate estimate (flat → daily if 8+ hrs → hourly × duration). */
22
+ export declare function calcLegacyRateEstimateCents(rates: LegacyGeneralRatesShape | null | undefined, durationHours: number): number;
23
+ /**
24
+ * Returns the suggested opening offer in USD cents for this bash, or 0 when
25
+ * no computable rate exists (bulk send should skip those services).
26
+ */
27
+ export declare function getDefaultOfferAmountCents(params: DefaultOfferAmountParams): number;
28
+ export declare function formatOfferAmountDollars(cents: number): string;
29
+ /** Host → provider bulk offers only when a positive USD default exists. */
30
+ export declare function isBulkHostOfferEligible(amountCents: number, isParticipationFeeService: boolean): boolean;
31
+ export declare const BULK_OFFER_MAX_COUNT = 10;
32
+ //# sourceMappingURL=defaultOfferAmountUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaultOfferAmountUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/service/defaultOfferAmountUtils.ts"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,8BAA8B,EACpC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAAE,4BAA4B,EAAE,CAAC;AAExC,MAAM,WAAW,uBAAuB;IACtC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,MAAM,8BAA8B,GAAG,8BAA8B,GAAG;IAC5E,uBAAuB,CAAC,EAAE;QACxB,mBAAmB,CAAC,EAAE,uBAAuB,GAAG,IAAI,CAAC;KACtD,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,8BAA8B,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,8EAA8E;AAC9E,wBAAgB,6BAA6B,CAC3C,aAAa,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/C,WAAW,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5C,MAAM,CAOR;AAED,mFAAmF;AACnF,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,uBAAuB,GAAG,IAAI,GAAG,SAAS,EACjD,aAAa,EAAE,MAAM,GACpB,MAAM,CAeR;AAyDD;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,wBAAwB,GAC/B,MAAM,CA0BR;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,2EAA2E;AAC3E,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,yBAAyB,EAAE,OAAO,GACjC,OAAO,CAET;AAED,eAAO,MAAM,oBAAoB,KAAK,CAAC"}