@bash-app/bash-common 30.48.0 → 30.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -0
- package/package.json +3 -2
- package/prisma/schema.prisma +178 -52
- package/src/extendedSchemas.ts +1 -0
- package/src/utils/apiUtils.ts +0 -0
- package/src/utils/arrayUtils.ts +0 -0
- package/src/utils/awsS3Utils.ts +0 -0
- package/src/utils/dateTimeUtils.ts +82 -76
- package/src/utils/entityUtils.ts +0 -0
- package/src/utils/generalDateTimeUtils.ts +0 -0
- package/src/utils/luxonUtils.ts +0 -5
- package/src/utils/mathUtils.ts +0 -0
- package/src/utils/objUtils.ts +0 -0
- package/src/utils/paymentUtils.ts +0 -0
- package/src/utils/promoCodesUtils.ts +0 -0
- package/src/utils/qrCodeUtils.ts +0 -0
- package/src/utils/recurrenceUtils.ts +36 -39
- package/src/utils/service/apiServiceBookingApiUtils.ts +0 -0
- package/src/utils/service/attendeeOptionUtils.ts +0 -0
- package/src/utils/service/regexUtils.ts +0 -0
- package/src/utils/service/serviceBookingStatusUtils.ts +14 -14
- package/src/utils/service/serviceDBUtils.ts +0 -0
- package/src/utils/service/serviceRateDBUtils.ts +0 -0
- package/src/utils/service/serviceUtils.ts +0 -0
- package/src/utils/service/venueUtils.ts +0 -0
- package/src/utils/sortUtils.ts +0 -0
- package/src/utils/stringUtils.ts +0 -0
- package/src/utils/stripeAccountUtils.ts +0 -0
- package/src/utils/ticketListUtils.ts +9 -9
- package/src/utils/typeUtils.ts +0 -0
- package/src/utils/urlUtils.ts +0 -0
- package/src/utils/userPromoCodeUtils.ts +0 -0
- package/src/utils/userSubscriptionUtils.ts +0 -0
package/README.md
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bash-app/bash-common",
|
|
3
|
-
"version": "30.
|
|
3
|
+
"version": "30.50.0",
|
|
4
4
|
"description": "Common data and scripts to use on the frontend and backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"@testing-library/jest-dom": "^6.6.3",
|
|
25
25
|
"@types/qrcode": "^1.5.5",
|
|
26
26
|
"lodash-es": "^4.17.21",
|
|
27
|
+
"mixpanel-browser": "^2.65.0",
|
|
27
28
|
"npm": "^10.5.0",
|
|
28
29
|
"qrcode": "^1.5.3"
|
|
29
30
|
},
|
|
30
31
|
"peerDependencies": {
|
|
31
32
|
"@prisma/client": "^6.1.0",
|
|
32
|
-
"dayjs": "^1.11.13",
|
|
33
33
|
"luxon": "^3.5.0",
|
|
34
34
|
"prisma": "^6.1.0",
|
|
35
35
|
"react-tailwindcss-datepicker": "^1.6.6",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/jest": "^29.5.5",
|
|
40
40
|
"@types/luxon": "^3.4.2",
|
|
41
|
+
"@types/mixpanel-browser": "^2.60.0",
|
|
41
42
|
"@types/node": "^20.11.1",
|
|
42
43
|
"@types/react": "^18.3.2",
|
|
43
44
|
"@types/shelljs": "^0.8.15",
|
package/prisma/schema.prisma
CHANGED
|
@@ -262,6 +262,11 @@ model Invitation {
|
|
|
262
262
|
enum BashEventSource {
|
|
263
263
|
Bash
|
|
264
264
|
Eventbrite
|
|
265
|
+
Insomniac
|
|
266
|
+
UtahValley
|
|
267
|
+
LinkedIn
|
|
268
|
+
Meetup
|
|
269
|
+
Facebook
|
|
265
270
|
}
|
|
266
271
|
|
|
267
272
|
model BashEvent {
|
|
@@ -751,7 +756,14 @@ enum Education {
|
|
|
751
756
|
enum UserIntent {
|
|
752
757
|
EventSeeker
|
|
753
758
|
EventOrganizer
|
|
759
|
+
Volunteer
|
|
760
|
+
EntertainmentService
|
|
761
|
+
EventService
|
|
762
|
+
Vendor
|
|
763
|
+
Sponsor
|
|
764
|
+
Exhibitor
|
|
754
765
|
VenueOwner
|
|
766
|
+
OrganizationOwner
|
|
755
767
|
Lonely
|
|
756
768
|
}
|
|
757
769
|
|
|
@@ -1115,6 +1127,8 @@ model User {
|
|
|
1115
1127
|
trendingBashThreshold Int @default(10) // Min attendees to trigger notification
|
|
1116
1128
|
organizerUser UserFollowing[] @relation("FollowingOrganizers")
|
|
1117
1129
|
favorites UserFavorite[]
|
|
1130
|
+
|
|
1131
|
+
vendorBid VendorBid[]
|
|
1118
1132
|
}
|
|
1119
1133
|
|
|
1120
1134
|
model UserPreferences {
|
|
@@ -1123,68 +1137,90 @@ model UserPreferences {
|
|
|
1123
1137
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1124
1138
|
|
|
1125
1139
|
// Notification Preferences
|
|
1126
|
-
emailNotifications
|
|
1127
|
-
pushNotifications
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1140
|
+
emailNotifications Boolean @default(true)
|
|
1141
|
+
pushNotifications Boolean @default(true)
|
|
1142
|
+
marketingEmails Boolean @default(true) // Added from our UI
|
|
1143
|
+
eventUpdates Boolean @default(true) // Added from our UI
|
|
1144
|
+
serviceBookingNotifications Boolean @default(true) // Added from our UI
|
|
1145
|
+
reviewReminders Boolean @default(true) // Added from our UI
|
|
1146
|
+
newFollowerNotifications Boolean @default(true) // Added from our UI
|
|
1147
|
+
trendingBashesNotify Boolean @default(true) // Updated default to true
|
|
1148
|
+
organizerUpdatesNotify Boolean @default(true) // Updated default to true
|
|
1149
|
+
recurringReminders Boolean @default(true) // NEW - multiple reminders as event approaches
|
|
1150
|
+
eventSuggestions Boolean @default(true) // NEW - event planning tips and suggestions
|
|
1151
|
+
serviceSuggestions Boolean @default(true) // NEW - vendor/service recommendations
|
|
1152
|
+
eventReminderNotify Boolean @default(true)
|
|
1153
|
+
newMessageNotify Boolean @default(true)
|
|
1154
|
+
invitationNotify Boolean @default(true)
|
|
1155
|
+
commentNotify Boolean @default(true)
|
|
1156
|
+
servicePromotionsNotify Boolean @default(true)
|
|
1138
1157
|
|
|
1139
1158
|
// Privacy Settings
|
|
1140
|
-
profileVisibility
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1159
|
+
profileVisibility String @default("public") // Updated to lowercase, matches our UI
|
|
1160
|
+
eventHistoryVisibility Boolean @default(true) // Added from our UI
|
|
1161
|
+
servicesVisibility Boolean @default(true) // Added from our UI
|
|
1162
|
+
searchVisibility Boolean @default(true) // Added from our UI
|
|
1163
|
+
hideFollowLists Boolean @default(false) // NEW - hide follower/following lists
|
|
1164
|
+
attendancePrivacy String @default("public") // Updated to lowercase, matches our UI
|
|
1165
|
+
hideEventPrices Boolean @default(false) // NEW - hide prices until day of event
|
|
1166
|
+
showOnlineStatus Boolean @default(true)
|
|
1167
|
+
allowDirectMessages Boolean @default(true)
|
|
1168
|
+
blockSearchEngineIndex Boolean @default(false)
|
|
1169
|
+
|
|
1170
|
+
// Contact Management (NEW SECTION)
|
|
1171
|
+
autoAddEventAttendees Boolean @default(true) // NEW - auto-add event attendees to contacts
|
|
1172
|
+
trackFirstEventAttended Boolean @default(true) // NEW - remember which bash connected you
|
|
1173
|
+
autoAddServiceClients Boolean @default(true) // NEW - auto-add service clients to contacts
|
|
1149
1174
|
|
|
1150
1175
|
// UI/UX Preferences
|
|
1151
|
-
theme String @default("
|
|
1152
|
-
language String @default("en-US
|
|
1176
|
+
theme String @default("system") // Updated to lowercase, matches our UI
|
|
1177
|
+
language String @default("en") // Simplified from en-US
|
|
1153
1178
|
timeZone String @default("America/New_York")
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
showSensitiveContent Boolean @default(false)
|
|
1168
|
-
|
|
1169
|
-
// Calendar & Event Preferences
|
|
1170
|
-
defaultCalendarView String @default("MONTH") // DAY, WEEK, MONTH, AGENDA
|
|
1171
|
-
calendarStartDay Int @default(0) // 0=Sunday, 1=Monday
|
|
1172
|
-
defaultEventReminder Int @default(60) // Minutes before event
|
|
1173
|
-
attendancePrivacy String @default("PUBLIC") // PUBLIC, FRIENDS, PRIVATE
|
|
1174
|
-
|
|
1175
|
-
// Communications Preferences
|
|
1176
|
-
communicationFrequency String @default("NORMAL") // LOW, NORMAL, HIGH
|
|
1177
|
-
preferredContactMethod String @default("EMAIL") // EMAIL, PUSH, SMS
|
|
1178
|
-
|
|
1179
|
-
// Data & Payment Preferences
|
|
1180
|
-
dataUsageConsent Boolean @default(true)
|
|
1181
|
-
analyticsConsent Boolean @default(true)
|
|
1179
|
+
|
|
1180
|
+
// Event Preferences
|
|
1181
|
+
eventReminderTiming String @default("1day") // NEW - 1hour, 1day, 1week (replaces defaultEventReminder)
|
|
1182
|
+
locationRadius Int @default(50) // NEW - miles for event suggestions
|
|
1183
|
+
calendarStartDay Int @default(0) // 0=Sunday, 1=Monday
|
|
1184
|
+
defaultCalendarView String @default("MONTH") // DAY, WEEK, MONTH, AGENDA
|
|
1185
|
+
|
|
1186
|
+
// Security & Consent Preferences
|
|
1187
|
+
biometricAuthEnabled Boolean @default(false) // NEW - Face ID/Touch ID/Fingerprint
|
|
1188
|
+
dataUsageConsent Boolean @default(true)
|
|
1189
|
+
analyticsConsent Boolean @default(true)
|
|
1190
|
+
|
|
1191
|
+
// Payment Preferences
|
|
1182
1192
|
preferredCurrency String @default("USD")
|
|
1183
1193
|
savePaymentInfo Boolean @default(false)
|
|
1184
1194
|
showEventPrices Boolean @default(true)
|
|
1185
1195
|
|
|
1186
1196
|
createdAt DateTime @default(now())
|
|
1187
1197
|
updatedAt DateTime @updatedAt
|
|
1198
|
+
|
|
1199
|
+
// Less Relevant Fields (moved to bottom)
|
|
1200
|
+
smsNotifications Boolean @default(false) // We're not using SMS
|
|
1201
|
+
friendRequestNotify Boolean @default(true) // We use followers, not friends
|
|
1202
|
+
allowTagging Boolean @default(true)
|
|
1203
|
+
showActivityStatus Boolean @default(true)
|
|
1204
|
+
hiddenBashIds String[] @default([])
|
|
1205
|
+
hideActivitySection Boolean @default(false)
|
|
1206
|
+
allowLocationSharing Boolean @default(false)
|
|
1207
|
+
defaultLandingPage String @default("dashboard")
|
|
1208
|
+
contentDensity String @default("COMFORTABLE") // COMPACT, COMFORTABLE, SPACIOUS
|
|
1209
|
+
fontScale String @default("MEDIUM") // SMALL, MEDIUM, LARGE
|
|
1210
|
+
animationsEnabled Boolean @default(true)
|
|
1211
|
+
useHighContrastMode Boolean @default(false)
|
|
1212
|
+
contentFilters String[] @default([])
|
|
1213
|
+
topicInterests String[] @default([])
|
|
1214
|
+
hideSeenContent Boolean @default(false)
|
|
1215
|
+
autoplayVideos Boolean @default(true)
|
|
1216
|
+
contentSortPreference String @default("RECENT") // RECENT, POPULAR, RELEVANT
|
|
1217
|
+
contentLanguages String[] @default(["en"])
|
|
1218
|
+
showSensitiveContent Boolean @default(false)
|
|
1219
|
+
defaultEventReminder Int @default(60) // Minutes before event (replaced by eventReminderTiming)
|
|
1220
|
+
communicationFrequency String @default("NORMAL") // LOW, NORMAL, HIGH
|
|
1221
|
+
preferredContactMethod String @default("EMAIL") // EMAIL, PUSH, SMS
|
|
1222
|
+
|
|
1223
|
+
@@map("user_preferences")
|
|
1188
1224
|
}
|
|
1189
1225
|
|
|
1190
1226
|
model UserFollowing {
|
|
@@ -1602,9 +1638,58 @@ model Vendor {
|
|
|
1602
1638
|
subType String?
|
|
1603
1639
|
otherSubType String?
|
|
1604
1640
|
detailsText String?
|
|
1605
|
-
|
|
1641
|
+
|
|
1642
|
+
// Booth fee range fields
|
|
1643
|
+
minBoothFeeCents Int? @default(0)
|
|
1644
|
+
maxBoothFeeCents Int? @default(0)
|
|
1645
|
+
preferredBoothFeeCents Int? @default(0)
|
|
1646
|
+
|
|
1647
|
+
service Service?
|
|
1648
|
+
vendorBids VendorBid[] // Relation to bids
|
|
1606
1649
|
}
|
|
1607
1650
|
|
|
1651
|
+
model VendorBid {
|
|
1652
|
+
id String @id @default(cuid())
|
|
1653
|
+
vendorId String
|
|
1654
|
+
vendor Vendor @relation(fields: [vendorId], references: [id], onDelete: Cascade)
|
|
1655
|
+
|
|
1656
|
+
// Host (bidder) information
|
|
1657
|
+
userId String
|
|
1658
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
1659
|
+
|
|
1660
|
+
// Bid details
|
|
1661
|
+
bidAmountCents Int
|
|
1662
|
+
eventDetails String @db.Text
|
|
1663
|
+
eventDate DateTime?
|
|
1664
|
+
expectedAttendees Int?
|
|
1665
|
+
|
|
1666
|
+
// Bid status
|
|
1667
|
+
status VendorBidStatus @default(Pending)
|
|
1668
|
+
respondedAt DateTime?
|
|
1669
|
+
responseMessage String?
|
|
1670
|
+
|
|
1671
|
+
// Payment tracking (if accepted)
|
|
1672
|
+
stripePaymentIntentId String?
|
|
1673
|
+
paidAt DateTime?
|
|
1674
|
+
|
|
1675
|
+
createdAt DateTime @default(now())
|
|
1676
|
+
updatedAt DateTime @updatedAt
|
|
1677
|
+
|
|
1678
|
+
@@index([vendorId])
|
|
1679
|
+
@@index([userId])
|
|
1680
|
+
@@index([status])
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
enum VendorBidStatus {
|
|
1684
|
+
Pending
|
|
1685
|
+
Accepted
|
|
1686
|
+
Rejected
|
|
1687
|
+
Withdrawn
|
|
1688
|
+
Expired
|
|
1689
|
+
Paid
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
|
|
1608
1693
|
model Exhibitor {
|
|
1609
1694
|
id String @id @default(cuid())
|
|
1610
1695
|
serviceRangeId String?
|
|
@@ -1875,6 +1960,42 @@ enum EventManagerFormat {
|
|
|
1875
1960
|
MultiVenueManager
|
|
1876
1961
|
}
|
|
1877
1962
|
|
|
1963
|
+
enum LightCleaningFormat {
|
|
1964
|
+
PreEventSetup
|
|
1965
|
+
DuringEventMaintenance
|
|
1966
|
+
PostEventCleanup
|
|
1967
|
+
VenueWipeDown
|
|
1968
|
+
TrashRemoval
|
|
1969
|
+
BathroomMaintenance
|
|
1970
|
+
DiningAreaCleanup
|
|
1971
|
+
KitchenBasics
|
|
1972
|
+
FloorSweeping
|
|
1973
|
+
SurfaceCleaning
|
|
1974
|
+
WindowCleaning
|
|
1975
|
+
TableReset
|
|
1976
|
+
ChairArrangement
|
|
1977
|
+
BasicVacuuming
|
|
1978
|
+
SpotCleaning
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
enum DeepCleaningFormat {
|
|
1982
|
+
PreEventDeepClean
|
|
1983
|
+
PostEventRestoration
|
|
1984
|
+
CarpetCleaning
|
|
1985
|
+
FloorStripping
|
|
1986
|
+
WindowWashing
|
|
1987
|
+
KitchenDeepClean
|
|
1988
|
+
BathroomSanitization
|
|
1989
|
+
UpholsteryClean
|
|
1990
|
+
VenueDisinfection
|
|
1991
|
+
EquipmentCleaning
|
|
1992
|
+
HighDusting
|
|
1993
|
+
PressureWashing
|
|
1994
|
+
GraffitiRemoval
|
|
1995
|
+
FloorWaxing
|
|
1996
|
+
DetailedSanitization
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1878
1999
|
enum VirtualAssistantFormat {
|
|
1879
2000
|
EventScheduling
|
|
1880
2001
|
VendorCoordination
|
|
@@ -3111,6 +3232,11 @@ model ServiceBooking {
|
|
|
3111
3232
|
bashEventId String?
|
|
3112
3233
|
bashEvent BashEvent? @relation(fields: [bashEventId], references: [id])
|
|
3113
3234
|
|
|
3235
|
+
// Vendor-specific booking fields
|
|
3236
|
+
isVendorBid Boolean @default(false)
|
|
3237
|
+
vendorBidAmountCents Int? // Custom bid amount for vendor bookings
|
|
3238
|
+
vendorEventDetails String? // Additional event details for vendor
|
|
3239
|
+
|
|
3114
3240
|
@@index([status])
|
|
3115
3241
|
@@index([creatorId])
|
|
3116
3242
|
@@index([forUserId])
|
package/src/extendedSchemas.ts
CHANGED
|
@@ -721,6 +721,7 @@ export const INVITATION_DATA_TO_INCLUDE = {
|
|
|
721
721
|
export interface InvitationExtraData extends Invitation {
|
|
722
722
|
isFreeGuest: boolean;
|
|
723
723
|
isOrganizer?: boolean;
|
|
724
|
+
isOwnershipTransfer?: boolean;
|
|
724
725
|
}
|
|
725
726
|
|
|
726
727
|
export interface AssociatedBashExt extends AssociatedBash {
|
package/src/utils/apiUtils.ts
CHANGED
|
File without changes
|
package/src/utils/arrayUtils.ts
CHANGED
|
File without changes
|
package/src/utils/awsS3Utils.ts
CHANGED
|
File without changes
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
1
2
|
import { DateType, DateValueType } from "react-tailwindcss-datepicker";
|
|
2
|
-
import dayjs, { Dayjs } from "dayjs";
|
|
3
|
-
import dayjsUtc from "dayjs/plugin/utc";
|
|
4
|
-
import dayjsTimeZone from "dayjs/plugin/timezone";
|
|
5
3
|
import { DateTimeArgType } from "../definitions";
|
|
6
4
|
|
|
7
|
-
dayjs.extend(dayjsUtc);
|
|
8
|
-
dayjs.extend(dayjsTimeZone);
|
|
9
|
-
|
|
10
5
|
const PARSE_TIME_REG = /^(\d{1,2}):(\d{2}) ?([APM]{0,2})$/i;
|
|
11
6
|
|
|
12
|
-
export const DATETIME_FORMAT_STANDARD = "MMM
|
|
13
|
-
export const DATETIME_FORMAT_ISO_LIKE = "
|
|
14
|
-
export const DATE_FORMAT_STANDARD = "MM/
|
|
15
|
-
export const DATE_FORMAT_ISO = "
|
|
16
|
-
export const TIME_FORMAT_AM_PM = "h:mm
|
|
7
|
+
export const DATETIME_FORMAT_STANDARD = "MMM d, yyyy - h:mm a";
|
|
8
|
+
export const DATETIME_FORMAT_ISO_LIKE = "yyyy-MM-dd HH:mm";
|
|
9
|
+
export const DATE_FORMAT_STANDARD = "MM/dd/yyyy";
|
|
10
|
+
export const DATE_FORMAT_ISO = "yyyy-MM-dd";
|
|
11
|
+
export const TIME_FORMAT_AM_PM = "h:mm a";
|
|
17
12
|
|
|
18
13
|
export interface ITime {
|
|
19
14
|
hours: number;
|
|
@@ -21,42 +16,46 @@ export interface ITime {
|
|
|
21
16
|
ampm: "AM" | "PM";
|
|
22
17
|
}
|
|
23
18
|
|
|
19
|
+
export function getLocalTimezoneName(): string {
|
|
20
|
+
return DateTime.local().zoneName;
|
|
21
|
+
}
|
|
22
|
+
|
|
24
23
|
export function formatDateRangeBasic(
|
|
25
24
|
startDateTimeArg: Date | null,
|
|
26
25
|
endDateTimeArg: Date | null
|
|
27
26
|
): string {
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
const userTimezone = getLocalTimezoneName();
|
|
28
|
+
const startDateTime = DateTime.fromJSDate(startDateTimeArg || new Date()).setZone(userTimezone);
|
|
29
|
+
const endDateTime = DateTime.fromJSDate(endDateTimeArg || new Date()).setZone(userTimezone);
|
|
30
|
+
|
|
31
|
+
if (startDateTime.hasSame(endDateTime, "day")) {
|
|
32
|
+
return `${startDateTime.toFormat(
|
|
32
33
|
DATETIME_FORMAT_STANDARD
|
|
33
|
-
)} to ${endDateTime.
|
|
34
|
+
)} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
return `${startDateTime.
|
|
37
|
+
return `${startDateTime.toFormat(
|
|
37
38
|
DATETIME_FORMAT_STANDARD
|
|
38
|
-
)} to ${endDateTime.
|
|
39
|
+
)} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export function formatDateRange(
|
|
42
43
|
startDateTimeArg: Date | null,
|
|
43
44
|
endDateTimeArg: Date | null
|
|
44
45
|
): string {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (startDateTime.isSame(endDateTime, "day")) {
|
|
52
|
-
return `${startDateTime.format(
|
|
46
|
+
const userTimezone = getLocalTimezoneName();
|
|
47
|
+
const startDateTime = ensureDateTimeIsLocalDateTime(startDateTimeArg).setZone(userTimezone);
|
|
48
|
+
const endDateTime = ensureDateTimeIsLocalDateTime(endDateTimeArg).setZone(userTimezone);
|
|
49
|
+
|
|
50
|
+
if (startDateTime.hasSame(endDateTime, "day")) {
|
|
51
|
+
return `${startDateTime.toFormat(
|
|
53
52
|
DATETIME_FORMAT_STANDARD
|
|
54
|
-
)} to ${endDateTime.
|
|
53
|
+
)} to ${endDateTime.toFormat(TIME_FORMAT_AM_PM)}`;
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
return `${startDateTime.
|
|
56
|
+
return `${startDateTime.toFormat(
|
|
58
57
|
DATETIME_FORMAT_STANDARD
|
|
59
|
-
)} to ${endDateTime.
|
|
58
|
+
)} to ${endDateTime.toFormat(DATETIME_FORMAT_STANDARD)}`;
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export function ensureIsDateTime(
|
|
@@ -84,8 +83,9 @@ export function normalizeDate(
|
|
|
84
83
|
}
|
|
85
84
|
|
|
86
85
|
// Normalize to UTC and start of minute
|
|
87
|
-
return
|
|
86
|
+
return DateTime.fromJSDate(date).toUTC().startOf("minute").toJSDate();
|
|
88
87
|
}
|
|
88
|
+
|
|
89
89
|
export function normalizeDates(
|
|
90
90
|
dates: (Date | string | undefined | null)[]
|
|
91
91
|
): Date[] {
|
|
@@ -108,12 +108,11 @@ export function dateWithinDateRange(
|
|
|
108
108
|
date: DateTimeArgType,
|
|
109
109
|
dateRange: DateValueType | undefined
|
|
110
110
|
): boolean {
|
|
111
|
-
const startDate =
|
|
112
|
-
const endDate =
|
|
111
|
+
const startDate = DateTime.fromJSDate(dateRange?.startDate || new Date()).startOf("day");
|
|
112
|
+
const endDate = DateTime.fromJSDate(dateRange?.endDate || new Date()).endOf("day");
|
|
113
|
+
const checkDate = DateTime.fromJSDate(new Date(date || ''));
|
|
113
114
|
|
|
114
|
-
return
|
|
115
|
-
compareDateTime(date, startDate) >= 0 && compareDateTime(date, endDate) < 0
|
|
116
|
-
);
|
|
115
|
+
return checkDate >= startDate && checkDate < endDate;
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
export function findLatestDateTime(
|
|
@@ -197,76 +196,82 @@ export function setDateButPreserveTime(
|
|
|
197
196
|
}
|
|
198
197
|
|
|
199
198
|
// Get local timezone
|
|
200
|
-
const localTimeZone =
|
|
201
|
-
|
|
202
|
-
//
|
|
203
|
-
const
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
199
|
+
const localTimeZone = getLocalTimezoneName();
|
|
200
|
+
|
|
201
|
+
// Extract date and time components using Luxon
|
|
202
|
+
const dateOnly = DateTime.fromJSDate(new Date(dateArg)).setZone(localTimeZone);
|
|
203
|
+
const timeOnly = DateTime.fromJSDate(new Date(dateWithTheTimeYouWantToKeep)).setZone(localTimeZone);
|
|
204
|
+
|
|
205
|
+
// Combine date from first argument with time from second argument
|
|
206
|
+
const combinedDateTime = dateOnly.set({
|
|
207
|
+
hour: timeOnly.hour,
|
|
208
|
+
minute: timeOnly.minute,
|
|
209
|
+
second: 0,
|
|
210
|
+
millisecond: 0
|
|
211
|
+
});
|
|
207
212
|
|
|
208
|
-
// Combine into an ISO string
|
|
209
|
-
const combinedDateTimeString = `${datePart}T${timePart}`;
|
|
210
213
|
console.log("Combining date and time:", {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
+
dateOnly: dateOnly.toISO(),
|
|
215
|
+
timeOnly: timeOnly.toFormat("HH:mm"),
|
|
216
|
+
combinedDateTime: combinedDateTime.toISO(),
|
|
214
217
|
localTimeZone,
|
|
215
218
|
});
|
|
216
219
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
.
|
|
220
|
-
.toDate();
|
|
221
|
-
if (isNaN(combinedDateTime.getTime())) {
|
|
222
|
-
console.error("Invalid combined datetime:", combinedDateTimeString);
|
|
220
|
+
const result = combinedDateTime.toJSDate();
|
|
221
|
+
if (isNaN(result.getTime())) {
|
|
222
|
+
console.error("Invalid combined datetime:", combinedDateTime.toISO());
|
|
223
223
|
throw new Error("Invalid date or time format.");
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
console.log("Final combined DateTime (UTC):",
|
|
227
|
-
return
|
|
226
|
+
console.log("Final combined DateTime (UTC):", result);
|
|
227
|
+
return result;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
export function setTimeOnDate(
|
|
231
231
|
date: DateType | Date | undefined,
|
|
232
232
|
parsedTime: ITime | null
|
|
233
233
|
): Date {
|
|
234
|
-
const
|
|
235
|
-
|
|
234
|
+
const dateTime = DateTime.fromJSDate(date ? new Date(date) : new Date());
|
|
235
|
+
|
|
236
236
|
if (parsedTime) {
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
237
|
+
const updatedDateTime = dateTime.set({
|
|
238
|
+
hour: parsedTime.hours,
|
|
239
|
+
minute: parsedTime.minutes,
|
|
240
|
+
second: 0,
|
|
241
|
+
millisecond: 0
|
|
242
|
+
});
|
|
243
|
+
return setDateButPreserveTime(dateTime.toJSDate(), updatedDateTime.toJSDate());
|
|
241
244
|
}
|
|
242
|
-
return dateTime;
|
|
245
|
+
return dateTime.toJSDate();
|
|
243
246
|
}
|
|
244
247
|
|
|
245
248
|
export function ensureDateTimeIsLocalDateTime(
|
|
246
|
-
dateArg: DateType |
|
|
247
|
-
):
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
249
|
+
dateArg: DateType | DateTime | undefined
|
|
250
|
+
): DateTime {
|
|
251
|
+
if (!dateArg) {
|
|
252
|
+
return DateTime.local();
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (dateArg instanceof DateTime) {
|
|
256
|
+
return dateArg.setZone(getLocalTimezoneName());
|
|
253
257
|
}
|
|
258
|
+
|
|
259
|
+
const dt = DateTime.fromJSDate(new Date(dateArg));
|
|
260
|
+
return dt.setZone(getLocalTimezoneName());
|
|
254
261
|
}
|
|
255
262
|
|
|
256
263
|
export function formatDateTimeToTimeString(
|
|
257
264
|
date: Date | string | undefined | null
|
|
258
265
|
): string {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
return result;
|
|
266
|
+
const dt = DateTime.fromJSDate(new Date(date ?? Date.now()));
|
|
267
|
+
return dt.toFormat("h:mm a");
|
|
262
268
|
}
|
|
263
269
|
|
|
264
270
|
export function formatDateTimeToTimeString24hr(
|
|
265
271
|
date: Date | string | undefined | null
|
|
266
272
|
): string {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return result;
|
|
273
|
+
const dt = DateTime.fromJSDate(new Date(date ?? Date.now()));
|
|
274
|
+
return dt.toFormat("H:mm");
|
|
270
275
|
}
|
|
271
276
|
|
|
272
277
|
export function parseTimeString(timeStr: string): ITime | null {
|
|
@@ -293,6 +298,7 @@ export function parseTimeString(timeStr: string): ITime | null {
|
|
|
293
298
|
}
|
|
294
299
|
return null;
|
|
295
300
|
}
|
|
301
|
+
|
|
296
302
|
export function timestampMinutesFromNow(minutes: number): number {
|
|
297
|
-
return Math.floor(
|
|
303
|
+
return Math.floor(DateTime.local().plus({ minutes }).toSeconds());
|
|
298
304
|
}
|
package/src/utils/entityUtils.ts
CHANGED
|
File without changes
|
|
File without changes
|
package/src/utils/luxonUtils.ts
CHANGED
|
@@ -281,11 +281,6 @@ export function getLocalTimezone() {
|
|
|
281
281
|
return utcOffsetMinutesToTimezone(localDateTime.offset);
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
export function getLocalTimezoneName() {
|
|
285
|
-
const localDateTime = DateTime.local();
|
|
286
|
-
return localDateTime.zoneName;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
284
|
export function dateTimeFormatDateRange(
|
|
290
285
|
startDateTimeArg: DateTime | null,
|
|
291
286
|
endDateTimeArg: DateTime | null
|
package/src/utils/mathUtils.ts
CHANGED
|
File without changes
|
package/src/utils/objUtils.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/utils/qrCodeUtils.ts
CHANGED
|
File without changes
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import {DayOfWeek, Recurrence, RecurringFrequency} from "@prisma/client";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {compareDateTime, DATETIME_FORMAT_ISO_LIKE} from "./dateTimeUtils";
|
|
6
|
-
|
|
7
|
-
dayjs.extend(dayjsWeekDay);
|
|
8
|
-
|
|
1
|
+
import { DayOfWeek, Recurrence, RecurringFrequency } from "@prisma/client";
|
|
2
|
+
import { DateTime, WeekdayNumbers } from "luxon";
|
|
3
|
+
import { DateTimeArgType } from "../definitions";
|
|
4
|
+
import { compareDateTime, DATETIME_FORMAT_ISO_LIKE } from "./dateTimeUtils";
|
|
9
5
|
|
|
10
6
|
export function getRecurringBashEventPossibleDateTimes(startDateTime: DateTimeArgType,
|
|
11
7
|
recurrence: Recurrence | undefined | null): Date[] {
|
|
@@ -13,20 +9,19 @@ export function getRecurringBashEventPossibleDateTimes(startDateTime: DateTimeAr
|
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
export function getRecurringBashEventPossibleDayjsTimes(startDateTime: DateTimeArgType,
|
|
16
|
-
recurrence: Recurrence | undefined | null):
|
|
17
|
-
return getRecurringBashEventPossibleDatesTimesInternal(startDateTime, recurrence, false) as
|
|
12
|
+
recurrence: Recurrence | undefined | null): DateTime[] {
|
|
13
|
+
return getRecurringBashEventPossibleDatesTimesInternal(startDateTime, recurrence, false) as DateTime[];
|
|
18
14
|
}
|
|
19
15
|
|
|
20
|
-
|
|
21
16
|
function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTimeArgType,
|
|
22
17
|
recurrence: Recurrence | undefined | null,
|
|
23
|
-
toDate: boolean): (
|
|
18
|
+
toDate: boolean): (DateTime | Date)[] {
|
|
24
19
|
if (!recurrence || !recurrence.frequency || recurrence.frequency === RecurringFrequency.Never) {
|
|
25
20
|
return [];
|
|
26
21
|
}
|
|
27
22
|
|
|
28
|
-
let recurrenceDates:
|
|
29
|
-
const beginningDate = findEarliestPossibleBashEventDate(startDateTime) as
|
|
23
|
+
let recurrenceDates: DateTime[] = [];
|
|
24
|
+
const beginningDate = findEarliestPossibleBashEventDate(startDateTime) as DateTime; // Don't allow dates before the current date
|
|
30
25
|
|
|
31
26
|
switch (recurrence.frequency) {
|
|
32
27
|
case RecurringFrequency.Weekly:
|
|
@@ -35,14 +30,15 @@ function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTime
|
|
|
35
30
|
default:
|
|
36
31
|
console.error(`Only weekly frequency is currently supported`);
|
|
37
32
|
}
|
|
38
|
-
return recurrenceDates.map((date:
|
|
33
|
+
return recurrenceDates.map((date: DateTime): string => date.toFormat(DATETIME_FORMAT_ISO_LIKE))
|
|
39
34
|
.sort()
|
|
40
|
-
.map((dateStr: string):
|
|
35
|
+
.map((dateStr: string): DateTime | Date => {
|
|
36
|
+
const luxonDate = DateTime.fromFormat(dateStr, DATETIME_FORMAT_ISO_LIKE);
|
|
41
37
|
if (toDate) {
|
|
42
|
-
return
|
|
38
|
+
return luxonDate.toJSDate();
|
|
43
39
|
}
|
|
44
40
|
else {
|
|
45
|
-
return
|
|
41
|
+
return luxonDate;
|
|
46
42
|
}
|
|
47
43
|
});
|
|
48
44
|
}
|
|
@@ -52,25 +48,25 @@ function getRecurringBashEventPossibleDatesTimesInternal(startDateTime: DateTime
|
|
|
52
48
|
* @param beginningDateTime The beginning DateTime of the event, adjusted to be no earlier than now.
|
|
53
49
|
* @param recurrence
|
|
54
50
|
*/
|
|
55
|
-
function getWeeklyRecurringDates(beginningDateTime:
|
|
51
|
+
function getWeeklyRecurringDates(beginningDateTime: DateTime, recurrence: Recurrence): DateTime[] {
|
|
56
52
|
if (recurrence.frequency !== RecurringFrequency.Weekly) {
|
|
57
53
|
throw new Error(`Cannot do a weekly recurrence if the frequency isn't weekly.`);
|
|
58
54
|
}
|
|
59
55
|
|
|
60
56
|
const interval = recurrence.interval ?? 1;
|
|
61
|
-
const recurrenceEnds =
|
|
62
|
-
const numberOfDays = recurrenceEnds.diff(beginningDateTime, 'days');
|
|
57
|
+
const recurrenceEnds = DateTime.fromJSDate(new Date(recurrence.ends || '')).endOf('day'); // Get the end of the day to not miss the last day
|
|
58
|
+
const numberOfDays = recurrenceEnds.diff(beginningDateTime, 'days').days;
|
|
63
59
|
const numberOfWeeks = Math.ceil((numberOfDays / 7) / interval); // Get the number of days and then round up so that we include the ending date
|
|
64
60
|
|
|
65
|
-
const recurrenceDates:
|
|
61
|
+
const recurrenceDates: DateTime[] = [];
|
|
66
62
|
let theNextWeekOfRecurrences = beginningDateTime;
|
|
67
63
|
|
|
68
64
|
// Go week by week getting the next recurrence date
|
|
69
65
|
for (let i = 0; i < numberOfWeeks; i++) {
|
|
70
|
-
let weekday:
|
|
66
|
+
let weekday: DateTime | null = null;
|
|
71
67
|
for (const dayOfWeekEnum of recurrence.repeatOnDays) {
|
|
72
68
|
const dayOfWeekNum = dayOfWeekEnumToDayNumber(dayOfWeekEnum);
|
|
73
|
-
|
|
69
|
+
weekday = theNextWeekOfRecurrences.set({ weekday: dayOfWeekNum as WeekdayNumbers });
|
|
74
70
|
if (weekday > recurrenceEnds || weekday < beginningDateTime) {
|
|
75
71
|
continue; // Continue because repeatOnDays isn't sorted by the day of the week
|
|
76
72
|
}
|
|
@@ -85,21 +81,22 @@ function getWeeklyRecurringDates(beginningDateTime: Dayjs, recurrence: Recurrenc
|
|
|
85
81
|
return recurrenceDates;
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
function copyTimeToDate(dateWithTimeToCopy:
|
|
89
|
-
if (dateWithTimeToCopy.second
|
|
84
|
+
function copyTimeToDate(dateWithTimeToCopy: DateTime, dateWhoseTimeToChange: DateTime): DateTime {
|
|
85
|
+
if (dateWithTimeToCopy.second !== 0) {
|
|
90
86
|
console.warn(`dateWithTimeToCopy has non-zero seconds: ${dateWithTimeToCopy.toString()} \nFixing...`);
|
|
91
|
-
dateWithTimeToCopy = dateWithTimeToCopy.set(
|
|
87
|
+
dateWithTimeToCopy = dateWithTimeToCopy.set({second: 0});
|
|
92
88
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
return dateWhoseTimeToChange.set({
|
|
90
|
+
hour: dateWithTimeToCopy.hour,
|
|
91
|
+
minute: dateWithTimeToCopy.minute,
|
|
92
|
+
second: 0
|
|
93
|
+
});
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
function dayOfWeekEnumToDayNumber(dayEnum: DayOfWeek): number {
|
|
100
97
|
switch (dayEnum) {
|
|
101
98
|
case DayOfWeek.Sunday:
|
|
102
|
-
return
|
|
99
|
+
return 7; // Luxon uses 1-7 where 7 is Sunday
|
|
103
100
|
case DayOfWeek.Monday:
|
|
104
101
|
return 1;
|
|
105
102
|
case DayOfWeek.Tuesday:
|
|
@@ -122,13 +119,13 @@ function dayOfWeekEnumToDayNumber(dayEnum: DayOfWeek): number {
|
|
|
122
119
|
* @param date
|
|
123
120
|
* @param interval
|
|
124
121
|
*/
|
|
125
|
-
function getBeginningOfWeekInterval(date:
|
|
122
|
+
function getBeginningOfWeekInterval(date: DateTime, interval: number): DateTime {
|
|
126
123
|
if (!interval) {
|
|
127
124
|
interval = 1; // Avoid 0
|
|
128
125
|
}
|
|
129
126
|
// An interval of 2 would be (2 - 1) * 7 + 1 = 8 days to add to skip a week and go into the next week
|
|
130
127
|
const numberOfDaysToAdd = interval > 1 ? (interval - 1) * 7 + 1 : 1;
|
|
131
|
-
return date.endOf('week').
|
|
128
|
+
return date.endOf('week').plus({ days: numberOfDaysToAdd });
|
|
132
129
|
}
|
|
133
130
|
|
|
134
131
|
export function freqToGrammarString(freq: RecurringFrequency, interval: number | undefined, toLowerCase: boolean = false): string {
|
|
@@ -154,18 +151,18 @@ export function freqToGrammarString(freq: RecurringFrequency, interval: number |
|
|
|
154
151
|
return toLowerCase ? result.toLowerCase() : result;
|
|
155
152
|
}
|
|
156
153
|
|
|
157
|
-
export function findEarliestPossibleBashEventDate(startDateTimeArg: DateTimeArgType):
|
|
154
|
+
export function findEarliestPossibleBashEventDate(startDateTimeArg: DateTimeArgType): DateTime | undefined {
|
|
158
155
|
return findEarliestOrLatestPossibleBashEventDate(startDateTimeArg, true);
|
|
159
156
|
}
|
|
160
157
|
|
|
161
|
-
function findEarliestOrLatestPossibleBashEventDate(startDateTimeArg: DateTimeArgType, findEarly: boolean):
|
|
158
|
+
function findEarliestOrLatestPossibleBashEventDate(startDateTimeArg: DateTimeArgType, findEarly: boolean): DateTime | undefined {
|
|
162
159
|
if (!startDateTimeArg) {
|
|
163
160
|
return;
|
|
164
161
|
}
|
|
165
162
|
// Don't allow dates before the current date
|
|
166
|
-
const startDateTime =
|
|
167
|
-
const currentDateTime =
|
|
168
|
-
const comparedDateTime = compareDateTime(currentDateTime.
|
|
163
|
+
const startDateTime = DateTime.fromJSDate(new Date(startDateTimeArg));
|
|
164
|
+
const currentDateTime = DateTime.local();
|
|
165
|
+
const comparedDateTime = compareDateTime(currentDateTime.toJSDate(), startDateTimeArg);
|
|
169
166
|
if (findEarly) {
|
|
170
167
|
return comparedDateTime > 0 ? currentDateTime : startDateTime;
|
|
171
168
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -107,20 +107,20 @@ export function serviceBookingCanHaveApprovalDecision(
|
|
|
107
107
|
errorMessage: "Approval decisions can only be made on booking requests.",
|
|
108
108
|
};
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
if (serviceBookingIsCanceled(booking)) {
|
|
111
|
+
return {
|
|
112
|
+
valid: false,
|
|
113
|
+
errorMessage:
|
|
114
|
+
"Approval decisions can not be made on canceled booking requests.",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (serviceBookingIsConfirmed(booking)) {
|
|
118
|
+
return {
|
|
119
|
+
valid: false,
|
|
120
|
+
errorMessage:
|
|
121
|
+
"Approval decisions can not be made on confirmed booking requests.",
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
124
|
|
|
125
125
|
return { valid: true };
|
|
126
126
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/utils/sortUtils.ts
CHANGED
|
File without changes
|
package/src/utils/stringUtils.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
NumberOfTicketsForDate,
|
|
4
|
+
URL_PARAMS_NUMBER_OF_TICKETS_TICKETS_DATE_DELIM,
|
|
5
|
+
URL_PARAMS_TICKET_LIST_DELIM,
|
|
6
|
+
URL_PARAMS_TICKET_TIER_ID_NUMBER_OF_TICKETS_DATE_DELIM,
|
|
7
|
+
URL_PARAMS_TICKETS_DATE_DELIM
|
|
8
8
|
} from "../definitions";
|
|
9
9
|
import { DATETIME_FORMAT_ISO_LIKE } from "./dateTimeUtils";
|
|
10
10
|
|
|
@@ -60,11 +60,11 @@ export function ticketListStrToTicketList(ticketListStr: string): Map<string, Nu
|
|
|
60
60
|
for (const ticketNumAndDateStr of ticketNumAndDates) {
|
|
61
61
|
// [numberOfTickets];;[date]
|
|
62
62
|
const [numberOfTickets, ticketDateTimeStr] = ticketNumAndDateStr.split(URL_PARAMS_TICKETS_DATE_DELIM);
|
|
63
|
-
const ticketDateTime =
|
|
63
|
+
const ticketDateTime = DateTime.fromISO(ticketDateTimeStr);
|
|
64
64
|
let ticketDateTimeFormattedStr: string | undefined = undefined;
|
|
65
65
|
|
|
66
|
-
if (ticketDateTime.isValid
|
|
67
|
-
ticketDateTimeFormattedStr = ticketDateTime.
|
|
66
|
+
if (ticketDateTime.isValid) {
|
|
67
|
+
ticketDateTimeFormattedStr = ticketDateTime.toFormat(DATETIME_FORMAT_ISO_LIKE);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
ticketNumAndDatesArr.push({
|
package/src/utils/typeUtils.ts
CHANGED
|
File without changes
|
package/src/utils/urlUtils.ts
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|