@bash-app/bash-common 30.321.0 → 30.322.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.
@@ -9,9 +9,13 @@ describe("sideQuestIdeas", () => {
9
9
  expect(hits.length).toBeGreaterThan(0);
10
10
  expect(hits.every((h) => JSON.stringify(h).toLowerCase().includes("transit") || h.category === "Transit")).toBe(true);
11
11
  });
12
- it("includes Vote in phase 1 types", () => {
12
+ it("includes Vote, Circuit, and Connect in phase 1 types", () => {
13
13
  expect(SIDE_QUEST_PHASE1_TYPES).toContain("Vote");
14
+ expect(SIDE_QUEST_PHASE1_TYPES).toContain("Circuit");
15
+ expect(SIDE_QUEST_PHASE1_TYPES).toContain("Connect");
14
16
  expect(SIDE_QUEST_TYPE_META.Vote.phase1).toBe(true);
17
+ expect(SIDE_QUEST_TYPE_META.Circuit.phase1).toBe(true);
18
+ expect(SIDE_QUEST_TYPE_META.Connect.phase1).toBe(true);
15
19
  });
16
20
  });
17
21
  //# sourceMappingURL=sideQuestIdeas.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestIdeas.test.js","sourceRoot":"","sources":["../../src/__tests__/sideQuestIdeas.test.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CACpE,IAAI,CACL,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,IAAI,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,CAAC,uBAAuB,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"sideQuestIdeas.test.js","sourceRoot":"","sources":["../../src/__tests__/sideQuestIdeas.test.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CACpE,IAAI,CACL,CAAC;QACF,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,IAAI,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,uBAAuB,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,CAAC,uBAAuB,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,uBAAuB,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QACrD,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,CAAC,oBAAoB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { buildSideQuestDeepLink, buildSideQuestLegacyPayload, parseSideQuestScanPayload, } from "../sideQuestTypes.js";
