@timardex/cluemart-shared 1.5.543 → 1.5.545
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/{chunk-PB3J52JN.mjs → chunk-L47NQHZ6.mjs} +2 -2
- package/dist/{chunk-RWA5G6NG.mjs → chunk-LOABFNIJ.mjs} +15 -18
- package/dist/chunk-LOABFNIJ.mjs.map +1 -0
- package/dist/{chunk-UNLHXGT4.mjs → chunk-Z3JWNX2U.mjs} +16 -22
- package/dist/chunk-Z3JWNX2U.mjs.map +1 -0
- package/dist/formFields/index.cjs +96 -0
- package/dist/formFields/index.cjs.map +1 -1
- package/dist/formFields/index.mjs +3 -3
- package/dist/{game-DAQTH29H.d.ts → game-1CSiEjlf.d.ts} +8 -12
- package/dist/{game-CKJKoqrR.d.mts → game-BPtE3yaQ.d.mts} +8 -12
- package/dist/graphql/index.d.mts +2 -2
- package/dist/graphql/index.d.ts +2 -2
- package/dist/hooks/index.cjs +96 -0
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.mts +2 -2
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.mjs +3 -3
- package/dist/index.cjs +28 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -12
- package/dist/index.d.ts +8 -12
- package/dist/index.mjs +28 -37
- package/dist/index.mjs.map +1 -1
- package/dist/{post-C22p1dDe.d.ts → post-C0CIWXwc.d.ts} +1 -1
- package/dist/{post-B65KQS6r.d.mts → post-DjuHzWo7.d.mts} +1 -1
- package/dist/types/index.cjs +14 -17
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.mts +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.mjs +1 -1
- package/dist/utils/index.cjs +28 -37
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-RWA5G6NG.mjs.map +0 -1
- package/dist/chunk-UNLHXGT4.mjs.map +0 -1
- /package/dist/{chunk-PB3J52JN.mjs.map → chunk-L47NQHZ6.mjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
mapArrayToOptions
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Z3JWNX2U.mjs";
|
|
4
4
|
import {
|
|
5
5
|
EnumFoodFlavor
|
|
6
6
|
} from "./chunk-ZR4TGWTS.mjs";
|
|
@@ -1952,4 +1952,4 @@ export {
|
|
|
1952
1952
|
contactUsFields,
|
|
1953
1953
|
partnerBasicInfoFields
|
|
1954
1954
|
};
|
|
1955
|
-
//# sourceMappingURL=chunk-
|
|
1955
|
+
//# sourceMappingURL=chunk-L47NQHZ6.mjs.map
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
// src/types/game.ts
|
|
2
|
+
var OBJECT_ID_PATH_SEGMENT = "[a-f0-9]{24}";
|
|
3
|
+
var OBJECT_ID_PATH_SEGMENT_END = `${OBJECT_ID_PATH_SEGMENT}$`;
|
|
2
4
|
var gameScreenIdentifierList = [
|
|
3
5
|
{
|
|
4
6
|
clue: "Where your actions turn into a timeline.",
|
|
@@ -18,7 +20,7 @@ var gameScreenIdentifierList = [
|
|
|
18
20
|
{
|
|
19
21
|
clue: "A single moment worth showing up for.",
|
|
20
22
|
id: "single-event",
|
|
21
|
-
match:
|
|
23
|
+
match: new RegExp(`^/events/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
22
24
|
},
|
|
23
25
|
{
|
|
24
26
|
clue: "What\u2019s happening around you, right now.",
|
|
@@ -31,15 +33,10 @@ var gameScreenIdentifierList = [
|
|
|
31
33
|
match: "/events"
|
|
32
34
|
},
|
|
33
35
|
{
|
|
34
|
-
clue: "What\u2019s happening in a wider area\
|
|
36
|
+
clue: "What\u2019s happening in a wider area \u2014 not just nearby.",
|
|
35
37
|
id: "events-region",
|
|
36
38
|
match: /^\/events\/region\/[^/]+$/
|
|
37
39
|
},
|
|
38
|
-
{
|
|
39
|
-
clue: "Where you go to find something specific.",
|
|
40
|
-
id: "events-search",
|
|
41
|
-
match: "/events/search"
|
|
42
|
-
},
|
|
43
40
|
{
|
|
44
41
|
clue: "Where fun becomes a challenge.",
|
|
45
42
|
id: "games",
|
|
@@ -51,7 +48,7 @@ var gameScreenIdentifierList = [
|
|
|
51
48
|
match: "/"
|
|
52
49
|
},
|
|
53
50
|
{
|
|
54
|
-
clue: "Where the app
|
|
51
|
+
clue: "Where the app whispers what you shouldn\u2019t miss.",
|
|
55
52
|
id: "notifications",
|
|
56
53
|
match: "/notifications"
|
|
57
54
|
},
|
|
@@ -61,19 +58,19 @@ var gameScreenIdentifierList = [
|
|
|
61
58
|
match: "/options"
|
|
62
59
|
},
|
|
63
60
|
{
|
|
64
|
-
clue: "
|
|
61
|
+
clue: "An organisation or creator supporting the community.",
|
|
65
62
|
id: "single-partner",
|
|
66
|
-
match:
|
|
63
|
+
match: new RegExp(`^/partners/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
67
64
|
},
|
|
68
65
|
{
|
|
69
|
-
clue: "
|
|
66
|
+
clue: "Organisations and creators supporting the community.",
|
|
70
67
|
id: "partners",
|
|
71
68
|
match: "/partners"
|
|
72
69
|
},
|
|
73
70
|
{
|
|
74
|
-
clue: "
|
|
71
|
+
clue: "A single published post in full view.",
|
|
75
72
|
id: "single-visitor-post",
|
|
76
|
-
match:
|
|
73
|
+
match: new RegExp(`^/visitors/post/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
77
74
|
},
|
|
78
75
|
{
|
|
79
76
|
clue: "Your identity, on display.",
|
|
@@ -81,17 +78,17 @@ var gameScreenIdentifierList = [
|
|
|
81
78
|
match: "/profile"
|
|
82
79
|
},
|
|
83
80
|
{
|
|
84
|
-
clue: "One
|
|
81
|
+
clue: "One stallholder offering something valuable.",
|
|
85
82
|
id: "single-vendor",
|
|
86
|
-
match:
|
|
83
|
+
match: new RegExp(`^/vendors/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
87
84
|
},
|
|
88
85
|
{
|
|
89
|
-
clue: "
|
|
86
|
+
clue: "Where every stallholder waits under the right category.",
|
|
90
87
|
id: "vendors",
|
|
91
88
|
match: "/vendors"
|
|
92
89
|
},
|
|
93
90
|
{
|
|
94
|
-
clue: "
|
|
91
|
+
clue: "Where you browse articles and posts from around the platform.",
|
|
95
92
|
id: "visitors",
|
|
96
93
|
match: "/visitors"
|
|
97
94
|
}
|
|
@@ -117,4 +114,4 @@ export {
|
|
|
117
114
|
gameTypeToDisplayName,
|
|
118
115
|
EnumGameStatus
|
|
119
116
|
};
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
117
|
+
//# sourceMappingURL=chunk-LOABFNIJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/game.ts"],"sourcesContent":["import { OwnerType } from \"./global\";\n\nconst OBJECT_ID_PATH_SEGMENT = \"[a-f0-9]{24}\";\nconst OBJECT_ID_PATH_SEGMENT_END = `${OBJECT_ID_PATH_SEGMENT}$`;\n\nexport const gameScreenIdentifierList = [\n {\n clue: \"Where your actions turn into a timeline.\",\n id: \"activities\",\n match: \"/profile/activities\",\n },\n {\n clue: \"Where conversations happen without speaking.\",\n id: \"chat\",\n match: \"/profile/chat\",\n },\n {\n clue: \"The place to redefine who you are.\",\n id: \"edit-profile\",\n match: \"/profile/edit-profile\",\n },\n {\n clue: \"A single moment worth showing up for.\",\n id: \"single-event\",\n match: new RegExp(`^/events/${OBJECT_ID_PATH_SEGMENT_END}`),\n },\n {\n clue: \"What’s happening around you, right now.\",\n id: \"events-near-me\",\n match: \"/events/events-near-me\",\n },\n {\n clue: \"A collection of things worth attending.\",\n id: \"events\",\n match: \"/events\",\n },\n {\n clue: \"What’s happening in a wider area — not just nearby.\",\n id: \"events-region\",\n match: /^\\/events\\/region\\/[^/]+$/,\n },\n {\n clue: \"Where fun becomes a challenge.\",\n id: \"games\",\n match: \"/games\",\n },\n {\n clue: \"Your starting point for everything.\",\n id: \"home\",\n match: \"/\",\n },\n {\n clue: \"Where the app whispers what you shouldn’t miss.\",\n id: \"notifications\",\n match: \"/notifications\",\n },\n {\n clue: \"Where you fine-tune your experience.\",\n id: \"options\",\n match: \"/options\",\n },\n {\n clue: \"An organisation or creator supporting the community.\",\n id: \"single-partner\",\n match: new RegExp(`^/partners/${OBJECT_ID_PATH_SEGMENT_END}`),\n },\n {\n clue: \"Organisations and creators supporting the community.\",\n id: \"partners\",\n match: \"/partners\",\n },\n {\n clue: \"A single published post in full view.\",\n id: \"single-visitor-post\",\n match: new RegExp(`^/visitors/post/${OBJECT_ID_PATH_SEGMENT_END}`),\n },\n {\n clue: \"Your identity, on display.\",\n id: \"profile\",\n match: \"/profile\",\n },\n {\n clue: \"One stallholder offering something valuable.\",\n id: \"single-vendor\",\n match: new RegExp(`^/vendors/${OBJECT_ID_PATH_SEGMENT_END}`),\n },\n {\n clue: \"Where every stallholder waits under the right category.\",\n id: \"vendors\",\n match: \"/vendors\",\n },\n {\n clue: \"Where you browse articles and posts from around the platform.\",\n id: \"visitors\",\n match: \"/visitors\",\n },\n] as const;\n\nexport type GamePlacement = (typeof gameScreenIdentifierList)[number][\"id\"];\nexport type GamePlacementClue =\n (typeof gameScreenIdentifierList)[number][\"clue\"];\n\nexport enum EnumGameType {\n DAILY_CLUE = \"dailyClue\",\n}\n\nexport const gameTypeToDisplayName: Record<EnumGameType, string> = {\n [EnumGameType.DAILY_CLUE]: \"Daily Clue\",\n};\n\nexport type GameDate = {\n startDate: Date;\n endDate: Date;\n};\n\nexport type BaseGame = {\n gameDate: GameDate;\n gameSolution: string;\n gameType: EnumGameType;\n};\n\nexport type DailyClueGameData = {\n gameFields: BaseGame;\n lastFoundDate: Date | null;\n points: number;\n letterInfo: {\n collected: string[] | null; // The letters the user has found, e.g. [\"C\", \"L\", \"U\"]\n shuffled: string[]; // The letters of the solution, but shuffled, e.g. [\"L\", \"C\", \"U\"]\n todaysLetter: string | null; // The letter the user has to find today, e.g. \"C\"\n todaysClue: GamePlacementClue | null; // The clue for user to find the letter, e.g. related to {todaysPlacement}\n todaysPlacement: GamePlacement | null; // The screen where the user has to find the clue, e.g. \"HomeScreen\"\n };\n // User has found the clue 3 days in a row, this is incrementing if the user finds the clue and decrements if user misses a day\n streak: number;\n};\n\nexport enum EnumGameStatus {\n GAME_COMPLETED = \"GAME_COMPLETED\",\n GAME_IN_PROGRESS = \"GAME_IN_PROGRESS\",\n GAME_LEFT = \"GAME_LEFT\",\n GAME_STARTED = \"GAME_STARTED\",\n}\n\nexport type GameHistory = {\n createdAt: Date;\n gameDate: GameDate;\n gameStatus: EnumGameStatus;\n gameType: EnumGameType;\n pointsEarned: number;\n};\n\ntype GameDataMap = {\n [EnumGameType.DAILY_CLUE]: DailyClueGameData;\n};\ntype GameDataType = {\n [K in keyof GameDataMap]?: GameDataMap[K] | null;\n};\n\nexport type GameType = {\n _id: string;\n active: boolean;\n createdAt: Date;\n gameData: GameDataType;\n gameHistory: GameHistory[] | null;\n gameType: EnumGameType;\n updatedAt: Date | null;\n};\n\nexport type GameDocType = {\n _id: string;\n active: boolean;\n createdAt: Date;\n deletedAt: Date | null;\n games: GameType[] | null;\n owner: OwnerType;\n points: number;\n updatedAt: Date | null;\n};\n\nexport type GameLeaderboard = {\n gameHistory: GameHistory[] | null;\n overallPoints: number;\n owner: OwnerType;\n};\n"],"mappings":";AAEA,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B,GAAG,sBAAsB;AAErD,IAAM,2BAA2B;AAAA,EACtC;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO,IAAI,OAAO,YAAY,0BAA0B,EAAE;AAAA,EAC5D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO,IAAI,OAAO,cAAc,0BAA0B,EAAE;AAAA,EAC9D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO,IAAI,OAAO,mBAAmB,0BAA0B,EAAE;AAAA,EACnE;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO,IAAI,OAAO,aAAa,0BAA0B,EAAE;AAAA,EAC7D;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,EACT;AACF;AAMO,IAAK,eAAL,kBAAKA,kBAAL;AACL,EAAAA,cAAA,gBAAa;AADH,SAAAA;AAAA,GAAA;AAIL,IAAM,wBAAsD;AAAA,EACjE,CAAC,4BAAuB,GAAG;AAC7B;AA4BO,IAAK,iBAAL,kBAAKC,oBAAL;AACL,EAAAA,gBAAA,oBAAiB;AACjB,EAAAA,gBAAA,sBAAmB;AACnB,EAAAA,gBAAA,eAAY;AACZ,EAAAA,gBAAA,kBAAe;AAJL,SAAAA;AAAA,GAAA;","names":["EnumGameType","EnumGameStatus"]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-ZR4TGWTS.mjs";
|
|
6
6
|
import {
|
|
7
7
|
gameScreenIdentifierList
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LOABFNIJ.mjs";
|
|
9
9
|
|
|
10
10
|
// src/utils/date.ts
|
|
11
11
|
import dayjs from "dayjs";
|
|
@@ -119,13 +119,14 @@ function computeDailyClueState(dailyClue) {
|
|
|
119
119
|
const today = nzStartOfDay();
|
|
120
120
|
const start = nzStartOfDay(startDate);
|
|
121
121
|
const end = nzStartOfDay(endDate);
|
|
122
|
+
if (today.isBefore(start)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
122
125
|
const shuffledPlacements = seededShuffle(
|
|
123
126
|
gameScreenIdentifierList,
|
|
124
127
|
start.toISOString()
|
|
125
128
|
);
|
|
126
|
-
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
+
const index = getDayIndex(start, today);
|
|
129
130
|
if (today.isAfter(end)) {
|
|
130
131
|
return {
|
|
131
132
|
todaysClue: null,
|
|
@@ -133,31 +134,24 @@ function computeDailyClueState(dailyClue) {
|
|
|
133
134
|
todaysPlacement: null
|
|
134
135
|
};
|
|
135
136
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
today: today.format()
|
|
145
|
-
});
|
|
146
|
-
if (index < 0 || index >= shuffled.length) return null;
|
|
147
|
-
const collectedCount = (collected ?? []).length;
|
|
148
|
-
if (collectedCount > index) {
|
|
137
|
+
if (index < 0 || index >= shuffled.length || index >= shuffledPlacements.length) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const letterToday = shuffled[index];
|
|
141
|
+
const placement = shuffledPlacements[index];
|
|
142
|
+
if (!letterToday || !placement) return null;
|
|
143
|
+
const alreadyCollectedToday = (collected ?? []).includes(letterToday);
|
|
144
|
+
if (alreadyCollectedToday) {
|
|
149
145
|
return {
|
|
150
146
|
todaysClue: null,
|
|
151
147
|
todaysLetter: null,
|
|
152
148
|
todaysPlacement: null
|
|
153
149
|
};
|
|
154
150
|
}
|
|
155
|
-
const letterToday = shuffled[index];
|
|
156
|
-
if (!letterToday) return null;
|
|
157
151
|
return {
|
|
158
|
-
todaysClue:
|
|
152
|
+
todaysClue: placement.clue,
|
|
159
153
|
todaysLetter: letterToday,
|
|
160
|
-
todaysPlacement:
|
|
154
|
+
todaysPlacement: placement.id
|
|
161
155
|
};
|
|
162
156
|
}
|
|
163
157
|
|
|
@@ -269,4 +263,4 @@ export {
|
|
|
269
263
|
IOS_URL,
|
|
270
264
|
ANDROID_URL
|
|
271
265
|
};
|
|
272
|
-
//# sourceMappingURL=chunk-
|
|
266
|
+
//# sourceMappingURL=chunk-Z3JWNX2U.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/date.ts","../src/utils/dailyClueGame.ts","../src/utils/utils.ts"],"sourcesContent":["import dayjs from \"dayjs\";\nimport customParseFormat from \"dayjs/plugin/customParseFormat.js\";\nimport isSameOrAfter from \"dayjs/plugin/isSameOrAfter.js\";\nimport timezone from \"dayjs/plugin/timezone.js\";\nimport utc from \"dayjs/plugin/utc.js\";\n\nexport const dateFormat = \"DD-MM-YYYY\";\nexport const timeFormat = \"HH:mm\";\n\n// Enable custom format parsing\ndayjs.extend(customParseFormat);\ndayjs.extend(utc);\ndayjs.extend(timezone);\ndayjs.extend(isSameOrAfter);\n\nconst NZ_TZ = \"Pacific/Auckland\";\n\nexport function toNZTime(date?: Date | string) {\n return date ? dayjs(date).tz(NZ_TZ) : dayjs().tz(NZ_TZ);\n}\n\n/** Start of the calendar day in Pacific/Auckland (daily games, streaks, etc.). */\nexport function nzStartOfDay(\n input?: Date | string | number | null,\n): dayjs.Dayjs {\n if (input == null) {\n return dayjs().tz(NZ_TZ).startOf(\"day\");\n }\n return dayjs.tz(input, NZ_TZ).startOf(\"day\");\n}\n\ntype DateFormat = \"date\" | \"time\" | \"datetime\";\n\n/**\n * Format a date string to a more readable format.\n * @param dateStr - the date string\n * @param timeStr - optional time string\n * @param display - 'date' | 'time' | 'datetime'\n * @returns formatted string based on display option\n */\nexport const formatDate = (\n dateStr: string,\n display: DateFormat = \"datetime\",\n timeStr?: string,\n) => {\n // Combine date and time into a single string if time is provided\n const dateTimeStr = timeStr ? `${dateStr} ${timeStr}` : dateStr;\n\n // Parse with formats\n const dateTime = timeStr\n ? dayjs(dateTimeStr, `${dateFormat} ${timeFormat}`)\n : dayjs(dateStr, dateFormat);\n\n // Format parts\n const formattedDate = dateTime.format(\"dddd, D MMMM, YYYY\");\n const formattedTime = dateTime.format(\"h:mm a\");\n\n // Return based on display option\n switch (display) {\n case \"date\":\n return formattedDate;\n case \"time\":\n return formattedTime;\n case \"datetime\":\n return `${formattedDate} at ${formattedTime}`;\n default:\n return formattedDate;\n }\n};\n\nexport const getCurrentAndFutureDates = <\n T extends { startDate: string; startTime: string },\n>(\n dates: T[],\n): T[] => {\n const now = dayjs(); // current date and time\n\n return dates.filter((dateObj) => {\n const dateTime = dayjs(\n `${dateObj.startDate} ${dateObj.startTime}`,\n `${dateFormat} ${timeFormat}`,\n );\n return dateTime.isSameOrAfter(now);\n });\n};\n\nexport const isFutureDatesBeforeThreshold = (\n date: {\n startDate: string;\n startTime: string;\n },\n minHoursFromNow: number,\n): boolean => {\n const threshold = minHoursFromNow\n ? dayjs().add(minHoursFromNow, \"hour\")\n : dayjs().startOf(\"day\");\n\n const dateTime = dayjs(\n `${date.startDate} ${date.startTime}`,\n `${dateFormat} ${timeFormat}`,\n );\n\n return dateTime.isSameOrAfter(threshold);\n};\n\nexport const formatTimestamp = (timestamp: string) => {\n const formattedDate = toNZTime(timestamp).format(dateFormat);\n\n return formatDate(formattedDate, \"date\");\n};\n\nexport const isIsoDateString = (value: unknown): value is string => {\n return typeof value === \"string\" && !isNaN(Date.parse(value));\n};\n\n/**\n * Sort an array of date strings by their proximity to the current date.\n * @param dates - The array of date strings to sort.\n * @returns - The sorted array of date strings.\n */\nexport function sortDatesChronologically<\n T extends { startDate: string; startTime: string },\n>(dates: T[]): T[] {\n if (!dates || !dates.length) {\n return [];\n }\n\n return [...dates].sort((a, b) => {\n const dateTimeFormat = `${dateFormat} ${timeFormat}`;\n const dateA = dayjs(`${a.startDate} ${a.startTime}`, dateTimeFormat);\n const dateB = dayjs(`${b.startDate} ${b.startTime}`, dateTimeFormat);\n return dateA.valueOf() - dateB.valueOf(); // chronological order\n });\n}\n","import type { Dayjs } from \"dayjs\";\n\nimport {\n DailyClueGameData,\n EnumGameStatus,\n GameHistory,\n GamePlacement,\n GamePlacementClue,\n gameScreenIdentifierList,\n} from \"../types/game\";\n\nimport { nzStartOfDay } from \"./date\";\n\nfunction createSeededRng(seed: number) {\n let t = seed >>> 0;\n\n return function random() {\n t += 0x6d2b79f5;\n let x = t;\n\n x = Math.imul(x ^ (x >>> 15), x | 1);\n x ^= x + Math.imul(x ^ (x >>> 7), x | 61);\n\n return ((x ^ (x >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nfunction hashStringToNumber(seed: string): number {\n let hash = 2166136261;\n\n for (let i = 0; i < seed.length; i++) {\n hash ^= seed.codePointAt(i) ?? 0;\n hash = Math.imul(hash, 16777619);\n }\n\n return hash >>> 0;\n}\n\n/** Seeded shuffle so all players see the same letter order / placements for a game. */\nexport function seededShuffle<T>(array: readonly T[], seed: string): T[] {\n const rng = createSeededRng(hashStringToNumber(seed));\n const result = [...array];\n\n for (let i = result.length - 1; i > 0; i--) {\n const j = Math.floor(rng() * (i + 1));\n [result[i], result[j]] = [result[j], result[i]];\n }\n\n return result;\n}\n\nfunction getDayIndex(start: Dayjs, today: Dayjs): number {\n return today.diff(start, \"day\");\n}\n\nexport function computeDailyClueState(dailyClue: DailyClueGameData): {\n todaysClue: GamePlacementClue | null;\n\n todaysLetter: string | null;\n\n todaysPlacement: GamePlacement | null;\n} | null {\n const { startDate, endDate } = dailyClue.gameFields.gameDate;\n const { shuffled, collected } = dailyClue.letterInfo;\n\n const today = nzStartOfDay();\n const start = nzStartOfDay(startDate);\n const end = nzStartOfDay(endDate);\n\n // Before game starts\n if (today.isBefore(start)) {\n return null;\n }\n\n const shuffledPlacements = seededShuffle(\n gameScreenIdentifierList,\n start.toISOString(),\n );\n\n const index = getDayIndex(start, today);\n\n // After game ends\n if (today.isAfter(end)) {\n return {\n todaysClue: null,\n todaysLetter: null,\n todaysPlacement: null,\n };\n }\n\n // Safety: index must exist in BOTH arrays\n if (\n index < 0 ||\n index >= shuffled.length ||\n index >= shuffledPlacements.length\n ) {\n return null;\n }\n\n const letterToday = shuffled[index];\n const placement = shuffledPlacements[index];\n\n if (!letterToday || !placement) return null;\n\n const alreadyCollectedToday = (collected ?? []).includes(letterToday);\n\n // Already completed today\n if (alreadyCollectedToday) {\n return {\n todaysClue: null,\n todaysLetter: null,\n todaysPlacement: null,\n };\n }\n\n // Active state\n return {\n todaysClue: placement.clue,\n todaysLetter: letterToday,\n todaysPlacement: placement.id,\n };\n}\n","import {\n EnumInviteStatus,\n EnumPaymentMethod,\n EnumRegions,\n EnumSocialMedia,\n EnumUserLicence,\n} from \"src/enums\";\nimport { OptionItem, SocialMediaType } from \"src/types\";\n\nimport { isIsoDateString } from \"./date\";\n\nexport const removeTypename = (obj: any): any => {\n // Preserve Date objects\n if (obj instanceof Date) {\n return obj;\n }\n\n // Preserve File objects (for apollo-upload-client)\n if (obj instanceof File) {\n return obj;\n }\n\n // Preserve ISO date strings\n if (isIsoDateString(obj)) {\n return obj;\n }\n\n // Handle arrays\n if (Array.isArray(obj)) {\n return obj.map(removeTypename);\n }\n\n // Handle plain objects only\n if (obj !== null && typeof obj === \"object\") {\n const { __typename, ...cleanedObj } = obj;\n\n return Object.keys(cleanedObj).reduce((acc: any, key) => {\n acc[key] = removeTypename(cleanedObj[key]);\n return acc;\n }, {});\n }\n\n // Primitives\n return obj;\n};\n\n/**\n * Truncate text to a specified length and append ellipsis if necessary.\n * @param text\n * @param maxLength\n * @returns\n */\nexport const truncateText = (text: string, maxLength: number = 30): string => {\n return text.length > maxLength ? text.substring(0, maxLength) + \"...\" : text;\n};\n\n/**\n * Convert an array of strings to an array of objects with label and value properties.\n * @param items - The array of strings to convert.\n * @returns - The converted array of objects.\n */\nexport const mapArrayToOptions = (items: string[]): OptionItem[] =>\n items.map((item) => ({\n label: item,\n value: item,\n }));\n\nexport const capitalizeFirstLetter = (str: string): string => {\n return str\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n};\n\nexport const statusOptions = [\n ...Object.values(EnumInviteStatus)\n .map((status) => ({\n label: status,\n value: status,\n }))\n .sort((a, b) => a.label.localeCompare(b.label)), // Sort the options alphabetically\n];\n\nexport const availableRegionTypes = Object.values(EnumRegions);\nexport const availableRegionOptions: OptionItem[] =\n mapArrayToOptions(availableRegionTypes);\n\nexport const paymentMethodOptions: OptionItem[] = mapArrayToOptions(\n Object.values(EnumPaymentMethod),\n);\n\nexport function normalizeUrl(url: string): string {\n if (!url.startsWith(\"http://\") && !url.startsWith(\"https://\")) {\n return `https://${url}`;\n }\n return url;\n}\n\nexport const licenseNiceNames: Record<EnumUserLicence, string> = {\n [EnumUserLicence.PRO_EVENT]: \"Pro Event\",\n [EnumUserLicence.PRO_VENDOR]: \"Pro Stallholder\",\n [EnumUserLicence.STANDARD_EVENT]: \"Standard Event\",\n [EnumUserLicence.STANDARD_VENDOR]: \"Standard Stallholder\",\n [EnumUserLicence.PRO_PLUS_EVENT]: \"Pro+Ads Event\",\n [EnumUserLicence.PRO_PLUS_VENDOR]: \"Pro+Ads Stallholder\",\n [EnumUserLicence.STANDARD_PARTNER]: \"Partner\",\n};\n\nexport const cluemartSocialMedia: SocialMediaType[] = [\n {\n link: \"https://www.facebook.com/ClueMartApp\",\n name: EnumSocialMedia.FACEBOOK,\n },\n {\n link: \"https://www.instagram.com/cluemart_app\",\n name: EnumSocialMedia.INSTAGRAM,\n },\n {\n link: \"https://www.tiktok.com/@cluemart\",\n name: EnumSocialMedia.TIKTOK,\n },\n {\n link: \"https://www.youtube.com/@ClueMart-App-NZ\",\n name: EnumSocialMedia.YOUTUBE,\n },\n];\n\nexport const IOS_URL = \"https://apps.apple.com/nz/app/cluemart/id6747251008\";\nexport const ANDROID_URL =\n \"https://play.google.com/store/apps/details?id=com.timardex.cluemart\";\n"],"mappings":"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","names":[]}
|
|
@@ -324,6 +324,102 @@ var EnumRegions = /* @__PURE__ */ ((EnumRegions2) => {
|
|
|
324
324
|
return EnumRegions2;
|
|
325
325
|
})(EnumRegions || {});
|
|
326
326
|
|
|
327
|
+
// src/types/game.ts
|
|
328
|
+
var OBJECT_ID_PATH_SEGMENT = "[a-f0-9]{24}";
|
|
329
|
+
var OBJECT_ID_PATH_SEGMENT_END = `${OBJECT_ID_PATH_SEGMENT}$`;
|
|
330
|
+
var gameScreenIdentifierList = [
|
|
331
|
+
{
|
|
332
|
+
clue: "Where your actions turn into a timeline.",
|
|
333
|
+
id: "activities",
|
|
334
|
+
match: "/profile/activities"
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
clue: "Where conversations happen without speaking.",
|
|
338
|
+
id: "chat",
|
|
339
|
+
match: "/profile/chat"
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
clue: "The place to redefine who you are.",
|
|
343
|
+
id: "edit-profile",
|
|
344
|
+
match: "/profile/edit-profile"
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
clue: "A single moment worth showing up for.",
|
|
348
|
+
id: "single-event",
|
|
349
|
+
match: new RegExp(`^/events/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
clue: "What\u2019s happening around you, right now.",
|
|
353
|
+
id: "events-near-me",
|
|
354
|
+
match: "/events/events-near-me"
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
clue: "A collection of things worth attending.",
|
|
358
|
+
id: "events",
|
|
359
|
+
match: "/events"
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
clue: "What\u2019s happening in a wider area \u2014 not just nearby.",
|
|
363
|
+
id: "events-region",
|
|
364
|
+
match: /^\/events\/region\/[^/]+$/
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
clue: "Where fun becomes a challenge.",
|
|
368
|
+
id: "games",
|
|
369
|
+
match: "/games"
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
clue: "Your starting point for everything.",
|
|
373
|
+
id: "home",
|
|
374
|
+
match: "/"
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
clue: "Where the app whispers what you shouldn\u2019t miss.",
|
|
378
|
+
id: "notifications",
|
|
379
|
+
match: "/notifications"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
clue: "Where you fine-tune your experience.",
|
|
383
|
+
id: "options",
|
|
384
|
+
match: "/options"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
clue: "An organisation or creator supporting the community.",
|
|
388
|
+
id: "single-partner",
|
|
389
|
+
match: new RegExp(`^/partners/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
clue: "Organisations and creators supporting the community.",
|
|
393
|
+
id: "partners",
|
|
394
|
+
match: "/partners"
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
clue: "A single published post in full view.",
|
|
398
|
+
id: "single-visitor-post",
|
|
399
|
+
match: new RegExp(`^/visitors/post/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
clue: "Your identity, on display.",
|
|
403
|
+
id: "profile",
|
|
404
|
+
match: "/profile"
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
clue: "One stallholder offering something valuable.",
|
|
408
|
+
id: "single-vendor",
|
|
409
|
+
match: new RegExp(`^/vendors/${OBJECT_ID_PATH_SEGMENT_END}`)
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
clue: "Where every stallholder waits under the right category.",
|
|
413
|
+
id: "vendors",
|
|
414
|
+
match: "/vendors"
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
clue: "Where you browse articles and posts from around the platform.",
|
|
418
|
+
id: "visitors",
|
|
419
|
+
match: "/visitors"
|
|
420
|
+
}
|
|
421
|
+
];
|
|
422
|
+
|
|
327
423
|
// src/utils/date.ts
|
|
328
424
|
var import_dayjs = __toESM(require("dayjs"));
|
|
329
425
|
var import_customParseFormat = __toESM(require("dayjs/plugin/customParseFormat.js"));
|