@timardex/cluemart-shared 1.5.599 → 1.5.601

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.
@@ -6,81 +6,10 @@ import {
6
6
  EnumPaymentMethod,
7
7
  EnumRegions
8
8
  } from "./chunk-ZR4TGWTS.mjs";
9
-
10
- // src/utils/date.ts
11
- import dayjs from "dayjs";
12
- import customParseFormat from "dayjs/plugin/customParseFormat.js";
13
- import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
14
- import timezone from "dayjs/plugin/timezone.js";
15
- import utc from "dayjs/plugin/utc.js";
16
- var dateFormat = "DD-MM-YYYY";
17
- var timeFormat = "HH:mm";
18
- dayjs.extend(customParseFormat);
19
- dayjs.extend(utc);
20
- dayjs.extend(timezone);
21
- dayjs.extend(isSameOrAfter);
22
- var NZ_TZ = "Pacific/Auckland";
23
- function toNZTime(date) {
24
- return date ? dayjs(date).tz(NZ_TZ) : dayjs().tz(NZ_TZ);
25
- }
26
- function nzStartOfDay(input) {
27
- if (input == null) {
28
- return dayjs().tz(NZ_TZ).startOf("day");
29
- }
30
- return dayjs.tz(input, NZ_TZ).startOf("day");
31
- }
32
- var formatDate = (dateStr, display = "datetime", timeStr) => {
33
- const dateTimeStr = timeStr ? `${dateStr} ${timeStr}` : dateStr;
34
- const dateTime = timeStr ? dayjs(dateTimeStr, `${dateFormat} ${timeFormat}`) : dayjs(dateStr, dateFormat);
35
- const formattedDate = dateTime.format("dddd, D MMMM, YYYY");
36
- const formattedTime = dateTime.format("h:mm a");
37
- switch (display) {
38
- case "date":
39
- return formattedDate;
40
- case "time":
41
- return formattedTime;
42
- case "datetime":
43
- return `${formattedDate} at ${formattedTime}`;
44
- default:
45
- return formattedDate;
46
- }
47
- };
48
- var getCurrentAndFutureDates = (dates) => {
49
- const now = dayjs();
50
- return dates.filter((dateObj) => {
51
- const dateTime = dayjs(
52
- `${dateObj.startDate} ${dateObj.startTime}`,
53
- `${dateFormat} ${timeFormat}`
54
- );
55
- return dateTime.isSameOrAfter(now);
56
- });
57
- };
58
- var isFutureDatesBeforeThreshold = (date, minHoursFromNow) => {
59
- const threshold = minHoursFromNow ? dayjs().add(minHoursFromNow, "hour") : dayjs().startOf("day");
60
- const dateTime = dayjs(
61
- `${date.startDate} ${date.startTime}`,
62
- `${dateFormat} ${timeFormat}`
63
- );
64
- return dateTime.isSameOrAfter(threshold);
65
- };
66
- var formatTimestamp = (timestamp) => {
67
- const formattedDate = toNZTime(timestamp).format(dateFormat);
68
- return formatDate(formattedDate, "date");
69
- };
70
- var isIsoDateString = (value) => {
71
- return typeof value === "string" && !isNaN(Date.parse(value));
72
- };
73
- function sortDatesChronologically(dates) {
74
- if (!dates || !dates.length) {
75
- return [];
76
- }
77
- return [...dates].sort((a, b) => {
78
- const dateTimeFormat = `${dateFormat} ${timeFormat}`;
79
- const dateA = dayjs(`${a.startDate} ${a.startTime}`, dateTimeFormat);
80
- const dateB = dayjs(`${b.startDate} ${b.startTime}`, dateTimeFormat);
81
- return dateA.valueOf() - dateB.valueOf();
82
- });
83
- }
9
+ import {
10
+ isIsoDateString,
11
+ nzStartOfDay
12
+ } from "./chunk-X4VPNOHX.mjs";
84
13
 
85
14
  // src/utils/dailyClueGame.ts