1
+ import { buildSideQuestDeepLink, buildSideQuestLegacyPayload, parseSideQuestScanPayload, parseTicketDoorQrPayload, } from "../sideQuestTypes.js";
2
2
  describe("sideQuestTypes deep links", () => {
3
3
  it("builds HTTPS ticket-details URLs", () => {
4
4
  expect(buildSideQuestDeepLink({
@@ -22,8 +22,40 @@ describe("sideQuestTypes deep links", () => {
22
22
  code: "AB12",
23
23
  });
24
24
  });
25
+ it("builds and parses checkpoint deep links", () => {
26
+ const url = buildSideQuestDeepLink({
27
+ bashEventId: "evt1",
28
+ questId: "q1",
29
+ code: "ab12",
30
+ checkpointId: "cp9",
31
+ frontendOrigin: "https://bash.community",
32
+ });
33
+ expect(url).toContain("checkpoint=cp9");
34
+ expect(parseSideQuestScanPayload(url)).toEqual({
35
+ bashEventId: "evt1",
36
+ questId: "q1",
37
+ checkpointId: "cp9",
38
+ code: "AB12",
39
+ });
40
+ });
25
41
  it("parses plain codes", () => {
26
42
  expect(parseSideQuestScanPayload("ab12")).toEqual({ code: "AB12" });
27
43
  });
44
+ it("parses ticket door QR JSON for Connect meets", () => {
45
+ expect(parseTicketDoorQrPayload(JSON.stringify({
46
+ eventId: "evt-1",
47
+ userId: "user-2",
48
+ ticketId: "tix-9",
49
+ qrToken: "tok",
50
+ timestamp: "2026-01-01T00:00:00.000Z",
51
+ }))).toEqual({
52
+ eventId: "evt-1",
53
+ userId: "user-2",
54
+ ticketId: "tix-9",
55
+ qrToken: "tok",
56
+ });
57
+ expect(parseTicketDoorQrPayload("not-json")).toBeNull();
58
+ expect(parseTicketDoorQrPayload(JSON.stringify({ eventId: "e", userId: "u" }))).toBeNull();
59
+ });
28
60
  });
29
61
  //# sourceMappingURL=sideQuestTypes.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestTypes.test.js","sourceRoot":"","sources":["../../src/__tests__/sideQuestTypes.test.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAE9B,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CACJ,sBAAsB,CAAC;YACrB,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;YACZ,cAAc,EAAE,wBAAwB;SACzC,CAAC,CACH,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CACJ,yBAAyB,CACvB,+DAA+D,CAChE,CACF,CAAC,OAAO,CAAC;YACR,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CACJ,yBAAyB,CAAC,2BAA2B,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAC7E,CAAC,OAAO,CAAC;YACR,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"sideQuestTypes.test.js","sourceRoot":"","sources":["../../src/__tests__/sideQuestTypes.test.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,sBAAsB,EACtB,2BAA2B,EAC3B,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC1C,MAAM,CACJ,sBAAsB,CAAC;YACrB,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;YACZ,cAAc,EAAE,wBAAwB;SACzC,CAAC,CACH,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACjC,MAAM,CACJ,yBAAyB,CACvB,+DAA+D,CAChE,CACF,CAAC,OAAO,CAAC;YACR,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CACJ,yBAAyB,CAAC,2BAA2B,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAC7E,CAAC,OAAO,CAAC;YACR,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACjD,MAAM,GAAG,GAAG,sBAAsB,CAAC;YACjC,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,MAAM;YACZ,YAAY,EAAE,KAAK;YACnB,cAAc,EAAE,wBAAwB;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACxC,MAAM,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7C,WAAW,EAAE,MAAM;YACnB,OAAO,EAAE,IAAI;YACb,YAAY,EAAE,KAAK;YACnB,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,CACJ,wBAAwB,CACtB,IAAI,CAAC,SAAS,CAAC;YACb,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,0BAA0B;SACtC,CAAC,CACH,CACF,CAAC,OAAO,CAAC;YACR,OAAO,EAAE,OAAO;YAChB,MAAM,EAAE,QAAQ;YAChB,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,KAAK;SACf,CAAC,CAAC;QACH,MAAM,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxD,MAAM,CACJ,wBAAwB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CACxE,CAAC,QAAQ,EAAE,CAAC;IACf,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -3,12 +3,12 @@
3
3
  * Behavior design: Action → Prove (quest type) → Reward.
4
4
  */
5
5
  export type SideQuestCategoryId = "Explore" | "Connect" | "Discover" | "SupportLocal" | "Compete" | "Transit" | "Create" | "GiveBack";
6
- export type SideQuestTypeId = "Qr" | "Code" | "Gps" | "Photo" | "CheckIn" | "Purchase" | "Vote" | "Sponsor" | "Social" | "Trivia";
6
+ export type SideQuestTypeId = "Qr" | "Code" | "Gps" | "Photo" | "CheckIn" | "Purchase" | "Vote" | "Sponsor" | "Social" | "Trivia" | "Circuit" | "Connect";
7
7
  export declare const SIDE_QUEST_CATEGORY_META: Record<SideQuestCategoryId, {
8
8
  label: string;
9
9
  emoji: string;
10
10
  }>;
11
- /** Phase 1 host-selectable quest types */
11
+ /** Host-selectable quest types (single-shot + Circuit/Connect) */
12
12
  export declare const SIDE_QUEST_PHASE1_TYPES: SideQuestTypeId[];
13
13
  export declare const SIDE_QUEST_TYPE_META: Record<SideQuestTypeId, {
14
14
  label: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestIdeas.d.ts","sourceRoot":"","sources":["../src/sideQuestIdeas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,UAAU,GACV,cAAc,GACd,SAAS,GACT,SAAS,GACT,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,MAAM,eAAe,GACvB,IAAI,GACJ,MAAM,GACN,KAAK,GACL,OAAO,GACP,SAAS,GACT,UAAU,GACV,MAAM,GACN,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,mBAAmB,EACnB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAUjC,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,uBAAuB,EAAE,eAAe,EAA2B,CAAC;AAEjF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CACvC,eAAe,EACf;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAoDxD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,EAAE,aAAa,EA6G3C,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAUpE;AAED,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;EAyBhC,CAAC"}
1
+ {"version":3,"file":"sideQuestIdeas.d.ts","sourceRoot":"","sources":["../src/sideQuestIdeas.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,mBAAmB,GAC3B,SAAS,GACT,SAAS,GACT,UAAU,GACV,cAAc,GACd,SAAS,GACT,SAAS,GACT,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,MAAM,eAAe,GACvB,IAAI,GACJ,MAAM,GACN,KAAK,GACL,OAAO,GACP,SAAS,GACT,UAAU,GACV,MAAM,GACN,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,SAAS,CAAC;AAEd,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAC3C,mBAAmB,EACnB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAUjC,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,EAAE,eAAe,EAMpD,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CACvC,eAAe,EACf;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CA+DxD,CAAC;AAEF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,eAAO,MAAM,gBAAgB,EAAE,aAAa,EA6G3C,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAUpE;AAED,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;EAyBhC,CAAC"}
@@ -12,8 +12,14 @@ export const SIDE_QUEST_CATEGORY_META = {
12
12
  Create: { label: "Create", emoji: "📸" },
13
13
  GiveBack: { label: "Give Back", emoji: "❤️" },
14
14
  };
15
- /** Phase 1 host-selectable quest types */
16
- export const SIDE_QUEST_PHASE1_TYPES = ["Qr", "Code", "Vote"];
15
+ /** Host-selectable quest types (single-shot + Circuit/Connect) */
16
+ export const SIDE_QUEST_PHASE1_TYPES = [
17
+ "Qr",
18
+ "Code",
19
+ "Vote",
20
+ "Circuit",
21
+ "Connect",
22
+ ];
17
23
  export const SIDE_QUEST_TYPE_META = {
18
24
  Qr: {
19
25
  label: "QR Quest",
@@ -65,6 +71,16 @@ export const SIDE_QUEST_TYPE_META = {
65
71
  description: "Answer a question correctly.",
66
72
  phase1: false,
67
73
  },
74
+ Circuit: {
75
+ label: "Vendor circuit",
76
+ description: "Guest scans QRs at N booths — progress ticks toward done.",
77
+ phase1: true,
78
+ },
79
+ Connect: {
80
+ label: "Icebreaker Connect",
81
+ description: "Meet N people by scanning their ticket QR after the icebreaker.",
82
+ phase1: true,
83
+ },
68
84
  };
69
85
  export const SIDE_QUEST_IDEAS = [
70
86
  {
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestIdeas.js","sourceRoot":"","sources":["../src/sideQuestIdeas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sideQuestIdeas.js","sourceRoot":"","sources":["../src/sideQuestIdeas.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,35 @@ export interface EventBadgeExt {
10
10
  imageUrl: string;
11
11
  createdByUserId?: string;
12
12
  }
13
+ export interface SideQuestCheckpointExt {
14
+ id: string;
15
+ label: string;
16
+ sortOrder: number;
17
+ code?: string;
18
+ /** Guest: whether this checkpoint was already hit */
19
+ hit?: boolean;
20
+ serviceBookingId?: string | null;
21
+ serviceId?: string | null;
22
+ vendorBookingRequestId?: string | null;
23
+ exhibitorBookingRequestId?: string | null;
24
+ contactEmail?: string | null;
25
+ contactName?: string | null;
26
+ /** Host: resolved assignee label for booth list */
27
+ assigneeLabel?: string | null;
28
+ /** Host: email we can send the booth QR to */
29
+ assigneeEmail?: string | null;
30
+ }
31
+ /** Assignable vendor/exhibitor for circuit booth picker (host). */
32
+ export interface CircuitVendorOptionExt {
33
+ sourceType: "serviceBooking" | "vendorRequest" | "exhibitorRequest";
34
+ id: string;
35
+ serviceId: string;
36
+ displayName: string;
37
+ status: string;
38
+ contactEmail: string | null;
39
+ contactName: string | null;
40
+ kindLabel: "Vendor" | "Exhibitor";
41
+ }
13
42
  export interface SideQuestExt {
14
43
  id: string;
15
44
  title: string;
@@ -32,6 +61,18 @@ export interface SideQuestExt {
32
61
  completed?: boolean;
33
62
  code?: string;
34
63
  completionCount?: number;
64
+ requiredTicks?: number;
65
+ icebreakerPrompt?: string | null;
66
+ /** Resolved prompt for Connect (bash icebreaker preferred) */
67
+ resolvedIcebreakerPrompt?: string | null;
68
+ progressCurrent?: number;
69
+ progressTarget?: number;
70
+ checkpoints?: SideQuestCheckpointExt[];
71
+ /** Guest Connect: names / users already logged */
72
+ meetHits?: Array<{
73
+ meetDisplayName: string | null;
74
+ meetUserId: string | null;
75
+ }>;
35
76
  }
36
77
  export interface SideQuestMilestoneExt {
37
78
  id: string;
@@ -61,6 +102,14 @@ export interface SideQuestLogExt {
61
102
  raffleEntries: number;
62
103
  pointsFromQuests: number;
63
104
  community: CommunityQuestGoalExt | null;
105
+ /** Aggregate Side Quest completions tonight (all guests) */
106
+ tonightCompletions?: number;
107
+ /** Next personal milestone distance (without leaking secret rewards) */
108
+ nextMilestone?: {
109
+ requiredCompletions: number;
110
+ remaining: number;
111
+ unlocksSecret: boolean;
112
+ } | null;
64
113
  }
65
114
  export interface SideQuestHostBundleExt {
66
115
  quests: SideQuestExt[];
@@ -92,11 +141,23 @@ export interface SideQuestAnalyticsExt {
92
141
  completedAt: string | Date;
93
142
  }>;
94
143
  }
144
+ /** Lifetime Progress page summary */
145
+ export interface SideQuestLifetimeSummaryExt {
146
+ totalCompletions: number;
147
+ eventsWithCompletions: number;
148
+ recent: Array<{
149
+ bashEventId: string;
150
+ bashTitle: string;
151
+ completionCount: number;
152
+ lastCompletedAt: string | Date;
153
+ }>;
154
+ }
95
155
  /** Absolute or path-only HTTPS deep link for booth QR codes. */
96
156
  export declare function buildSideQuestDeepLink(params: {
97
157
  bashEventId: string;
98
158
  questId: string;
99
159
  code: string;
160
+ checkpointId?: string;
100
161
  /** Origin without trailing slash, e.g. https://bash.community */
101
162
  frontendOrigin?: string;
102
163
  slug?: string | null;
@@ -106,6 +167,7 @@ export declare function buildSideQuestLegacyPayload(bashEventId: string, questId
106
167
  export type ParsedSideQuestScan = {
107
168
  bashEventId?: string;
108
169
  questId?: string;
170
+ checkpointId?: string;
109
171
  code: string;
110
172
  };
111
173
  /**
@@ -113,4 +175,18 @@ export type ParsedSideQuestScan = {
113
175
  * Supports HTTPS ticket-details URLs and legacy `bash-side-quest:` payloads.
114
176
  */
115
177
  export declare function parseSideQuestScanPayload(raw: string): ParsedSideQuestScan | null;
178
+ /** Normalize a Connect meet display name for soft dedupe (legacy name hits). */
179
+ export declare function normalizeMeetNameKey(name: string): string;
180
+ /** Ticket door-scan QR payload (JSON string on guest ticket QR). */
181
+ export type ParsedTicketDoorQr = {
182
+ eventId: string;
183
+ userId: string;
184
+ ticketId: string;
185
+ qrToken?: string;
186
+ };
187
+ /**
188
+ * Parse a ticket check-in / door QR JSON payload.
189
+ * Used by Connect Side Quests: scan their ticket → log the meet.
190
+ */
191
+ export declare function parseTicketDoorQrPayload(raw: string): ParsedTicketDoorQr | null;
116
192
  //# sourceMappingURL=sideQuestTypes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestTypes.d.ts","sourceRoot":"","sources":["../src/sideQuestTypes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sideQuestTypes.d.ts","sourceRoot":"","sources":["../src/sideQuestTypes.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,9 @@ export function buildSideQuestDeepLink(params) {
10
10
  quest: params.questId,
11
11
  code,
12
12
  });
13
+ if (params.checkpointId) {
14
+ qs.set("checkpoint", params.checkpointId);
15
+ }
13
16
  const path = `${TICKET_DETAILS}/${params.bashEventId}?${qs.toString()}`;
14
17
  const origin = (params.frontendOrigin ?? "").replace(/\/$/, "");
15
18
  return origin ? `${origin}${path}` : path;
@@ -43,10 +46,12 @@ export function parseSideQuestScanPayload(raw) {
43
46
  ? new URL(trimmed)
44
47
  : new URL(trimmed, "https://bash.community");
45
48
  const questId = url.searchParams.get("quest") ?? undefined;
49
+ const checkpointId = url.searchParams.get("checkpoint") ?? undefined;
46
50
  const codeParam = url.searchParams.get("code");
47
51
  if (codeParam) {
48
52
  return {
49
53
  questId: questId || undefined,
54
+ checkpointId: checkpointId || undefined,
50
55
  code: codeParam.trim().toUpperCase().replace(/\s+/g, ""),
51
56
  bashEventId: url.pathname.includes("/ticket-details/")
52
57
  ? url.pathname.split("/ticket-details/")[1]?.split(/[/?#]/)[0]
@@ -64,4 +69,34 @@ export function parseSideQuestScanPayload(raw) {
64
69
  }
65
70
  return null;
66
71
  }
72
+ /** Normalize a Connect meet display name for soft dedupe (legacy name hits). */
73
+ export function normalizeMeetNameKey(name) {
74
+ return name.trim().toLowerCase().replace(/\s+/g, " ");
75
+ }
76
+ /**
77
+ * Parse a ticket check-in / door QR JSON payload.
78
+ * Used by Connect Side Quests: scan their ticket → log the meet.
79
+ */
80
+ export function parseTicketDoorQrPayload(raw) {
81
+ const trimmed = raw.trim();
82
+ if (!trimmed.startsWith("{"))
83
+ return null;
84
+ try {
85
+ const data = JSON.parse(trimmed);
86
+ const eventId = typeof data.eventId === "string" ? data.eventId.trim() : "";
87
+ const userId = typeof data.userId === "string" ? data.userId.trim() : "";
88
+ const ticketId = typeof data.ticketId === "string" ? data.ticketId.trim() : "";
89
+ if (!eventId || !userId || !ticketId)
90
+ return null;
91
+ const qrToken = typeof data.qrToken === "string" && data.qrToken.trim()
92
+ ? data.qrToken.trim()
93
+ : undefined;
94
+ return qrToken
95
+ ? { eventId, userId, ticketId, qrToken }
96
+ : { eventId, userId, ticketId };
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
67
102
  //# sourceMappingURL=sideQuestTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sideQuestTypes.js","sourceRoot":"","sources":["../src/sideQuestTypes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sideQuestTypes.js","sourceRoot":"","sources":["../src/sideQuestTypes.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bash-app/bash-common",
3
- "version": "30.321.0",
3
+ "version": "30.322.0",
4
4
  "description": "Common data and scripts to use on the frontend and backend",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -2043,7 +2043,7 @@ enum SideQuestCategory {
2043
2043
  GiveBack
2044
2044
  }
2045
2045
 
2046
- /// How the guest proves completion. Phase 1: Qr + Code. Others reserved.
2046
+ /// How the guest proves completion. Phase 1+: Qr, Code, Vote, Circuit, Connect. Others reserved.
2047
2047
  enum SideQuestType {
2048
2048
  Qr
2049
2049
  Code
@@ -2055,6 +2055,10 @@ enum SideQuestType {
2055
2055
  Sponsor
2056
2056
  Social
2057
2057
  Trivia
2058
+ /// Multi-stop booth tour — guest scans N checkpoint QRs
2059
+ Circuit
2060
+ /// Meet N people — scan their ticket QR after the icebreaker (requiredTicks)
2061
+ Connect
2058
2062
  }
2059
2063
 
2060
2064
  enum EventBadgeAwardSource {
@@ -2089,6 +2093,12 @@ model SideQuest {
2089
2093
  sponsorServiceId String?
2090
2094
  /// When questType is Vote: the competition casting a vote completes this quest
2091
2095
  competitionId String?
2096
+ /// Ticks needed for this guest to complete (1 = single-shot; Circuit/Connect use N)
2097
+ requiredTicks Int @default(1)
2098
+ /// Quest-local icebreaker when bash icebreaker is off (Connect quests)
2099
+ icebreakerPrompt String?
2100
+ /// Set when timed-window-open push has been sent (cron)
2101
+ windowOpenedNotifiedAt DateTime?
2092
2102
  createdAt DateTime @default(now())
2093
2103
  updatedAt DateTime @updatedAt
2094
2104
 
@@ -2097,11 +2107,70 @@ model SideQuest {
2097
2107
  competition Competition? @relation(fields: [competitionId], references: [id], onDelete: SetNull)
2098
2108
  completions SideQuestCompletion[]
2099
2109
  milestonesUnlocking SideQuestMilestone[] @relation("MilestoneUnlocksQuest")
2110
+ checkpoints SideQuestCheckpoint[]
2111
+ progressHits SideQuestProgressHit[]
2100
2112
 
2101
2113
  @@index([bashEventId])
2102
2114
  @@index([bashEventId, sortOrder])
2103
2115
  @@index([eventBadgeId])
2104
2116
  @@index([competitionId])
2117
+ @@index([startsAt, windowOpenedNotifiedAt])
2118
+ }
2119
+
2120
+ model SideQuestCheckpoint {
2121
+ id String @id @default(cuid())
2122
+ sideQuestId String
2123
+ label String
2124
+ sortOrder Int @default(0)
2125
+ code String
2126
+ codeHash String
2127
+ /// Platform hire (Vendors / Exhibitors) — Pending, Approved, or Confirmed.
2128
+ serviceBookingId String?
2129
+ serviceId String?
2130
+ /// Partner request flows (vendor or exhibitor) before/at confirm.
2131
+ vendorBookingRequestId String?
2132
+ exhibitorBookingRequestId String?
2133
+ /// Off-platform vendor — QR emailed here; optional display name.
2134
+ contactEmail String?
2135
+ contactName String?
2136
+ createdAt DateTime @default(now())
2137
+ updatedAt DateTime @updatedAt
2138
+
2139
+ sideQuest SideQuest @relation(fields: [sideQuestId], references: [id], onDelete: Cascade)
2140
+ hits SideQuestProgressHit[]
2141
+ serviceBooking ServiceBooking? @relation(fields: [serviceBookingId], references: [id], onDelete: SetNull)
2142
+ service Service? @relation(fields: [serviceId], references: [id], onDelete: SetNull)
2143
+ vendorBookingRequest VendorBookingRequest? @relation(fields: [vendorBookingRequestId], references: [id], onDelete: SetNull)
2144
+ exhibitorBookingRequest ExhibitorBookingRequest? @relation(fields: [exhibitorBookingRequestId], references: [id], onDelete: SetNull)
2145
+
2146
+ @@index([sideQuestId, sortOrder])
2147
+ @@index([sideQuestId, codeHash])
2148
+ @@index([serviceBookingId])
2149
+ @@index([vendorBookingRequestId])
2150
+ @@index([exhibitorBookingRequestId])
2151
+ }
2152
+
2153
+ /// Per-guest progress toward requiredTicks (checkpoint scan or Connect meet).
2154
+ model SideQuestProgressHit {
2155
+ id String @id @default(cuid())
2156
+ sideQuestId String
2157
+ userId String
2158
+ /// Stable key: "cp:{checkpointId}" | "user:{meetUserId}" | "name:{normalized}"
2159
+ dedupeKey String
2160
+ checkpointId String?
2161
+ meetDisplayName String?
2162
+ meetUserId String?
2163
+ createdAt DateTime @default(now())
2164
+
2165
+ sideQuest SideQuest @relation(fields: [sideQuestId], references: [id], onDelete: Cascade)
2166
+ user User @relation("SideQuestProgressHits", fields: [userId], references: [id], onDelete: Cascade)
2167
+ checkpoint SideQuestCheckpoint? @relation(fields: [checkpointId], references: [id], onDelete: Cascade)
2168
+ meetUser User? @relation("SideQuestMeetTargets", fields: [meetUserId], references: [id], onDelete: SetNull)
2169
+
2170
+ @@unique([sideQuestId, userId, dedupeKey])
2171
+ @@index([sideQuestId, userId])
2172
+ @@index([userId])
2173
+ @@index([checkpointId])
2105
2174
  }
2106
2175
 
2107
2176
  model SideQuestCompletion {
@@ -2217,6 +2286,8 @@ model CommunityQuestGoal {
2217
2286
  eventBadgeId String?
2218
2287
  bashPointsReward Int?
2219
2288
  unlockedAt DateTime?
2289
+ /// Set when ~80% near-goal push has been sent (once per event)
2290
+ nearGoalNotifiedAt DateTime?
2220
2291
  createdAt DateTime @default(now())
2221
2292
  updatedAt DateTime @updatedAt
2222
2293
 
@@ -3815,6 +3886,8 @@ model User {
3815
3886
  eventBadgeAwards EventBadgeAward[] @relation("EventBadgeAwards")
3816
3887
  sideQuestMilestoneClaims SideQuestMilestoneClaim[] @relation("SideQuestMilestoneClaims")
3817
3888
  sideQuestPrizeEntries SideQuestPrizeEntry[] @relation("SideQuestPrizeEntries")
3889
+ sideQuestProgressHits SideQuestProgressHit[] @relation("SideQuestProgressHits")
3890
+ sideQuestMeetTargets SideQuestProgressHit[] @relation("SideQuestMeetTargets")
3818
3891
  contacts Contact[]
3819
3892
  contactLists ContactList[] @relation("UserContactLists")
3820
3893
  contactlist ContactList[]
@@ -4638,6 +4711,7 @@ model Service {
4638
4711
  googleReviews GoogleReview[]
4639
4712
  serviceReviews ServiceReview[]
4640
4713
  providerHostReviews ProviderHostReview[]
4714
+ sideQuestCheckpoints SideQuestCheckpoint[]
4641
4715
 
4642
4716
  @@index([serviceListingStripeSubscriptionId])
4643
4717
  @@index([paymentAccountId])
@@ -6383,6 +6457,7 @@ model ServiceBooking {
6383
6457
  representedByOrganization Organization? @relation(fields: [representedByOrganizationId], references: [id], onDelete: SetNull)
6384
6458
  representation OrganizationArtistRepresentation? @relation("BookingRepresentation", fields: [representationId], references: [id], onDelete: SetNull)
6385
6459
  agencySettlement AgencyBookingSettlement?
6460
+ sideQuestCheckpoints SideQuestCheckpoint[]
6386
6461
 
6387
6462
  @@index([status])
6388
6463
  @@index([creatorId])
@@ -6452,6 +6527,7 @@ model VendorBookingRequest {
6452
6527
  vendorService Service @relation("VendorBookingService", fields: [vendorServiceId], references: [id], onDelete: Cascade)
6453
6528
  offers ServiceBookingOffer[]
6454
6529
  categoryExclusivities VendorCategoryExclusivity[]
6530
+ sideQuestCheckpoints SideQuestCheckpoint[]
6455
6531
 
6456
6532
  @@index([hostUserId])
6457
6533
  @@index([vendorServiceId])
@@ -6575,6 +6651,7 @@ model ExhibitorBookingRequest {
6575
6651
  exhibitorService Service @relation("ExhibitorBookingService", fields: [exhibitorServiceId], references: [id], onDelete: Cascade)
6576
6652
  hostUser User @relation("ExhibitorBookingHost", fields: [hostUserId], references: [id], onDelete: Cascade)
6577
6653
  serviceMessages ServiceBookingMessage[] @relation("ExhibitorServiceMessages")
6654
+ sideQuestCheckpoints SideQuestCheckpoint[]
6578
6655
 
6579
6656
  @@index([hostUserId])
6580
6657
  @@index([exhibitorServiceId])
@@ -7080,6 +7157,8 @@ enum NotificationType {
7080
7157
  PartnerPromotionBlast // Attendee: partner on-site promo deal at an event
7081
7158
  SideQuestRevealed // Attendee: host revealed a secret Side Quest
7082
7159
  CommunityQuestUnlocked // Attendee: community quest goal unlocked
7160
+ CommunityQuestNearGoal // Attendee: community goal ~80% of the way
7161
+ SideQuestWindowOpened // Attendee: a timed Side Quest just went live
7083
7162
  }
7084
7163
 
7085
7164
  /// Opt-in reminder for a scheduled tier release (v1.5).
@@ -19,8 +19,12 @@ describe("sideQuestIdeas", () => {
19
19
  expect(hits.every((h) => JSON.stringify(h).toLowerCase().includes("transit") || h.category === "Transit")).toBe(true);
20
20
  });
21
21
 
22
- it("includes Vote in phase 1 types", () => {
22
+ it("includes Vote, Circuit, and Connect in phase 1 types", () => {
23
23
  expect(SIDE_QUEST_PHASE1_TYPES).toContain("Vote");
24
+ expect(SIDE_QUEST_PHASE1_TYPES).toContain("Circuit");
25
+ expect(SIDE_QUEST_PHASE1_TYPES).toContain("Connect");
24
26
  expect(SIDE_QUEST_TYPE_META.Vote.phase1).toBe(true);
27
+ expect(SIDE_QUEST_TYPE_META.Circuit.phase1).toBe(true);
28
+ expect(SIDE_QUEST_TYPE_META.Connect.phase1).toBe(true);
25
29
  });
26
30
  });
@@ -2,6 +2,7 @@ import {
2
2
  buildSideQuestDeepLink,
3
3
  buildSideQuestLegacyPayload,
4
4
  parseSideQuestScanPayload,
5
+ parseTicketDoorQrPayload,
5
6
  } from "../sideQuestTypes.js";
6
7
 
7
8
  describe("sideQuestTypes deep links", () => {
@@ -38,7 +39,47 @@ describe("sideQuestTypes deep links", () => {
38
39
  });
39
40
  });
40
41
 
42
+ it("builds and parses checkpoint deep links", () => {
43
+ const url = buildSideQuestDeepLink({
44
+ bashEventId: "evt1",
45
+ questId: "q1",
46
+ code: "ab12",
47
+ checkpointId: "cp9",
48
+ frontendOrigin: "https://bash.community",
49
+ });
50
+ expect(url).toContain("checkpoint=cp9");
51
+ expect(parseSideQuestScanPayload(url)).toEqual({
52
+ bashEventId: "evt1",
53
+ questId: "q1",
54
+ checkpointId: "cp9",
55
+ code: "AB12",
56
+ });
57
+ });
58
+
41
59
  it("parses plain codes", () => {
42
60
  expect(parseSideQuestScanPayload("ab12")).toEqual({ code: "AB12" });
43
61
  });
62
+
63
+ it("parses ticket door QR JSON for Connect meets", () => {
64
+ expect(
65
+ parseTicketDoorQrPayload(
66
+ JSON.stringify({
67
+ eventId: "evt-1",
68
+ userId: "user-2",
69
+ ticketId: "tix-9",
70
+ qrToken: "tok",
71
+ timestamp: "2026-01-01T00:00:00.000Z",
72
+ })
73
+ )
74
+ ).toEqual({
75
+ eventId: "evt-1",
76
+ userId: "user-2",
77
+ ticketId: "tix-9",
78
+ qrToken: "tok",
79
+ });
80
+ expect(parseTicketDoorQrPayload("not-json")).toBeNull();
81
+ expect(
82
+ parseTicketDoorQrPayload(JSON.stringify({ eventId: "e", userId: "u" }))
83
+ ).toBeNull();
84
+ });
44
85
  });
@@ -23,7 +23,9 @@ export type SideQuestTypeId =
23
23
  | "Vote"
24
24
  | "Sponsor"
25
25
  | "Social"
26
- | "Trivia";
26
+ | "Trivia"
27
+ | "Circuit"
28
+ | "Connect";
27
29
 
28
30
  export const SIDE_QUEST_CATEGORY_META: Record<
29
31
  SideQuestCategoryId,
@@ -39,8 +41,14 @@ export const SIDE_QUEST_CATEGORY_META: Record<
39
41
  GiveBack: { label: "Give Back", emoji: "❤️" },
40
42
  };
41
43
 
42
- /** Phase 1 host-selectable quest types */
43
- export const SIDE_QUEST_PHASE1_TYPES: SideQuestTypeId[] = ["Qr", "Code", "Vote"];
44
+ /** Host-selectable quest types (single-shot + Circuit/Connect) */
45
+ export const SIDE_QUEST_PHASE1_TYPES: SideQuestTypeId[] = [
46
+ "Qr",
47
+ "Code",
48
+ "Vote",
49
+ "Circuit",
50
+ "Connect",
51
+ ];
44
52
 
45
53
  export const SIDE_QUEST_TYPE_META: Record<
46
54
  SideQuestTypeId,
@@ -96,6 +104,17 @@ export const SIDE_QUEST_TYPE_META: Record<
96
104
  description: "Answer a question correctly.",
97
105
  phase1: false,
98
106
  },
107
+ Circuit: {
108
+ label: "Vendor circuit",
109
+ description: "Guest scans QRs at N booths — progress ticks toward done.",
110
+ phase1: true,
111
+ },
112
+ Connect: {
113
+ label: "Icebreaker Connect",
114
+ description:
115
+ "Meet N people by scanning their ticket QR after the icebreaker.",
116
+ phase1: true,
117
+ },
99
118
  };
100
119
 
101
120
  export interface SideQuestIdea {
@@ -14,6 +14,37 @@ export interface EventBadgeExt {
14
14
  createdByUserId?: string;
15
15
  }
16
16
 
17
+ export interface SideQuestCheckpointExt {
18
+ id: string;
19
+ label: string;
20
+ sortOrder: number;
21
+ code?: string;
22
+ /** Guest: whether this checkpoint was already hit */
23
+ hit?: boolean;
24
+ serviceBookingId?: string | null;
25
+ serviceId?: string | null;
26
+ vendorBookingRequestId?: string | null;
27
+ exhibitorBookingRequestId?: string | null;
28
+ contactEmail?: string | null;
29
+ contactName?: string | null;
30
+ /** Host: resolved assignee label for booth list */
31
+ assigneeLabel?: string | null;
32
+ /** Host: email we can send the booth QR to */
33
+ assigneeEmail?: string | null;
34
+ }
35
+
36
+ /** Assignable vendor/exhibitor for circuit booth picker (host). */
37
+ export interface CircuitVendorOptionExt {
38
+ sourceType: "serviceBooking" | "vendorRequest" | "exhibitorRequest";
39
+ id: string;
40
+ serviceId: string;
41
+ displayName: string;
42
+ status: string;
43
+ contactEmail: string | null;
44
+ contactName: string | null;
45
+ kindLabel: "Vendor" | "Exhibitor";
46
+ }
47
+
17
48
  export interface SideQuestExt {
18
49
  id: string;
19
50
  title: string;
@@ -39,6 +70,18 @@ export interface SideQuestExt {
39
70
  completed?: boolean;
40
71
  code?: string;
41
72
  completionCount?: number;
73
+ requiredTicks?: number;
74
+ icebreakerPrompt?: string | null;
75
+ /** Resolved prompt for Connect (bash icebreaker preferred) */
76
+ resolvedIcebreakerPrompt?: string | null;
77
+ progressCurrent?: number;
78
+ progressTarget?: number;
79
+ checkpoints?: SideQuestCheckpointExt[];
80
+ /** Guest Connect: names / users already logged */
81
+ meetHits?: Array<{
82
+ meetDisplayName: string | null;
83
+ meetUserId: string | null;
84
+ }>;
42
85
  }
43
86
 
44
87
  export interface SideQuestMilestoneExt {
@@ -71,6 +114,14 @@ export interface SideQuestLogExt {
71
114
  raffleEntries: number;
72
115
  pointsFromQuests: number;
73
116
  community: CommunityQuestGoalExt | null;
117
+ /** Aggregate Side Quest completions tonight (all guests) */
118
+ tonightCompletions?: number;
119
+ /** Next personal milestone distance (without leaking secret rewards) */
120
+ nextMilestone?: {
121
+ requiredCompletions: number;
122
+ remaining: number;
123
+ unlocksSecret: boolean;
124
+ } | null;
74
125
  }
75
126
 
76
127
  export interface SideQuestHostBundleExt {
@@ -105,6 +156,18 @@ export interface SideQuestAnalyticsExt {
105
156
  }>;
106
157
  }
107
158
 
159
+ /** Lifetime Progress page summary */
160
+ export interface SideQuestLifetimeSummaryExt {
161
+ totalCompletions: number;
162
+ eventsWithCompletions: number;
163
+ recent: Array<{
164
+ bashEventId: string;
165
+ bashTitle: string;
166
+ completionCount: number;
167
+ lastCompletedAt: string | Date;
168
+ }>;
169
+ }
170
+
108
171
  const LEGACY_PREFIX = "bash-side-quest:";
109
172
 
110
173
  /** Absolute or path-only HTTPS deep link for booth QR codes. */
@@ -112,6 +175,7 @@ export function buildSideQuestDeepLink(params: {
112
175
  bashEventId: string;
113
176
  questId: string;
114
177
  code: string;
178
+ checkpointId?: string;
115
179
  /** Origin without trailing slash, e.g. https://bash.community */
116
180
  frontendOrigin?: string;
117
181
  slug?: string | null;
@@ -121,6 +185,9 @@ export function buildSideQuestDeepLink(params: {
121
185
  quest: params.questId,
122
186
  code,
123
187
  });
188
+ if (params.checkpointId) {
189
+ qs.set("checkpoint", params.checkpointId);
190
+ }
124
191
  const path = `${TICKET_DETAILS}/${params.bashEventId}?${qs.toString()}`;
125
192
  const origin = (params.frontendOrigin ?? "").replace(/\/$/, "");
126
193
  return origin ? `${origin}${path}` : path;
@@ -139,6 +206,7 @@ export function buildSideQuestLegacyPayload(
139
206
  export type ParsedSideQuestScan = {
140
207
  bashEventId?: string;
141
208
  questId?: string;
209
+ checkpointId?: string;
142
210
  code: string;
143
211
  };
144
212
 
@@ -166,10 +234,12 @@ export function parseSideQuestScanPayload(raw: string): ParsedSideQuestScan | nu
166
234
  ? new URL(trimmed)
167
235
  : new URL(trimmed, "https://bash.community");
168
236
  const questId = url.searchParams.get("quest") ?? undefined;
237
+ const checkpointId = url.searchParams.get("checkpoint") ?? undefined;
169
238
  const codeParam = url.searchParams.get("code");
170
239
  if (codeParam) {
171
240
  return {
172
241
  questId: questId || undefined,
242
+ checkpointId: checkpointId || undefined,
173
243
  code: codeParam.trim().toUpperCase().replace(/\s+/g, ""),
174
244
  bashEventId: url.pathname.includes("/ticket-details/")
175
245
  ? url.pathname.split("/ticket-details/")[1]?.split(/[/?#]/)[0]
@@ -188,3 +258,44 @@ export function parseSideQuestScanPayload(raw: string): ParsedSideQuestScan | nu
188
258
 
189
259
  return null;
190
260
  }
261
+
262
+ /** Normalize a Connect meet display name for soft dedupe (legacy name hits). */
263
+ export function normalizeMeetNameKey(name: string): string {
264
+ return name.trim().toLowerCase().replace(/\s+/g, " ");
265
+ }
266
+
267
+ /** Ticket door-scan QR payload (JSON string on guest ticket QR). */
268
+ export type ParsedTicketDoorQr = {
269
+ eventId: string;
270
+ userId: string;
271
+ ticketId: string;
272
+ qrToken?: string;
273
+ };
274
+
275
+ /**
276
+ * Parse a ticket check-in / door QR JSON payload.
277
+ * Used by Connect Side Quests: scan their ticket → log the meet.
278
+ */
279
+ export function parseTicketDoorQrPayload(
280
+ raw: string
281
+ ): ParsedTicketDoorQr | null {
282
+ const trimmed = raw.trim();
283
+ if (!trimmed.startsWith("{")) return null;
284
+ try {
285
+ const data = JSON.parse(trimmed) as Record<string, unknown>;
286
+ const eventId = typeof data.eventId === "string" ? data.eventId.trim() : "";
287
+ const userId = typeof data.userId === "string" ? data.userId.trim() : "";
288
+ const ticketId =
289
+ typeof data.ticketId === "string" ? data.ticketId.trim() : "";
290
+ if (!eventId || !userId || !ticketId) return null;
291
+ const qrToken =
292
+ typeof data.qrToken === "string" && data.qrToken.trim()
293
+ ? data.qrToken.trim()
294
+ : undefined;
295
+ return qrToken
296
+ ? { eventId, userId, ticketId, qrToken }
297
+ : { eventId, userId, ticketId };
298
+ } catch {
299
+ return null;
300
+ }
301
+ }