@bash-app/bash-common 29.66.0 → 29.68.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/package.json +3 -1
- package/prisma/schema.prisma +217 -67
- package/src/definitions.ts +131 -60
- package/src/extendedSchemas.ts +166 -111
- package/src/index.ts +9 -0
- package/src/utils/dateTimeUtils.ts +120 -60
- package/src/utils/generalDateTimeUtils.ts +43 -0
- package/src/utils/luxonUtils.ts +871 -72
- package/src/utils/mathUtils.ts +3 -0
- package/src/utils/service/attendeeOptionUtils.ts +19 -0
- package/src/utils/service/serviceBookingApiUtils.ts +116 -0
- package/src/utils/service/serviceBookingUtils.ts +321 -0
- package/src/utils/service/serviceDBUtils.ts +51 -0
- package/src/utils/service/serviceRateDBUtils.ts +179 -0
- package/src/utils/service/serviceRateUtils.ts +350 -0
- package/src/utils/service/serviceUtils.ts +35 -0
- package/src/utils/typeUtils.ts +16 -0
- package/tsconfig.json +2 -2
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {DateType, DateValueType} from "react-tailwindcss-datepicker";
|
|
2
|
-
import dayjs, {Dayjs} from "dayjs";
|
|
1
|
+
import { DateType, DateValueType } from "react-tailwindcss-datepicker";
|
|
2
|
+
import dayjs, { Dayjs } from "dayjs";
|
|
3
3
|
import dayjsUtc from "dayjs/plugin/utc";
|
|
4
4
|
import dayjsTimeZone from "dayjs/plugin/timezone";
|
|
5
|
-
import {DateTimeArgType} from "../definitions";
|
|
5
|
+
import { DateTimeArgType } from "../definitions";
|
|
6
6
|
|
|
7
7
|
dayjs.extend(dayjsUtc);
|
|
8
8
|
dayjs.extend(dayjsTimeZone);
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
const PARSE_TIME_REG = /^(\d{1,2}):(\d{2}) ?([APM]{0,2})$/i;
|
|
12
11
|
|
|
13
12
|
export const DATETIME_FORMAT_STANDARD = "MMM D, YYYY - h:mm A";
|
|
14
|
-
export const DATETIME_FORMAT_ISO_LIKE = "YYYY-MM-DD HH:mm"
|
|
13
|
+
export const DATETIME_FORMAT_ISO_LIKE = "YYYY-MM-DD HH:mm";
|
|
15
14
|
export const DATE_FORMAT_STANDARD = "MM/DD/YYYY";
|
|
16
15
|
export const DATE_FORMAT_ISO = "YYYY-MM-DD";
|
|
17
16
|
export const TIME_FORMAT_AM_PM = "h:mm A";
|
|
@@ -19,27 +18,62 @@ export const TIME_FORMAT_AM_PM = "h:mm A";
|
|
|
19
18
|
export interface ITime {
|
|
20
19
|
hours: number;
|
|
21
20
|
minutes: number;
|
|
22
|
-
ampm:
|
|
21
|
+
ampm: "AM" | "PM";
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
export function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
export function formatDateRangeBasic(
|
|
25
|
+
startDateTimeArg: Date | null,
|
|
26
|
+
endDateTimeArg: Date | null
|
|
27
|
+
): string {
|
|
28
|
+
const startDateTime = dayjs(startDateTimeArg).tz(dayjs.tz.guess());
|
|
29
|
+
const endDateTime = dayjs(endDateTimeArg).tz(dayjs.tz.guess());
|
|
30
|
+
if (startDateTime.isSame(endDateTime, "day")) {
|
|
31
|
+
return `${startDateTime.format(
|
|
32
|
+
DATETIME_FORMAT_STANDARD
|
|
33
|
+
)} to ${endDateTime.format(TIME_FORMAT_AM_PM)}`;
|
|
30
34
|
}
|
|
31
35
|
|
|
32
|
-
return `${startDateTime.format(
|
|
36
|
+
return `${startDateTime.format(
|
|
37
|
+
DATETIME_FORMAT_STANDARD
|
|
38
|
+
)} to ${endDateTime.format(DATETIME_FORMAT_STANDARD)}`;
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
export function
|
|
41
|
+
export function formatDateRange(
|
|
42
|
+
startDateTimeArg: Date | null,
|
|
43
|
+
endDateTimeArg: Date | null
|
|
44
|
+
): string {
|
|
45
|
+
const startDateTime = ensureDateTimeIsLocalDateTime(startDateTimeArg).tz(
|
|
46
|
+
dayjs.tz.guess()
|
|
47
|
+
);
|
|
48
|
+
const endDateTime = ensureDateTimeIsLocalDateTime(endDateTimeArg).tz(
|
|
49
|
+
dayjs.tz.guess()
|
|
50
|
+
);
|
|
51
|
+
if (startDateTime.isSame(endDateTime, "day")) {
|
|
52
|
+
return `${startDateTime.format(
|
|
53
|
+
DATETIME_FORMAT_STANDARD
|
|
54
|
+
)} to ${endDateTime.format(TIME_FORMAT_AM_PM)}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return `${startDateTime.format(
|
|
58
|
+
DATETIME_FORMAT_STANDARD
|
|
59
|
+
)} to ${endDateTime.format(DATETIME_FORMAT_STANDARD)}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function ensureIsDateTime(
|
|
63
|
+
possiblyADate: DateTimeArgType
|
|
64
|
+
): Date | undefined {
|
|
36
65
|
if (!possiblyADate) {
|
|
37
66
|
return undefined;
|
|
38
67
|
}
|
|
39
|
-
return typeof possiblyADate ===
|
|
68
|
+
return typeof possiblyADate === "string"
|
|
69
|
+
? new Date(possiblyADate)
|
|
70
|
+
: possiblyADate;
|
|
40
71
|
}
|
|
41
72
|
|
|
42
|
-
|
|
73
|
+
//convert to utc and round minutes
|
|
74
|
+
export function normalizeDate(
|
|
75
|
+
validDate: Date | string | undefined | null
|
|
76
|
+
): Date | undefined {
|
|
43
77
|
if (!validDate) return undefined;
|
|
44
78
|
|
|
45
79
|
const date = new Date(validDate);
|
|
@@ -52,14 +86,17 @@ export function normalizeDate(validDate: Date | string | undefined | null): Date
|
|
|
52
86
|
// Normalize to UTC and start of minute
|
|
53
87
|
return dayjs(date).utc().startOf("minute").toDate();
|
|
54
88
|
}
|
|
55
|
-
export function normalizeDates(
|
|
89
|
+
export function normalizeDates(
|
|
90
|
+
dates: (Date | string | undefined | null)[]
|
|
91
|
+
): Date[] {
|
|
56
92
|
return dates
|
|
57
93
|
.map((date) => normalizeDate(date)) // Normalize each date
|
|
58
94
|
.filter((date): date is Date => !!date); // Filter out invalid dates
|
|
59
95
|
}
|
|
60
96
|
|
|
61
|
-
|
|
62
|
-
|
|
97
|
+
export function formatDateTimeToISODateTimeString(
|
|
98
|
+
date: DateTimeArgType
|
|
99
|
+
): string | undefined {
|
|
63
100
|
if (!date) {
|
|
64
101
|
return undefined;
|
|
65
102
|
}
|
|
@@ -67,25 +104,31 @@ export function formatDateTimeToISODateTimeString(date: DateTimeArgType): string
|
|
|
67
104
|
return date.toISOString();
|
|
68
105
|
}
|
|
69
106
|
|
|
70
|
-
export function dateWithinDateRange(
|
|
71
|
-
|
|
72
|
-
|
|
107
|
+
export function dateWithinDateRange(
|
|
108
|
+
date: DateTimeArgType,
|
|
109
|
+
dateRange: DateValueType | undefined
|
|
110
|
+
): boolean {
|
|
111
|
+
const startDate = dayjs(dateRange?.startDate).startOf("day").toDate();
|
|
112
|
+
const endDate = dayjs(dateRange?.endDate).endOf("day").toDate();
|
|
73
113
|
|
|
74
|
-
return
|
|
75
|
-
compareDateTime(date, endDate) < 0
|
|
114
|
+
return (
|
|
115
|
+
compareDateTime(date, startDate) >= 0 && compareDateTime(date, endDate) < 0
|
|
116
|
+
);
|
|
76
117
|
}
|
|
77
118
|
|
|
78
|
-
export function findLatestDateTime(
|
|
119
|
+
export function findLatestDateTime(
|
|
120
|
+
date1Arg: DateTimeArgType,
|
|
121
|
+
date2Arg: DateTimeArgType
|
|
122
|
+
): Date | undefined {
|
|
79
123
|
const date1 = dateTimeTypeToDate(date1Arg);
|
|
80
124
|
const date2 = dateTimeTypeToDate(date2Arg);
|
|
81
125
|
return compareDateTime(date1, date2) > 0 ? date1 : date2;
|
|
82
126
|
}
|
|
83
127
|
|
|
84
128
|
function dateTimeTypeToDate(date: DateTimeArgType): Date | undefined {
|
|
85
|
-
if (typeof date ===
|
|
129
|
+
if (typeof date === "string") {
|
|
86
130
|
return new Date(date);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
131
|
+
} else {
|
|
89
132
|
return date ?? undefined;
|
|
90
133
|
}
|
|
91
134
|
}
|
|
@@ -94,8 +137,10 @@ export function isDateTimeLaterThanNow(date: DateTimeArgType): boolean {
|
|
|
94
137
|
return compareDateTime(date, new Date()) > 0;
|
|
95
138
|
}
|
|
96
139
|
|
|
97
|
-
export function areDateTimesEqual(
|
|
98
|
-
|
|
140
|
+
export function areDateTimesEqual(
|
|
141
|
+
date1: DateTimeArgType,
|
|
142
|
+
date2: DateTimeArgType
|
|
143
|
+
): boolean {
|
|
99
144
|
return compareDateTime(date1, date2) === 0;
|
|
100
145
|
}
|
|
101
146
|
|
|
@@ -104,8 +149,10 @@ export function areDateTimesEqual(date1: DateTimeArgType,
|
|
|
104
149
|
* @param date1
|
|
105
150
|
* @param date2
|
|
106
151
|
*/
|
|
107
|
-
export function compareDateTime(
|
|
108
|
-
|
|
152
|
+
export function compareDateTime(
|
|
153
|
+
date1: DateTimeArgType,
|
|
154
|
+
date2: DateTimeArgType
|
|
155
|
+
): number {
|
|
109
156
|
if (!date1 && !date2) {
|
|
110
157
|
return 0;
|
|
111
158
|
}
|
|
@@ -115,10 +162,10 @@ export function compareDateTime(date1: DateTimeArgType,
|
|
|
115
162
|
if (!date2) {
|
|
116
163
|
return 1;
|
|
117
164
|
}
|
|
118
|
-
if (typeof date1 ===
|
|
165
|
+
if (typeof date1 === "string") {
|
|
119
166
|
date1 = new Date(date1);
|
|
120
167
|
}
|
|
121
|
-
if (typeof date2 ===
|
|
168
|
+
if (typeof date2 === "string") {
|
|
122
169
|
date2 = new Date(date2);
|
|
123
170
|
}
|
|
124
171
|
|
|
@@ -130,8 +177,7 @@ export function compareDateTime(date1: DateTimeArgType,
|
|
|
130
177
|
}
|
|
131
178
|
if (date1Time === date2Time) {
|
|
132
179
|
return 0;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
180
|
+
} else {
|
|
135
181
|
return -1;
|
|
136
182
|
}
|
|
137
183
|
}
|
|
@@ -141,8 +187,13 @@ export function setDateButPreserveTime(
|
|
|
141
187
|
dateWithTheTimeYouWantToKeep: DateType | undefined
|
|
142
188
|
): Date {
|
|
143
189
|
if (!dateArg || !dateWithTheTimeYouWantToKeep) {
|
|
144
|
-
console.error("Invalid arguments:", {
|
|
145
|
-
|
|
190
|
+
console.error("Invalid arguments:", {
|
|
191
|
+
dateArg,
|
|
192
|
+
dateWithTheTimeYouWantToKeep,
|
|
193
|
+
});
|
|
194
|
+
throw new Error(
|
|
195
|
+
"Both dateArg and dateWithTheTimeYouWantToKeep are required."
|
|
196
|
+
);
|
|
146
197
|
}
|
|
147
198
|
|
|
148
199
|
// Get local timezone
|
|
@@ -150,7 +201,9 @@ export function setDateButPreserveTime(
|
|
|
150
201
|
|
|
151
202
|
// Format date and time parts
|
|
152
203
|
const datePart = dayjs(dateArg).tz(localTimeZone).format("YYYY-MM-DD"); // Local date
|
|
153
|
-
const timePart = dayjs(dateWithTheTimeYouWantToKeep)
|
|
204
|
+
const timePart = dayjs(dateWithTheTimeYouWantToKeep)
|
|
205
|
+
.tz(localTimeZone)
|
|
206
|
+
.format("HH:mm"); // Local time
|
|
154
207
|
|
|
155
208
|
// Combine into an ISO string
|
|
156
209
|
const combinedDateTimeString = `${datePart}T${timePart}`;
|
|
@@ -162,7 +215,9 @@ export function setDateButPreserveTime(
|
|
|
162
215
|
});
|
|
163
216
|
|
|
164
217
|
// Convert to UTC
|
|
165
|
-
const combinedDateTime = dayjs
|
|
218
|
+
const combinedDateTime = dayjs
|
|
219
|
+
.tz(combinedDateTimeString, localTimeZone)
|
|
220
|
+
.toDate();
|
|
166
221
|
if (isNaN(combinedDateTime.getTime())) {
|
|
167
222
|
console.error("Invalid combined datetime:", combinedDateTimeString);
|
|
168
223
|
throw new Error("Invalid date or time format.");
|
|
@@ -172,8 +227,10 @@ export function setDateButPreserveTime(
|
|
|
172
227
|
return combinedDateTime;
|
|
173
228
|
}
|
|
174
229
|
|
|
175
|
-
|
|
176
|
-
|
|
230
|
+
export function setTimeOnDate(
|
|
231
|
+
date: DateType | Date | undefined,
|
|
232
|
+
parsedTime: ITime | null
|
|
233
|
+
): Date {
|
|
177
234
|
const isValidDate = dayjs(date).isValid();
|
|
178
235
|
const dateTime = new Date(isValidDate && date ? date : Date.now());
|
|
179
236
|
if (parsedTime) {
|
|
@@ -185,23 +242,28 @@ export function setTimeOnDate(date: DateType | Date | undefined, parsedTime: ITi
|
|
|
185
242
|
return dateTime;
|
|
186
243
|
}
|
|
187
244
|
|
|
188
|
-
export function ensureDateTimeIsLocalDateTime(
|
|
245
|
+
export function ensureDateTimeIsLocalDateTime(
|
|
246
|
+
dateArg: DateType | Dayjs | undefined
|
|
247
|
+
): Dayjs {
|
|
189
248
|
if (dayjs(dateArg).isUTC()) {
|
|
190
249
|
const dateLocalTimeZone = dayjs(dateArg);
|
|
191
250
|
return dateLocalTimeZone;
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
251
|
+
} else {
|
|
194
252
|
return dayjs(dateArg ?? Date.now());
|
|
195
253
|
}
|
|
196
254
|
}
|
|
197
255
|
|
|
198
|
-
export function formatDateTimeToTimeString(
|
|
256
|
+
export function formatDateTimeToTimeString(
|
|
257
|
+
date: Date | string | undefined | null
|
|
258
|
+
): string {
|
|
199
259
|
date = new Date(date ?? Date.now());
|
|
200
260
|
const result = dayjs(date).format("h:mm A");
|
|
201
261
|
return result;
|
|
202
262
|
}
|
|
203
263
|
|
|
204
|
-
export function formatDateTimeToTimeString24hr(
|
|
264
|
+
export function formatDateTimeToTimeString24hr(
|
|
265
|
+
date: Date | string | undefined | null
|
|
266
|
+
): string {
|
|
205
267
|
date = new Date(date ?? Date.now());
|
|
206
268
|
const result = dayjs(date).format("h:mm");
|
|
207
269
|
return result;
|
|
@@ -215,24 +277,22 @@ export function parseTimeString(timeStr: string): ITime | null {
|
|
|
215
277
|
const minutes = parseInt(match[2], 10);
|
|
216
278
|
const ampm = match[3].toUpperCase();
|
|
217
279
|
|
|
218
|
-
if (
|
|
280
|
+
if (
|
|
281
|
+
hours >= 0 &&
|
|
282
|
+
hours <= 12 &&
|
|
283
|
+
minutes >= 0 &&
|
|
284
|
+
minutes <= 59 &&
|
|
285
|
+
(ampm === "AM" || ampm === "PM")
|
|
286
|
+
) {
|
|
219
287
|
return {
|
|
220
|
-
hours: ampm ===
|
|
288
|
+
hours: ampm === "PM" && hours < 12 ? hours + 12 : hours,
|
|
221
289
|
minutes,
|
|
222
|
-
ampm
|
|
290
|
+
ampm,
|
|
291
|
+
};
|
|
223
292
|
}
|
|
224
293
|
}
|
|
225
294
|
return null;
|
|
226
295
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const newDate = new Date(date.getUTCFullYear(), date.getUTCMonth(),
|
|
230
|
-
date.getUTCDate(), date.getUTCHours(),
|
|
231
|
-
date.getUTCMinutes(), date.getUTCSeconds());
|
|
232
|
-
|
|
233
|
-
return newDate;
|
|
296
|
+
export function timestampMinutesFromNow(minutes: number): number {
|
|
297
|
+
return Math.floor(new Date().getTime() / 1000 + minutes * 60);
|
|
234
298
|
}
|
|
235
|
-
|
|
236
|
-
export function timestampMinutseFromNow(minutes: number): number {
|
|
237
|
-
return Math.floor((new Date().getTime() / 1000) + (minutes * 60));
|
|
238
|
-
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DayOfWeek } from "@prisma/client";
|
|
2
|
+
|
|
3
|
+
export type DayOfWeekIdx = 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
4
|
+
|
|
5
|
+
export const dayOfWeekToString: { [key in DayOfWeek]: string } = {
|
|
6
|
+
[DayOfWeek.Monday]: "M",
|
|
7
|
+
[DayOfWeek.Tuesday]: "T",
|
|
8
|
+
[DayOfWeek.Wednesday]: "W",
|
|
9
|
+
[DayOfWeek.Thursday]: "TR",
|
|
10
|
+
[DayOfWeek.Friday]: "F",
|
|
11
|
+
[DayOfWeek.Saturday]: "S",
|
|
12
|
+
[DayOfWeek.Sunday]: "S",
|
|
13
|
+
} as const;
|
|
14
|
+
|
|
15
|
+
export const dayOfWeekToIdx: { [key in DayOfWeek]: DayOfWeekIdx } = {
|
|
16
|
+
[DayOfWeek.Monday]: 1,
|
|
17
|
+
[DayOfWeek.Tuesday]: 2,
|
|
18
|
+
[DayOfWeek.Wednesday]: 3,
|
|
19
|
+
[DayOfWeek.Thursday]: 4,
|
|
20
|
+
[DayOfWeek.Friday]: 5,
|
|
21
|
+
[DayOfWeek.Saturday]: 6,
|
|
22
|
+
[DayOfWeek.Sunday]: 7,
|
|
23
|
+
} as const;
|
|
24
|
+
|
|
25
|
+
export const dayOfWeekIdxToDayOfWeek: { [key in DayOfWeekIdx]: DayOfWeek } = {
|
|
26
|
+
[1]: DayOfWeek.Monday,
|
|
27
|
+
[2]: DayOfWeek.Tuesday,
|
|
28
|
+
[3]: DayOfWeek.Wednesday,
|
|
29
|
+
[4]: DayOfWeek.Thursday,
|
|
30
|
+
[5]: DayOfWeek.Friday,
|
|
31
|
+
[6]: DayOfWeek.Saturday,
|
|
32
|
+
[7]: DayOfWeek.Sunday,
|
|
33
|
+
} as const;
|
|
34
|
+
|
|
35
|
+
export const dayOfWeekIdxToDay: { [key in DayOfWeekIdx]: DayOfWeekIdx } = {
|
|
36
|
+
[7]: 1,
|
|
37
|
+
[1]: 2,
|
|
38
|
+
[2]: 3,
|
|
39
|
+
[3]: 4,
|
|
40
|
+
[4]: 5,
|
|
41
|
+
[5]: 6,
|
|
42
|
+
[6]: 7,
|
|
43
|
+
} as const;
|