86
15
  function createSeededRng(seed) {
@@ -241,16 +170,6 @@ var SCHOOL_MIN_STUDENT_COUNT = 300;
241
170
  var SCHOOL_MAX_STUDENT_COUNT = 0;
242
171
 
243
172
  export {
244
- dateFormat,
245
- timeFormat,
246
- toNZTime,
247
- nzStartOfDay,
248
- formatDate,
249
- getCurrentAndFutureDates,
250
- isFutureDatesBeforeThreshold,
251
- formatTimestamp,
252
- isIsoDateString,
253
- sortDatesChronologically,
254
173
  seededShuffle,
255
174
  computeDailyClueState,
256
175
  removeTypename,
@@ -269,4 +188,4 @@ export {
269
188
  SCHOOL_MIN_STUDENT_COUNT,
270
189
  SCHOOL_MAX_STUDENT_COUNT
271
190
  };
272
- //# sourceMappingURL=chunk-YV2JDG4R.mjs.map
191
+ //# sourceMappingURL=chunk-3VUHAHP7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/dailyClueGame.ts","../src/utils/utils.ts","../src/utils/school.ts"],"sourcesContent":["import type { Dayjs } from \"dayjs\";\n\nimport {\n DailyClueGameData,\n GamePlacement,\n GamePlacementClue,\n gameScreenIdentifierList,\n} from \"../types/game/dailyClue\";\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 todaysLetter: string | null;\n todaysPlacement: GamePlacement | null;\n} | null {\n const { startDate, endDate } = dailyClue.gameFields.gameDate;\n const { solutionShuffled, 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 >= solutionShuffled.length ||\n index >= shuffledPlacements.length\n ) {\n return null;\n }\n\n const letterToday = solutionShuffled[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","export const SCHOOL_MIN_STUDENT_COUNT = 300;\nexport const SCHOOL_MAX_STUDENT_COUNT = 0;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,88 @@
1
+ // src/utils/date.ts
2
+ import dayjs from "dayjs";
3
+ import customParseFormat from "dayjs/plugin/customParseFormat.js";
4
+ import isSameOrAfter from "dayjs/plugin/isSameOrAfter.js";
5
+ import timezone from "dayjs/plugin/timezone.js";
6
+ import utc from "dayjs/plugin/utc.js";
7
+ var dateFormat = "DD-MM-YYYY";
8
+ var timeFormat = "HH:mm";
9
+ dayjs.extend(customParseFormat);
10
+ dayjs.extend(utc);
11
+ dayjs.extend(timezone);
12
+ dayjs.extend(isSameOrAfter);
13
+ var NZ_TZ = "Pacific/Auckland";
14
+ function toNZTime(date) {
15
+ return date ? dayjs(date).tz(NZ_TZ) : dayjs().tz(NZ_TZ);
16
+ }
17
+ function nzStartOfDay(input) {
18
+ if (input == null) {
19
+ return dayjs().tz(NZ_TZ).startOf("day");
20
+ }
21
+ return dayjs.tz(input, NZ_TZ).startOf("day");
22
+ }
23
+ var formatDate = (dateStr, display = "datetime", timeStr) => {
24
+ const dateTimeStr = timeStr ? `${dateStr} ${timeStr}` : dateStr;
25
+ const dateTime = timeStr ? dayjs(dateTimeStr, `${dateFormat} ${timeFormat}`) : dayjs(dateStr, dateFormat);
26
+ const formattedDate = dateTime.format("dddd, D MMMM, YYYY");
27
+ const formattedTime = dateTime.format("h:mm a");
28
+ switch (display) {
29
+ case "date":
30
+ return formattedDate;
31
+ case "time":
32
+ return formattedTime;
33
+ case "datetime":
34
+ return `${formattedDate} at ${formattedTime}`;
35
+ default:
36
+ return formattedDate;
37
+ }
38
+ };
39
+ var getCurrentAndFutureDates = (dates) => {
40
+ const now = dayjs();
41
+ return dates.filter((dateObj) => {
42
+ const dateTime = dayjs(
43
+ `${dateObj.startDate} ${dateObj.startTime}`,
44
+ `${dateFormat} ${timeFormat}`
45
+ );
46
+ return dateTime.isSameOrAfter(now);
47
+ });
48
+ };
49
+ var isFutureDatesBeforeThreshold = (date, minHoursFromNow) => {
50
+ const threshold = minHoursFromNow ? dayjs().add(minHoursFromNow, "hour") : dayjs().startOf("day");
51
+ const dateTime = dayjs(
52
+ `${date.startDate} ${date.startTime}`,
53
+ `${dateFormat} ${timeFormat}`
54
+ );
55
+ return dateTime.isSameOrAfter(threshold);
56
+ };
57
+ var formatTimestamp = (timestamp) => {
58
+ const formattedDate = toNZTime(timestamp).format(dateFormat);
59
+ return formatDate(formattedDate, "date");
60
+ };
61
+ var isIsoDateString = (value) => {
62
+ return typeof value === "string" && !isNaN(Date.parse(value));
63
+ };
64
+ function sortDatesChronologically(dates) {
65
+ if (!dates || !dates.length) {
66
+ return [];
67
+ }
68
+ return [...dates].sort((a, b) => {
69
+ const dateTimeFormat = `${dateFormat} ${timeFormat}`;
70
+ const dateA = dayjs(`${a.startDate} ${a.startTime}`, dateTimeFormat);
71
+ const dateB = dayjs(`${b.startDate} ${b.startTime}`, dateTimeFormat);
72
+ return dateA.valueOf() - dateB.valueOf();
73
+ });
74
+ }
75
+
76
+ export {
77
+ dateFormat,
78
+ timeFormat,
79
+ toNZTime,
80
+ nzStartOfDay,
81
+ formatDate,
82
+ getCurrentAndFutureDates,
83
+ isFutureDatesBeforeThreshold,
84
+ formatTimestamp,
85
+ isIsoDateString,
86
+ sortDatesChronologically
87
+ };
88
+ //# sourceMappingURL=chunk-X4VPNOHX.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/date.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"],"mappings":";AAAA,OAAO,WAAW;AAClB,OAAO,uBAAuB;AAC9B,OAAO,mBAAmB;AAC1B,OAAO,cAAc;AACrB,OAAO,SAAS;AAET,IAAM,aAAa;AACnB,IAAM,aAAa;AAG1B,MAAM,OAAO,iBAAiB;AAC9B,MAAM,OAAO,GAAG;AAChB,MAAM,OAAO,QAAQ;AACrB,MAAM,OAAO,aAAa;AAE1B,IAAM,QAAQ;AAEP,SAAS,SAAS,MAAsB;AAC7C,SAAO,OAAO,MAAM,IAAI,EAAE,GAAG,KAAK,IAAI,MAAM,EAAE,GAAG,KAAK;AACxD;AAGO,SAAS,aACd,OACa;AACb,MAAI,SAAS,MAAM;AACjB,WAAO,MAAM,EAAE,GAAG,KAAK,EAAE,QAAQ,KAAK;AAAA,EACxC;AACA,SAAO,MAAM,GAAG,OAAO,KAAK,EAAE,QAAQ,KAAK;AAC7C;AAWO,IAAM,aAAa,CACxB,SACA,UAAsB,YACtB,YACG;AAEH,QAAM,cAAc,UAAU,GAAG,OAAO,IAAI,OAAO,KAAK;AAGxD,QAAM,WAAW,UACb,MAAM,aAAa,GAAG,UAAU,IAAI,UAAU,EAAE,IAChD,MAAM,SAAS,UAAU;AAG7B,QAAM,gBAAgB,SAAS,OAAO,oBAAoB;AAC1D,QAAM,gBAAgB,SAAS,OAAO,QAAQ;AAG9C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,GAAG,aAAa,OAAO,aAAa;AAAA,IAC7C;AACE,aAAO;AAAA,EACX;AACF;AAEO,IAAM,2BAA2B,CAGtC,UACQ;AACR,QAAM,MAAM,MAAM;AAElB,SAAO,MAAM,OAAO,CAAC,YAAY;AAC/B,UAAM,WAAW;AAAA,MACf,GAAG,QAAQ,SAAS,IAAI,QAAQ,SAAS;AAAA,MACzC,GAAG,UAAU,IAAI,UAAU;AAAA,IAC7B;AACA,WAAO,SAAS,cAAc,GAAG;AAAA,EACnC,CAAC;AACH;AAEO,IAAM,+BAA+B,CAC1C,MAIA,oBACY;AACZ,QAAM,YAAY,kBACd,MAAM,EAAE,IAAI,iBAAiB,MAAM,IACnC,MAAM,EAAE,QAAQ,KAAK;AAEzB,QAAM,WAAW;AAAA,IACf,GAAG,KAAK,SAAS,IAAI,KAAK,SAAS;AAAA,IACnC,GAAG,UAAU,IAAI,UAAU;AAAA,EAC7B;AAEA,SAAO,SAAS,cAAc,SAAS;AACzC;AAEO,IAAM,kBAAkB,CAAC,cAAsB;AACpD,QAAM,gBAAgB,SAAS,SAAS,EAAE,OAAO,UAAU;AAE3D,SAAO,WAAW,eAAe,MAAM;AACzC;AAEO,IAAM,kBAAkB,CAAC,UAAoC;AAClE,SAAO,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,MAAM,KAAK,CAAC;AAC9D;AAOO,SAAS,yBAEd,OAAiB;AACjB,MAAI,CAAC,SAAS,CAAC,MAAM,QAAQ;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,iBAAiB,GAAG,UAAU,IAAI,UAAU;AAClD,UAAM,QAAQ,MAAM,GAAG,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,cAAc;AACnE,UAAM,QAAQ,MAAM,GAAG,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,cAAc;AACnE,WAAO,MAAM,QAAQ,IAAI,MAAM,QAAQ;AAAA,EACzC,CAAC;AACH;","names":[]}
@@ -1,3 +1,55 @@
1
+ import {
2
+ formatDate
3
+ } from "./chunk-X4VPNOHX.mjs";
4
+
5
+ // src/sharing/relationShareTypes.ts
6
+ var RELATION_SHARE_INVITATION = "invitation";
7
+ var RELATION_SHARE_APPLICATION = "application";
8
+ var RELATION_SHARE_RESOURCE_TYPES = [
9
+ RELATION_SHARE_INVITATION,
10
+ RELATION_SHARE_APPLICATION
11
+ ];
12
+ function isRelationShareResourceType(resourceType) {
13
+ return RELATION_SHARE_RESOURCE_TYPES.includes(
14
+ resourceType
15
+ );
16
+ }
17
+
18
+ // src/sharing/constants.ts
19
+ var SHARE_SITE_URL = "https://cluemart.co.nz";
20
+ var SHARE_CALENDAR_ICON = "\u{1F4C5}";
21
+ var SHARE_MARKET_DATES_SECTION_HEADING = `${SHARE_CALENDAR_ICON} Market dates:`;
22
+ var SHARE_CHECKMARK_ICON = "\u2705";
23
+ var SHARE_REQUIREMENTS_SECTION_HEADING = `${SHARE_CHECKMARK_ICON} Requirements:`;
24
+ var SHARE_CATEGORY_ICON = "\u{1F3F7}\uFE0F";
25
+ var SHARE_CATEGORIES_SECTION_HEADING = `${SHARE_CATEGORY_ICON} Categories:`;
26
+ var DEFAULT_SHARE_OG_IMAGE = `${SHARE_SITE_URL}/assets/logo.webp`;
27
+ var RESOURCE_SHARE_TYPES = [
28
+ "market",
29
+ "stallholder",
30
+ "partner"
31
+ ];
32
+ var POST_SHARE_RESOURCE_TYPES = [
33
+ "daily_meets",
34
+ "daily_tips",
35
+ "daily_games"
36
+ ];
37
+ var SHARE_RESOURCE_LABEL = {
38
+ [RELATION_SHARE_APPLICATION]: "Application",
39
+ [RELATION_SHARE_INVITATION]: "Invitation",
40
+ daily_games: "Daily Game",
41
+ daily_meets: "Daily Meet",
42
+ daily_tips: "Daily Tip",
43
+ market: "Market",
44
+ partner: "Partner",
45
+ stallholder: "Stallholder"
46
+ };
47
+ function isPostShareResourceType(resourceType) {
48
+ return POST_SHARE_RESOURCE_TYPES.includes(
49
+ resourceType
50
+ );
51
+ }
52
+
1
53
  // src/sharing/formatCategoryLabel.ts
2
54
  function formatCategoryLabel(category) {
3
55
  const subcategoryNames = category.subcategories.map((subcategory) => subcategory.name).filter(Boolean);
@@ -10,25 +62,43 @@ function formatCategoryLabel(category) {
10
62
  // src/sharing/joinShareDescriptionSections.ts
11
63
  var SHARE_DESCRIPTION_SECTION_SEPARATOR = " \xB7 ";
12
64
  var SHARE_DESCRIPTION_SECTION_BREAK = "\n\n";
65
+ var OG_DESCRIPTION_LINE_BREAK = "&#10;";
66
+ function joinShareOgDescriptionSections(sections) {
67
+ return sections.map((section) => typeof section === "string" ? section.trim() : "").filter((section) => section.length > 0).join(OG_DESCRIPTION_LINE_BREAK);
68
+ }
13
69
  function joinShareDescriptionSections(sections) {
14
70
  return sections.filter((section) => Boolean(section)).join(SHARE_DESCRIPTION_SECTION_BREAK);
15
71
  }
16
72
 
17
73
  // src/sharing/buildRelationShareDescription.ts
18
- function formatShareDate(isoDate) {
19
- try {
20
- return new Intl.DateTimeFormat("en-NZ", {
21
- day: "numeric",
22
- month: "short",
23
- year: "numeric"
24
- }).format(new Date(isoDate));
25
- } catch {
26
- return isoDate;
27
- }
74
+ function formatShareMarketDate(dateStr) {
75
+ return formatDate(dateStr, "date");
28
76
  }
29
77
  function formatStallCapacityLabel(stallCapacity) {
30
78
  return stallCapacity > 0 ? ` (${stallCapacity} spaces available)` : " - Full";
31
79
  }
80
+ function formatShareStallLine(stall) {
81
+ return ` - ${stall.label} \u2014 $${stall.price}${formatStallCapacityLabel(stall.stallCapacity)}`;
82
+ }
83
+ function formatShareInvitationMarketDatesSection(dateTime) {
84
+ const dateBlocks = dateTime.map((date) => {
85
+ const formattedDate = formatShareMarketDate(date.startDate);
86
+ const stallLines = date.stallTypes.map(formatShareStallLine);
87
+ return [`- ${formattedDate}`, ...stallLines].join("\n");
88
+ });
89
+ return `${SHARE_MARKET_DATES_SECTION_HEADING}
90
+ ${dateBlocks.join("\n")}`;
91
+ }
92
+ function formatShareInvitationRequirementsSection(requirementLabels) {
93
+ const bullets = requirementLabels.map((label) => `- ${label}`);
94
+ return `${SHARE_REQUIREMENTS_SECTION_HEADING}
95
+ ${bullets.join("\n")}`;
96
+ }
97
+ function formatShareApplicationCategoriesSection(categoryLabels) {
98
+ const bullets = categoryLabels.map((label) => `- ${label}`);
99
+ return `${SHARE_CATEGORIES_SECTION_HEADING}
100
+ ${bullets.join("\n")}`;
101
+ }
32
102
  function buildInvitationShareDescription(event, eventInfo) {
33
103
  const stallTypes = eventInfo?.dateTime?.flatMap((date) => date.stallTypes) ?? [];
34
104
  if (!eventInfo || stallTypes.length === 0) {
@@ -37,15 +107,9 @@ function buildInvitationShareDescription(event, eventInfo) {
37
107
  const requirementLabels = (eventInfo.requirements ?? []).filter((item) => item.value).map((item) => item.label);
38
108
  const sections = [
39
109
  event.location.fullAddress,
40
- ...event.dateTime.map((date) => {
41
- const start = formatShareDate(date.startDate);
42
- return `Market date: ${start}`;
43
- }),
110
+ formatShareInvitationMarketDatesSection(eventInfo.dateTime),
44
111
  `Application deadline: vendors must apply at least ${eventInfo.applicationDeadlineHours} hours before each market date.`,
45
- ...stallTypes.map(
46
- (stall) => `Stall: ${stall.label} \u2014 $${stall.price}${formatStallCapacityLabel(stall.stallCapacity)}`
47
- ),
48
- requirementLabels.length > 0 && `Requirements: ${requirementLabels.join(", ")}`
112
+ requirementLabels.length > 0 && formatShareInvitationRequirementsSection(requirementLabels)
49
113
  ];
50
114
  return joinShareDescriptionSections(sections);
51
115
  }
@@ -63,57 +127,15 @@ function buildApplicationShareDescription(vendor, vendorInfo) {
63
127
  ].filter(Boolean);
64
128
  const profileDescription = vendor.description?.trim();
65
129
  const sections = [
66
- categoryLabels.length > 0 && `Categories: ${categoryLabels.join(", ")}`,
130
+ categoryLabels.length > 0 && formatShareApplicationCategoriesSection(categoryLabels),
67
131
  `Stall size: ${vendorInfo.stallInfo.size.width}m \xD7 ${vendorInfo.stallInfo.size.depth}m`,
68
- `Compliance: ${complianceLabels.length > 0 ? complianceLabels.join(", ") : "Not specified"}`,
132
+ complianceLabels.length > 0 && `Compliance: ${complianceLabels.join(", ")}`,
69
133
  `Price range: $${vendorInfo.product.priceRange.min} \u2013 $${vendorInfo.product.priceRange.max}`,
70
134
  profileDescription
71
135
  ];
72
136
  return joinShareDescriptionSections(sections);
73
137
  }
74
138
 
75
- // src/sharing/relationShareTypes.ts
76
- var RELATION_SHARE_INVITATION = "invitation";
77
- var RELATION_SHARE_APPLICATION = "application";
78
- var RELATION_SHARE_RESOURCE_TYPES = [
79
- RELATION_SHARE_INVITATION,
80
- RELATION_SHARE_APPLICATION
81
- ];
82
- function isRelationShareResourceType(resourceType) {
83
- return RELATION_SHARE_RESOURCE_TYPES.includes(
84
- resourceType
85
- );
86
- }
87
-
88
- // src/sharing/constants.ts
89
- var SHARE_SITE_URL = "https://cluemart.co.nz";
90
- var DEFAULT_SHARE_OG_IMAGE = `${SHARE_SITE_URL}/assets/logo.webp`;
91
- var RESOURCE_SHARE_TYPES = [
92
- "market",
93
- "stallholder",
94
- "partner"
95
- ];
96
- var POST_SHARE_RESOURCE_TYPES = [
97
- "daily_meets",
98
- "daily_tips",
99
- "daily_games"
100
- ];
101
- var SHARE_RESOURCE_LABEL = {
102
- [RELATION_SHARE_APPLICATION]: "Application",
103
- [RELATION_SHARE_INVITATION]: "Invitation",
104
- daily_games: "Daily Game",
105
- daily_meets: "Daily Meet",
106
- daily_tips: "Daily Tip",
107
- market: "Market",
108
- partner: "Partner",
109
- stallholder: "Stallholder"
110
- };
111
- function isPostShareResourceType(resourceType) {
112
- return POST_SHARE_RESOURCE_TYPES.includes(
113
- resourceType
114
- );
115
- }
116
-
117
139
  // src/sharing/buildShareUrl.ts
118
140
  var PUBLIC_SHARE_PATH_TYPES = [
119
141
  ...RESOURCE_SHARE_TYPES,
@@ -135,7 +157,14 @@ function normalizeShareSection(value) {
135
157
  if (value == null) {
136
158
  return "";
137
159
  }
138
- return value.trim().split("\n").map((line) => line.trim().replace(/[ \t]+/g, " ")).join("\n").replace(/\n{3,}/g, "\n\n");
160
+ return value.trim().split("\n").map((line) => {
161
+ const match = line.match(/^([ \t]*)(.*)$/);
162
+ if (!match) {
163
+ return line;
164
+ }
165
+ const [, leading, rest] = match;
166
+ return leading + rest.trim().replace(/[ \t]{2,}/g, " ");
167
+ }).join("\n").replace(/\n{3,}/g, "\n\n");
139
168
  }
140
169
  function stripLegacyBulletPrefix(section) {
141
170
  return section.startsWith(LEGACY_BULLET_PREFIX) ? section.slice(LEGACY_BULLET_PREFIX.length) : section;
@@ -170,14 +199,7 @@ function formatShareSectionsForCompactDisplay(value) {
170
199
  );
171
200
  }
172
201
  function normalizeShareOgDescription(value) {
173
- const trimmed = value.trim();
174
- if (!trimmed) {
175
- return "";
176
- }
177
- if (/\n\n/.test(trimmed) || trimmed.includes(SHARE_DESCRIPTION_SECTION_SEPARATOR)) {
178
- return formatShareSectionsForCompactDisplay(trimmed);
179
- }
180
- return trimmed.replace(/\s+/g, " ").trim();
202
+ return joinShareOgDescriptionSections(splitShareDescriptionSections(value));
181
203
  }
182
204
  function buildFacebookShareQuote(title, description) {
183
205
  const titleSection = normalizeShareSection(title);
@@ -188,8 +210,11 @@ function buildFacebookShareQuote(title, description) {
188
210
  const quote = sections.join(SHARE_DESCRIPTION_SECTION_BREAK).trim();
189
211
  return quote.length > 0 ? quote : void 0;
190
212
  }
213
+ function buildShareOgDescriptionFromSections(sections) {
214
+ return joinShareOgDescriptionSections(sections);
215
+ }
191
216
  function buildShareOgDescription(_title, description) {
192
- return normalizeShareOgDescription(description);
217
+ return joinShareOgDescriptionSections(splitShareDescriptionSections(description));
193
218
  }
194
219
 
195
220
  // src/sharing/normalizeShareRouteId.ts
@@ -205,33 +230,47 @@ function buildSharePagePath(resourceType, rawId) {
205
230
  }
206
231
 
207
232
  export {
208
- formatCategoryLabel,
209
- SHARE_DESCRIPTION_SECTION_SEPARATOR,
210
- SHARE_DESCRIPTION_SECTION_BREAK,
211
- joinShareDescriptionSections,
212
- formatStallCapacityLabel,
213
- buildInvitationShareDescription,
214
- buildApplicationShareDescription,
215
233
  RELATION_SHARE_INVITATION,
216
234
  RELATION_SHARE_APPLICATION,
217
235
  RELATION_SHARE_RESOURCE_TYPES,
218
236
  isRelationShareResourceType,
219
237
  SHARE_SITE_URL,
238
+ SHARE_CALENDAR_ICON,
239
+ SHARE_MARKET_DATES_SECTION_HEADING,
240
+ SHARE_CHECKMARK_ICON,
241
+ SHARE_REQUIREMENTS_SECTION_HEADING,
242
+ SHARE_CATEGORY_ICON,
243
+ SHARE_CATEGORIES_SECTION_HEADING,
220
244
  DEFAULT_SHARE_OG_IMAGE,
221
245
  RESOURCE_SHARE_TYPES,
222
246
  POST_SHARE_RESOURCE_TYPES,
223
247
  SHARE_RESOURCE_LABEL,
224
248
  isPostShareResourceType,
249
+ formatCategoryLabel,
250
+ SHARE_DESCRIPTION_SECTION_SEPARATOR,
251
+ SHARE_DESCRIPTION_SECTION_BREAK,
252
+ OG_DESCRIPTION_LINE_BREAK,
253
+ joinShareOgDescriptionSections,
254
+ joinShareDescriptionSections,
255
+ formatShareMarketDate,
256
+ formatStallCapacityLabel,
257
+ formatShareInvitationMarketDatesSection,
258
+ formatShareInvitationRequirementsSection,
259
+ formatShareApplicationCategoriesSection,
260
+ buildInvitationShareDescription,
261
+ buildApplicationShareDescription,
225
262
  PUBLIC_SHARE_PATH_TYPES,
226
263
  RESOURCE_SHARE_TYPES_FOR_URL,
227
264
  SHARE_TYPE_PATH_REGEX,
228
265
  buildShareUrl,
266
+ splitShareDescriptionSections,
229
267
  formatShareSectionsForMultilineDisplay,
230
268
  formatShareSectionsForCompactDisplay,
231
269
  normalizeShareOgDescription,
232
270
  buildFacebookShareQuote,
271
+ buildShareOgDescriptionFromSections,
233
272
  buildShareOgDescription,
234
273
  normalizeShareRouteId,
235
274
  buildSharePagePath
236
275
  };
237
- //# sourceMappingURL=chunk-HBVPPRHO.mjs.map
276
+ //# sourceMappingURL=chunk-Y6OS3HDB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sharing/relationShareTypes.ts","../src/sharing/constants.ts","../src/sharing/formatCategoryLabel.ts","../src/sharing/joinShareDescriptionSections.ts","../src/sharing/buildRelationShareDescription.ts","../src/sharing/buildShareUrl.ts","../src/sharing/normalizeShareDescription.ts","../src/sharing/normalizeShareRouteId.ts"],"sourcesContent":["/** Path segments for relation share URLs — must match mobile `RelationTitle` values. */\nexport const RELATION_SHARE_INVITATION = \"invitation\" as const;\nexport const RELATION_SHARE_APPLICATION = \"application\" as const;\n\nexport const RELATION_SHARE_RESOURCE_TYPES = [\n RELATION_SHARE_INVITATION,\n RELATION_SHARE_APPLICATION,\n] as const;\n\nexport type RelationShareResourceType =\n (typeof RELATION_SHARE_RESOURCE_TYPES)[number];\n\nexport function isRelationShareResourceType(\n resourceType: string,\n): resourceType is RelationShareResourceType {\n return (RELATION_SHARE_RESOURCE_TYPES as readonly string[]).includes(\n resourceType,\n );\n}\n","import {\n RELATION_SHARE_APPLICATION,\n RELATION_SHARE_INVITATION,\n type RelationShareResourceType,\n} from \"./relationShareTypes\";\n\nexport {\n RELATION_SHARE_APPLICATION,\n RELATION_SHARE_INVITATION,\n RELATION_SHARE_RESOURCE_TYPES,\n isRelationShareResourceType,\n type RelationShareResourceType,\n} from \"./relationShareTypes\";\n\nexport const SHARE_SITE_URL = \"https://cluemart.co.nz\";\n\n/** Calendar marker for invitation market-dates share copy (U+1F4C5 📅). */\nexport const SHARE_CALENDAR_ICON = \"\\u{1F4C5}\";\n\nexport const SHARE_MARKET_DATES_SECTION_HEADING = `${SHARE_CALENDAR_ICON} Market dates:`;\n\n/** Check mark for invitation requirements share copy (U+2705 ✅). */\nexport const SHARE_CHECKMARK_ICON = \"\\u{2705}\";\n\nexport const SHARE_REQUIREMENTS_SECTION_HEADING = `${SHARE_CHECKMARK_ICON} Requirements:`;\n\n/** Label tag for application categories share copy (U+1F3F7 🏷️). */\nexport const SHARE_CATEGORY_ICON = \"\\u{1F3F7}\\u{FE0F}\";\n\nexport const SHARE_CATEGORIES_SECTION_HEADING = `${SHARE_CATEGORY_ICON} Categories:`;\n\nexport const DEFAULT_SHARE_OG_IMAGE = `${SHARE_SITE_URL}/assets/logo.webp`;\n\nexport const RESOURCE_SHARE_TYPES = [\n \"market\",\n \"stallholder\",\n \"partner\",\n] as const;\n\nexport type ResourceShareType = (typeof RESOURCE_SHARE_TYPES)[number];\n\nexport const POST_SHARE_RESOURCE_TYPES = [\n \"daily_meets\",\n \"daily_tips\",\n \"daily_games\",\n] as const;\n\nexport type PostShareResourceType = (typeof POST_SHARE_RESOURCE_TYPES)[number];\n\nexport type ShareResourceType =\n | ResourceShareType\n | PostShareResourceType\n | RelationShareResourceType;\n\nexport const SHARE_RESOURCE_LABEL: Record<ShareResourceType, string> = {\n [RELATION_SHARE_APPLICATION]: \"Application\",\n [RELATION_SHARE_INVITATION]: \"Invitation\",\n daily_games: \"Daily Game\",\n daily_meets: \"Daily Meet\",\n daily_tips: \"Daily Tip\",\n market: \"Market\",\n partner: \"Partner\",\n stallholder: \"Stallholder\",\n};\n\nexport function isPostShareResourceType(\n resourceType: ShareResourceType,\n): resourceType is PostShareResourceType {\n return (POST_SHARE_RESOURCE_TYPES as readonly string[]).includes(\n resourceType,\n );\n}\n","import type { ShareVendorCategory } from \"./shareRelationTypes\";\n\nexport function formatCategoryLabel(category: ShareVendorCategory): string {\n const subcategoryNames = category.subcategories\n .map((subcategory) => subcategory.name)\n .filter(Boolean);\n\n if (subcategoryNames.length === 0) {\n return category.name;\n }\n\n return `${category.name} (${subcategoryNames.join(\", \")})`;\n}\n","/** Visible separator for multi-block share text when line breaks are stripped (legacy OG). */\nexport const SHARE_DESCRIPTION_SECTION_SEPARATOR = \" · \";\n\n/** Blank line between share sections — title, address, dates, URL, etc. */\nexport const SHARE_DESCRIPTION_SECTION_BREAK = \"\\n\\n\";\n\n/**\n * Line break for `og:description` meta content. Use instead of `\\n` — Next.js\n * HTML serialisation collapses literal newlines to spaces; Facebook reads `&#10;`.\n */\nexport const OG_DESCRIPTION_LINE_BREAK = \"&#10;\";\n\n/** Joins OG description sections for Facebook link cards (and Twitter). */\nexport function joinShareOgDescriptionSections(\n sections: ReadonlyArray<string | false | null | undefined>,\n): string {\n return sections\n .map((section) => (typeof section === \"string\" ? section.trim() : \"\"))\n .filter((section): section is string => section.length > 0)\n .join(OG_DESCRIPTION_LINE_BREAK);\n}\n\nexport function joinShareDescriptionSections(\n sections: ReadonlyArray<string | false | null | undefined>,\n): string {\n return sections\n .filter((section): section is string => Boolean(section))\n .join(SHARE_DESCRIPTION_SECTION_BREAK);\n}\n","import { formatDate } from \"../utils/date\";\n\nimport {\n SHARE_CATEGORIES_SECTION_HEADING,\n SHARE_MARKET_DATES_SECTION_HEADING,\n SHARE_REQUIREMENTS_SECTION_HEADING,\n} from \"./constants\";\nimport { formatCategoryLabel } from \"./formatCategoryLabel\";\nimport { joinShareDescriptionSections } from \"./joinShareDescriptionSections\";\nimport type {\n ShareEventForInvitation,\n ShareEventInfoForInvitation,\n ShareStallType,\n ShareVendorForApplication,\n ShareVendorInfoForApplication,\n} from \"./shareRelationTypes\";\n\nexport type {\n ShareEventDateTime,\n ShareEventForInvitation,\n ShareEventInfoForInvitation,\n ShareStallType,\n ShareVendorCategory,\n ShareVendorForApplication,\n ShareVendorInfoForApplication,\n} from \"./shareRelationTypes\";\n\n/** Formats event `startDate` (`DD-MM-YYYY`) for share copy — same as share preview UI. */\nexport function formatShareMarketDate(dateStr: string): string {\n return formatDate(dateStr, \"date\");\n}\n\nexport function formatStallCapacityLabel(stallCapacity: number): string {\n return stallCapacity > 0 ? ` (${stallCapacity} spaces available)` : \" - Full\";\n}\n\nfunction formatShareStallLine(stall: ShareStallType): string {\n return ` - ${stall.label} — $${stall.price}${formatStallCapacityLabel(stall.stallCapacity)}`;\n}\n\n/** Nested market dates + per-date stall lines for invitation share copy. */\nexport function formatShareInvitationMarketDatesSection(\n dateTime: ShareEventInfoForInvitation[\"dateTime\"],\n): string {\n const dateBlocks = dateTime.map((date) => {\n const formattedDate = formatShareMarketDate(date.startDate);\n const stallLines = date.stallTypes.map(formatShareStallLine);\n return [`- ${formattedDate}`, ...stallLines].join(\"\\n\");\n });\n\n return `${SHARE_MARKET_DATES_SECTION_HEADING}\\n${dateBlocks.join(\"\\n\")}`;\n}\n\n/** Bulleted requirements list for invitation share copy. */\nexport function formatShareInvitationRequirementsSection(\n requirementLabels: string[],\n): string {\n const bullets = requirementLabels.map((label) => `- ${label}`);\n return `${SHARE_REQUIREMENTS_SECTION_HEADING}\\n${bullets.join(\"\\n\")}`;\n}\n\n/** Bulleted categories list for application share copy. */\nexport function formatShareApplicationCategoriesSection(\n categoryLabels: string[],\n): string {\n const bullets = categoryLabels.map((label) => `- ${label}`);\n return `${SHARE_CATEGORIES_SECTION_HEADING}\\n${bullets.join(\"\\n\")}`;\n}\n\nexport function buildInvitationShareDescription(\n event: ShareEventForInvitation,\n eventInfo: ShareEventInfoForInvitation | null | undefined,\n): string {\n const stallTypes =\n eventInfo?.dateTime?.flatMap((date) => date.stallTypes) ?? [];\n\n if (!eventInfo || stallTypes.length === 0) {\n return event.description?.trim() || \"\";\n }\n\n const requirementLabels = (eventInfo.requirements ?? [])\n .filter((item) => item.value)\n .map((item) => item.label);\n\n const sections = [\n event.location.fullAddress,\n formatShareInvitationMarketDatesSection(eventInfo.dateTime),\n `Application deadline: vendors must apply at least ${eventInfo.applicationDeadlineHours} hours before each market date.`,\n requirementLabels.length > 0 &&\n formatShareInvitationRequirementsSection(requirementLabels),\n ];\n\n return joinShareDescriptionSections(sections);\n}\n\nexport function buildApplicationShareDescription(\n vendor: ShareVendorForApplication,\n vendorInfo: ShareVendorInfoForApplication | null | undefined,\n): string {\n const categoryLabels = vendor.categories.map((category) =>\n formatCategoryLabel(category),\n );\n\n if (!vendorInfo) {\n return vendor.description?.trim() || \"\";\n }\n\n const compliance = vendorInfo.compliance;\n const complianceLabels = [\n compliance?.liabilityInsurance && \"Liability insurance\",\n compliance?.foodBeverageLicense && \"Food & beverage licence\",\n ].filter(Boolean);\n\n const profileDescription = vendor.description?.trim();\n\n const sections = [\n categoryLabels.length > 0 &&\n formatShareApplicationCategoriesSection(categoryLabels),\n `Stall size: ${vendorInfo.stallInfo.size.width}m × ${vendorInfo.stallInfo.size.depth}m`,\n complianceLabels.length > 0 && `Compliance: ${complianceLabels.join(\", \")}`,\n `Price range: $${vendorInfo.product.priceRange.min} – $${vendorInfo.product.priceRange.max}`,\n profileDescription,\n ];\n\n return joinShareDescriptionSections(sections);\n}\n","import {\n POST_SHARE_RESOURCE_TYPES,\n RESOURCE_SHARE_TYPES,\n SHARE_SITE_URL,\n} from \"./constants\";\nimport {\n RELATION_SHARE_APPLICATION,\n RELATION_SHARE_INVITATION,\n} from \"./relationShareTypes\";\n\n/** Path segments for public resource share URLs (markets, posts, etc.). */\nexport const PUBLIC_SHARE_PATH_TYPES = [\n ...RESOURCE_SHARE_TYPES,\n ...POST_SHARE_RESOURCE_TYPES,\n] as const;\n\nexport type PublicSharePathType = (typeof PUBLIC_SHARE_PATH_TYPES)[number];\n\n/** @deprecated Use {@link PUBLIC_SHARE_PATH_TYPES} — kept for mobile deep-link helpers. */\nexport const RESOURCE_SHARE_TYPES_FOR_URL = PUBLIC_SHARE_PATH_TYPES;\n\nexport type RelationSharePathType =\n | typeof RELATION_SHARE_INVITATION\n | typeof RELATION_SHARE_APPLICATION;\n\nexport type ShareType = PublicSharePathType | RelationSharePathType;\n\n/** Alternation for deep-link regexes — keep in sync with {@link ShareType}. */\nexport const SHARE_TYPE_PATH_REGEX = [\n ...PUBLIC_SHARE_PATH_TYPES,\n RELATION_SHARE_APPLICATION,\n RELATION_SHARE_INVITATION,\n].join(\"|\");\n\nexport function buildShareUrl(type: ShareType, id: string): string {\n return `${SHARE_SITE_URL}/share/${type}/${encodeURIComponent(id)}`;\n}\n","import {\n joinShareOgDescriptionSections,\n OG_DESCRIPTION_LINE_BREAK,\n SHARE_DESCRIPTION_SECTION_BREAK,\n SHARE_DESCRIPTION_SECTION_SEPARATOR,\n} from \"./joinShareDescriptionSections\";\n\nexport {\n joinShareOgDescriptionSections,\n OG_DESCRIPTION_LINE_BREAK,\n SHARE_DESCRIPTION_SECTION_BREAK,\n SHARE_DESCRIPTION_SECTION_SEPARATOR,\n};\n\nconst LEGACY_BULLET_PREFIX = \"• \";\n\n/** Trims a share section and collapses spaces per line; preserves line breaks. */\nfunction normalizeShareSection(value: string | null | undefined): string {\n if (value == null) {\n return \"\";\n }\n return value\n .trim()\n .split(\"\\n\")\n .map((line) => {\n const match = line.match(/^([ \\t]*)(.*)$/);\n if (!match) {\n return line;\n }\n const [, leading, rest] = match;\n return leading + rest.trim().replace(/[ \\t]{2,}/g, \" \");\n })\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\");\n}\n\nfunction stripLegacyBulletPrefix(section: string): string {\n return section.startsWith(LEGACY_BULLET_PREFIX)\n ? section.slice(LEGACY_BULLET_PREFIX.length)\n : section;\n}\n\nexport function splitShareDescriptionSections(value: string): string[] {\n const trimmed = value.trim();\n if (!trimmed) {\n return [];\n }\n\n if (trimmed.includes(SHARE_DESCRIPTION_SECTION_SEPARATOR)) {\n return trimmed\n .split(SHARE_DESCRIPTION_SECTION_SEPARATOR)\n .map((section) => stripLegacyBulletPrefix(normalizeShareSection(section)))\n .filter((section) => section.length > 0);\n }\n\n if (/\\n\\n/.test(trimmed)) {\n return trimmed\n .split(/\\n\\n+/)\n .map((section) => stripLegacyBulletPrefix(normalizeShareSection(section)))\n .filter((section) => section.length > 0);\n }\n\n if (/\\n/.test(trimmed)) {\n return trimmed\n .split(/\\n+/)\n .map((section) => stripLegacyBulletPrefix(normalizeShareSection(section)))\n .filter((section) => section.length > 0);\n }\n\n return [stripLegacyBulletPrefix(normalizeShareSection(trimmed))];\n}\n\nfunction collapseExcessiveBlankLines(value: string): string {\n return value.replace(/\\n{4,}/g, \"\\n\\n\\n\").trim();\n}\n\n/**\n * Share copy with a blank line between each section (share sheet message, previews).\n */\nexport function formatShareSectionsForMultilineDisplay(value: string): string {\n return collapseExcessiveBlankLines(\n splitShareDescriptionSections(value).join(SHARE_DESCRIPTION_SECTION_BREAK),\n );\n}\n\n/**\n * Formats multiline share copy for UIs that strip line breaks (legacy OG one-liners).\n */\nexport function formatShareSectionsForCompactDisplay(value: string): string {\n return splitShareDescriptionSections(value).join(\n SHARE_DESCRIPTION_SECTION_SEPARATOR,\n );\n}\n\n/**\n * Formats share descriptions for Open Graph / Twitter meta tags.\n * Sections are joined with {@link OG_DESCRIPTION_LINE_BREAK} (`&#10;`).\n */\nexport function normalizeShareOgDescription(value: string): string {\n return joinShareOgDescriptionSections(splitShareDescriptionSections(value));\n}\n\n/**\n * Quote text for Facebook ShareDialog on iOS (`ShareLinkContent.quote`).\n *\n * Title + blank lines + body sections. URL is omitted — `contentUrl` supplies\n * the link card (OG on `/share/*` controls card title/image).\n */\nexport function buildFacebookShareQuote(\n title: string,\n description: string,\n): string | undefined {\n const titleSection = normalizeShareSection(title);\n const body = formatShareSectionsForMultilineDisplay(\n normalizeShareSection(description),\n );\n const sections = [titleSection, body].filter((section) => section.length > 0);\n const quote = sections.join(SHARE_DESCRIPTION_SECTION_BREAK).trim();\n return quote.length > 0 ? quote : undefined;\n}\n\n/**\n * Open Graph / Twitter description from pre-built section strings.\n * Prefer {@link joinShareOgDescriptionSections} when sections are already known.\n */\nexport function buildShareOgDescriptionFromSections(\n sections: ReadonlyArray<string | false | null | undefined>,\n): string {\n return joinShareOgDescriptionSections(sections);\n}\n\n/**\n * Open Graph / Twitter description — body sections only (`og:title` is separate).\n * Multiline / legacy ` · ` input is split into sections, then joined with `&#10;`.\n */\nexport function buildShareOgDescription(\n _title: string,\n description: string,\n): string {\n return joinShareOgDescriptionSections(splitShareDescriptionSections(description));\n}\n","import type { ShareResourceType } from \"./constants\";\n\nexport function normalizeShareRouteId(id: string): string {\n try {\n return decodeURIComponent(id);\n } catch {\n return id;\n }\n}\n\nexport function buildSharePagePath(\n resourceType: ShareResourceType,\n rawId: string,\n): string {\n return `/share/${resourceType}/${encodeURIComponent(normalizeShareRouteId(rawId))}`;\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mapArrayToOptions
3
- } from "./chunk-YV2JDG4R.mjs";
3
+ } from "./chunk-3VUHAHP7.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-2NQUR2AV.mjs.map
1955
+ //# sourceMappingURL=chunk-ZDDWPO5Y.mjs.map
@@ -43,10 +43,11 @@ import {
43
43
  vendorStallSize,
44
44
  vendorStartDateFields,
45
45
  vendorTable
46
- } from "../chunk-2NQUR2AV.mjs";
47
- import "../chunk-YV2JDG4R.mjs";
46
+ } from "../chunk-ZDDWPO5Y.mjs";
47
+ import "../chunk-3VUHAHP7.mjs";
48
48
  import "../chunk-SBY5HTAP.mjs";
49
49
  import "../chunk-ZR4TGWTS.mjs";
50
+ import "../chunk-X4VPNOHX.mjs";
50
51
  export {
51
52
  availableCategories,
52
53
  availableTagTypes,
@@ -4769,6 +4769,12 @@ var RELATION_SHARE_APPLICATION = "application";
4769
4769
 
4770
4770
  // src/sharing/constants.ts
4771
4771
  var SHARE_SITE_URL = "https://cluemart.co.nz";
4772
+ var SHARE_CALENDAR_ICON = "\u{1F4C5}";
4773
+ var SHARE_MARKET_DATES_SECTION_HEADING = `${SHARE_CALENDAR_ICON} Market dates:`;
4774
+ var SHARE_CHECKMARK_ICON = "\u2705";
4775
+ var SHARE_REQUIREMENTS_SECTION_HEADING = `${SHARE_CHECKMARK_ICON} Requirements:`;
4776
+ var SHARE_CATEGORY_ICON = "\u{1F3F7}\uFE0F";
4777
+ var SHARE_CATEGORIES_SECTION_HEADING = `${SHARE_CATEGORY_ICON} Categories:`;
4772
4778
  var DEFAULT_SHARE_OG_IMAGE = `${SHARE_SITE_URL}/assets/logo.webp`;
4773
4779
  var RESOURCE_SHARE_TYPES = [
4774
4780
  "market",