@bash-app/bash-common 30.214.0 → 30.216.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/definitions.d.ts +9 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +2 -0
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +100 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +2 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/legalTemplates.d.ts +11 -0
- package/dist/legalTemplates.d.ts.map +1 -0
- package/dist/legalTemplates.js +19 -0
- package/dist/legalTemplates.js.map +1 -0
- package/dist/utmAttribution.d.ts +29 -0
- package/dist/utmAttribution.d.ts.map +1 -0
- package/dist/utmAttribution.js +124 -0
- package/dist/utmAttribution.js.map +1 -0
- package/package.json +1 -1
- package/prisma/schema.prisma +72 -0
- package/src/definitions.ts +10 -2
- package/src/extendedSchemas.ts +2 -0
- package/src/index.ts +2 -0
- package/src/legalTemplates.ts +21 -0
- package/src/utmAttribution.ts +142 -0
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default copy for host opt-in photo/video consent at event checkout.
|
|
3
|
+
* When `BashEvent.photoReleaseText` is null and `photoReleaseEnabled` is true, use this text.
|
|
4
|
+
* Not legal advice; hosts may supply custom text via the wizard.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_PHOTO_RELEASE_TEXT = "By attending this event, you understand that photography, audio recording, and video recording may occur. You consent to being photographed, filmed, and/or recorded, and you grant the event organizer and its licensees the right to use your name, image, likeness, and voice in any media (including for promotion of this and future events), without payment or other compensation, unless prohibited by law.\n\nIf you do not wish to appear in promotional materials, contact the event organizer before or during the event. For minors, a parent or guardian must agree to this consent.";
|
|
7
|
+
/**
|
|
8
|
+
* Effective photo release text for display (wizard preview, event page, checkout).
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPhotoReleaseDisplayText(photoReleaseText: string | null | undefined): string;
|
|
11
|
+
//# sourceMappingURL=legalTemplates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legalTemplates.d.ts","sourceRoot":"","sources":["../src/legalTemplates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,ukBAEqI,CAAC;AAE7K;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC1C,MAAM,CAMR"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default copy for host opt-in photo/video consent at event checkout.
|
|
3
|
+
* When `BashEvent.photoReleaseText` is null and `photoReleaseEnabled` is true, use this text.
|
|
4
|
+
* Not legal advice; hosts may supply custom text via the wizard.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_PHOTO_RELEASE_TEXT = `By attending this event, you understand that photography, audio recording, and video recording may occur. You consent to being photographed, filmed, and/or recorded, and you grant the event organizer and its licensees the right to use your name, image, likeness, and voice in any media (including for promotion of this and future events), without payment or other compensation, unless prohibited by law.
|
|
7
|
+
|
|
8
|
+
If you do not wish to appear in promotional materials, contact the event organizer before or during the event. For minors, a parent or guardian must agree to this consent.`;
|
|
9
|
+
/**
|
|
10
|
+
* Effective photo release text for display (wizard preview, event page, checkout).
|
|
11
|
+
*/
|
|
12
|
+
export function getPhotoReleaseDisplayText(photoReleaseText) {
|
|
13
|
+
const trimmed = photoReleaseText?.trim();
|
|
14
|
+
if (trimmed) {
|
|
15
|
+
return trimmed;
|
|
16
|
+
}
|
|
17
|
+
return DEFAULT_PHOTO_RELEASE_TEXT;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=legalTemplates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legalTemplates.js","sourceRoot":"","sources":["../src/legalTemplates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;;4KAEkI,CAAC;AAE7K;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,gBAA2C;IAE3C,MAAM,OAAO,GAAG,gBAAgB,EAAE,IAAI,EAAE,CAAC;IACzC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,0BAA0B,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTM / marketing attribution: first-touch capture in sessionStorage, Stripe metadata keys,
|
|
3
|
+
* and persistence on Ticket rows.
|
|
4
|
+
*/
|
|
5
|
+
export interface UtmFields {
|
|
6
|
+
utmSource?: string;
|
|
7
|
+
utmMedium?: string;
|
|
8
|
+
utmCampaign?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Normalize optional UTM strings from API args (Stripe checkout / payment intent body). */
|
|
11
|
+
export declare function utmFieldsFromCheckoutArgs(args: UtmFields): UtmFields | undefined;
|
|
12
|
+
/** Stripe Checkout / PaymentIntent metadata (snake_case keys). */
|
|
13
|
+
export declare function utmFieldsToStripeMetadata(utm: UtmFields | undefined): Record<string, string>;
|
|
14
|
+
/** Prisma `Ticket` columns for persisted UTM (omit empty). */
|
|
15
|
+
export declare function utmFieldsToTicketColumns(utm: UtmFields): {
|
|
16
|
+
utmSource?: string;
|
|
17
|
+
utmMedium?: string;
|
|
18
|
+
utmCampaign?: string;
|
|
19
|
+
};
|
|
20
|
+
/** Read UTM from Stripe object metadata into Prisma Ticket field names. */
|
|
21
|
+
export declare function utmFieldsFromStripeMetadata(md: Record<string, string | undefined> | null | undefined): UtmFields;
|
|
22
|
+
/**
|
|
23
|
+
* First-touch per session: store each UTM component the first time it appears in the URL.
|
|
24
|
+
* Call on route changes so client-side navigations to ?utm_*= still capture.
|
|
25
|
+
*/
|
|
26
|
+
export declare function captureFirstTouchUtmFromUrlSearchParams(search: string): void;
|
|
27
|
+
/** Values previously captured for this tab session (for checkout API bodies). */
|
|
28
|
+
export declare function getStoredUtmFields(): UtmFields;
|
|
29
|
+
//# sourceMappingURL=utmAttribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utmAttribution.d.ts","sourceRoot":"","sources":["../src/utmAttribution.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,4FAA4F;AAC5F,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAkBhF;AAED,kEAAkE;AAClE,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAe5F;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,SAAS,GAAG;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAYA;AAED,2EAA2E;AAC3E,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GACxD,SAAS,CAkBX;AAED;;;GAGG;AACH,wBAAgB,uCAAuC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAkB5E;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,IAAI,SAAS,CAkB9C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTM / marketing attribution: first-touch capture in sessionStorage, Stripe metadata keys,
|
|
3
|
+
* and persistence on Ticket rows.
|
|
4
|
+
*/
|
|
5
|
+
const SESSION_KEYS = {
|
|
6
|
+
utmSource: "bash_utm_source",
|
|
7
|
+
utmMedium: "bash_utm_medium",
|
|
8
|
+
utmCampaign: "bash_utm_campaign",
|
|
9
|
+
};
|
|
10
|
+
/** Normalize optional UTM strings from API args (Stripe checkout / payment intent body). */
|
|
11
|
+
export function utmFieldsFromCheckoutArgs(args) {
|
|
12
|
+
const s = args.utmSource?.trim();
|
|
13
|
+
const m = args.utmMedium?.trim();
|
|
14
|
+
const c = args.utmCampaign?.trim();
|
|
15
|
+
if (!s && !m && !c) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const out = {};
|
|
19
|
+
if (s) {
|
|
20
|
+
out.utmSource = s.slice(0, 500);
|
|
21
|
+
}
|
|
22
|
+
if (m) {
|
|
23
|
+
out.utmMedium = m.slice(0, 500);
|
|
24
|
+
}
|
|
25
|
+
if (c) {
|
|
26
|
+
out.utmCampaign = c.slice(0, 500);
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/** Stripe Checkout / PaymentIntent metadata (snake_case keys). */
|
|
31
|
+
export function utmFieldsToStripeMetadata(utm) {
|
|
32
|
+
if (!utm) {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
const out = {};
|
|
36
|
+
if (utm.utmSource) {
|
|
37
|
+
out.utm_source = utm.utmSource;
|
|
38
|
+
}
|
|
39
|
+
if (utm.utmMedium) {
|
|
40
|
+
out.utm_medium = utm.utmMedium;
|
|
41
|
+
}
|
|
42
|
+
if (utm.utmCampaign) {
|
|
43
|
+
out.utm_campaign = utm.utmCampaign;
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
/** Prisma `Ticket` columns for persisted UTM (omit empty). */
|
|
48
|
+
export function utmFieldsToTicketColumns(utm) {
|
|
49
|
+
const out = {};
|
|
50
|
+
if (utm.utmSource) {
|
|
51
|
+
out.utmSource = utm.utmSource;
|
|
52
|
+
}
|
|
53
|
+
if (utm.utmMedium) {
|
|
54
|
+
out.utmMedium = utm.utmMedium;
|
|
55
|
+
}
|
|
56
|
+
if (utm.utmCampaign) {
|
|
57
|
+
out.utmCampaign = utm.utmCampaign;
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
/** Read UTM from Stripe object metadata into Prisma Ticket field names. */
|
|
62
|
+
export function utmFieldsFromStripeMetadata(md) {
|
|
63
|
+
if (!md) {
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
const s = md.utm_source?.trim();
|
|
67
|
+
const m = md.utm_medium?.trim();
|
|
68
|
+
const c = md.utm_campaign?.trim();
|
|
69
|
+
const out = {};
|
|
70
|
+
if (s) {
|
|
71
|
+
out.utmSource = s.slice(0, 500);
|
|
72
|
+
}
|
|
73
|
+
if (m) {
|
|
74
|
+
out.utmMedium = m.slice(0, 500);
|
|
75
|
+
}
|
|
76
|
+
if (c) {
|
|
77
|
+
out.utmCampaign = c.slice(0, 500);
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* First-touch per session: store each UTM component the first time it appears in the URL.
|
|
83
|
+
* Call on route changes so client-side navigations to ?utm_*= still capture.
|
|
84
|
+
*/
|
|
85
|
+
export function captureFirstTouchUtmFromUrlSearchParams(search) {
|
|
86
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined") {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const q = search.startsWith("?") ? search.slice(1) : search;
|
|
90
|
+
const params = new URLSearchParams(q);
|
|
91
|
+
const pairs = [
|
|
92
|
+
["utmSource", "utm_source"],
|
|
93
|
+
["utmMedium", "utm_medium"],
|
|
94
|
+
["utmCampaign", "utm_campaign"],
|
|
95
|
+
];
|
|
96
|
+
for (const [storageField, paramName] of pairs) {
|
|
97
|
+
const v = params.get(paramName)?.trim();
|
|
98
|
+
const key = SESSION_KEYS[storageField];
|
|
99
|
+
if (v && !sessionStorage.getItem(key)) {
|
|
100
|
+
sessionStorage.setItem(key, v.slice(0, 500));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** Values previously captured for this tab session (for checkout API bodies). */
|
|
105
|
+
export function getStoredUtmFields() {
|
|
106
|
+
if (typeof sessionStorage === "undefined") {
|
|
107
|
+
return {};
|
|
108
|
+
}
|
|
109
|
+
const s = sessionStorage.getItem(SESSION_KEYS.utmSource)?.trim();
|
|
110
|
+
const m = sessionStorage.getItem(SESSION_KEYS.utmMedium)?.trim();
|
|
111
|
+
const c = sessionStorage.getItem(SESSION_KEYS.utmCampaign)?.trim();
|
|
112
|
+
const out = {};
|
|
113
|
+
if (s) {
|
|
114
|
+
out.utmSource = s;
|
|
115
|
+
}
|
|
116
|
+
if (m) {
|
|
117
|
+
out.utmMedium = m;
|
|
118
|
+
}
|
|
119
|
+
if (c) {
|
|
120
|
+
out.utmCampaign = c;
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=utmAttribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utmAttribution.js","sourceRoot":"","sources":["../src/utmAttribution.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/prisma/schema.prisma
CHANGED
|
@@ -615,6 +615,10 @@ model BashEvent {
|
|
|
615
615
|
waiverUrl String?
|
|
616
616
|
waiverRequired Boolean @default(false)
|
|
617
617
|
waiverDisplayType String? @default("inline")
|
|
618
|
+
/// Host opt-in: show photo/video consent at checkout; null photoReleaseText = platform default template
|
|
619
|
+
photoReleaseEnabled Boolean @default(false)
|
|
620
|
+
photoReleaseRequired Boolean @default(true)
|
|
621
|
+
photoReleaseText String? @db.Text
|
|
618
622
|
targetAudienceId String? @unique
|
|
619
623
|
amountOfGuestsId String? @unique
|
|
620
624
|
vibe String?
|
|
@@ -793,6 +797,7 @@ model BashEvent {
|
|
|
793
797
|
// Per-event referral rewards
|
|
794
798
|
eventReferralRewards EventReferralReward[]
|
|
795
799
|
eventReferrals EventReferral[]
|
|
800
|
+
bashEventDonations BashEventDonation[]
|
|
796
801
|
|
|
797
802
|
// User night itineraries (events in user's "My Night" plan)
|
|
798
803
|
userItineraryItems UserItineraryItem[]
|
|
@@ -1316,6 +1321,8 @@ model Ticket {
|
|
|
1316
1321
|
waitlistJoinedAt DateTime?
|
|
1317
1322
|
waitlistNotifiedAt DateTime?
|
|
1318
1323
|
waitlistExpiresAt DateTime?
|
|
1324
|
+
/** Set when we send the "your waitlist window expires soon" reminder (once per ticket). */
|
|
1325
|
+
waitlistReminderSentAt DateTime?
|
|
1319
1326
|
refundRequestedAt DateTime? // Set when RefundPending; cleared once refund processes
|
|
1320
1327
|
checkInLocation String?
|
|
1321
1328
|
checkOutLocation String?
|
|
@@ -1325,12 +1332,19 @@ model Ticket {
|
|
|
1325
1332
|
lastValidationAttempt DateTime?
|
|
1326
1333
|
lastValidatedBy String?
|
|
1327
1334
|
waitlistUserId String?
|
|
1335
|
+
/// Rotated when ticket is transferred; QR payload must match for check-in (null = legacy tickets, no strict check).
|
|
1336
|
+
qrToken String?
|
|
1328
1337
|
|
|
1329
1338
|
// BashPoints Purchase Tracking
|
|
1330
1339
|
purchaseType String? // "USD", "BashPoints", "Free", "Comp"
|
|
1331
1340
|
pointsPaid Int? // BashPoints amount paid (if purchaseType="BashPoints")
|
|
1332
1341
|
stripePurchaseId String? // Stripe payment ID (if purchaseType="USD")
|
|
1333
1342
|
|
|
1343
|
+
// Marketing attribution (from landing URL → sessionStorage → Stripe metadata → ticket row)
|
|
1344
|
+
utmSource String?
|
|
1345
|
+
utmMedium String?
|
|
1346
|
+
utmCampaign String?
|
|
1347
|
+
|
|
1334
1348
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id])
|
|
1335
1349
|
checkout Checkout? @relation(fields: [checkoutId], references: [id])
|
|
1336
1350
|
forUser User? @relation("TicketsISent", fields: [forUserId], references: [id])
|
|
@@ -1340,6 +1354,7 @@ model Ticket {
|
|
|
1340
1354
|
waitlistUser User? @relation("TicketsOnWaitlist", fields: [waitlistUserId], references: [id])
|
|
1341
1355
|
metadata TicketMetadata[]
|
|
1342
1356
|
transfers TicketTransfer[]
|
|
1357
|
+
transferInvite TicketTransferInvite?
|
|
1343
1358
|
appliedDiscounts AppliedDiscount[] // NEW - Discounts applied to this ticket
|
|
1344
1359
|
eventReferral EventReferral? // When this ticket was purchased via a referral link
|
|
1345
1360
|
|
|
@@ -1361,6 +1376,33 @@ model TicketTransfer {
|
|
|
1361
1376
|
@@index([ticketId])
|
|
1362
1377
|
}
|
|
1363
1378
|
|
|
1379
|
+
enum TicketTransferInviteStatus {
|
|
1380
|
+
PENDING
|
|
1381
|
+
ACCEPTED
|
|
1382
|
+
DECLINED
|
|
1383
|
+
EXPIRED
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
/// Pending peer-to-peer transfer; completes into `TicketTransfer` on accept.
|
|
1387
|
+
model TicketTransferInvite {
|
|
1388
|
+
id String @id @default(cuid())
|
|
1389
|
+
ticketId String @unique
|
|
1390
|
+
fromUserId String
|
|
1391
|
+
toEmail String?
|
|
1392
|
+
toUserId String?
|
|
1393
|
+
token String @unique
|
|
1394
|
+
status TicketTransferInviteStatus @default(PENDING)
|
|
1395
|
+
expiresAt DateTime
|
|
1396
|
+
createdAt DateTime @default(now())
|
|
1397
|
+
|
|
1398
|
+
ticket Ticket @relation(fields: [ticketId], references: [id], onDelete: Cascade)
|
|
1399
|
+
fromUser User @relation("TicketTransferInviteFrom", fields: [fromUserId], references: [id])
|
|
1400
|
+
invitedUser User? @relation("TicketTransferInviteToUser", fields: [toUserId], references: [id])
|
|
1401
|
+
|
|
1402
|
+
@@index([token])
|
|
1403
|
+
@@index([fromUserId])
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1364
1406
|
model TicketMetadata {
|
|
1365
1407
|
id String @id @default(cuid())
|
|
1366
1408
|
ticketId String
|
|
@@ -1373,6 +1415,27 @@ model TicketMetadata {
|
|
|
1373
1415
|
@@index([ticketId])
|
|
1374
1416
|
}
|
|
1375
1417
|
|
|
1418
|
+
/// Stripe donation to an event (Checkout session or PaymentIntent); includes optional UTM attribution.
|
|
1419
|
+
model BashEventDonation {
|
|
1420
|
+
id String @id @default(cuid())
|
|
1421
|
+
bashEventId String
|
|
1422
|
+
donorId String?
|
|
1423
|
+
donorEmail String?
|
|
1424
|
+
amountCents Int
|
|
1425
|
+
stripeCheckoutSessionId String? @unique
|
|
1426
|
+
stripePaymentIntentId String? @unique
|
|
1427
|
+
utmSource String?
|
|
1428
|
+
utmMedium String?
|
|
1429
|
+
utmCampaign String?
|
|
1430
|
+
createdAt DateTime @default(now())
|
|
1431
|
+
|
|
1432
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
1433
|
+
donor User? @relation(fields: [donorId], references: [id], onDelete: Cascade)
|
|
1434
|
+
|
|
1435
|
+
@@index([bashEventId])
|
|
1436
|
+
@@index([donorId])
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1376
1439
|
model unusedModelButNeededForSomeTypesToBeDefinedForTypescript {
|
|
1377
1440
|
id String @id @default(cuid())
|
|
1378
1441
|
doNotUseVibeEnum BashEventVibeTags @default(Wild)
|
|
@@ -1607,6 +1670,9 @@ model Review {
|
|
|
1607
1670
|
bashEventId String
|
|
1608
1671
|
createdAt DateTime @default(now())
|
|
1609
1672
|
updatedAt DateTime @updatedAt
|
|
1673
|
+
/// Public reply from the event host (service provider) to the reviewer.
|
|
1674
|
+
hostReplyText String? @db.Text
|
|
1675
|
+
hostReplyAt DateTime?
|
|
1610
1676
|
comments BashComment[]
|
|
1611
1677
|
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
1612
1678
|
creator User @relation(fields: [creatorId], references: [id], onDelete: Cascade)
|
|
@@ -1724,6 +1790,8 @@ model User {
|
|
|
1724
1790
|
birthdayReminderEnabled Boolean @default(false)
|
|
1725
1791
|
birthdayReminderDaysAdvance Int @default(7)
|
|
1726
1792
|
birthdayCategories String[] @default([]) // e.g. restaurant, coffee, dessert
|
|
1793
|
+
/// Calendar year when we last sent the "your birthday month freebies" reminder (cron on 1st of month).
|
|
1794
|
+
birthdayMonthReminderSentYear Int?
|
|
1727
1795
|
idDocumentUrl String? // Optional: secure ID upload for verification
|
|
1728
1796
|
gender Gender?
|
|
1729
1797
|
sex Sex?
|
|
@@ -1905,9 +1973,12 @@ model User {
|
|
|
1905
1973
|
stripeAccounts StripeAccount[]
|
|
1906
1974
|
ticketsISent Ticket[] @relation("TicketsISent")
|
|
1907
1975
|
ticketsIOwn Ticket[] @relation("TicketsIOwn")
|
|
1976
|
+
bashEventDonations BashEventDonation[]
|
|
1908
1977
|
ticketsOnWaitlist Ticket[] @relation("TicketsOnWaitlist")
|
|
1909
1978
|
transfersFrom TicketTransfer[] @relation("TransfersFrom")
|
|
1910
1979
|
transfersTo TicketTransfer[] @relation("TransfersTo")
|
|
1980
|
+
ticketTransferInvitesFrom TicketTransferInvite[] @relation("TicketTransferInviteFrom")
|
|
1981
|
+
ticketTransferInvitesToUser TicketTransferInvite[] @relation("TicketTransferInviteToUser")
|
|
1911
1982
|
unblocksReceived UnblockedUserHistory[] @relation("UserUnblocksReceived")
|
|
1912
1983
|
unblocksCreated UnblockedUserHistory[] @relation("UserUnblocksMade")
|
|
1913
1984
|
suspendedBy User? @relation("SuspendedUsers", fields: [suspendedById], references: [id])
|
|
@@ -4075,6 +4146,7 @@ enum NotificationType {
|
|
|
4075
4146
|
HostSalesAccelerating // Host: "Your event sales increased 38% today"
|
|
4076
4147
|
HostTopPromoter // Host: "Top promoter: Alex (6 tickets today)"
|
|
4077
4148
|
HostSalesSlowing // Host: "Sales slowed today. Try sharing your event."
|
|
4149
|
+
TicketSold // Host: a ticket was purchased for your event (debounced in webhook)
|
|
4078
4150
|
}
|
|
4079
4151
|
|
|
4080
4152
|
enum NotificationPriority {
|
package/src/definitions.ts
CHANGED
|
@@ -21,6 +21,7 @@ import { ApiServiceCantBookReason } from "./utils/service/apiServiceBookingApiUt
|
|
|
21
21
|
import { ServiceAttendeeOption } from "./utils/service/attendeeOptionUtils.js";
|
|
22
22
|
import { FrontendServiceGetPriceToBookResult } from "./utils/service/frontendServiceBookingUtils.js";
|
|
23
23
|
import { ServiceSubscriptionTier } from "./utils/userSubscriptionUtils.js";
|
|
24
|
+
import type { UtmFields } from "./utmAttribution.js";
|
|
24
25
|
|
|
25
26
|
export const PASSWORD_MIN_LENGTH = 8 as const;
|
|
26
27
|
export const PASSWORD_REQUIREMENTS_REGEX = new RegExp(
|
|
@@ -259,6 +260,9 @@ export const SERVICE_BOOKING_DETAILS_SERVICE_VIEW_URL_PAGE =
|
|
|
259
260
|
"/service/${serviceId}/${serviceType}/${specificId}/booking/${bookingId}/serviceView" as const;
|
|
260
261
|
|
|
261
262
|
export const VERIFICATION_RETURN_URL = `/sign-up` as const;
|
|
263
|
+
|
|
264
|
+
/** Stripe Identity hosted flow returns here (see `createStripeVerificationSession`). */
|
|
265
|
+
export const STRIPE_IDENTITY_RETURN_URL = `/verify-id` as const;
|
|
262
266
|
export const MY_SERVICES_URL = "/my-services" as const;
|
|
263
267
|
export const BASH_DETAIL_URL = `/bash` as const;
|
|
264
268
|
export const BASH_DETAIL_URL_PATTERN = `/bash/$bashEventIdSlug` as const;
|
|
@@ -684,7 +688,7 @@ export interface StripePaymentMethod {
|
|
|
684
688
|
};
|
|
685
689
|
}
|
|
686
690
|
|
|
687
|
-
export interface StripeCreateBashEventTicketsCheckoutSessionArgs {
|
|
691
|
+
export interface StripeCreateBashEventTicketsCheckoutSessionArgs extends UtmFields {
|
|
688
692
|
bashEventId: string;
|
|
689
693
|
currency: string;
|
|
690
694
|
paymentMethodType: string;
|
|
@@ -705,11 +709,15 @@ export interface StripeCreateBashEventTicketsCheckoutSessionArgs {
|
|
|
705
709
|
attributionRef?: string;
|
|
706
710
|
}
|
|
707
711
|
|
|
708
|
-
export interface StripeCreateBashEventDonationCheckoutSessionArgs {
|
|
712
|
+
export interface StripeCreateBashEventDonationCheckoutSessionArgs extends UtmFields {
|
|
709
713
|
bashEventId: string;
|
|
710
714
|
currency: string;
|
|
711
715
|
paymentMethodType: string;
|
|
712
716
|
donationAmount: number;
|
|
717
|
+
/** Required for guest (unauthenticated) donation checkout — Stripe collects payment; we persist receipt to this email. */
|
|
718
|
+
guestEmail?: string;
|
|
719
|
+
guestFirstName?: string;
|
|
720
|
+
guestLastName?: string;
|
|
713
721
|
}
|
|
714
722
|
|
|
715
723
|
export interface StripeCreateSetupPaymentMethodSessionArgs {
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -146,6 +146,8 @@ export const FRONT_END_USER_DATA_TO_SELECT = {
|
|
|
146
146
|
sex: true,
|
|
147
147
|
documentIDId: true,
|
|
148
148
|
// documentID: true,
|
|
149
|
+
/** Set when Stripe Identity verification completes (hosted flow). */
|
|
150
|
+
idVerified: true,
|
|
149
151
|
reviews: true,
|
|
150
152
|
contacts: true,
|
|
151
153
|
accepted: true,
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default copy for host opt-in photo/video consent at event checkout.
|
|
3
|
+
* When `BashEvent.photoReleaseText` is null and `photoReleaseEnabled` is true, use this text.
|
|
4
|
+
* Not legal advice; hosts may supply custom text via the wizard.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_PHOTO_RELEASE_TEXT = `By attending this event, you understand that photography, audio recording, and video recording may occur. You consent to being photographed, filmed, and/or recorded, and you grant the event organizer and its licensees the right to use your name, image, likeness, and voice in any media (including for promotion of this and future events), without payment or other compensation, unless prohibited by law.
|
|
7
|
+
|
|
8
|
+
If you do not wish to appear in promotional materials, contact the event organizer before or during the event. For minors, a parent or guardian must agree to this consent.`;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Effective photo release text for display (wizard preview, event page, checkout).
|
|
12
|
+
*/
|
|
13
|
+
export function getPhotoReleaseDisplayText(
|
|
14
|
+
photoReleaseText: string | null | undefined
|
|
15
|
+
): string {
|
|
16
|
+
const trimmed = photoReleaseText?.trim();
|
|
17
|
+
if (trimmed) {
|
|
18
|
+
return trimmed;
|
|
19
|
+
}
|
|
20
|
+
return DEFAULT_PHOTO_RELEASE_TEXT;
|
|
21
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTM / marketing attribution: first-touch capture in sessionStorage, Stripe metadata keys,
|
|
3
|
+
* and persistence on Ticket rows.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface UtmFields {
|
|
7
|
+
utmSource?: string;
|
|
8
|
+
utmMedium?: string;
|
|
9
|
+
utmCampaign?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const SESSION_KEYS = {
|
|
13
|
+
utmSource: "bash_utm_source",
|
|
14
|
+
utmMedium: "bash_utm_medium",
|
|
15
|
+
utmCampaign: "bash_utm_campaign",
|
|
16
|
+
} as const;
|
|
17
|
+
|
|
18
|
+
/** Normalize optional UTM strings from API args (Stripe checkout / payment intent body). */
|
|
19
|
+
export function utmFieldsFromCheckoutArgs(args: UtmFields): UtmFields | undefined {
|
|
20
|
+
const s = args.utmSource?.trim();
|
|
21
|
+
const m = args.utmMedium?.trim();
|
|
22
|
+
const c = args.utmCampaign?.trim();
|
|
23
|
+
if (!s && !m && !c) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
const out: UtmFields = {};
|
|
27
|
+
if (s) {
|
|
28
|
+
out.utmSource = s.slice(0, 500);
|
|
29
|
+
}
|
|
30
|
+
if (m) {
|
|
31
|
+
out.utmMedium = m.slice(0, 500);
|
|
32
|
+
}
|
|
33
|
+
if (c) {
|
|
34
|
+
out.utmCampaign = c.slice(0, 500);
|
|
35
|
+
}
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Stripe Checkout / PaymentIntent metadata (snake_case keys). */
|
|
40
|
+
export function utmFieldsToStripeMetadata(utm: UtmFields | undefined): Record<string, string> {
|
|
41
|
+
if (!utm) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
const out: Record<string, string> = {};
|
|
45
|
+
if (utm.utmSource) {
|
|
46
|
+
out.utm_source = utm.utmSource;
|
|
47
|
+
}
|
|
48
|
+
if (utm.utmMedium) {
|
|
49
|
+
out.utm_medium = utm.utmMedium;
|
|
50
|
+
}
|
|
51
|
+
if (utm.utmCampaign) {
|
|
52
|
+
out.utm_campaign = utm.utmCampaign;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Prisma `Ticket` columns for persisted UTM (omit empty). */
|
|
58
|
+
export function utmFieldsToTicketColumns(utm: UtmFields): {
|
|
59
|
+
utmSource?: string;
|
|
60
|
+
utmMedium?: string;
|
|
61
|
+
utmCampaign?: string;
|
|
62
|
+
} {
|
|
63
|
+
const out: { utmSource?: string; utmMedium?: string; utmCampaign?: string } = {};
|
|
64
|
+
if (utm.utmSource) {
|
|
65
|
+
out.utmSource = utm.utmSource;
|
|
66
|
+
}
|
|
67
|
+
if (utm.utmMedium) {
|
|
68
|
+
out.utmMedium = utm.utmMedium;
|
|
69
|
+
}
|
|
70
|
+
if (utm.utmCampaign) {
|
|
71
|
+
out.utmCampaign = utm.utmCampaign;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Read UTM from Stripe object metadata into Prisma Ticket field names. */
|
|
77
|
+
export function utmFieldsFromStripeMetadata(
|
|
78
|
+
md: Record<string, string | undefined> | null | undefined
|
|
79
|
+
): UtmFields {
|
|
80
|
+
if (!md) {
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
const s = md.utm_source?.trim();
|
|
84
|
+
const m = md.utm_medium?.trim();
|
|
85
|
+
const c = md.utm_campaign?.trim();
|
|
86
|
+
const out: UtmFields = {};
|
|
87
|
+
if (s) {
|
|
88
|
+
out.utmSource = s.slice(0, 500);
|
|
89
|
+
}
|
|
90
|
+
if (m) {
|
|
91
|
+
out.utmMedium = m.slice(0, 500);
|
|
92
|
+
}
|
|
93
|
+
if (c) {
|
|
94
|
+
out.utmCampaign = c.slice(0, 500);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* First-touch per session: store each UTM component the first time it appears in the URL.
|
|
101
|
+
* Call on route changes so client-side navigations to ?utm_*= still capture.
|
|
102
|
+
*/
|
|
103
|
+
export function captureFirstTouchUtmFromUrlSearchParams(search: string): void {
|
|
104
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined") {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const q = search.startsWith("?") ? search.slice(1) : search;
|
|
108
|
+
const params = new URLSearchParams(q);
|
|
109
|
+
const pairs: Array<[keyof typeof SESSION_KEYS, string]> = [
|
|
110
|
+
["utmSource", "utm_source"],
|
|
111
|
+
["utmMedium", "utm_medium"],
|
|
112
|
+
["utmCampaign", "utm_campaign"],
|
|
113
|
+
];
|
|
114
|
+
for (const [storageField, paramName] of pairs) {
|
|
115
|
+
const v = params.get(paramName)?.trim();
|
|
116
|
+
const key = SESSION_KEYS[storageField];
|
|
117
|
+
if (v && !sessionStorage.getItem(key)) {
|
|
118
|
+
sessionStorage.setItem(key, v.slice(0, 500));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Values previously captured for this tab session (for checkout API bodies). */
|
|
124
|
+
export function getStoredUtmFields(): UtmFields {
|
|
125
|
+
if (typeof sessionStorage === "undefined") {
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
const s = sessionStorage.getItem(SESSION_KEYS.utmSource)?.trim();
|
|
129
|
+
const m = sessionStorage.getItem(SESSION_KEYS.utmMedium)?.trim();
|
|
130
|
+
const c = sessionStorage.getItem(SESSION_KEYS.utmCampaign)?.trim();
|
|
131
|
+
const out: UtmFields = {};
|
|
132
|
+
if (s) {
|
|
133
|
+
out.utmSource = s;
|
|
134
|
+
}
|
|
135
|
+
if (m) {
|
|
136
|
+
out.utmMedium = m;
|
|
137
|
+
}
|
|
138
|
+
if (c) {
|
|
139
|
+
out.utmCampaign = c;
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|