@bash-app/bash-common 30.281.0 → 30.285.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/__tests__/storePrintArtworkUtils.test.d.ts +2 -0
- package/dist/__tests__/storePrintArtworkUtils.test.d.ts.map +1 -0
- package/dist/__tests__/storePrintArtworkUtils.test.js +35 -0
- package/dist/__tests__/storePrintArtworkUtils.test.js.map +1 -0
- package/dist/definitions.d.ts +3 -2
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +3 -2
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +15 -5
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/icebreakerPrompts.d.ts +9 -0
- package/dist/icebreakerPrompts.d.ts.map +1 -0
- package/dist/icebreakerPrompts.js +77 -0
- package/dist/icebreakerPrompts.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/mirroredPrismaEnums.d.ts +14 -0
- package/dist/mirroredPrismaEnums.d.ts.map +1 -1
- package/dist/mirroredPrismaEnums.js +13 -0
- package/dist/mirroredPrismaEnums.js.map +1 -1
- package/dist/storePrintArtworkUtils.d.ts +22 -0
- package/dist/storePrintArtworkUtils.d.ts.map +1 -0
- package/dist/storePrintArtworkUtils.js +74 -0
- package/dist/storePrintArtworkUtils.js.map +1 -0
- package/dist/storeTypes.d.ts +81 -0
- package/dist/storeTypes.d.ts.map +1 -0
- package/dist/storeTypes.js +20 -0
- package/dist/storeTypes.js.map +1 -0
- package/dist/venueMatch.d.ts +165 -0
- package/dist/venueMatch.d.ts.map +1 -0
- package/dist/venueMatch.js +68 -0
- package/dist/venueMatch.js.map +1 -0
- package/package.json +1 -1
- package/prisma/schema.prisma +382 -19
- package/src/__tests__/storePrintArtworkUtils.test.ts +53 -0
- package/src/definitions.ts +2 -2
- package/src/extendedSchemas.ts +25 -11
- package/src/icebreakerPrompts.ts +75 -0
- package/src/index.ts +4 -0
- package/src/mirroredPrismaEnums.ts +16 -0
- package/src/storePrintArtworkUtils.ts +93 -0
- package/src/storeTypes.ts +109 -0
- package/src/venueMatch.ts +202 -0
package/prisma/schema.prisma
CHANGED
|
@@ -130,6 +130,7 @@ model BashFeedComment {
|
|
|
130
130
|
parent BashFeedComment? @relation("FeedCommentReplies", fields: [parentId], references: [id], onDelete: Cascade)
|
|
131
131
|
replies BashFeedComment[] @relation("FeedCommentReplies")
|
|
132
132
|
likes BashFeedCommentLike[]
|
|
133
|
+
reports BashFeedReport[]
|
|
133
134
|
|
|
134
135
|
@@index([postId])
|
|
135
136
|
@@index([parentId])
|
|
@@ -169,7 +170,8 @@ model BashFeedRating {
|
|
|
169
170
|
model BashFeedReport {
|
|
170
171
|
id String @id @default(cuid())
|
|
171
172
|
userId String
|
|
172
|
-
postId String
|
|
173
|
+
postId String?
|
|
174
|
+
commentId String?
|
|
173
175
|
reason BashFeedReportReason
|
|
174
176
|
description String? @db.Text
|
|
175
177
|
status ReportStatus @default(Pending)
|
|
@@ -177,11 +179,14 @@ model BashFeedReport {
|
|
|
177
179
|
reviewedAt DateTime?
|
|
178
180
|
createdAt DateTime @default(now())
|
|
179
181
|
|
|
180
|
-
user User
|
|
181
|
-
post BashFeedPost
|
|
182
|
-
|
|
182
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
183
|
+
post BashFeedPost? @relation(fields: [postId], references: [id], onDelete: Cascade)
|
|
184
|
+
comment BashFeedComment? @relation(fields: [commentId], references: [id], onDelete: Cascade)
|
|
185
|
+
reviewer User? @relation("ReviewedReports", fields: [reviewedBy], references: [id])
|
|
183
186
|
|
|
187
|
+
@@unique([userId, commentId])
|
|
184
188
|
@@index([postId])
|
|
189
|
+
@@index([commentId])
|
|
185
190
|
@@index([status])
|
|
186
191
|
@@index([userId])
|
|
187
192
|
}
|
|
@@ -232,6 +237,13 @@ model Competition {
|
|
|
232
237
|
startTime DateTime? // Competition start time (for voting)
|
|
233
238
|
endTime DateTime? // Competition end time (for voting)
|
|
234
239
|
allowSelfRegistration Boolean @default(false)
|
|
240
|
+
/// When true, participant requests are auto-approved (ACCEPTED) instead of queued for host review.
|
|
241
|
+
autoApproveParticipants Boolean @default(false)
|
|
242
|
+
/// How the participant roster appears on the bash page ("All" | "Hidden").
|
|
243
|
+
participantDisplayMode String @default("All")
|
|
244
|
+
/// AUDIENCE_VOTE only: when true, only attendees (ticket holders / RSVPs) may vote.
|
|
245
|
+
/// Default false keeps voting open to any signed-in viewer.
|
|
246
|
+
restrictVotingToAttendees Boolean @default(false)
|
|
235
247
|
maxParticipants Int? // Optional cap on participants
|
|
236
248
|
|
|
237
249
|
// Tournament bracket fields
|
|
@@ -311,6 +323,8 @@ model CompetitionSponsor {
|
|
|
311
323
|
sponsorName String?
|
|
312
324
|
logoUrl String?
|
|
313
325
|
description String?
|
|
326
|
+
/// Optional outbound link to the sponsor's website (clickable on the public competition page)
|
|
327
|
+
websiteUrl String?
|
|
314
328
|
paidOn String?
|
|
315
329
|
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
316
330
|
sponsor User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
@@ -367,10 +381,9 @@ model CompetitionParticipant {
|
|
|
367
381
|
votes CompetitionVote[]
|
|
368
382
|
|
|
369
383
|
// Tournament bracket relations
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
judgeScores CompetitionJudgeScore[]
|
|
384
|
+
matchEntries CompetitionMatchEntrant[]
|
|
385
|
+
matchesWon CompetitionMatch[] @relation("MatchWinner")
|
|
386
|
+
judgeScores CompetitionJudgeScore[]
|
|
374
387
|
|
|
375
388
|
@@index([competitionId])
|
|
376
389
|
@@index([userId])
|
|
@@ -379,26 +392,28 @@ model CompetitionParticipant {
|
|
|
379
392
|
@@index([status])
|
|
380
393
|
}
|
|
381
394
|
|
|
382
|
-
// Tournament bracket matches
|
|
395
|
+
// Tournament bracket matches (1v1, heats, or battle royale via entrants join table)
|
|
383
396
|
model CompetitionMatch {
|
|
384
397
|
id String @id @default(cuid())
|
|
385
398
|
competitionId String
|
|
386
399
|
round Int // 1 = first round, 2 = semifinals, etc.
|
|
387
400
|
matchNumber Int // Position in round (1, 2, 3...)
|
|
388
401
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
402
|
+
format CompetitionMatchFormat @default(HEAD_TO_HEAD)
|
|
403
|
+
capacity Int? // Max entrants (heat lanes, server slots)
|
|
404
|
+
advanceCount Int? // How many advance from this heat/pool
|
|
405
|
+
heatIndex Int? // Wave number within a round (e.g. heat 12 of 50)
|
|
406
|
+
|
|
407
|
+
winnerId String?
|
|
392
408
|
|
|
393
409
|
scheduledTime DateTime?
|
|
394
410
|
completedAt DateTime?
|
|
395
|
-
score Json? // {participant1
|
|
411
|
+
score Json? // Legacy H2H: {participant1, participant2}; multi-entrant scores live on entrants
|
|
396
412
|
notes String? // Match notes
|
|
397
413
|
|
|
398
|
-
competition
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
winner CompetitionParticipant? @relation("MatchWinner", fields: [winnerId], references: [id])
|
|
414
|
+
competition Competition @relation(fields: [competitionId], references: [id], onDelete: Cascade)
|
|
415
|
+
winner CompetitionParticipant? @relation("MatchWinner", fields: [winnerId], references: [id])
|
|
416
|
+
entrants CompetitionMatchEntrant[]
|
|
402
417
|
|
|
403
418
|
createdAt DateTime @default(now())
|
|
404
419
|
updatedAt DateTime @updatedAt
|
|
@@ -408,6 +423,29 @@ model CompetitionMatch {
|
|
|
408
423
|
@@index([round])
|
|
409
424
|
}
|
|
410
425
|
|
|
426
|
+
// N entrants per match — heats, battle royales, and head-to-head (slots 1 & 2)
|
|
427
|
+
model CompetitionMatchEntrant {
|
|
428
|
+
id String @id @default(cuid())
|
|
429
|
+
matchId String
|
|
430
|
+
participantId String
|
|
431
|
+
slot Int // Lane/pod position (1-based)
|
|
432
|
+
placement Int? // Finish order within the match
|
|
433
|
+
score Json? // Time, points, etc.
|
|
434
|
+
eliminatedAt DateTime?
|
|
435
|
+
advanced Boolean? // Heat qualifiers: true when advancing to next stage
|
|
436
|
+
|
|
437
|
+
match CompetitionMatch @relation(fields: [matchId], references: [id], onDelete: Cascade)
|
|
438
|
+
participant CompetitionParticipant @relation(fields: [participantId], references: [id], onDelete: Cascade)
|
|
439
|
+
|
|
440
|
+
createdAt DateTime @default(now())
|
|
441
|
+
updatedAt DateTime @updatedAt
|
|
442
|
+
|
|
443
|
+
@@unique([matchId, slot])
|
|
444
|
+
@@unique([matchId, participantId])
|
|
445
|
+
@@index([matchId])
|
|
446
|
+
@@index([participantId])
|
|
447
|
+
}
|
|
448
|
+
|
|
411
449
|
model CompetitionVote {
|
|
412
450
|
id String @id @default(cuid())
|
|
413
451
|
competitionId String
|
|
@@ -823,6 +861,9 @@ model BashEvent {
|
|
|
823
861
|
collaborationEnabled Boolean @default(true)
|
|
824
862
|
/// Host opt-in: show icebreaker prompts on the bash detail page for guests
|
|
825
863
|
icebreakerEnabled Boolean @default(false)
|
|
864
|
+
/// Optional host-authored / host-picked icebreaker prompt. When set, it is shown
|
|
865
|
+
/// instead of a random canned prompt on the bash detail page.
|
|
866
|
+
icebreakerPrompt String?
|
|
826
867
|
/// Host-curated merch catalog for this event (informational; not a checkout line item for MVP)
|
|
827
868
|
merchandiseItems Json?
|
|
828
869
|
externalPriceMax Int? // Maximum ticket price in cents (for imported events)
|
|
@@ -905,6 +946,8 @@ model BashEvent {
|
|
|
905
946
|
userConnections UserConnection[]
|
|
906
947
|
aiRecommendationLogs AIRecommendationLog[]
|
|
907
948
|
aiRecommendationCaches AIRecommendationCache[]
|
|
949
|
+
venueMatchRuns VenueMatchRun[]
|
|
950
|
+
venueSupplyLeadEvents VenueSupplyLeadEvent[]
|
|
908
951
|
// Template tracking
|
|
909
952
|
templateId String?
|
|
910
953
|
template BashEventTemplate? @relation("CreatedFromTemplate", fields: [templateId], references: [id])
|
|
@@ -2026,8 +2069,9 @@ model TicketTier {
|
|
|
2026
2069
|
title String @default("Free")
|
|
2027
2070
|
sortOrder Int?
|
|
2028
2071
|
description String?
|
|
2029
|
-
maximumNumberOfTickets Int
|
|
2030
|
-
|
|
2072
|
+
maximumNumberOfTickets Int?
|
|
2073
|
+
/// @deprecated Legacy duplicate of maximumNumberOfTickets — do not read or write.
|
|
2074
|
+
maximumTicketCount Int?
|
|
2031
2075
|
isDonationTier Boolean?
|
|
2032
2076
|
hidden Boolean?
|
|
2033
2077
|
promoCodes BashEventPromoCode[]
|
|
@@ -3019,6 +3063,8 @@ model User {
|
|
|
3019
3063
|
userItineraries UserItinerary[]
|
|
3020
3064
|
aiRecommendationLogs AIRecommendationLog[]
|
|
3021
3065
|
scoutReferralsReceived ScoutReferral[] @relation("ScoutReferred")
|
|
3066
|
+
venueMatchRuns VenueMatchRun[] @relation("VenueMatchRunHost")
|
|
3067
|
+
assignedSupplyLeads VenueSupplyLead[] @relation("SupplyLeadAssignee")
|
|
3022
3068
|
|
|
3023
3069
|
// Service Category Requests
|
|
3024
3070
|
serviceCategoryRequests ServiceCategoryRequest[]
|
|
@@ -3040,6 +3086,7 @@ model User {
|
|
|
3040
3086
|
bashFeedRatings BashFeedRating[]
|
|
3041
3087
|
bashFeedReports BashFeedReport[]
|
|
3042
3088
|
reviewedFeedReports BashFeedReport[] @relation("ReviewedReports")
|
|
3089
|
+
storeOrders StoreOrder[]
|
|
3043
3090
|
bashFeedSaves BashFeedSave[]
|
|
3044
3091
|
bashFeedReposts BashFeedRepost[]
|
|
3045
3092
|
reviewHelpfulVotes ReviewHelpfulVote[]
|
|
@@ -3594,6 +3641,10 @@ model Service {
|
|
|
3594
3641
|
verifiedAt DateTime? // When verification was approved
|
|
3595
3642
|
licenseNumber String? // License/registration number
|
|
3596
3643
|
certifications String[] @default([]) // Array of certification names
|
|
3644
|
+
/// Geo anchor for distance scoring (Venue Match + future geo queries).
|
|
3645
|
+
/// Backfilled from googlePlaceId / address via api/scripts/backfillServiceCoordinates.ts.
|
|
3646
|
+
latitude Float?
|
|
3647
|
+
longitude Float?
|
|
3597
3648
|
bashFeedPosts BashFeedPost[]
|
|
3598
3649
|
bashEventArtists BashEventArtist[]
|
|
3599
3650
|
bashCreativeSubmissions BashCreativeSubmission[]
|
|
@@ -3640,6 +3691,8 @@ model Service {
|
|
|
3640
3691
|
competitionPrizesSourced Prize[] @relation("PrizeSourceService")
|
|
3641
3692
|
competitionSponsorCredits CompetitionSponsor[] @relation("CompetitionSponsorSourceService")
|
|
3642
3693
|
competitionPrizeOffersSourced CompetitionPrizeOffer[] @relation("CompetitionPrizeOfferSourceService")
|
|
3694
|
+
venueMatchCandidates VenueMatchCandidate[]
|
|
3695
|
+
supplyLeadConversions VenueSupplyLead[] @relation("SupplyLeadConvertedService")
|
|
3643
3696
|
|
|
3644
3697
|
@@index([serviceListingStripeSubscriptionId])
|
|
3645
3698
|
@@index([paymentAccountId])
|
|
@@ -3647,6 +3700,7 @@ model Service {
|
|
|
3647
3700
|
@@index([isVerified])
|
|
3648
3701
|
@@index([isLicensed])
|
|
3649
3702
|
@@index([isFeaturedService, featuredReason, featuredAt])
|
|
3703
|
+
@@index([latitude, longitude])
|
|
3650
3704
|
}
|
|
3651
3705
|
|
|
3652
3706
|
model StripeAccount {
|
|
@@ -6250,6 +6304,14 @@ enum BracketType {
|
|
|
6250
6304
|
DOUBLE_ELIMINATION // Lose twice, you're out
|
|
6251
6305
|
ROUND_ROBIN // Everyone plays everyone
|
|
6252
6306
|
SWISS // Pairing based on performance
|
|
6307
|
+
HEAT // Wave-based qualifiers (many entrants per match, top performers advance)
|
|
6308
|
+
BATTLE_ROYALE // Last standing / placement in a multi-entrant match
|
|
6309
|
+
}
|
|
6310
|
+
|
|
6311
|
+
enum CompetitionMatchFormat {
|
|
6312
|
+
HEAD_TO_HEAD // Traditional 1v1 (slots 1 & 2)
|
|
6313
|
+
HEAT // Sequential wave with capacity-limited entrants
|
|
6314
|
+
BATTLE_ROYALE // All entrants compete simultaneously until one remains
|
|
6253
6315
|
}
|
|
6254
6316
|
|
|
6255
6317
|
enum ParticipantStatus {
|
|
@@ -9501,6 +9563,127 @@ enum OrgProductStatus {
|
|
|
9501
9563
|
Archived
|
|
9502
9564
|
}
|
|
9503
9565
|
|
|
9566
|
+
enum StoreProductStatus {
|
|
9567
|
+
Active
|
|
9568
|
+
Draft
|
|
9569
|
+
Archived
|
|
9570
|
+
}
|
|
9571
|
+
|
|
9572
|
+
enum StoreProductCategory {
|
|
9573
|
+
Apparel
|
|
9574
|
+
Accessories
|
|
9575
|
+
Other
|
|
9576
|
+
}
|
|
9577
|
+
|
|
9578
|
+
enum StorePrintArtwork {
|
|
9579
|
+
BashLogoBig
|
|
9580
|
+
BashLogoLetters
|
|
9581
|
+
BashLogoBigWhite
|
|
9582
|
+
BashLogoLettersWhite
|
|
9583
|
+
}
|
|
9584
|
+
|
|
9585
|
+
enum StoreFulfillmentProvider {
|
|
9586
|
+
Platform
|
|
9587
|
+
Printify
|
|
9588
|
+
Printful
|
|
9589
|
+
}
|
|
9590
|
+
|
|
9591
|
+
enum StoreOrderStatus {
|
|
9592
|
+
Pending
|
|
9593
|
+
Paid
|
|
9594
|
+
Fulfilled
|
|
9595
|
+
Failed
|
|
9596
|
+
Canceled
|
|
9597
|
+
}
|
|
9598
|
+
|
|
9599
|
+
enum StoreFulfillmentStatus {
|
|
9600
|
+
Pending
|
|
9601
|
+
Submitted
|
|
9602
|
+
Fulfilled
|
|
9603
|
+
Failed
|
|
9604
|
+
}
|
|
9605
|
+
|
|
9606
|
+
/// Official Bash merch sold on /store (merchant-of-record via Stripe).
|
|
9607
|
+
model StoreProduct {
|
|
9608
|
+
id String @id @default(cuid())
|
|
9609
|
+
slug String @unique
|
|
9610
|
+
title String
|
|
9611
|
+
description String? @db.Text
|
|
9612
|
+
images String[] @default([])
|
|
9613
|
+
priceCents Int
|
|
9614
|
+
inventory Int @default(0)
|
|
9615
|
+
status StoreProductStatus @default(Draft)
|
|
9616
|
+
category StoreProductCategory @default(Apparel)
|
|
9617
|
+
sortOrder Int @default(0)
|
|
9618
|
+
fulfillmentProvider StoreFulfillmentProvider @default(Platform)
|
|
9619
|
+
externalProductId String?
|
|
9620
|
+
printArtwork StorePrintArtwork?
|
|
9621
|
+
printArtworkUrl String?
|
|
9622
|
+
createdAt DateTime @default(now())
|
|
9623
|
+
updatedAt DateTime @updatedAt
|
|
9624
|
+
variants StoreProductVariant[]
|
|
9625
|
+
orderLines StoreOrderLine[]
|
|
9626
|
+
|
|
9627
|
+
@@index([status, sortOrder])
|
|
9628
|
+
}
|
|
9629
|
+
|
|
9630
|
+
model StoreProductVariant {
|
|
9631
|
+
id String @id @default(cuid())
|
|
9632
|
+
productId String
|
|
9633
|
+
label String
|
|
9634
|
+
priceCents Int?
|
|
9635
|
+
inventory Int @default(0)
|
|
9636
|
+
externalVariantId String?
|
|
9637
|
+
sortOrder Int @default(0)
|
|
9638
|
+
product StoreProduct @relation(fields: [productId], references: [id], onDelete: Cascade)
|
|
9639
|
+
|
|
9640
|
+
@@index([productId])
|
|
9641
|
+
}
|
|
9642
|
+
|
|
9643
|
+
model StoreOrder {
|
|
9644
|
+
id String @id @default(cuid())
|
|
9645
|
+
buyerId String
|
|
9646
|
+
status StoreOrderStatus @default(Pending)
|
|
9647
|
+
fulfillmentStatus StoreFulfillmentStatus @default(Pending)
|
|
9648
|
+
subtotalCents Int
|
|
9649
|
+
totalCents Int
|
|
9650
|
+
currency String @default("usd")
|
|
9651
|
+
stripeCheckoutSessionId String? @unique
|
|
9652
|
+
stripePaymentIntentId String?
|
|
9653
|
+
// Shipping address captured from Stripe checkout
|
|
9654
|
+
shippingName String?
|
|
9655
|
+
shippingLine1 String?
|
|
9656
|
+
shippingLine2 String?
|
|
9657
|
+
shippingCity String?
|
|
9658
|
+
shippingState String?
|
|
9659
|
+
shippingPostalCode String?
|
|
9660
|
+
shippingCountry String?
|
|
9661
|
+
createdAt DateTime @default(now())
|
|
9662
|
+
updatedAt DateTime @updatedAt
|
|
9663
|
+
buyer User @relation(fields: [buyerId], references: [id], onDelete: Cascade)
|
|
9664
|
+
lines StoreOrderLine[]
|
|
9665
|
+
|
|
9666
|
+
@@index([buyerId])
|
|
9667
|
+
@@index([status])
|
|
9668
|
+
}
|
|
9669
|
+
|
|
9670
|
+
model StoreOrderLine {
|
|
9671
|
+
id String @id @default(cuid())
|
|
9672
|
+
orderId String
|
|
9673
|
+
productId String?
|
|
9674
|
+
variantId String?
|
|
9675
|
+
titleSnapshot String
|
|
9676
|
+
unitPriceCents Int
|
|
9677
|
+
quantity Int @default(1)
|
|
9678
|
+
fulfillmentProvider StoreFulfillmentProvider
|
|
9679
|
+
externalProductId String?
|
|
9680
|
+
externalVariantId String?
|
|
9681
|
+
order StoreOrder @relation(fields: [orderId], references: [id], onDelete: Cascade)
|
|
9682
|
+
product StoreProduct? @relation(fields: [productId], references: [id], onDelete: SetNull)
|
|
9683
|
+
|
|
9684
|
+
@@index([orderId])
|
|
9685
|
+
}
|
|
9686
|
+
|
|
9504
9687
|
/// Lifecycle of a host's external Stripe nonprofit-pricing application. Recorded
|
|
9505
9688
|
/// for analytics; does NOT gate Bash-side verification or platform-fee waivers.
|
|
9506
9689
|
enum StripeNonprofitPricingStatus {
|
|
@@ -9509,3 +9692,183 @@ enum StripeNonprofitPricingStatus {
|
|
|
9509
9692
|
Approved
|
|
9510
9693
|
Declined
|
|
9511
9694
|
}
|
|
9695
|
+
|
|
9696
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9697
|
+
// Venue Match pipeline (retrieve → score → explain) + supply sales pipeline.
|
|
9698
|
+
// JSON column shapes live in bash-common/src/venueMatch.ts (VenueMatchIntent,
|
|
9699
|
+
// VenueMatchScoreBreakdown, VenueCandidateDisplay).
|
|
9700
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
9701
|
+
|
|
9702
|
+
enum VenueMatchCandidateSource {
|
|
9703
|
+
Marketplace
|
|
9704
|
+
GooglePlaces
|
|
9705
|
+
}
|
|
9706
|
+
|
|
9707
|
+
enum VenueMatchHostAction {
|
|
9708
|
+
None
|
|
9709
|
+
Viewed
|
|
9710
|
+
Accepted
|
|
9711
|
+
AcceptedOffPlatform
|
|
9712
|
+
Dismissed
|
|
9713
|
+
CalledPhone
|
|
9714
|
+
InvitedVenue
|
|
9715
|
+
}
|
|
9716
|
+
|
|
9717
|
+
enum VenueSupplyLeadStage {
|
|
9718
|
+
Surfaced
|
|
9719
|
+
Prioritized
|
|
9720
|
+
Queued
|
|
9721
|
+
Contacted
|
|
9722
|
+
Interested
|
|
9723
|
+
DemoScheduled
|
|
9724
|
+
Listed
|
|
9725
|
+
Declined
|
|
9726
|
+
DoNotContact
|
|
9727
|
+
}
|
|
9728
|
+
|
|
9729
|
+
enum ExternalPlaceSource {
|
|
9730
|
+
OutscraperCsv
|
|
9731
|
+
OutscraperApi
|
|
9732
|
+
Manual
|
|
9733
|
+
}
|
|
9734
|
+
|
|
9735
|
+
/// One scoring run for a bash. Content-hash dedupes identical re-runs.
|
|
9736
|
+
model VenueMatchRun {
|
|
9737
|
+
id String @id @default(cuid())
|
|
9738
|
+
bashEventId String
|
|
9739
|
+
hostUserId String
|
|
9740
|
+
/// `VenueMatchIntent` — occasion, guestCount, anchor coords, vibe, budget.
|
|
9741
|
+
intent Json
|
|
9742
|
+
contentHash String
|
|
9743
|
+
/// Run telemetry: latencyMs, candidateCounts, googleCalls, cacheHits.
|
|
9744
|
+
meta Json?
|
|
9745
|
+
createdAt DateTime @default(now())
|
|
9746
|
+
|
|
9747
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
9748
|
+
hostUser User @relation("VenueMatchRunHost", fields: [hostUserId], references: [id], onDelete: Cascade)
|
|
9749
|
+
candidates VenueMatchCandidate[]
|
|
9750
|
+
|
|
9751
|
+
@@index([bashEventId, createdAt])
|
|
9752
|
+
@@index([hostUserId])
|
|
9753
|
+
}
|
|
9754
|
+
|
|
9755
|
+
/// Every scored candidate in a run (not just the top 3 shown).
|
|
9756
|
+
model VenueMatchCandidate {
|
|
9757
|
+
id String @id @default(cuid())
|
|
9758
|
+
runId String
|
|
9759
|
+
rank Int
|
|
9760
|
+
score Int
|
|
9761
|
+
/// `VenueMatchScoreBreakdown` — per-factor score + applied weight.
|
|
9762
|
+
scoreBreakdown Json
|
|
9763
|
+
/// Host-facing reason strings ("2.1 mi away", "Fits 25 guests").
|
|
9764
|
+
reasons Json
|
|
9765
|
+
source VenueMatchCandidateSource
|
|
9766
|
+
serviceId String?
|
|
9767
|
+
googlePlaceId String?
|
|
9768
|
+
/// `VenueCandidateDisplay` — snapshot so GET never re-hits Google.
|
|
9769
|
+
displaySnapshot Json
|
|
9770
|
+
hostAction VenueMatchHostAction @default(None)
|
|
9771
|
+
hostActionAt DateTime?
|
|
9772
|
+
|
|
9773
|
+
run VenueMatchRun @relation(fields: [runId], references: [id], onDelete: Cascade)
|
|
9774
|
+
service Service? @relation(fields: [serviceId], references: [id], onDelete: SetNull)
|
|
9775
|
+
|
|
9776
|
+
@@index([runId, rank])
|
|
9777
|
+
@@index([googlePlaceId])
|
|
9778
|
+
@@index([serviceId])
|
|
9779
|
+
}
|
|
9780
|
+
|
|
9781
|
+
/// ToS-compatible place data (Outscraper CSV/API imports). The ONLY allowed
|
|
9782
|
+
/// contact-data source for VenueSupplyLead — Google Place fields are never
|
|
9783
|
+
/// copied here (see GooglePlaceCache for the ephemeral display tier).
|
|
9784
|
+
model ExternalPlaceCatalog {
|
|
9785
|
+
id String @id @default(cuid())
|
|
9786
|
+
googlePlaceId String? @unique
|
|
9787
|
+
phoneE164 String?
|
|
9788
|
+
name String
|
|
9789
|
+
fullAddress String? @db.Text
|
|
9790
|
+
city String?
|
|
9791
|
+
state String?
|
|
9792
|
+
postalCode String?
|
|
9793
|
+
latitude Float?
|
|
9794
|
+
longitude Float?
|
|
9795
|
+
rating Float?
|
|
9796
|
+
reviewCount Int?
|
|
9797
|
+
category String?
|
|
9798
|
+
website String? @db.Text
|
|
9799
|
+
source ExternalPlaceSource @default(OutscraperCsv)
|
|
9800
|
+
/// Scraped/ file stem or Outscraper query that produced this row.
|
|
9801
|
+
sourceKey String?
|
|
9802
|
+
importedAt DateTime @default(now())
|
|
9803
|
+
refreshedAt DateTime?
|
|
9804
|
+
|
|
9805
|
+
supplyLeads VenueSupplyLead[]
|
|
9806
|
+
|
|
9807
|
+
@@index([phoneE164])
|
|
9808
|
+
@@index([city, state])
|
|
9809
|
+
}
|
|
9810
|
+
|
|
9811
|
+
/// Off-platform venue prospect for the sales pipeline. Contact fields come
|
|
9812
|
+
/// from ExternalPlaceCatalog (denormalized name/phone kept for fast lists).
|
|
9813
|
+
model VenueSupplyLead {
|
|
9814
|
+
id String @id @default(cuid())
|
|
9815
|
+
catalogId String?
|
|
9816
|
+
googlePlaceId String? @unique
|
|
9817
|
+
/// Set when the venue converts (publishes a Service on Bash).
|
|
9818
|
+
serviceId String?
|
|
9819
|
+
/// Dedup link to the Vapi dialer lead when phoneE164 matches.
|
|
9820
|
+
outreachLeadId String?
|
|
9821
|
+
name String
|
|
9822
|
+
phoneE164 String?
|
|
9823
|
+
city String?
|
|
9824
|
+
state String?
|
|
9825
|
+
/// Count of DISTINCT bash events that surfaced this venue (top 10).
|
|
9826
|
+
distinctEventCount Int @default(0)
|
|
9827
|
+
firstSurfacedAt DateTime @default(now())
|
|
9828
|
+
lastSurfacedAt DateTime @default(now())
|
|
9829
|
+
stage VenueSupplyLeadStage @default(Surfaced)
|
|
9830
|
+
assignedToUserId String?
|
|
9831
|
+
notes String? @db.Text
|
|
9832
|
+
createdAt DateTime @default(now())
|
|
9833
|
+
updatedAt DateTime @updatedAt
|
|
9834
|
+
|
|
9835
|
+
catalog ExternalPlaceCatalog? @relation(fields: [catalogId], references: [id], onDelete: SetNull)
|
|
9836
|
+
service Service? @relation("SupplyLeadConvertedService", fields: [serviceId], references: [id], onDelete: SetNull)
|
|
9837
|
+
assignedTo User? @relation("SupplyLeadAssignee", fields: [assignedToUserId], references: [id], onDelete: SetNull)
|
|
9838
|
+
surfaceEvents VenueSupplyLeadEvent[]
|
|
9839
|
+
|
|
9840
|
+
@@index([stage, distinctEventCount])
|
|
9841
|
+
@@index([city, state])
|
|
9842
|
+
@@index([phoneE164])
|
|
9843
|
+
@@index([assignedToUserId])
|
|
9844
|
+
}
|
|
9845
|
+
|
|
9846
|
+
/// Join row: which bash surfaced this lead, with occasion context for
|
|
9847
|
+
/// cold-call scripts ("4 hosts searched bachelor party venues near you").
|
|
9848
|
+
model VenueSupplyLeadEvent {
|
|
9849
|
+
id String @id @default(cuid())
|
|
9850
|
+
supplyLeadId String
|
|
9851
|
+
bashEventId String
|
|
9852
|
+
matchCandidateId String?
|
|
9853
|
+
occasion String?
|
|
9854
|
+
guestCountEstimate Int?
|
|
9855
|
+
surfacedAt DateTime @default(now())
|
|
9856
|
+
|
|
9857
|
+
supplyLead VenueSupplyLead @relation(fields: [supplyLeadId], references: [id], onDelete: Cascade)
|
|
9858
|
+
bashEvent BashEvent @relation(fields: [bashEventId], references: [id], onDelete: Cascade)
|
|
9859
|
+
|
|
9860
|
+
@@unique([supplyLeadId, bashEventId])
|
|
9861
|
+
@@index([bashEventId])
|
|
9862
|
+
}
|
|
9863
|
+
|
|
9864
|
+
/// Ephemeral Google Place display data (48h TTL). NEVER copied into
|
|
9865
|
+
/// VenueSupplyLead or ExternalPlaceCatalog — Google ToS tier C only.
|
|
9866
|
+
model GooglePlaceCache {
|
|
9867
|
+
googlePlaceId String @id
|
|
9868
|
+
/// Display-only snapshot: name, address, rating, reviewCount, photoUrl, phone, lat/lng.
|
|
9869
|
+
displaySnapshot Json
|
|
9870
|
+
fetchedAt DateTime @default(now())
|
|
9871
|
+
expiresAt DateTime
|
|
9872
|
+
|
|
9873
|
+
@@index([expiresAt])
|
|
9874
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { StorePrintArtwork } from "@prisma/client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isDarkGarmentColor,
|
|
5
|
+
resolveStorePrintArtwork,
|
|
6
|
+
resolveStorePrintArtworkPath,
|
|
7
|
+
} from "../storePrintArtworkUtils.js";
|
|
8
|
+
|
|
9
|
+
describe("isDarkGarmentColor", () => {
|
|
10
|
+
it("detects common dark garment names", () => {
|
|
11
|
+
expect(isDarkGarmentColor("Black / M")).toBe(true);
|
|
12
|
+
expect(isDarkGarmentColor("navy")).toBe(true);
|
|
13
|
+
expect(isDarkGarmentColor("charcoal heather")).toBe(true);
|
|
14
|
+
expect(isDarkGarmentColor("White / L")).toBe(false);
|
|
15
|
+
expect(isDarkGarmentColor("Heather grey / M")).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("detects dark hex colors", () => {
|
|
19
|
+
expect(isDarkGarmentColor("#000000")).toBe(true);
|
|
20
|
+
expect(isDarkGarmentColor("#ffffff")).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe("resolveStorePrintArtwork", () => {
|
|
25
|
+
it("keeps royal-blue artwork on light garments", () => {
|
|
26
|
+
expect(
|
|
27
|
+
resolveStorePrintArtwork("BashLogoBig" as StorePrintArtwork, {
|
|
28
|
+
garmentColor: "White / M",
|
|
29
|
+
})
|
|
30
|
+
).toBe("BashLogoBig");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("routes to white knock-out on dark garments", () => {
|
|
34
|
+
expect(
|
|
35
|
+
resolveStorePrintArtwork("BashLogoBig" as StorePrintArtwork, {
|
|
36
|
+
garmentColor: "Black / L",
|
|
37
|
+
})
|
|
38
|
+
).toBe("BashLogoBigWhite");
|
|
39
|
+
expect(
|
|
40
|
+
resolveStorePrintArtwork("BashLogoLetters" as StorePrintArtwork, {
|
|
41
|
+
garmentColor: "Black / One size",
|
|
42
|
+
})
|
|
43
|
+
).toBe("BashLogoLettersWhite");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("returns public paths for resolved artwork", () => {
|
|
47
|
+
expect(
|
|
48
|
+
resolveStorePrintArtworkPath("BashLogoBig" as StorePrintArtwork, {
|
|
49
|
+
garmentColor: "Black",
|
|
50
|
+
})
|
|
51
|
+
).toBe("/bashLogoBigWhite.png");
|
|
52
|
+
});
|
|
53
|
+
});
|
package/src/definitions.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BashEventType,
|
|
3
|
-
BracketType,
|
|
4
3
|
CompetitionType,
|
|
5
4
|
Contact,
|
|
6
5
|
DietaryOption,
|
|
@@ -1137,9 +1136,10 @@ export const YearsOfExperienceToString: { [key in YearsOfExperienceEnum]: string
|
|
|
1137
1136
|
[YearsOfExperience.FivePlusYears]: "More than five years",
|
|
1138
1137
|
};
|
|
1139
1138
|
|
|
1139
|
+
export { BracketType } from "./mirroredPrismaEnums.js";
|
|
1140
|
+
|
|
1140
1141
|
// Export Prisma enums for use in frontend
|
|
1141
1142
|
export {
|
|
1142
|
-
BracketType,
|
|
1143
1143
|
CompetitionType,
|
|
1144
1144
|
EntertainmentServiceType,
|
|
1145
1145
|
JudgingType,
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BracketType } from "./mirroredPrismaEnums.js";
|
|
1
2
|
import {
|
|
2
3
|
AmountOfGuests,
|
|
3
4
|
AssociatedBash,
|
|
@@ -280,14 +281,23 @@ export interface CompetitionPrizeOfferExt {
|
|
|
280
281
|
} | null;
|
|
281
282
|
}
|
|
282
283
|
|
|
283
|
-
|
|
284
|
-
|
|
284
|
+
/** Competition row + relations; Override keeps new columns visible before consumers refresh Prisma. */
|
|
285
|
+
export type CompetitionExt = Override<
|
|
286
|
+
Competition,
|
|
287
|
+
{
|
|
288
|
+
autoApproveParticipants: boolean;
|
|
289
|
+
participantDisplayMode: string;
|
|
290
|
+
restrictVotingToAttendees: boolean;
|
|
291
|
+
bracketType: BracketType | null;
|
|
292
|
+
prizes: PrizeExt[];
|
|
293
|
+
}
|
|
294
|
+
> & {
|
|
285
295
|
participants?: CompetitionParticipant[];
|
|
286
296
|
votes?: CompetitionVote[];
|
|
287
297
|
entryTicketTier?: TicketTier | null;
|
|
288
298
|
sponsor?: CompetitionSponsor[];
|
|
289
299
|
prizeOffers?: CompetitionPrizeOfferExt[];
|
|
290
|
-
}
|
|
300
|
+
};
|
|
291
301
|
|
|
292
302
|
/** One row in BashEvent.merchandiseItems (host wizard; informational catalog) */
|
|
293
303
|
export type BashEventHostMerchItem = {
|
|
@@ -356,12 +366,15 @@ export type BashEventHiredServicePublic = {
|
|
|
356
366
|
}>;
|
|
357
367
|
};
|
|
358
368
|
|
|
359
|
-
export interface BashEventExt extends
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
export interface BashEventExt extends Override<
|
|
370
|
+
Omit<
|
|
371
|
+
BashEvent,
|
|
372
|
+
| "ideaExpiresAt"
|
|
373
|
+
| "ideaInterestThreshold"
|
|
374
|
+
| "isAutoApprovable"
|
|
375
|
+
| "merchandiseItems"
|
|
376
|
+
>,
|
|
377
|
+
{ icebreakerPrompt: string | null }
|
|
365
378
|
> {
|
|
366
379
|
/** Host-curated merch catalog (wizard); stored as JSON on BashEvent. Null = no merch configured. */
|
|
367
380
|
merchandiseItems: BashEventMerchCatalog | null;
|
|
@@ -984,8 +997,9 @@ export interface ServiceExt extends Service {
|
|
|
984
997
|
|
|
985
998
|
stripeAccount?: PublicStripeAccount | null;
|
|
986
999
|
|
|
987
|
-
|
|
988
|
-
|
|
1000
|
+
/** Geo anchor — explicit on ext type for consumers before Prisma client catches up */
|
|
1001
|
+
latitude: number | null;
|
|
1002
|
+
longitude: number | null;
|
|
989
1003
|
|
|
990
1004
|
// availableDateTimes?: Availability[];
|
|
991
1005
|
|