@bash-app/bash-common 30.97.0 → 30.98.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 +2 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +2 -2
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +176 -1
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +11 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +42 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +43 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/venueTypeFormatter.d.ts +10 -0
- package/dist/utils/venueTypeFormatter.d.ts.map +1 -0
- package/dist/utils/venueTypeFormatter.js +25 -0
- package/dist/utils/venueTypeFormatter.js.map +1 -0
- package/package.json +1 -1
- package/prisma/MIGRATION-CHECKLIST.md +198 -0
- package/prisma/manual-migration-add-missing-columns.sql +182 -0
- package/prisma/quick-migration.sql +47 -0
- package/prisma/schema.prisma +262 -63
- package/src/definitions.ts +3 -1
- package/src/extendedSchemas.ts +22 -0
- package/src/index.ts +1 -0
- package/src/utils/contentFilterUtils.ts +1 -0
- package/src/utils/index.ts +43 -0
- package/src/utils/venueTypeFormatter.ts +30 -0
package/prisma/schema.prisma
CHANGED
|
@@ -3,9 +3,8 @@ generator client {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
datasource db {
|
|
6
|
-
provider
|
|
7
|
-
url
|
|
8
|
-
directUrl = env("POSTGRES_URL_NON_POOLING")
|
|
6
|
+
provider = "postgresql"
|
|
7
|
+
url = env("POSTGRES_PRISMA_URL")
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
model Club {
|
|
@@ -54,16 +53,25 @@ model BashComment {
|
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
model Competition {
|
|
57
|
-
id
|
|
58
|
-
name
|
|
59
|
-
description
|
|
60
|
-
userId
|
|
61
|
-
bashEventId
|
|
62
|
-
numberOfPrizes
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
56
|
+
id String @id @default(cuid())
|
|
57
|
+
name String
|
|
58
|
+
description String @db.Text
|
|
59
|
+
userId String
|
|
60
|
+
bashEventId String
|
|
61
|
+
numberOfPrizes Int
|
|
62
|
+
competitionType CompetitionType? // Main category
|
|
63
|
+
subtype String? // Subcategory
|
|
64
|
+
rules String? @db.Text // Detailed rules/disclaimers
|
|
65
|
+
judgingType JudgingType? // How winner is determined
|
|
66
|
+
createdAt DateTime @default(now())
|
|
67
|
+
updatedAt DateTime @updatedAt
|
|
68
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
69
|
+
owner User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
70
|
+
sponsor CompetitionSponsor[]
|
|
71
|
+
prizes Prize[]
|
|
72
|
+
|
|
73
|
+
@@index([bashEventId])
|
|
74
|
+
@@index([competitionType])
|
|
67
75
|
}
|
|
68
76
|
|
|
69
77
|
model CompetitionSponsor {
|
|
@@ -366,6 +374,8 @@ model BashEvent {
|
|
|
366
374
|
media Media[] @relation("BashEventToMedia")
|
|
367
375
|
associatedServicesReferencingMe Service[] @relation("BashEventToService")
|
|
368
376
|
userConnections UserConnection[]
|
|
377
|
+
aiRecommendationLogs AIRecommendationLog[]
|
|
378
|
+
aiRecommendationCaches AIRecommendationCache[]
|
|
369
379
|
}
|
|
370
380
|
|
|
371
381
|
model Coordinates {
|
|
@@ -732,14 +742,20 @@ model Prize {
|
|
|
732
742
|
id String @id @default(cuid())
|
|
733
743
|
prizeWorth Float?
|
|
734
744
|
prizeType PrizeType
|
|
735
|
-
name String
|
|
745
|
+
name String // Prize name (e.g., "$100 Cash", "Backpack")
|
|
746
|
+
placeName String? // Display name (e.g., "1st Place", "Winner")
|
|
736
747
|
prizeLevel Int
|
|
737
748
|
description String
|
|
738
749
|
competitionId String?
|
|
739
750
|
paidOn String?
|
|
740
751
|
winnerUserId String?
|
|
741
|
-
|
|
752
|
+
wonAt DateTime? // When the prize was awarded
|
|
753
|
+
claimedAt DateTime? // When the prize was claimed
|
|
754
|
+
competition Competition? @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
742
755
|
winner User? @relation(fields: [winnerUserId], references: [id], onDelete: Cascade)
|
|
756
|
+
|
|
757
|
+
@@index([competitionId])
|
|
758
|
+
@@index([winnerUserId]) // For fetching user's wins
|
|
743
759
|
}
|
|
744
760
|
|
|
745
761
|
model Review {
|
|
@@ -807,16 +823,22 @@ model SocialMediaProfile {
|
|
|
807
823
|
}
|
|
808
824
|
|
|
809
825
|
model User {
|
|
810
|
-
id
|
|
811
|
-
username
|
|
812
|
-
email
|
|
813
|
-
createdOn
|
|
814
|
-
stripeCustomerId
|
|
815
|
-
stripeAccountId
|
|
816
|
-
isSuperUser
|
|
817
|
-
isSuspended
|
|
818
|
-
intent
|
|
819
|
-
googleCalendarAccess
|
|
826
|
+
id String @id @default(cuid())
|
|
827
|
+
username String? @unique
|
|
828
|
+
email String @unique
|
|
829
|
+
createdOn DateTime @default(now())
|
|
830
|
+
stripeCustomerId String? @unique
|
|
831
|
+
stripeAccountId String? @unique
|
|
832
|
+
isSuperUser Boolean @default(false)
|
|
833
|
+
isSuspended Boolean @default(false)
|
|
834
|
+
intent UserIntent?
|
|
835
|
+
googleCalendarAccess String?
|
|
836
|
+
|
|
837
|
+
// Google OAuth tokens for API access (Contacts, Calendar, etc.)
|
|
838
|
+
googleAccessToken String?
|
|
839
|
+
googleRefreshToken String?
|
|
840
|
+
googleTokenExpiry DateTime?
|
|
841
|
+
|
|
820
842
|
givenName String?
|
|
821
843
|
familyName String?
|
|
822
844
|
nameChangeCount Int @default(0)
|
|
@@ -901,8 +923,9 @@ model User {
|
|
|
901
923
|
|
|
902
924
|
// Security Fields
|
|
903
925
|
accountLockedUntil DateTime? // Account lockout timestamp for failed login protection
|
|
904
|
-
|
|
905
|
-
|
|
926
|
+
revokedTokens RevokedToken[] @relation("RevokedTokens") // Revoked JWT tokens
|
|
927
|
+
auditLogs AuditLog[] @relation("UserAuditLogs")
|
|
928
|
+
auditLogsPerformed AuditLog[] @relation("PerformedByUser")
|
|
906
929
|
consents UserConsent[]
|
|
907
930
|
|
|
908
931
|
associatedBashes AssociatedBash[]
|
|
@@ -980,6 +1003,7 @@ model User {
|
|
|
980
1003
|
connectionRequestsReceived UserConnection[] @relation("ConnectionRequestsReceived")
|
|
981
1004
|
links UserLink[]
|
|
982
1005
|
preferences UserPreferences?
|
|
1006
|
+
rankings UserRankings?
|
|
983
1007
|
userPromoCodeRedemption UserPromoCodeRedemption[]
|
|
984
1008
|
referralCode UserReferralCode?
|
|
985
1009
|
referralTokens UserReferralToken[] @relation("UserReferralTokens")
|
|
@@ -990,6 +1014,7 @@ model User {
|
|
|
990
1014
|
userSubscription UserSubscription?
|
|
991
1015
|
vendorBid VendorBid[]
|
|
992
1016
|
vendorBookingMessages VendorBookingMessage[] @relation("VendorMessageSender")
|
|
1017
|
+
serviceAnalytics ServiceAnalytics[] // Track service analytics for this user
|
|
993
1018
|
vendorBookingRequestsAsHost VendorBookingRequest[] @relation("VendorBookingHost")
|
|
994
1019
|
volunteerService VolunteerService[]
|
|
995
1020
|
reviewedAmbashadorApps AmbashadorApplication[] @relation("AmbashadorReviewer")
|
|
@@ -999,6 +1024,7 @@ model User {
|
|
|
999
1024
|
bashEventPromoCodesIUsed BashEventPromoCode[] @relation("BashEventPromoCodeToUser")
|
|
1000
1025
|
ticketTiersWaitListsIveJoined TicketTier[] @relation("TicketTierToUser")
|
|
1001
1026
|
scoutReferralsMade ScoutReferral[] @relation("ScoutReferrer")
|
|
1027
|
+
aiRecommendationLogs AIRecommendationLog[]
|
|
1002
1028
|
scoutReferralsReceived ScoutReferral[] @relation("ScoutReferred")
|
|
1003
1029
|
bookingCommissionsEarned BookingCommission[] @relation("CommissionReferrer")
|
|
1004
1030
|
|
|
@@ -1043,6 +1069,7 @@ model UserPreferences {
|
|
|
1043
1069
|
showEmailPublicly Boolean @default(true)
|
|
1044
1070
|
showPhonePublicly Boolean @default(false)
|
|
1045
1071
|
showAddressPublicly Boolean @default(false)
|
|
1072
|
+
showCompetitionWins Boolean @default(true) // Display competition wins on public profile
|
|
1046
1073
|
theme String @default("system")
|
|
1047
1074
|
language String @default("en")
|
|
1048
1075
|
timeZone String @default("America/New_York")
|
|
@@ -1098,6 +1125,9 @@ model UserPreferences {
|
|
|
1098
1125
|
localEventsToCalendarSync Boolean @default(false)
|
|
1099
1126
|
localEventsCity String @default("")
|
|
1100
1127
|
localEventsState String @default("")
|
|
1128
|
+
showRankings Boolean @default(true) // Show rankings on profile
|
|
1129
|
+
showAttendeeRank Boolean @default(true) // Show attendee rank publicly
|
|
1130
|
+
showHostRank Boolean @default(true) // Show host rank publicly
|
|
1101
1131
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1102
1132
|
}
|
|
1103
1133
|
|
|
@@ -1116,6 +1146,42 @@ model UserFollowing {
|
|
|
1116
1146
|
@@unique([userId, followingId])
|
|
1117
1147
|
}
|
|
1118
1148
|
|
|
1149
|
+
model UserRankings {
|
|
1150
|
+
id String @id @default(cuid())
|
|
1151
|
+
userId String @unique
|
|
1152
|
+
attendeeScore Int @default(0) // Number of events attended
|
|
1153
|
+
hostScore Int @default(0) // Number of events hosted
|
|
1154
|
+
totalAttendeesScore Int @default(0) // Total attendees across all hosted events
|
|
1155
|
+
attendeeRankGlobal Int? // Global rank as attendee
|
|
1156
|
+
attendeeRankNational Int? // National rank as attendee
|
|
1157
|
+
attendeeRankCity Int? // City rank as attendee
|
|
1158
|
+
hostRankGlobal Int? // Global rank as host
|
|
1159
|
+
hostRankNational Int? // National rank as host
|
|
1160
|
+
hostRankCity Int? // City rank as host
|
|
1161
|
+
totalAttendeesRankGlobal Int? // Global rank by total attendees
|
|
1162
|
+
totalAttendeesRankNational Int? // National rank by total attendees
|
|
1163
|
+
totalAttendeesRankCity Int? // City rank by total attendees
|
|
1164
|
+
attendeePercentile Float? // Percentile rank as attendee (0-100)
|
|
1165
|
+
hostPercentile Float? // Percentile rank as host (0-100)
|
|
1166
|
+
totalAttendeesPercentile Float? // Percentile rank by total attendees (0-100)
|
|
1167
|
+
city String? // City for location-based rankings
|
|
1168
|
+
country String @default("US") // Country for location-based rankings
|
|
1169
|
+
lastScoreUpdate DateTime @default(now()) // When scores were last calculated
|
|
1170
|
+
lastCalculated DateTime @default(now()) // When ranks were last calculated
|
|
1171
|
+
createdAt DateTime @default(now())
|
|
1172
|
+
updatedAt DateTime @updatedAt
|
|
1173
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1174
|
+
|
|
1175
|
+
@@index([userId])
|
|
1176
|
+
@@index([attendeeScore])
|
|
1177
|
+
@@index([hostScore])
|
|
1178
|
+
@@index([totalAttendeesScore])
|
|
1179
|
+
@@index([city])
|
|
1180
|
+
@@index([country])
|
|
1181
|
+
@@index([attendeeRankGlobal])
|
|
1182
|
+
@@index([hostRankGlobal])
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1119
1185
|
model UserConnection {
|
|
1120
1186
|
id String @id @default(cuid())
|
|
1121
1187
|
requesterId String // User who sent the request
|
|
@@ -1366,6 +1432,7 @@ model Service {
|
|
|
1366
1432
|
associatedBashesReferencingMe AssociatedBash[] @relation("AssociatedBashToService")
|
|
1367
1433
|
bashEvent BashEvent[] @relation("BashEventToService")
|
|
1368
1434
|
media Media[] @relation("MediaToService")
|
|
1435
|
+
analytics ServiceAnalytics[] // Track service analytics
|
|
1369
1436
|
scoutReferrals ScoutReferral[] @relation("ScoutServiceProfile")
|
|
1370
1437
|
bookingCommissions BookingCommission[] @relation("CommissionServiceProfile")
|
|
1371
1438
|
|
|
@@ -1863,42 +1930,42 @@ model ServiceBookingCheckout {
|
|
|
1863
1930
|
}
|
|
1864
1931
|
|
|
1865
1932
|
model ServiceBooking {
|
|
1866
|
-
id
|
|
1867
|
-
creatorId
|
|
1868
|
-
forUserId
|
|
1869
|
-
daysTotalATBCents
|
|
1870
|
-
serviceId
|
|
1871
|
-
rateOption
|
|
1872
|
-
flatRateCents
|
|
1873
|
-
status
|
|
1874
|
-
bookingType
|
|
1875
|
-
timezone
|
|
1876
|
-
requestedOn
|
|
1877
|
-
requestDecisionOn
|
|
1878
|
-
bookedOn
|
|
1879
|
-
canceledOn
|
|
1880
|
-
isFreeGuest
|
|
1881
|
-
allowPromiseToPay
|
|
1882
|
-
totalATBCents
|
|
1883
|
-
subtotalATBCents
|
|
1884
|
-
bashEventId
|
|
1885
|
-
isVendorBid
|
|
1886
|
-
vendorBidAmountCents
|
|
1887
|
-
vendorEventDetails
|
|
1888
|
-
bashCashApplied
|
|
1889
|
-
bashCashTransactionId String?
|
|
1890
|
-
notification
|
|
1891
|
-
bashEvent
|
|
1892
|
-
creator
|
|
1893
|
-
forUser
|
|
1894
|
-
service
|
|
1895
|
-
addOns
|
|
1896
|
-
checkout
|
|
1897
|
-
bookedDays
|
|
1898
|
-
additionalFees
|
|
1899
|
-
messages
|
|
1900
|
-
packages
|
|
1901
|
-
commissions
|
|
1933
|
+
id String @id @default(cuid())
|
|
1934
|
+
creatorId String
|
|
1935
|
+
forUserId String
|
|
1936
|
+
daysTotalATBCents Int
|
|
1937
|
+
serviceId String
|
|
1938
|
+
rateOption ServiceBookingRateOption @default(TimeBased)
|
|
1939
|
+
flatRateCents Int?
|
|
1940
|
+
status ServiceBookingStatus @default(Pending)
|
|
1941
|
+
bookingType ServiceBookingType @default(Request)
|
|
1942
|
+
timezone String
|
|
1943
|
+
requestedOn DateTime?
|
|
1944
|
+
requestDecisionOn DateTime?
|
|
1945
|
+
bookedOn DateTime?
|
|
1946
|
+
canceledOn DateTime?
|
|
1947
|
+
isFreeGuest Boolean @default(false)
|
|
1948
|
+
allowPromiseToPay Boolean @default(false)
|
|
1949
|
+
totalATBCents Int
|
|
1950
|
+
subtotalATBCents Int @default(0)
|
|
1951
|
+
bashEventId String?
|
|
1952
|
+
isVendorBid Boolean @default(false)
|
|
1953
|
+
vendorBidAmountCents Int?
|
|
1954
|
+
vendorEventDetails String?
|
|
1955
|
+
bashCashApplied Int? // BashCash credits applied to this booking
|
|
1956
|
+
bashCashTransactionId String? // Link to BashCreditTransaction
|
|
1957
|
+
notification Notification[]
|
|
1958
|
+
bashEvent BashEvent? @relation(fields: [bashEventId], references: [id])
|
|
1959
|
+
creator User @relation("BookingCreator", fields: [creatorId], references: [id])
|
|
1960
|
+
forUser User @relation("BookingForUser", fields: [forUserId], references: [id])
|
|
1961
|
+
service Service @relation(fields: [serviceId], references: [id])
|
|
1962
|
+
addOns ServiceBookingAddOn[]
|
|
1963
|
+
checkout ServiceBookingCheckout?
|
|
1964
|
+
bookedDays ServiceBookingDay[]
|
|
1965
|
+
additionalFees ServiceBookingFee[]
|
|
1966
|
+
messages ServiceBookingMessage[]
|
|
1967
|
+
packages ServiceBookingPackage[]
|
|
1968
|
+
commissions BookingCommission[] @relation("BookingCommissions")
|
|
1902
1969
|
|
|
1903
1970
|
@@index([status])
|
|
1904
1971
|
@@index([creatorId])
|
|
@@ -2795,6 +2862,31 @@ enum PrizeType {
|
|
|
2795
2862
|
Combo
|
|
2796
2863
|
}
|
|
2797
2864
|
|
|
2865
|
+
enum CompetitionType {
|
|
2866
|
+
RAFFLE // Raffles & Drawings
|
|
2867
|
+
SKILL // Skill-Based Contests
|
|
2868
|
+
PHYSICAL // Physical & Outdoor
|
|
2869
|
+
INTERACTIVE // Interactive Audience
|
|
2870
|
+
SOCIAL_MEDIA // Social Media-Driven
|
|
2871
|
+
KIDS_FAMILY // Kids & Family
|
|
2872
|
+
FOOD_DRINK // Food & Drink
|
|
2873
|
+
VENDOR_BOOTH // Vendor Booth
|
|
2874
|
+
BUSINESS_PROFESSIONAL // Business / Professional
|
|
2875
|
+
RANDOMIZED // Randomized Participation
|
|
2876
|
+
SEASONAL_HOLIDAY // Seasonal or Holiday
|
|
2877
|
+
AUDIENCE_VOTING // Audience Voting-Based
|
|
2878
|
+
}
|
|
2879
|
+
|
|
2880
|
+
enum JudgingType {
|
|
2881
|
+
RANDOM_DRAW // Raffle-style random selection
|
|
2882
|
+
JUDGES // Panel of judges decides
|
|
2883
|
+
AUDIENCE_VOTE // Attendees vote
|
|
2884
|
+
METRICS // Based on measurable metrics
|
|
2885
|
+
HOST_CHOOSES // Host/organizer picks winner
|
|
2886
|
+
FIRST_COME // First X people win
|
|
2887
|
+
HIGHEST_BID // Auction-style
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2798
2890
|
enum Sex {
|
|
2799
2891
|
Male
|
|
2800
2892
|
Female
|
|
@@ -4240,6 +4332,25 @@ model AuditLog {
|
|
|
4240
4332
|
@@index([ipAddress])
|
|
4241
4333
|
}
|
|
4242
4334
|
|
|
4335
|
+
/// Token Revocation System
|
|
4336
|
+
/// Tracks revoked JWT tokens to prevent their reuse
|
|
4337
|
+
/// Required for secure logout, password changes, and account termination
|
|
4338
|
+
model RevokedToken {
|
|
4339
|
+
id String @id @default(cuid())
|
|
4340
|
+
userId String // Owner of the revoked token
|
|
4341
|
+
jti String @unique // JWT ID from token payload
|
|
4342
|
+
revokedAt DateTime @default(now())
|
|
4343
|
+
expiresAt DateTime // When the original token would have expired (for cleanup)
|
|
4344
|
+
reason String? // Why it was revoked: "logout", "password_change", "suspicious_activity", etc.
|
|
4345
|
+
|
|
4346
|
+
// Relation to user
|
|
4347
|
+
user User @relation("RevokedTokens", fields: [userId], references: [id], onDelete: Cascade)
|
|
4348
|
+
|
|
4349
|
+
@@index([jti]) // Fast lookup for token validation
|
|
4350
|
+
@@index([userId, revokedAt]) // User-specific revocation history
|
|
4351
|
+
@@index([expiresAt]) // For cleanup of old expired tokens
|
|
4352
|
+
}
|
|
4353
|
+
|
|
4243
4354
|
enum AuditAction {
|
|
4244
4355
|
// Authentication
|
|
4245
4356
|
LOGIN_SUCCESS
|
|
@@ -4300,6 +4411,11 @@ enum AuditAction {
|
|
|
4300
4411
|
DATA_IMPORTED
|
|
4301
4412
|
SENSITIVE_DATA_ACCESSED
|
|
4302
4413
|
|
|
4414
|
+
// Compliance
|
|
4415
|
+
CONSENT_GIVEN
|
|
4416
|
+
CONSENT_WITHDRAWN
|
|
4417
|
+
POLICY_ACCEPTED
|
|
4418
|
+
|
|
4303
4419
|
// Security
|
|
4304
4420
|
SUSPICIOUS_ACTIVITY_DETECTED
|
|
4305
4421
|
RATE_LIMIT_EXCEEDED
|
|
@@ -4317,6 +4433,7 @@ enum AuditCategory {
|
|
|
4317
4433
|
Tickets
|
|
4318
4434
|
AdminAction
|
|
4319
4435
|
DataAccess
|
|
4436
|
+
Compliance
|
|
4320
4437
|
Security
|
|
4321
4438
|
}
|
|
4322
4439
|
|
|
@@ -4326,6 +4443,88 @@ enum AuditSeverity {
|
|
|
4326
4443
|
Critical // Security incidents
|
|
4327
4444
|
}
|
|
4328
4445
|
|
|
4446
|
+
// Service Analytics Tracking
|
|
4447
|
+
model ServiceAnalytics {
|
|
4448
|
+
id String @id @default(cuid())
|
|
4449
|
+
serviceId String
|
|
4450
|
+
userId String? // null for anonymous views
|
|
4451
|
+
eventType ServiceAnalyticsEvent
|
|
4452
|
+
serviceType ServiceTypes? // Venues, EventServices, etc.
|
|
4453
|
+
specificType String? // For detailed tracking (e.g., "WeddingVenue", "Restaurant")
|
|
4454
|
+
timestamp DateTime @default(now())
|
|
4455
|
+
sessionId String? // Track user sessions
|
|
4456
|
+
referrer String? // Where the user came from
|
|
4457
|
+
deviceType String? // mobile, desktop, tablet
|
|
4458
|
+
metadata Json? // Additional context data
|
|
4459
|
+
|
|
4460
|
+
service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
|
|
4461
|
+
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
|
4462
|
+
|
|
4463
|
+
@@index([serviceId])
|
|
4464
|
+
@@index([userId])
|
|
4465
|
+
@@index([eventType])
|
|
4466
|
+
@@index([timestamp])
|
|
4467
|
+
@@index([serviceType])
|
|
4468
|
+
@@index([specificType])
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4471
|
+
enum ServiceAnalyticsEvent {
|
|
4472
|
+
VIEW // Card/listing viewed
|
|
4473
|
+
CLICK // Card clicked
|
|
4474
|
+
DETAIL_VIEW // Detail page viewed
|
|
4475
|
+
FAVORITE // Added to favorites
|
|
4476
|
+
UNFAVORITE // Removed from favorites
|
|
4477
|
+
SHARE // Shared via link/social
|
|
4478
|
+
CONTACT_CLICK // Contact button clicked
|
|
4479
|
+
BOOKING_STARTED // Booking process initiated
|
|
4480
|
+
BOOKING_COMPLETED // Booking confirmed
|
|
4481
|
+
BOOKING_ABANDONED // User left during booking
|
|
4482
|
+
INQUIRY_SENT // Inquiry form submitted
|
|
4483
|
+
PHONE_CLICK // Phone number clicked
|
|
4484
|
+
EMAIL_CLICK // Email clicked
|
|
4485
|
+
WEBSITE_CLICK // Website link clicked
|
|
4486
|
+
DIRECTIONS_CLICK // Directions/map clicked
|
|
4487
|
+
PHOTO_VIEW // Photo gallery viewed
|
|
4488
|
+
VIDEO_PLAY // Video played
|
|
4489
|
+
REVIEW_VIEW // Reviews section viewed
|
|
4490
|
+
FILTER_APPLIED // When a user filters results
|
|
4491
|
+
}
|
|
4492
|
+
|
|
4493
|
+
// AI Recommendation System - Logs each recommendation request
|
|
4494
|
+
model AIRecommendationLog {
|
|
4495
|
+
id String @id @default(cuid())
|
|
4496
|
+
eventId String
|
|
4497
|
+
userId String
|
|
4498
|
+
venueId String?
|
|
4499
|
+
serviceType ServiceTypes
|
|
4500
|
+
recommendationCount Int @default(0)
|
|
4501
|
+
cacheHit Boolean @default(false)
|
|
4502
|
+
createdAt DateTime @default(now())
|
|
4503
|
+
|
|
4504
|
+
event BashEvent @relation(fields: [eventId], references: [id], onDelete: Cascade)
|
|
4505
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
4506
|
+
|
|
4507
|
+
@@index([eventId])
|
|
4508
|
+
@@index([userId])
|
|
4509
|
+
@@index([createdAt])
|
|
4510
|
+
}
|
|
4511
|
+
|
|
4512
|
+
// AI Recommendation Cache - Stores recommendations to reduce API costs
|
|
4513
|
+
model AIRecommendationCache {
|
|
4514
|
+
id String @id @default(cuid())
|
|
4515
|
+
cacheKey String @unique
|
|
4516
|
+
eventId String
|
|
4517
|
+
serviceType ServiceTypes
|
|
4518
|
+
recommendations Json // Array of ServiceRecommendation objects
|
|
4519
|
+
expiresAt DateTime
|
|
4520
|
+
createdAt DateTime @default(now())
|
|
4521
|
+
|
|
4522
|
+
event BashEvent @relation(fields: [eventId], references: [id], onDelete: Cascade)
|
|
4523
|
+
|
|
4524
|
+
@@index([eventId])
|
|
4525
|
+
@@index([expiresAt])
|
|
4526
|
+
}
|
|
4527
|
+
|
|
4329
4528
|
enum VoucherStatus {
|
|
4330
4529
|
Active
|
|
4331
4530
|
Redeemed
|
package/src/definitions.ts
CHANGED
|
@@ -2,8 +2,10 @@ import {
|
|
|
2
2
|
BashEventDressTags,
|
|
3
3
|
BashEventType,
|
|
4
4
|
BashEventVibeTags,
|
|
5
|
+
CompetitionType,
|
|
5
6
|
Contact,
|
|
6
7
|
EntertainmentServiceType,
|
|
8
|
+
JudgingType,
|
|
7
9
|
MembershipTier,
|
|
8
10
|
MusicGenreType,
|
|
9
11
|
Prisma,
|
|
@@ -877,7 +879,7 @@ export const YearsOfExperienceToString: { [key in YearsOfExperience]: string } =
|
|
|
877
879
|
};
|
|
878
880
|
|
|
879
881
|
// Export Prisma enums for use in frontend
|
|
880
|
-
export { YearsOfExperience, EntertainmentServiceType, MusicGenreType, ServiceTypes };
|
|
882
|
+
export { YearsOfExperience, EntertainmentServiceType, MusicGenreType, ServiceTypes, CompetitionType, JudgingType };
|
|
881
883
|
|
|
882
884
|
export type BashEventTypeToStringType = {
|
|
883
885
|
[key in BashEventType]: string;
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
BlogPost,
|
|
11
11
|
BlogTag,
|
|
12
12
|
Checkout,
|
|
13
|
+
Competition,
|
|
13
14
|
Contact,
|
|
14
15
|
Coordinates,
|
|
15
16
|
Demerit,
|
|
@@ -23,6 +24,7 @@ import {
|
|
|
23
24
|
Notification,
|
|
24
25
|
Organization,
|
|
25
26
|
Prisma,
|
|
27
|
+
Prize,
|
|
26
28
|
Recurrence,
|
|
27
29
|
Reminder,
|
|
28
30
|
Review,
|
|
@@ -154,6 +156,14 @@ export const PRIVATE_USER_ACCOUNT_TO_SELECT = {
|
|
|
154
156
|
|
|
155
157
|
export interface SponsoredEventExt extends SponsoredEvent {}
|
|
156
158
|
|
|
159
|
+
export interface PrizeExt extends Prize {
|
|
160
|
+
winner?: PublicUser | null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface CompetitionExt extends Competition {
|
|
164
|
+
prizes: PrizeExt[];
|
|
165
|
+
}
|
|
166
|
+
|
|
157
167
|
export interface BashEventExt extends BashEvent {
|
|
158
168
|
targetAudience?: TargetAudience;
|
|
159
169
|
amountOfGuests?: AmountOfGuests;
|
|
@@ -169,6 +179,7 @@ export interface BashEventExt extends BashEvent {
|
|
|
169
179
|
venueServiceId?: string;
|
|
170
180
|
venueOwner?: PublicUser;
|
|
171
181
|
sponsorships?: SponsoredEventExt[];
|
|
182
|
+
competitions?: CompetitionExt[];
|
|
172
183
|
}
|
|
173
184
|
|
|
174
185
|
export const TICKET_TIER_DATA_TO_INCLUDE = {
|
|
@@ -206,6 +217,17 @@ export const BASH_EVENT_DATA_TO_INCLUDE = {
|
|
|
206
217
|
media: true,
|
|
207
218
|
eventTasks: true,
|
|
208
219
|
invitations: true,
|
|
220
|
+
competitions: {
|
|
221
|
+
include: {
|
|
222
|
+
prizes: {
|
|
223
|
+
include: {
|
|
224
|
+
winner: {
|
|
225
|
+
select: FRONT_END_USER_DATA_TO_SELECT,
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
209
231
|
} satisfies Prisma.BashEventInclude;
|
|
210
232
|
|
|
211
233
|
export const BASH_EVENT_DATA_TO_CLONE = [
|
package/src/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from "./utils/service/serviceDBUtils";
|
|
|
38
38
|
export * from "./utils/service/serviceRateUtils";
|
|
39
39
|
export * from "./utils/stripeAccountUtils";
|
|
40
40
|
export * from "./utils/userUtils";
|
|
41
|
+
export * from "./utils/venueTypeFormatter";
|
|
41
42
|
|
|
42
43
|
// Export typeUtils types individually to avoid ValueOf conflict with definitions
|
|
43
44
|
export { createAllTrueObject } from "./utils/typeUtils";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export * from './addressUtils';
|
|
2
|
+
export * from './apiUtils';
|
|
3
|
+
export * from './arrayUtils';
|
|
4
|
+
export * from './awsS3Utils';
|
|
5
|
+
export * from './badgeUtils';
|
|
6
|
+
export * from './bashCashPaymentUtils';
|
|
7
|
+
export * from './blog/blogDbUtils';
|
|
8
|
+
export * from './blogUtils';
|
|
9
|
+
export * from './contentFilterUtils';
|
|
10
|
+
export * from './dateTimeUtils';
|
|
11
|
+
export * from './entityUtils';
|
|
12
|
+
export * from './generalDateTimeUtils';
|
|
13
|
+
export * from './luxonUtils';
|
|
14
|
+
export * from './mathUtils';
|
|
15
|
+
export * from './objUtils';
|
|
16
|
+
export * from './paymentUtils';
|
|
17
|
+
export * from './promoCodesUtils';
|
|
18
|
+
export * from './qrCodeUtils';
|
|
19
|
+
export * from './recurrenceUtils';
|
|
20
|
+
export * from './reviewUtils';
|
|
21
|
+
export * from './service/apiServiceBookingApiUtils';
|
|
22
|
+
export * from './service/attendeeOptionUtils';
|
|
23
|
+
export * from './service/frontendServiceBookingUtils';
|
|
24
|
+
export * from './service/regexUtils';
|
|
25
|
+
export * from './service/serviceBookingStatusUtils';
|
|
26
|
+
export * from './service/serviceBookingTypes';
|
|
27
|
+
export * from './service/serviceDBUtils';
|
|
28
|
+
// export * from './service/serviceRateDBUtils'; // File is all commented out
|
|
29
|
+
export * from './service/serviceRateTypes';
|
|
30
|
+
export * from './service/serviceRateUtils';
|
|
31
|
+
export * from './service/serviceUtils';
|
|
32
|
+
export * from './slugUtils';
|
|
33
|
+
export * from './sortUtils';
|
|
34
|
+
export * from './stringUtils';
|
|
35
|
+
export * from './stripeAccountUtils';
|
|
36
|
+
export * from './ticketListUtils';
|
|
37
|
+
export * from './typeUtils';
|
|
38
|
+
export * from './urlUtils';
|
|
39
|
+
export * from './userPromoCodeUtils';
|
|
40
|
+
export * from './userSubscriptionUtils';
|
|
41
|
+
export * from './userUtils';
|
|
42
|
+
export * from './venueTypeFormatter';
|
|
43
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats venue type enum values into human-readable display names
|
|
3
|
+
* Example: "OutdoorSpace" -> "Outdoor Space", "WeddingVenue" -> "Wedding Venue"
|
|
4
|
+
*/
|
|
5
|
+
export function formatVenueType(venueType: string): string {
|
|
6
|
+
if (!venueType) return '';
|
|
7
|
+
|
|
8
|
+
// Insert space before capital letters (but not at the start)
|
|
9
|
+
return venueType.replace(/([A-Z])/g, ' $1').trim();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Formats an array of venue types into a human-readable string
|
|
14
|
+
*/
|
|
15
|
+
export function formatVenueTypes(venueTypes: string[], maxDisplay: number = 2): string {
|
|
16
|
+
if (!Array.isArray(venueTypes) || venueTypes.length === 0) {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const formatted = venueTypes.slice(0, maxDisplay).map(formatVenueType);
|
|
21
|
+
const remaining = venueTypes.length - maxDisplay;
|
|
22
|
+
|
|
23
|
+
if (remaining > 0) {
|
|
24
|
+
return `${formatted.join(', ')} +${remaining} more`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return formatted.join(', ');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|