@bash-app/bash-common 30.383.0 → 30.386.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__/accessScreening.test.js +39 -1
- package/dist/__tests__/accessScreening.test.js.map +1 -1
- package/dist/__tests__/applicationFunnel.test.d.ts +2 -0
- package/dist/__tests__/applicationFunnel.test.d.ts.map +1 -0
- package/dist/__tests__/applicationFunnel.test.js +126 -0
- package/dist/__tests__/applicationFunnel.test.js.map +1 -0
- package/dist/__tests__/definitionsHelpers.test.js +20 -1
- package/dist/__tests__/definitionsHelpers.test.js.map +1 -1
- package/dist/__tests__/fundingMeter.test.d.ts +2 -0
- package/dist/__tests__/fundingMeter.test.d.ts.map +1 -0
- package/dist/__tests__/fundingMeter.test.js +129 -0
- package/dist/__tests__/fundingMeter.test.js.map +1 -0
- package/dist/__tests__/giveaway.test.d.ts +2 -0
- package/dist/__tests__/giveaway.test.d.ts.map +1 -0
- package/dist/__tests__/giveaway.test.js +65 -0
- package/dist/__tests__/giveaway.test.js.map +1 -0
- package/dist/__tests__/promoterCompetitionUtils.test.d.ts +2 -0
- package/dist/__tests__/promoterCompetitionUtils.test.d.ts.map +1 -0
- package/dist/__tests__/promoterCompetitionUtils.test.js +262 -0
- package/dist/__tests__/promoterCompetitionUtils.test.js.map +1 -0
- package/dist/accessScreening.d.ts +18 -3
- package/dist/accessScreening.d.ts.map +1 -1
- package/dist/accessScreening.js +26 -0
- package/dist/accessScreening.js.map +1 -1
- package/dist/applicationFunnel.d.ts +58 -0
- package/dist/applicationFunnel.d.ts.map +1 -0
- package/dist/applicationFunnel.js +147 -0
- package/dist/applicationFunnel.js.map +1 -0
- package/dist/definitions.d.ts +146 -5
- package/dist/definitions.d.ts.map +1 -1
- package/dist/definitions.js +138 -5
- package/dist/definitions.js.map +1 -1
- package/dist/extendedSchemas.d.ts +174 -0
- package/dist/extendedSchemas.d.ts.map +1 -1
- package/dist/extendedSchemas.js +15 -0
- package/dist/extendedSchemas.js.map +1 -1
- package/dist/fundingMeter.d.ts +66 -0
- package/dist/fundingMeter.d.ts.map +1 -0
- package/dist/fundingMeter.js +99 -0
- package/dist/fundingMeter.js.map +1 -0
- package/dist/giveaway.d.ts +71 -0
- package/dist/giveaway.d.ts.map +1 -0
- package/dist/giveaway.js +117 -0
- package/dist/giveaway.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/__tests__/bashHostIdentity.test.d.ts +2 -0
- package/dist/utils/__tests__/bashHostIdentity.test.d.ts.map +1 -0
- package/dist/utils/__tests__/bashHostIdentity.test.js +39 -0
- package/dist/utils/__tests__/bashHostIdentity.test.js.map +1 -0
- package/dist/utils/__tests__/paymentUtils.test.js +28 -1
- package/dist/utils/__tests__/paymentUtils.test.js.map +1 -1
- package/dist/utils/__tests__/promoterCompetitionUtils.test.d.ts +2 -0
- package/dist/utils/__tests__/promoterCompetitionUtils.test.d.ts.map +1 -0
- package/dist/utils/__tests__/promoterCompetitionUtils.test.js +104 -0
- package/dist/utils/__tests__/promoterCompetitionUtils.test.js.map +1 -0
- package/dist/utils/__tests__/serviceAvailabilityDisplay.test.js +56 -1
- package/dist/utils/__tests__/serviceAvailabilityDisplay.test.js.map +1 -1
- package/dist/utils/__tests__/slugUtils.test.js +31 -2
- package/dist/utils/__tests__/slugUtils.test.js.map +1 -1
- package/dist/utils/bashHostIdentity.d.ts +18 -0
- package/dist/utils/bashHostIdentity.d.ts.map +1 -0
- package/dist/utils/bashHostIdentity.js +17 -0
- package/dist/utils/bashHostIdentity.js.map +1 -0
- package/dist/utils/paymentUtils.d.ts +18 -1
- package/dist/utils/paymentUtils.d.ts.map +1 -1
- package/dist/utils/paymentUtils.js +29 -2
- package/dist/utils/paymentUtils.js.map +1 -1
- package/dist/utils/promoterCompetitionUtils.d.ts +89 -0
- package/dist/utils/promoterCompetitionUtils.d.ts.map +1 -0
- package/dist/utils/promoterCompetitionUtils.js +158 -0
- package/dist/utils/promoterCompetitionUtils.js.map +1 -0
- package/dist/utils/serviceAvailabilityDisplay.d.ts +28 -2
- package/dist/utils/serviceAvailabilityDisplay.d.ts.map +1 -1
- package/dist/utils/serviceAvailabilityDisplay.js +39 -0
- package/dist/utils/serviceAvailabilityDisplay.js.map +1 -1
- package/dist/utils/slugUtils.d.ts +2 -0
- package/dist/utils/slugUtils.d.ts.map +1 -1
- package/dist/utils/slugUtils.js +5 -1
- package/dist/utils/slugUtils.js.map +1 -1
- package/package.json +1 -1
- package/prisma/schema.prisma +465 -29
- package/src/__tests__/accessScreening.test.ts +69 -1
- package/src/__tests__/applicationFunnel.test.ts +197 -0
- package/src/__tests__/definitionsHelpers.test.ts +24 -0
- package/src/__tests__/fundingMeter.test.ts +143 -0
- package/src/__tests__/giveaway.test.ts +111 -0
- package/src/__tests__/promoterCompetitionUtils.test.ts +334 -0
- package/src/accessScreening.ts +49 -0
- package/src/applicationFunnel.ts +225 -0
- package/src/definitions.ts +182 -5
- package/src/extendedSchemas.ts +131 -0
- package/src/fundingMeter.ts +188 -0
- package/src/giveaway.ts +182 -0
- package/src/index.ts +14 -0
- package/src/utils/__tests__/bashHostIdentity.test.ts +57 -0
- package/src/utils/__tests__/paymentUtils.test.ts +36 -0
- package/src/utils/__tests__/promoterCompetitionUtils.test.ts +128 -0
- package/src/utils/__tests__/serviceAvailabilityDisplay.test.ts +73 -0
- package/src/utils/__tests__/slugUtils.test.ts +46 -0
- package/src/utils/bashHostIdentity.ts +30 -0
- package/src/utils/paymentUtils.ts +47 -2
- package/src/utils/promoterCompetitionUtils.ts +235 -0
- package/src/utils/serviceAvailabilityDisplay.ts +82 -2
- package/src/utils/slugUtils.ts +11 -0
package/src/definitions.ts
CHANGED
|
@@ -520,6 +520,10 @@ export const DONATION_CHECKOUT_RETURN_SUCCESS_URL_PAGE =
|
|
|
520
520
|
"/bash/${bashEventIdSlug}/donation-success/${checkoutSessionId}" as const;
|
|
521
521
|
export const DONATION_CHECKOUT_RETURN_CANCEL_URL_PAGE =
|
|
522
522
|
"/bash/${bashEventIdSlug}/donation-cancel/${checkoutSessionId}" as const;
|
|
523
|
+
export const FUNDING_CHECKOUT_RETURN_SUCCESS_URL_PAGE =
|
|
524
|
+
"/bash/${bashEventIdSlug}/funding-success/${checkoutSessionId}" as const;
|
|
525
|
+
export const FUNDING_CHECKOUT_RETURN_CANCEL_URL_PAGE =
|
|
526
|
+
"/bash/${bashEventIdSlug}/funding-cancel/${checkoutSessionId}" as const;
|
|
523
527
|
|
|
524
528
|
export const SERVICE_BOOKING_CHECKOUT_RETURN_SUCCESS_URL =
|
|
525
529
|
"/service/${SERVICE_ID}/${SERVICE_TYPE}/${SPECIFIC_ID}/booking/${BOOKING_ID}/checkout-return/success/{CHECKOUT_SESSION_ID}" as const; //CHECKOUT_SESSION_ID filled by stripe
|
|
@@ -550,12 +554,91 @@ export const BASH_DETAIL_URL = `/bash` as const;
|
|
|
550
554
|
export const BASH_DETAIL_URL_PATTERN = `/bash/$bashEventIdSlug` as const;
|
|
551
555
|
|
|
552
556
|
/**
|
|
553
|
-
* Bash event wizard
|
|
554
|
-
* `
|
|
557
|
+
* Bash event wizard major/substep indices. Must match `AppWizard.Step` /
|
|
558
|
+
* `SubStep` child order in bash-app `BashEventWizard.tsx`. Deep links use
|
|
559
|
+
* these names — do not hardcode `/major/sub` integers.
|
|
555
560
|
*/
|
|
556
|
-
export const
|
|
557
|
-
|
|
558
|
-
|
|
561
|
+
export const BASH_EVENT_WIZARD_MAJOR = {
|
|
562
|
+
TEMPLATES: 0,
|
|
563
|
+
GENERATE: 1,
|
|
564
|
+
WHO: 2,
|
|
565
|
+
WHAT: 3,
|
|
566
|
+
WHERE: 4,
|
|
567
|
+
WHEN: 5,
|
|
568
|
+
WHY: 6,
|
|
569
|
+
HOW: 7,
|
|
570
|
+
FINISH: 8,
|
|
571
|
+
} as const;
|
|
572
|
+
|
|
573
|
+
export const BASH_EVENT_WIZARD_HOW_MAJOR_STEP = BASH_EVENT_WIZARD_MAJOR.HOW;
|
|
574
|
+
|
|
575
|
+
export const BASH_EVENT_WIZARD_TEMPLATES_SUBSTEP = {
|
|
576
|
+
START: 0,
|
|
577
|
+
} as const;
|
|
578
|
+
|
|
579
|
+
export const BASH_EVENT_WIZARD_GENERATE_SUBSTEP = {
|
|
580
|
+
START: 0,
|
|
581
|
+
} as const;
|
|
582
|
+
|
|
583
|
+
export const BASH_EVENT_WIZARD_WHO_SUBSTEP = {
|
|
584
|
+
TARGET_AUDIENCE: 0,
|
|
585
|
+
CROWD_SIZE: 1,
|
|
586
|
+
PRIVACY: 2,
|
|
587
|
+
INVITEES: 3,
|
|
588
|
+
ORGANIZERS: 4,
|
|
589
|
+
} as const;
|
|
590
|
+
|
|
591
|
+
/** Title and Type share one SubStep (index 0). Later What pages start at Vibe. */
|
|
592
|
+
export const BASH_EVENT_WIZARD_WHAT_SUBSTEP = {
|
|
593
|
+
TITLE: 0,
|
|
594
|
+
TYPE: 0,
|
|
595
|
+
VIBE_DRESS: 1,
|
|
596
|
+
SCHEDULE: 2,
|
|
597
|
+
COMPETITION: 3,
|
|
598
|
+
SIDE_QUESTS: 4,
|
|
599
|
+
POTLUCK: 5,
|
|
600
|
+
ALLOWED_NOT_ALLOWED: 6,
|
|
601
|
+
COMMUNITY: 7,
|
|
602
|
+
} as const;
|
|
603
|
+
|
|
604
|
+
export const BASH_EVENT_WIZARD_WHERE_SUBSTEP = {
|
|
605
|
+
LOCATION: 0,
|
|
606
|
+
UPLOAD_MEDIA: 1,
|
|
607
|
+
} as const;
|
|
608
|
+
|
|
609
|
+
export const BASH_EVENT_WIZARD_WHEN_SUBSTEP = {
|
|
610
|
+
DATE_TIME: 0,
|
|
611
|
+
} as const;
|
|
612
|
+
|
|
613
|
+
export const BASH_EVENT_WIZARD_WHY_SUBSTEP = {
|
|
614
|
+
WHY: 0,
|
|
615
|
+
} as const;
|
|
616
|
+
|
|
617
|
+
export const BASH_EVENT_WIZARD_HOW_SUBSTEP = {
|
|
618
|
+
PRICE: 0,
|
|
619
|
+
APPLICATION: 1,
|
|
620
|
+
PROMOTER_CHALLENGE: 2,
|
|
621
|
+
PROMO_CODES: 3,
|
|
622
|
+
SPECIAL_OFFERS: 4,
|
|
623
|
+
BUDGET: 5,
|
|
624
|
+
MERCH: 6,
|
|
625
|
+
GIVEAWAYS: 7,
|
|
626
|
+
SERVICES_PARTNERS: 8,
|
|
627
|
+
TASKS: 9,
|
|
628
|
+
PAYOUT: 10,
|
|
629
|
+
WAIVERS: 11,
|
|
630
|
+
CANCELLATION_POLICIES: 12,
|
|
631
|
+
FLYER_BLAST: 13,
|
|
632
|
+
ANALYTICS: 14,
|
|
633
|
+
} as const;
|
|
634
|
+
|
|
635
|
+
export const BASH_EVENT_WIZARD_FINISH_SUBSTEP = {
|
|
636
|
+
START: 0,
|
|
637
|
+
} as const;
|
|
638
|
+
|
|
639
|
+
/** Alias for Stripe Connect / payout deep links. */
|
|
640
|
+
export const BASH_EVENT_WIZARD_HOW_SUBSTEP_PAYOUT =
|
|
641
|
+
BASH_EVENT_WIZARD_HOW_SUBSTEP.PAYOUT;
|
|
559
642
|
|
|
560
643
|
export const BASH_EVENT_WIZARD_PATH_PREFIX = "/bash-event-wizard" as const;
|
|
561
644
|
|
|
@@ -1122,6 +1205,19 @@ export interface StripeCreateBashEventDonationCheckoutSessionArgs extends UtmFie
|
|
|
1122
1205
|
guestLastName?: string;
|
|
1123
1206
|
}
|
|
1124
1207
|
|
|
1208
|
+
export interface StripeCreateBudgetFundingCheckoutSessionArgs extends UtmFields {
|
|
1209
|
+
bashEventId: string;
|
|
1210
|
+
budgetId: string;
|
|
1211
|
+
currency: string;
|
|
1212
|
+
paymentMethodType: string;
|
|
1213
|
+
amountCents: number;
|
|
1214
|
+
displayName?: string;
|
|
1215
|
+
note?: string;
|
|
1216
|
+
guestEmail?: string;
|
|
1217
|
+
guestFirstName?: string;
|
|
1218
|
+
guestLastName?: string;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1125
1221
|
export interface StripeCreateSetupPaymentMethodSessionArgs {
|
|
1126
1222
|
// currency: string;
|
|
1127
1223
|
// successUrl: string;
|
|
@@ -1318,6 +1414,68 @@ export const YearsOfExperienceToString: { [key in YearsOfExperienceEnum]: string
|
|
|
1318
1414
|
|
|
1319
1415
|
export { BracketType, ServiceBookingSettlementStatusLabel } from "./mirroredPrismaEnums.js";
|
|
1320
1416
|
|
|
1417
|
+
// ─── Promoter Competition enums ───────────────────────────────────────────────
|
|
1418
|
+
// Mirrored here (standalone const objects) so they compile and work at runtime
|
|
1419
|
+
// before consumers re-generate @prisma/client from the updated schema.
|
|
1420
|
+
// Pattern matches BracketType in mirroredPrismaEnums.ts.
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* Mirrors Prisma `CompetitionPurpose` — distinguishes consumer contests
|
|
1424
|
+
* (vote/bracket/raffle) from ticket-sales promoter races.
|
|
1425
|
+
*/
|
|
1426
|
+
export const CompetitionPurpose = {
|
|
1427
|
+
CONSUMER: "CONSUMER",
|
|
1428
|
+
PROMOTER: "PROMOTER",
|
|
1429
|
+
} as const;
|
|
1430
|
+
export type CompetitionPurpose = (typeof CompetitionPurpose)[keyof typeof CompetitionPurpose];
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* Mirrors Prisma `PromoterRewardMode` — how milestone rewards are calculated
|
|
1434
|
+
* in a PROMOTER competition.
|
|
1435
|
+
*/
|
|
1436
|
+
export const PromoterRewardMode = {
|
|
1437
|
+
TOTAL_AT_MILESTONE: "TOTAL_AT_MILESTONE",
|
|
1438
|
+
ADDITIVE: "ADDITIVE",
|
|
1439
|
+
} as const;
|
|
1440
|
+
export type PromoterRewardMode = (typeof PromoterRewardMode)[keyof typeof PromoterRewardMode];
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* Mirrors Prisma `PromoterRecruitMode` — who can enroll as a promoter.
|
|
1444
|
+
*/
|
|
1445
|
+
export const PromoterRecruitMode = {
|
|
1446
|
+
Public: "Public",
|
|
1447
|
+
InviteOnly: "InviteOnly",
|
|
1448
|
+
Private: "Private",
|
|
1449
|
+
} as const;
|
|
1450
|
+
export type PromoterRecruitMode = (typeof PromoterRecruitMode)[keyof typeof PromoterRecruitMode];
|
|
1451
|
+
|
|
1452
|
+
/**
|
|
1453
|
+
* Mirrors Prisma `PromoterRewardType` — category of reward a promoter can earn.
|
|
1454
|
+
*/
|
|
1455
|
+
export const PromoterRewardType = {
|
|
1456
|
+
CASH: "CASH",
|
|
1457
|
+
TICKET: "TICKET",
|
|
1458
|
+
TICKET_UPGRADE: "TICKET_UPGRADE",
|
|
1459
|
+
TABLE: "TABLE",
|
|
1460
|
+
ACCESS: "ACCESS",
|
|
1461
|
+
MERCH: "MERCH",
|
|
1462
|
+
SPONSOR_PRIZE: "SPONSOR_PRIZE",
|
|
1463
|
+
CREDIT: "CREDIT",
|
|
1464
|
+
CUSTOM: "CUSTOM",
|
|
1465
|
+
} as const;
|
|
1466
|
+
export type PromoterRewardType = (typeof PromoterRewardType)[keyof typeof PromoterRewardType];
|
|
1467
|
+
|
|
1468
|
+
/**
|
|
1469
|
+
* Mirrors Prisma `PromoterRewardStatus` — lifecycle state of a single earned reward.
|
|
1470
|
+
*/
|
|
1471
|
+
export const PromoterRewardStatus = {
|
|
1472
|
+
PENDING: "PENDING",
|
|
1473
|
+
EARNED: "EARNED",
|
|
1474
|
+
FULFILLED: "FULFILLED",
|
|
1475
|
+
REVOKED: "REVOKED",
|
|
1476
|
+
} as const;
|
|
1477
|
+
export type PromoterRewardStatus = (typeof PromoterRewardStatus)[keyof typeof PromoterRewardStatus];
|
|
1478
|
+
|
|
1321
1479
|
// Re-exported for backward compatibility during migration — see serviceTypeLabels.ts/targetAudienceLabels.ts
|
|
1322
1480
|
// for the canonical, consolidated source (following the BracketType precedent above).
|
|
1323
1481
|
export { SERVICE_TYPE_LABELS } from "./serviceTypeLabels.js";
|
|
@@ -1815,6 +1973,25 @@ export function canonicalBashEventRowKey(raw: string): string {
|
|
|
1815
1973
|
return trimmed;
|
|
1816
1974
|
}
|
|
1817
1975
|
|
|
1976
|
+
/**
|
|
1977
|
+
* Homepage / category row key for an event's `eventType`. Blank, whitespace,
|
|
1978
|
+
* and unset values group under `Other` so drafts without a picked type still
|
|
1979
|
+
* appear on the home page.
|
|
1980
|
+
*/
|
|
1981
|
+
export function homepageBashEventRowKey(
|
|
1982
|
+
eventType: string | null | undefined
|
|
1983
|
+
): string {
|
|
1984
|
+
const key = canonicalBashEventRowKey(eventType ?? "");
|
|
1985
|
+
return key || BashEventType.Other;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/** True when the wizard should treat type as unselected (blank dropdown). */
|
|
1989
|
+
export function isUnsetBashEventType(
|
|
1990
|
+
eventType: string | null | undefined
|
|
1991
|
+
): boolean {
|
|
1992
|
+
return homepageBashEventRowKey(eventType) === BashEventType.Other;
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1818
1995
|
/**
|
|
1819
1996
|
* Heading shown on the home page row and the `/category/...` page for a bash
|
|
1820
1997
|
* `eventType` / section key. Uses plural-friendly copy for Prisma
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -360,8 +360,106 @@ export type CompetitionExt = Override<
|
|
|
360
360
|
entryTicketTier?: TicketTier | null;
|
|
361
361
|
sponsor?: CompetitionSponsor[];
|
|
362
362
|
prizeOffers?: CompetitionPrizeOfferExt[];
|
|
363
|
+
/** PROMOTER competitions: milestone reward steps defined by the organizer. */
|
|
364
|
+
promoterMilestones?: PromoterMilestoneExt[];
|
|
365
|
+
/** PROMOTER competitions: per-promoter earned/pending/revoked reward rows. */
|
|
366
|
+
promoterRewards?: PromoterRewardExt[];
|
|
367
|
+
competitionPurpose?: string;
|
|
368
|
+
promoterSalesGoal?: number | null;
|
|
369
|
+
promoterRewardBudgetCents?: number | null;
|
|
370
|
+
promoterRewardMode?: string | null;
|
|
371
|
+
promoterRecruitMode?: string | null;
|
|
363
372
|
};
|
|
364
373
|
|
|
374
|
+
// ─── Promoter Competition types ───────────────────────────────────────────────
|
|
375
|
+
// Defined as plain interfaces (not extending @prisma/client) because PromoterMilestone
|
|
376
|
+
// and PromoterReward are new models; consumers must run `npx prisma generate` in
|
|
377
|
+
// bash-common to get the generated Prisma types. These shapes mirror the schema exactly.
|
|
378
|
+
|
|
379
|
+
/** Base shape of a PromoterMilestone row (mirrors Prisma model; stable before prisma generate). */
|
|
380
|
+
export interface PromoterMilestoneBase {
|
|
381
|
+
id: string;
|
|
382
|
+
competitionId: string;
|
|
383
|
+
threshold: number | null;
|
|
384
|
+
rank: number | null;
|
|
385
|
+
rewardType: string; // PromoterRewardType — string union until client is regenerated
|
|
386
|
+
rewardAmountCents: number | null;
|
|
387
|
+
rewardDescription: string | null;
|
|
388
|
+
ticketTierId: string | null;
|
|
389
|
+
sponsorPrizeId: string | null;
|
|
390
|
+
displayOrder: number;
|
|
391
|
+
createdAt: Date;
|
|
392
|
+
updatedAt: Date;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** PromoterMilestone row with optional reward rows loaded. */
|
|
396
|
+
export interface PromoterMilestoneExt extends PromoterMilestoneBase {
|
|
397
|
+
rewards?: PromoterRewardExt[];
|
|
398
|
+
competition?: Competition | null;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** Base shape of a PromoterReward row (mirrors Prisma model; stable before prisma generate). */
|
|
402
|
+
export interface PromoterRewardBase {
|
|
403
|
+
id: string;
|
|
404
|
+
competitionId: string;
|
|
405
|
+
promoterId: string;
|
|
406
|
+
milestoneId: string | null;
|
|
407
|
+
rank: number | null;
|
|
408
|
+
qualifiedSalesSnapshot: number;
|
|
409
|
+
status: string; // PromoterRewardStatus — string union until client is regenerated
|
|
410
|
+
earnedAt: Date | null;
|
|
411
|
+
fulfilledAt: Date | null;
|
|
412
|
+
revokedAt: Date | null;
|
|
413
|
+
revokeReason: string | null;
|
|
414
|
+
createdAt: Date;
|
|
415
|
+
updatedAt: Date;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/** PromoterReward row with optional milestone and competition loaded. */
|
|
419
|
+
export interface PromoterRewardExt extends PromoterRewardBase {
|
|
420
|
+
milestone?: PromoterMilestoneBase | null;
|
|
421
|
+
competition?: Competition | null;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** Persisted per-promoter per-event performance record (PromoterEventPerformance model). */
|
|
425
|
+
export interface PromoterEventPerformanceExt {
|
|
426
|
+
id: string;
|
|
427
|
+
promoterUserId: string;
|
|
428
|
+
bashEventId: string;
|
|
429
|
+
competitionId: string;
|
|
430
|
+
clicks: number;
|
|
431
|
+
checkoutStarts: number;
|
|
432
|
+
qualifiedOrders: number;
|
|
433
|
+
qualifiedTickets: number;
|
|
434
|
+
revenueGeneratedCents: number;
|
|
435
|
+
highestMilestoneThreshold: number | null;
|
|
436
|
+
finalRank: number | null;
|
|
437
|
+
eventCategory: string | null;
|
|
438
|
+
eventCity: string | null;
|
|
439
|
+
eventRegion: string | null;
|
|
440
|
+
joinedAt: Date;
|
|
441
|
+
lastSaleAt: Date | null;
|
|
442
|
+
completedAt: Date | null;
|
|
443
|
+
createdAt: Date;
|
|
444
|
+
updatedAt: Date;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Cross-event organizer ↔ promoter relationship (OrganizerPromoterRelationship model). */
|
|
448
|
+
export interface OrganizerPromoterRelationshipExt {
|
|
449
|
+
id: string;
|
|
450
|
+
organizerUserId: string;
|
|
451
|
+
promoterUserId: string;
|
|
452
|
+
timesInvited: number;
|
|
453
|
+
timesJoined: number;
|
|
454
|
+
eventsWithSale: number;
|
|
455
|
+
totalTicketsGenerated: number;
|
|
456
|
+
totalRevenueGeneratedCents: number;
|
|
457
|
+
lastWorkedTogetherAt: Date | null;
|
|
458
|
+
lastInvitedAt: Date;
|
|
459
|
+
createdAt: Date;
|
|
460
|
+
updatedAt: Date;
|
|
461
|
+
}
|
|
462
|
+
|
|
365
463
|
/** One row in BashEvent.merchandiseItems (host wizard; informational catalog) */
|
|
366
464
|
export type BashEventHostMerchItem = {
|
|
367
465
|
id: string;
|
|
@@ -518,6 +616,8 @@ type BashEventExtBase = Override<
|
|
|
518
616
|
venue?: Venue | null;
|
|
519
617
|
/** Host organization when included on the event payload */
|
|
520
618
|
organization?: Pick<Organization, "id" | "name" | "slug" | "logoUrl"> | null;
|
|
619
|
+
/** Host-as-service identity when included on the event payload */
|
|
620
|
+
hostedByService?: ServiceRefLite | null;
|
|
521
621
|
targetAudience?: TargetAudience;
|
|
522
622
|
amountOfGuests?: AmountOfGuests;
|
|
523
623
|
recurrence?: Recurrence;
|
|
@@ -554,6 +654,12 @@ type BashEventExtBase = Override<
|
|
|
554
654
|
goingCount?: number;
|
|
555
655
|
/** GET /event/:id — true when at least one Budget line has `showOnBashDetailPage` set. Drives the "View budget" reveal on the public bash page; never carries dollar amounts. */
|
|
556
656
|
hasVisibleBudget?: boolean;
|
|
657
|
+
/** Public funding meter: value coming in toward included budget lines. */
|
|
658
|
+
showFundingMeter?: boolean;
|
|
659
|
+
/** When false, guests do not see host identity on cards or Meet the host. */
|
|
660
|
+
showHostOnBashPage?: boolean;
|
|
661
|
+
fundingAllowCommitments?: boolean;
|
|
662
|
+
fundingShowPledgesOnMeter?: boolean;
|
|
557
663
|
/** GET /event/:id when status=Idea — total IdeaInterest rows */
|
|
558
664
|
ideaInterestCount?: number;
|
|
559
665
|
/** Feed/card alias for idea interest (some list payloads use this name). */
|
|
@@ -580,6 +686,8 @@ type BashEventExtBase = Override<
|
|
|
580
686
|
};
|
|
581
687
|
/** GET /event/:id and GET /public-event/:id (authenticated) when accessScreeningEnabled — viewer's latest access request status */
|
|
582
688
|
myAccessRequestStatus?: "None" | "Pending" | "Approved" | "Denied" | null;
|
|
689
|
+
/** Public pending + approved application / RSVP totals when Application is on. Hidden at 0. */
|
|
690
|
+
applicationApplicantCount?: number;
|
|
583
691
|
/** GET /event/:id when status=Idea — viewer's IdeaInterest row (matched by email) */
|
|
584
692
|
myIdeaInterest?:
|
|
585
693
|
| (IdeaInterest & { responses: IdeaInterestResponse[] })
|
|
@@ -665,6 +773,8 @@ export type BashEventUpsertWireInput = Override<
|
|
|
665
773
|
targetAudience?: Partial<TargetAudience>;
|
|
666
774
|
/** Wizard itinerary blocks stored as BashEvent.itinerary JSON. */
|
|
667
775
|
itinerary?: ItineraryItem[] | Prisma.JsonValue | null;
|
|
776
|
+
/** Delete these competition ids on upsert (does not clear other competitions). */
|
|
777
|
+
removeCompetitionIds?: string[];
|
|
668
778
|
}
|
|
669
779
|
>;
|
|
670
780
|
|
|
@@ -699,6 +809,12 @@ export const BASH_EVENT_DATA_TO_INCLUDE = {
|
|
|
699
809
|
creator: {
|
|
700
810
|
select: FRONT_END_USER_DATA_TO_SELECT,
|
|
701
811
|
},
|
|
812
|
+
organization: {
|
|
813
|
+
select: { id: true, name: true, slug: true, logoUrl: true },
|
|
814
|
+
},
|
|
815
|
+
hostedByService: {
|
|
816
|
+
select: SERVICE_REF_LITE_SELECT,
|
|
817
|
+
},
|
|
702
818
|
payoutUser: {
|
|
703
819
|
select: { givenName: true, familyName: true, email: true },
|
|
704
820
|
},
|
|
@@ -911,6 +1027,15 @@ export const SERVICE_PUBLIC_LIST_DATA_TO_INCLUDE = {
|
|
|
911
1027
|
serviceRatesAssociation: {
|
|
912
1028
|
include: {
|
|
913
1029
|
serviceGeneralRates: true,
|
|
1030
|
+
// Lean blocked/premium windows so list calendars can count open days
|
|
1031
|
+
// without the full rates association payload.
|
|
1032
|
+
serviceSpecialRates: {
|
|
1033
|
+
select: {
|
|
1034
|
+
startDate: true,
|
|
1035
|
+
endDate: true,
|
|
1036
|
+
isAvailable: true,
|
|
1037
|
+
},
|
|
1038
|
+
},
|
|
914
1039
|
},
|
|
915
1040
|
},
|
|
916
1041
|
venue: {
|
|
@@ -1298,6 +1423,12 @@ export interface ServiceExt extends Service {
|
|
|
1298
1423
|
/** Attached by list endpoints (public/owner) for popularity sort and recency badges. */
|
|
1299
1424
|
bookingStats?: ServiceBookingStats;
|
|
1300
1425
|
|
|
1426
|
+
/**
|
|
1427
|
+
* Confirmed/Approved booking windows for the public availability calendar.
|
|
1428
|
+
* Attached by the public list endpoint; not a Prisma relation.
|
|
1429
|
+
*/
|
|
1430
|
+
bookedRanges?: Array<{ start: Date | string; end: Date | string }>;
|
|
1431
|
+
|
|
1301
1432
|
// bookedCheckouts: ServiceBookingCheckoutExt[]; //not necessary to include
|
|
1302
1433
|
}
|
|
1303
1434
|
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public funding meter contract — value coming in toward included budget lines.
|
|
3
|
+
* Consumers may copy these types until this package is published with this module.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const BUDGET_FUNDING_CHECKOUT_PURPOSE = "budget_funding" as const;
|
|
7
|
+
|
|
8
|
+
export type BudgetContributionKind = "Cash" | "InKind";
|
|
9
|
+
export type BudgetContributionStatus =
|
|
10
|
+
| "Pledged"
|
|
11
|
+
| "Paid"
|
|
12
|
+
| "Fulfilled"
|
|
13
|
+
| "Declined"
|
|
14
|
+
| "Cancelled";
|
|
15
|
+
export type BudgetContributionSource = "Stripe" | "HostEntered" | "PublicPledge";
|
|
16
|
+
|
|
17
|
+
export type FundingMeterLine = {
|
|
18
|
+
budgetId: string;
|
|
19
|
+
name: string;
|
|
20
|
+
category: string | null;
|
|
21
|
+
allocatedCents: number;
|
|
22
|
+
collectedCents: number;
|
|
23
|
+
pledgedCents: number;
|
|
24
|
+
remainingCents: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type FundingMeterPledge = {
|
|
28
|
+
displayName: string;
|
|
29
|
+
amountCents: number;
|
|
30
|
+
kind: BudgetContributionKind;
|
|
31
|
+
note: string | null;
|
|
32
|
+
budgetName: string | null;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export type FundingMeterProgress = {
|
|
36
|
+
showFundingMeter: boolean;
|
|
37
|
+
fundingAllowCommitments: boolean;
|
|
38
|
+
fundingShowPledgesOnMeter: boolean;
|
|
39
|
+
hostStripeConnected: boolean;
|
|
40
|
+
goalCents: number;
|
|
41
|
+
collectedCents: number;
|
|
42
|
+
pledgedCents: number;
|
|
43
|
+
unallocatedCents: number;
|
|
44
|
+
percentFunded: number;
|
|
45
|
+
lines: FundingMeterLine[];
|
|
46
|
+
pledges: FundingMeterPledge[];
|
|
47
|
+
unallocated: FundingMeterPledge[];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type FundingContributionForProgress = {
|
|
51
|
+
budgetId: string | null;
|
|
52
|
+
amountCents: number;
|
|
53
|
+
kind: BudgetContributionKind;
|
|
54
|
+
status: BudgetContributionStatus;
|
|
55
|
+
source: BudgetContributionSource;
|
|
56
|
+
displayName: string;
|
|
57
|
+
note: string | null;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type FundingLineForProgress = {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
category: string | null;
|
|
64
|
+
totalAllocatedCents: number;
|
|
65
|
+
includeOnFundingMeter: boolean;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const INACTIVE: ReadonlySet<BudgetContributionStatus> = new Set([
|
|
69
|
+
"Declined",
|
|
70
|
+
"Cancelled",
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
/** Line-attached collected: Stripe Paid + host-entered (cash Paid or in-kind Fulfilled/Paid). */
|
|
74
|
+
export function contributionCountsAsCollected(
|
|
75
|
+
row: FundingContributionForProgress
|
|
76
|
+
): boolean {
|
|
77
|
+
if (INACTIVE.has(row.status)) return false;
|
|
78
|
+
if (row.source === "HostEntered") {
|
|
79
|
+
return row.status === "Paid" || row.status === "Fulfilled";
|
|
80
|
+
}
|
|
81
|
+
return row.status === "Paid";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function contributionCountsAsOpenPledge(
|
|
85
|
+
row: FundingContributionForProgress
|
|
86
|
+
): boolean {
|
|
87
|
+
return row.status === "Pledged";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function computeFundingMeterProgress(input: {
|
|
91
|
+
showFundingMeter: boolean;
|
|
92
|
+
fundingAllowCommitments: boolean;
|
|
93
|
+
fundingShowPledgesOnMeter: boolean;
|
|
94
|
+
hostStripeConnected: boolean;
|
|
95
|
+
lines: FundingLineForProgress[];
|
|
96
|
+
contributions: FundingContributionForProgress[];
|
|
97
|
+
}): FundingMeterProgress {
|
|
98
|
+
const included = input.lines.filter((line) => line.includeOnFundingMeter);
|
|
99
|
+
const includedIds = new Set(included.map((line) => line.id));
|
|
100
|
+
const nameById = new Map(input.lines.map((line) => [line.id, line.name]));
|
|
101
|
+
|
|
102
|
+
const goalCents = included.reduce((sum, line) => sum + line.totalAllocatedCents, 0);
|
|
103
|
+
|
|
104
|
+
let collectedCents = 0;
|
|
105
|
+
let pledgedCents = 0;
|
|
106
|
+
let unallocatedCents = 0;
|
|
107
|
+
const collectedByLine = new Map<string, number>();
|
|
108
|
+
const pledgedByLine = new Map<string, number>();
|
|
109
|
+
const pledges: FundingMeterPledge[] = [];
|
|
110
|
+
const unallocated: FundingMeterPledge[] = [];
|
|
111
|
+
|
|
112
|
+
for (const row of input.contributions) {
|
|
113
|
+
if (INACTIVE.has(row.status)) continue;
|
|
114
|
+
|
|
115
|
+
const isCollected = contributionCountsAsCollected(row);
|
|
116
|
+
const isPledge = contributionCountsAsOpenPledge(row);
|
|
117
|
+
|
|
118
|
+
if (!row.budgetId) {
|
|
119
|
+
if (isCollected || isPledge) {
|
|
120
|
+
unallocatedCents += row.amountCents;
|
|
121
|
+
unallocated.push({
|
|
122
|
+
displayName: row.displayName,
|
|
123
|
+
amountCents: row.amountCents,
|
|
124
|
+
kind: row.kind,
|
|
125
|
+
note: row.note,
|
|
126
|
+
budgetName: null,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (!includedIds.has(row.budgetId)) continue;
|
|
133
|
+
|
|
134
|
+
if (isCollected) {
|
|
135
|
+
collectedCents += row.amountCents;
|
|
136
|
+
collectedByLine.set(
|
|
137
|
+
row.budgetId,
|
|
138
|
+
(collectedByLine.get(row.budgetId) ?? 0) + row.amountCents
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
if (isPledge) {
|
|
142
|
+
pledgedCents += row.amountCents;
|
|
143
|
+
pledgedByLine.set(
|
|
144
|
+
row.budgetId,
|
|
145
|
+
(pledgedByLine.get(row.budgetId) ?? 0) + row.amountCents
|
|
146
|
+
);
|
|
147
|
+
pledges.push({
|
|
148
|
+
displayName: row.displayName,
|
|
149
|
+
amountCents: row.amountCents,
|
|
150
|
+
kind: row.kind,
|
|
151
|
+
note: row.note,
|
|
152
|
+
budgetName: nameById.get(row.budgetId) ?? null,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const lines: FundingMeterLine[] = included.map((line) => {
|
|
158
|
+
const lineCollected = collectedByLine.get(line.id) ?? 0;
|
|
159
|
+
const linePledged = pledgedByLine.get(line.id) ?? 0;
|
|
160
|
+
return {
|
|
161
|
+
budgetId: line.id,
|
|
162
|
+
name: line.name,
|
|
163
|
+
category: line.category,
|
|
164
|
+
allocatedCents: line.totalAllocatedCents,
|
|
165
|
+
collectedCents: lineCollected,
|
|
166
|
+
pledgedCents: linePledged,
|
|
167
|
+
remainingCents: Math.max(0, line.totalAllocatedCents - lineCollected),
|
|
168
|
+
};
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const percentFunded =
|
|
172
|
+
goalCents > 0 ? Math.min(100, Math.round((collectedCents / goalCents) * 100)) : 0;
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
showFundingMeter: input.showFundingMeter,
|
|
176
|
+
fundingAllowCommitments: input.fundingAllowCommitments,
|
|
177
|
+
fundingShowPledgesOnMeter: input.fundingShowPledgesOnMeter,
|
|
178
|
+
hostStripeConnected: input.hostStripeConnected,
|
|
179
|
+
goalCents,
|
|
180
|
+
collectedCents,
|
|
181
|
+
pledgedCents,
|
|
182
|
+
unallocatedCents,
|
|
183
|
+
percentFunded,
|
|
184
|
+
lines,
|
|
185
|
+
pledges,
|
|
186
|
+
unallocated,
|
|
187
|
+
};
|
|
188
|
+
}
|