@careflair/common 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/index.d.ts +78 -0
- package/dist/constants/index.js +102 -13
- package/dist/index.d.ts +8 -7
- package/dist/index.js +23 -19
- package/dist/interfaces/common-fields.input.d.ts +15 -15
- package/dist/interfaces/common-fields.input.js +2 -2
- package/dist/interfaces/common-fields.output.d.ts +26 -26
- package/dist/interfaces/common-fields.output.js +2 -2
- package/dist/interfaces/index.d.ts +0 -0
- package/dist/interfaces/index.js +1 -0
- package/dist/schemas/availabilitySchemaValidation.d.ts +56 -56
- package/dist/schemas/availabilitySchemaValidation.js +79 -79
- package/dist/schemas/businessServicesValidation.d.ts +6 -6
- package/dist/schemas/businessServicesValidation.js +23 -23
- package/dist/schemas/educationSchemas.d.ts +38 -38
- package/dist/schemas/educationSchemas.js +29 -29
- package/dist/schemas/forms.d.ts +210 -0
- package/dist/schemas/forms.js +192 -0
- package/dist/schemas/hourlyRateSchemaValidation.d.ts +36 -36
- package/dist/schemas/hourlyRateSchemaValidation.js +25 -25
- package/dist/schemas/index.d.ts +2 -6
- package/dist/schemas/index.js +18 -16
- package/dist/schemas/userValiationSchema.d.ts +30 -30
- package/dist/schemas/userValiationSchema.js +38 -38
- package/dist/schemas/validation.d.ts +33 -0
- package/dist/schemas/validation.js +38 -0
- package/dist/schemas/workHistorySchema.d.ts +33 -33
- package/dist/schemas/workHistorySchema.js +28 -28
- package/dist/utils/date.d.ts +35 -0
- package/dist/utils/date.js +166 -0
- package/dist/utils/debounce.d.ts +8 -0
- package/dist/utils/debounce.js +22 -0
- package/dist/utils/enum.d.ts +6 -0
- package/dist/utils/enum.js +9 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +28 -0
- package/dist/utils/phone.d.ts +9 -0
- package/dist/utils/phone.js +52 -0
- package/dist/utils/time.d.ts +63 -0
- package/dist/utils/time.js +134 -0
- package/dist/utils/utils.d.ts +6 -6
- package/dist/utils/utils.js +9 -9
- package/dist/utils/video.d.ts +25 -0
- package/dist/utils/video.js +80 -0
- package/dist/utils/videoValidation.d.ts +31 -31
- package/dist/utils/videoValidation.js +119 -119
- package/package.json +81 -46
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WorkHistorySchema = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
|
-
const limits_1 = require("../constants/limits");
|
|
6
|
-
exports.WorkHistorySchema = zod_1.z
|
|
7
|
-
.object({
|
|
8
|
-
jobTitle: zod_1.z
|
|
9
|
-
.string()
|
|
10
|
-
.min(1, "Job title is required")
|
|
11
|
-
.max(limits_1.WORK_HISTORY_TITLE_MAX_LENGTH, `Job title must be at most ${limits_1.WORK_HISTORY_TITLE_MAX_LENGTH} characters long`),
|
|
12
|
-
startDate: zod_1.z.date(),
|
|
13
|
-
endDate: zod_1.z.date().optional().nullable(),
|
|
14
|
-
organisation: zod_1.z
|
|
15
|
-
.string()
|
|
16
|
-
.min(1, "Organisation is required")
|
|
17
|
-
.max(limits_1.WORK_HISTORY_ORGANIZATION_MAX_LENGTH, `Organisation must be at most ${limits_1.WORK_HISTORY_ORGANIZATION_MAX_LENGTH} characters long`),
|
|
18
|
-
isCurrentlyWorking: zod_1.z.boolean().default(false),
|
|
19
|
-
})
|
|
20
|
-
.refine((data) => {
|
|
21
|
-
if (data.endDate) {
|
|
22
|
-
return !data.isCurrentlyWorking;
|
|
23
|
-
}
|
|
24
|
-
return data.isCurrentlyWorking || data.endDate !== undefined;
|
|
25
|
-
}, {
|
|
26
|
-
message: "If there is an endDate, is Currently Working must be false. If is Currently Working is false, endDate must be provided.",
|
|
27
|
-
path: ["endDate", "isCurrentlyWorking"],
|
|
28
|
-
});
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WorkHistorySchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const limits_1 = require("../constants/limits");
|
|
6
|
+
exports.WorkHistorySchema = zod_1.z
|
|
7
|
+
.object({
|
|
8
|
+
jobTitle: zod_1.z
|
|
9
|
+
.string()
|
|
10
|
+
.min(1, "Job title is required")
|
|
11
|
+
.max(limits_1.WORK_HISTORY_TITLE_MAX_LENGTH, `Job title must be at most ${limits_1.WORK_HISTORY_TITLE_MAX_LENGTH} characters long`),
|
|
12
|
+
startDate: zod_1.z.date(),
|
|
13
|
+
endDate: zod_1.z.date().optional().nullable(),
|
|
14
|
+
organisation: zod_1.z
|
|
15
|
+
.string()
|
|
16
|
+
.min(1, "Organisation is required")
|
|
17
|
+
.max(limits_1.WORK_HISTORY_ORGANIZATION_MAX_LENGTH, `Organisation must be at most ${limits_1.WORK_HISTORY_ORGANIZATION_MAX_LENGTH} characters long`),
|
|
18
|
+
isCurrentlyWorking: zod_1.z.boolean().default(false),
|
|
19
|
+
})
|
|
20
|
+
.refine((data) => {
|
|
21
|
+
if (data.endDate) {
|
|
22
|
+
return !data.isCurrentlyWorking;
|
|
23
|
+
}
|
|
24
|
+
return data.isCurrentlyWorking || data.endDate !== undefined;
|
|
25
|
+
}, {
|
|
26
|
+
message: "If there is an endDate, is Currently Working must be false. If is Currently Working is false, endDate must be provided.",
|
|
27
|
+
path: ["endDate", "isCurrentlyWorking"],
|
|
28
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a date to display relative time (e.g., "2 hours ago", "Yesterday")
|
|
3
|
+
*/
|
|
4
|
+
export declare const formatPostDate: (createdAt: Date) => string;
|
|
5
|
+
/**
|
|
6
|
+
* Format time difference between two dates (e.g., "2h ago", "3d ago")
|
|
7
|
+
*/
|
|
8
|
+
export declare const formatTimeDifference: (startDate: Date, endDate?: Date) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Formats date like WhatsApp:
|
|
11
|
+
* - For today: shows time (e.g., "2:30 PM")
|
|
12
|
+
* - For yesterday: shows "Yesterday"
|
|
13
|
+
* - For this week: shows day name (e.g., "Monday", "Tuesday")
|
|
14
|
+
* - For same year: shows day and month (e.g., "24 Jan")
|
|
15
|
+
* - For different year: shows day, month, and year (e.g., "24 Jan 2022")
|
|
16
|
+
*/
|
|
17
|
+
export declare const formatWhatsAppStyle: (date: Date | string) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Format job posting date consistently across the application
|
|
20
|
+
* Handles timezone conversion from UTC to user's local timezone
|
|
21
|
+
*/
|
|
22
|
+
export declare const formatJobPostDate: (createdAt: string | Date) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Format job posting date for absolute display (e.g., "Dec 15")
|
|
25
|
+
* Handles timezone conversion from UTC to user's local timezone
|
|
26
|
+
*/
|
|
27
|
+
export declare const formatJobPostDateAbsolute: (createdAt: string | Date) => string;
|
|
28
|
+
/**
|
|
29
|
+
* Format a date/time to display in a user-friendly format
|
|
30
|
+
*/
|
|
31
|
+
export declare const formatDateTime: (dateTime: string | Date) => string;
|
|
32
|
+
/**
|
|
33
|
+
* Format a date to display in a user-friendly format
|
|
34
|
+
*/
|
|
35
|
+
export declare const formatDate: (dateTime: string | Date) => string;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDate = exports.formatDateTime = exports.formatJobPostDateAbsolute = exports.formatJobPostDate = exports.formatWhatsAppStyle = exports.formatTimeDifference = exports.formatPostDate = void 0;
|
|
4
|
+
const date_fns_1 = require("date-fns");
|
|
5
|
+
/**
|
|
6
|
+
* Format a date to display relative time (e.g., "2 hours ago", "Yesterday")
|
|
7
|
+
*/
|
|
8
|
+
const formatPostDate = (createdAt) => {
|
|
9
|
+
const now = new Date();
|
|
10
|
+
const minutesAgo = (0, date_fns_1.differenceInMinutes)(now, createdAt);
|
|
11
|
+
const hoursAgo = (0, date_fns_1.differenceInHours)(now, createdAt);
|
|
12
|
+
const daysAgo = (0, date_fns_1.differenceInDays)(now, createdAt);
|
|
13
|
+
if (minutesAgo < 1) {
|
|
14
|
+
return "Just now";
|
|
15
|
+
}
|
|
16
|
+
if (minutesAgo < 60) {
|
|
17
|
+
return `${minutesAgo} minute${minutesAgo > 1 ? "s" : ""} ago`;
|
|
18
|
+
}
|
|
19
|
+
if (hoursAgo < 24) {
|
|
20
|
+
return `${hoursAgo} hour${hoursAgo > 1 ? "s" : ""} ago`;
|
|
21
|
+
}
|
|
22
|
+
if (daysAgo === 1) {
|
|
23
|
+
return "Yesterday";
|
|
24
|
+
}
|
|
25
|
+
if (daysAgo <= 7) {
|
|
26
|
+
return `${daysAgo} day${daysAgo > 1 ? "s" : ""} ago`;
|
|
27
|
+
}
|
|
28
|
+
// For older posts, show a formatted date
|
|
29
|
+
return (0, date_fns_1.format)(createdAt, "MMMM d, yyyy h:mm a"); // For example: "January 15, 2023 2:45 PM"
|
|
30
|
+
};
|
|
31
|
+
exports.formatPostDate = formatPostDate;
|
|
32
|
+
/**
|
|
33
|
+
* Format time difference between two dates (e.g., "2h ago", "3d ago")
|
|
34
|
+
*/
|
|
35
|
+
const formatTimeDifference = (startDate, endDate = new Date()) => {
|
|
36
|
+
const duration = (0, date_fns_1.intervalToDuration)({ start: startDate, end: endDate });
|
|
37
|
+
const minutesDifference = (0, date_fns_1.differenceInMinutes)(endDate, startDate);
|
|
38
|
+
// Return "just now" if less than 2 minutes
|
|
39
|
+
if (minutesDifference < 2) {
|
|
40
|
+
return "just now";
|
|
41
|
+
}
|
|
42
|
+
if (duration.years && duration.years >= 1) {
|
|
43
|
+
return `${duration.years}y ago`;
|
|
44
|
+
}
|
|
45
|
+
if (duration.weeks && duration.weeks >= 1) {
|
|
46
|
+
return `${duration.weeks}w ago`;
|
|
47
|
+
}
|
|
48
|
+
if (duration.days && duration.days >= 1) {
|
|
49
|
+
return `${duration.days}d ago`;
|
|
50
|
+
}
|
|
51
|
+
if (duration.hours && duration.hours >= 1) {
|
|
52
|
+
return `${duration.hours}h ago`;
|
|
53
|
+
}
|
|
54
|
+
if (duration.minutes && duration.minutes >= 1) {
|
|
55
|
+
return `${duration.minutes}m ago`;
|
|
56
|
+
}
|
|
57
|
+
return "just now"; // fallback if less than 1 minute
|
|
58
|
+
};
|
|
59
|
+
exports.formatTimeDifference = formatTimeDifference;
|
|
60
|
+
/**
|
|
61
|
+
* Formats date like WhatsApp:
|
|
62
|
+
* - For today: shows time (e.g., "2:30 PM")
|
|
63
|
+
* - For yesterday: shows "Yesterday"
|
|
64
|
+
* - For this week: shows day name (e.g., "Monday", "Tuesday")
|
|
65
|
+
* - For same year: shows day and month (e.g., "24 Jan")
|
|
66
|
+
* - For different year: shows day, month, and year (e.g., "24 Jan 2022")
|
|
67
|
+
*/
|
|
68
|
+
const formatWhatsAppStyle = (date) => {
|
|
69
|
+
if (!date)
|
|
70
|
+
return "";
|
|
71
|
+
const messageDate = typeof date === "string" ? new Date(date) : date;
|
|
72
|
+
const now = new Date();
|
|
73
|
+
// Invalid date
|
|
74
|
+
if (isNaN(messageDate.getTime()))
|
|
75
|
+
return "";
|
|
76
|
+
// Today: show time (e.g., "2:30 PM")
|
|
77
|
+
if ((0, date_fns_1.isToday)(messageDate)) {
|
|
78
|
+
return (0, date_fns_1.format)(messageDate, "h:mm a");
|
|
79
|
+
}
|
|
80
|
+
// Yesterday: show "Yesterday"
|
|
81
|
+
if ((0, date_fns_1.isYesterday)(messageDate)) {
|
|
82
|
+
return "Yesterday";
|
|
83
|
+
}
|
|
84
|
+
// This week (but not today or yesterday): show day name (e.g., "Monday")
|
|
85
|
+
if ((0, date_fns_1.isSameWeek)(messageDate, now)) {
|
|
86
|
+
return (0, date_fns_1.format)(messageDate, "EEEE"); // Full day name
|
|
87
|
+
}
|
|
88
|
+
// Same year: show date without year (e.g., "24 Jan")
|
|
89
|
+
if ((0, date_fns_1.isSameYear)(messageDate, now)) {
|
|
90
|
+
return (0, date_fns_1.format)(messageDate, "d MMM");
|
|
91
|
+
}
|
|
92
|
+
// Different year: show date with year (e.g., "24 Jan 2022")
|
|
93
|
+
return (0, date_fns_1.format)(messageDate, "d MMM yyyy");
|
|
94
|
+
};
|
|
95
|
+
exports.formatWhatsAppStyle = formatWhatsAppStyle;
|
|
96
|
+
/**
|
|
97
|
+
* Format job posting date consistently across the application
|
|
98
|
+
* Handles timezone conversion from UTC to user's local timezone
|
|
99
|
+
*/
|
|
100
|
+
const formatJobPostDate = (createdAt) => {
|
|
101
|
+
if (!createdAt)
|
|
102
|
+
return "";
|
|
103
|
+
const postDate = typeof createdAt === "string" ? new Date(createdAt) : createdAt;
|
|
104
|
+
const now = new Date();
|
|
105
|
+
// Invalid date
|
|
106
|
+
if (isNaN(postDate.getTime()))
|
|
107
|
+
return "";
|
|
108
|
+
const minutesAgo = (0, date_fns_1.differenceInMinutes)(now, postDate);
|
|
109
|
+
const hoursAgo = (0, date_fns_1.differenceInHours)(now, postDate);
|
|
110
|
+
const daysAgo = (0, date_fns_1.differenceInDays)(now, postDate);
|
|
111
|
+
if (minutesAgo < 1) {
|
|
112
|
+
return "Just now";
|
|
113
|
+
}
|
|
114
|
+
if (minutesAgo < 60) {
|
|
115
|
+
return `${minutesAgo} minute${minutesAgo > 1 ? "s" : ""} ago`;
|
|
116
|
+
}
|
|
117
|
+
if (hoursAgo < 24) {
|
|
118
|
+
return `${hoursAgo} hour${hoursAgo > 1 ? "s" : ""} ago`;
|
|
119
|
+
}
|
|
120
|
+
if (daysAgo === 1) {
|
|
121
|
+
return "Yesterday";
|
|
122
|
+
}
|
|
123
|
+
if (daysAgo <= 7) {
|
|
124
|
+
return `${daysAgo} day${daysAgo > 1 ? "s" : ""} ago`;
|
|
125
|
+
}
|
|
126
|
+
// For older posts, show formatted date in user's timezone
|
|
127
|
+
return (0, date_fns_1.format)(postDate, "MMM d");
|
|
128
|
+
};
|
|
129
|
+
exports.formatJobPostDate = formatJobPostDate;
|
|
130
|
+
/**
|
|
131
|
+
* Format job posting date for absolute display (e.g., "Dec 15")
|
|
132
|
+
* Handles timezone conversion from UTC to user's local timezone
|
|
133
|
+
*/
|
|
134
|
+
const formatJobPostDateAbsolute = (createdAt) => {
|
|
135
|
+
if (!createdAt)
|
|
136
|
+
return "";
|
|
137
|
+
const postDate = typeof createdAt === "string" ? new Date(createdAt) : createdAt;
|
|
138
|
+
// Invalid date
|
|
139
|
+
if (isNaN(postDate.getTime()))
|
|
140
|
+
return "";
|
|
141
|
+
// Format date in user's local timezone
|
|
142
|
+
return (0, date_fns_1.format)(postDate, "MMM d");
|
|
143
|
+
};
|
|
144
|
+
exports.formatJobPostDateAbsolute = formatJobPostDateAbsolute;
|
|
145
|
+
/**
|
|
146
|
+
* Format a date/time to display in a user-friendly format
|
|
147
|
+
*/
|
|
148
|
+
const formatDateTime = (dateTime) => {
|
|
149
|
+
return new Date(dateTime).toLocaleTimeString("en-US", {
|
|
150
|
+
hour: "numeric",
|
|
151
|
+
minute: "2-digit",
|
|
152
|
+
hour12: true,
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
exports.formatDateTime = formatDateTime;
|
|
156
|
+
/**
|
|
157
|
+
* Format a date to display in a user-friendly format
|
|
158
|
+
*/
|
|
159
|
+
const formatDate = (dateTime) => {
|
|
160
|
+
return new Date(dateTime).toLocaleDateString("en-US", {
|
|
161
|
+
weekday: "long",
|
|
162
|
+
month: "short",
|
|
163
|
+
day: "numeric",
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
exports.formatDate = formatDate;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a debounced version of a function
|
|
3
|
+
* Platform-agnostic implementation that works in both browser and Node.js
|
|
4
|
+
* @param func - The function to debounce
|
|
5
|
+
* @param delay - The delay in milliseconds
|
|
6
|
+
* @returns A debounced function
|
|
7
|
+
*/
|
|
8
|
+
export declare function debounce<T extends (...args: any[]) => void>(func: T, delay: number): (...args: Parameters<T>) => void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.debounce = debounce;
|
|
4
|
+
/**
|
|
5
|
+
* Creates a debounced version of a function
|
|
6
|
+
* Platform-agnostic implementation that works in both browser and Node.js
|
|
7
|
+
* @param func - The function to debounce
|
|
8
|
+
* @param delay - The delay in milliseconds
|
|
9
|
+
* @returns A debounced function
|
|
10
|
+
*/
|
|
11
|
+
function debounce(func, delay) {
|
|
12
|
+
let timer;
|
|
13
|
+
return (...args) => {
|
|
14
|
+
if (timer !== undefined) {
|
|
15
|
+
clearTimeout(timer);
|
|
16
|
+
}
|
|
17
|
+
timer = setTimeout(() => {
|
|
18
|
+
func(...args);
|
|
19
|
+
timer = undefined;
|
|
20
|
+
}, delay);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enumToOptions = enumToOptions;
|
|
4
|
+
function enumToOptions(enumObj) {
|
|
5
|
+
return Object.values(enumObj).map((value) => ({
|
|
6
|
+
label: value, // Use the enum value for the label
|
|
7
|
+
value: value, // Use the enum value for the value
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
// Phone validation utilities
|
|
18
|
+
__exportStar(require("./phone"), exports);
|
|
19
|
+
// Date formatting utilities
|
|
20
|
+
__exportStar(require("./date"), exports);
|
|
21
|
+
// Time/shift utilities
|
|
22
|
+
__exportStar(require("./time"), exports);
|
|
23
|
+
// Functional utilities
|
|
24
|
+
__exportStar(require("./debounce"), exports);
|
|
25
|
+
// Enum utilities
|
|
26
|
+
__exportStar(require("./enum"), exports);
|
|
27
|
+
// Video validation utilities
|
|
28
|
+
__exportStar(require("./video"), exports);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PhoneValidationResult = {
|
|
2
|
+
isValid: boolean;
|
|
3
|
+
error?: string;
|
|
4
|
+
formattedNumber?: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Validates an Australian phone number (mobile only)
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateAustralianPhoneNumber(phoneNumber: string): PhoneValidationResult;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateAustralianPhoneNumber = validateAustralianPhoneNumber;
|
|
4
|
+
const libphonenumber_js_1 = require("libphonenumber-js");
|
|
5
|
+
/**
|
|
6
|
+
* Validates an Australian phone number (mobile only)
|
|
7
|
+
*/
|
|
8
|
+
function validateAustralianPhoneNumber(phoneNumber) {
|
|
9
|
+
try {
|
|
10
|
+
// Trim whitespace
|
|
11
|
+
const trimmedNumber = phoneNumber.trim();
|
|
12
|
+
// Check if empty
|
|
13
|
+
if (!trimmedNumber) {
|
|
14
|
+
return {
|
|
15
|
+
isValid: false,
|
|
16
|
+
error: "Phone number cannot be empty",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// Check if it's a valid Australian mobile number
|
|
20
|
+
if (!(0, libphonenumber_js_1.isValidPhoneNumber)(trimmedNumber, "AU")) {
|
|
21
|
+
return {
|
|
22
|
+
isValid: false,
|
|
23
|
+
error: "Please enter a valid Australian phone number",
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
const parsedNumber = (0, libphonenumber_js_1.parsePhoneNumberFromString)(trimmedNumber, "AU");
|
|
27
|
+
if (!parsedNumber || parsedNumber.country !== "AU") {
|
|
28
|
+
return {
|
|
29
|
+
isValid: false,
|
|
30
|
+
error: "Please enter a valid Australian phone number",
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Check if it's a mobile number (landlines not allowed)
|
|
34
|
+
const numberType = parsedNumber.getType();
|
|
35
|
+
if (numberType !== "MOBILE" && numberType !== "FIXED_LINE_OR_MOBILE") {
|
|
36
|
+
return {
|
|
37
|
+
isValid: false,
|
|
38
|
+
error: "Only Australian mobile numbers are allowed",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Just return valid - no formatting needed
|
|
42
|
+
return {
|
|
43
|
+
isValid: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return {
|
|
48
|
+
isValid: false,
|
|
49
|
+
error: "Please enter a valid Australian phone number",
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse time string to minutes for comparison
|
|
3
|
+
*/
|
|
4
|
+
export declare const parseTimeToMinutes: (timeStr: string) => number;
|
|
5
|
+
/**
|
|
6
|
+
* Get shift duration in minutes
|
|
7
|
+
*/
|
|
8
|
+
export declare const getShiftDurationMinutes: (startTime: string, endTime: string) => number;
|
|
9
|
+
/**
|
|
10
|
+
* Get shift duration in hours
|
|
11
|
+
*/
|
|
12
|
+
export declare const getShiftDurationHours: (startTime: string, endTime: string) => number;
|
|
13
|
+
/**
|
|
14
|
+
* Check if two shifts overlap
|
|
15
|
+
*/
|
|
16
|
+
export declare const areShiftsOverlapping: (shift1: {
|
|
17
|
+
startTime: string;
|
|
18
|
+
endTime: string;
|
|
19
|
+
}, shift2: {
|
|
20
|
+
startTime: string;
|
|
21
|
+
endTime: string;
|
|
22
|
+
}) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Check if shifts overlap for a given day
|
|
25
|
+
*/
|
|
26
|
+
export declare const checkForOverlappingShifts: (shifts: {
|
|
27
|
+
startTime: string;
|
|
28
|
+
endTime: string;
|
|
29
|
+
}[]) => boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Check if a shift is too short (less than minimum minutes)
|
|
32
|
+
*/
|
|
33
|
+
export declare const isShiftTooShort: (shift: {
|
|
34
|
+
startTime: string;
|
|
35
|
+
endTime: string;
|
|
36
|
+
}, minimumMinutes?: number) => boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Validate a single shift
|
|
39
|
+
*/
|
|
40
|
+
export declare const validateShift: (shift: {
|
|
41
|
+
startTime: string;
|
|
42
|
+
endTime: string;
|
|
43
|
+
}, allShifts: {
|
|
44
|
+
startTime: string;
|
|
45
|
+
endTime: string;
|
|
46
|
+
}[], shiftIndex: number) => {
|
|
47
|
+
errors: string[];
|
|
48
|
+
warnings: string[];
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Generate a new shift time based on the last shift
|
|
52
|
+
*/
|
|
53
|
+
export declare const generateNewShiftTime: (lastShift?: {
|
|
54
|
+
startTime: string;
|
|
55
|
+
endTime: string;
|
|
56
|
+
}) => {
|
|
57
|
+
startTime: string;
|
|
58
|
+
endTime: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Convert time string to ISO format
|
|
62
|
+
*/
|
|
63
|
+
export declare const timeStringToISO: (timeString: string) => string;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timeStringToISO = exports.generateNewShiftTime = exports.validateShift = exports.isShiftTooShort = exports.checkForOverlappingShifts = exports.areShiftsOverlapping = exports.getShiftDurationHours = exports.getShiftDurationMinutes = exports.parseTimeToMinutes = void 0;
|
|
4
|
+
const date_fns_1 = require("date-fns");
|
|
5
|
+
/**
|
|
6
|
+
* Parse time string to minutes for comparison
|
|
7
|
+
*/
|
|
8
|
+
const parseTimeToMinutes = (timeStr) => {
|
|
9
|
+
const [hours, minutes] = timeStr.split(":").map(Number);
|
|
10
|
+
return hours * 60 + minutes;
|
|
11
|
+
};
|
|
12
|
+
exports.parseTimeToMinutes = parseTimeToMinutes;
|
|
13
|
+
/**
|
|
14
|
+
* Get shift duration in minutes
|
|
15
|
+
*/
|
|
16
|
+
const getShiftDurationMinutes = (startTime, endTime) => {
|
|
17
|
+
return (0, exports.parseTimeToMinutes)(endTime) - (0, exports.parseTimeToMinutes)(startTime);
|
|
18
|
+
};
|
|
19
|
+
exports.getShiftDurationMinutes = getShiftDurationMinutes;
|
|
20
|
+
/**
|
|
21
|
+
* Get shift duration in hours
|
|
22
|
+
*/
|
|
23
|
+
const getShiftDurationHours = (startTime, endTime) => {
|
|
24
|
+
return (0, exports.getShiftDurationMinutes)(startTime, endTime) / 60;
|
|
25
|
+
};
|
|
26
|
+
exports.getShiftDurationHours = getShiftDurationHours;
|
|
27
|
+
/**
|
|
28
|
+
* Check if two shifts overlap
|
|
29
|
+
*/
|
|
30
|
+
const areShiftsOverlapping = (shift1, shift2) => {
|
|
31
|
+
const start1 = (0, exports.parseTimeToMinutes)(shift1.startTime);
|
|
32
|
+
const end1 = (0, exports.parseTimeToMinutes)(shift1.endTime);
|
|
33
|
+
const start2 = (0, exports.parseTimeToMinutes)(shift2.startTime);
|
|
34
|
+
const end2 = (0, exports.parseTimeToMinutes)(shift2.endTime);
|
|
35
|
+
return start1 < end2 && start2 < end1;
|
|
36
|
+
};
|
|
37
|
+
exports.areShiftsOverlapping = areShiftsOverlapping;
|
|
38
|
+
/**
|
|
39
|
+
* Check if shifts overlap for a given day
|
|
40
|
+
*/
|
|
41
|
+
const checkForOverlappingShifts = (shifts) => {
|
|
42
|
+
if (shifts.length <= 1)
|
|
43
|
+
return false;
|
|
44
|
+
// Sort shifts by start time
|
|
45
|
+
const sortedShifts = [...shifts].sort((a, b) => {
|
|
46
|
+
return (new Date(`2023-01-01T${a.startTime}`).getTime() -
|
|
47
|
+
new Date(`2023-01-01T${b.startTime}`).getTime());
|
|
48
|
+
});
|
|
49
|
+
// Check for overlaps
|
|
50
|
+
for (let i = 0; i < sortedShifts.length - 1; i++) {
|
|
51
|
+
const currentShiftEnd = new Date(`2023-01-01T${sortedShifts[i].endTime}`);
|
|
52
|
+
const nextShiftStart = new Date(`2023-01-01T${sortedShifts[i + 1].startTime}`);
|
|
53
|
+
if (currentShiftEnd > nextShiftStart) {
|
|
54
|
+
return true; // Found an overlap
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
exports.checkForOverlappingShifts = checkForOverlappingShifts;
|
|
60
|
+
/**
|
|
61
|
+
* Check if a shift is too short (less than minimum minutes)
|
|
62
|
+
*/
|
|
63
|
+
const isShiftTooShort = (shift, minimumMinutes = 60) => {
|
|
64
|
+
const startTime = new Date(`2023-01-01T${shift.startTime}`);
|
|
65
|
+
const endTime = new Date(`2023-01-01T${shift.endTime}`);
|
|
66
|
+
// Calculate difference in minutes
|
|
67
|
+
const diffMinutes = (endTime.getTime() - startTime.getTime()) / (1000 * 60);
|
|
68
|
+
return diffMinutes < minimumMinutes;
|
|
69
|
+
};
|
|
70
|
+
exports.isShiftTooShort = isShiftTooShort;
|
|
71
|
+
/**
|
|
72
|
+
* Validate a single shift
|
|
73
|
+
*/
|
|
74
|
+
const validateShift = (shift, allShifts, shiftIndex) => {
|
|
75
|
+
const errors = [];
|
|
76
|
+
const warnings = [];
|
|
77
|
+
// 1. Check if times are provided
|
|
78
|
+
if (!shift.startTime || !shift.endTime) {
|
|
79
|
+
errors.push("Both start and end times are required");
|
|
80
|
+
return { errors, warnings };
|
|
81
|
+
}
|
|
82
|
+
// 2. End time after start time
|
|
83
|
+
if ((0, exports.parseTimeToMinutes)(shift.endTime) <= (0, exports.parseTimeToMinutes)(shift.startTime)) {
|
|
84
|
+
errors.push("End time must be after start time");
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// 3. Minimum shift duration (1 hour)
|
|
88
|
+
const durationHours = (0, exports.getShiftDurationHours)(shift.startTime, shift.endTime);
|
|
89
|
+
if (durationHours < 1) {
|
|
90
|
+
errors.push("Shift must be at least 1 hour");
|
|
91
|
+
}
|
|
92
|
+
// 4. Maximum shift duration (12 hours)
|
|
93
|
+
if (durationHours > 12) {
|
|
94
|
+
errors.push("Shift must be at most 12 hours");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// 5. Check for overlapping shifts
|
|
98
|
+
const otherShifts = [...allShifts];
|
|
99
|
+
otherShifts.splice(shiftIndex, 1); // Remove current shift from array
|
|
100
|
+
for (let i = 0; i < otherShifts.length; i++) {
|
|
101
|
+
if ((0, exports.areShiftsOverlapping)(shift, otherShifts[i])) {
|
|
102
|
+
errors.push("Shifts cannot overlap");
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return { errors, warnings };
|
|
107
|
+
};
|
|
108
|
+
exports.validateShift = validateShift;
|
|
109
|
+
/**
|
|
110
|
+
* Generate a new shift time based on the last shift
|
|
111
|
+
*/
|
|
112
|
+
const generateNewShiftTime = (lastShift) => {
|
|
113
|
+
let newStartTime = "09:00";
|
|
114
|
+
let newEndTime = "10:00";
|
|
115
|
+
if (lastShift) {
|
|
116
|
+
// Start the new shift right after the last shift ends (no gap)
|
|
117
|
+
const lastEndTime = new Date(`2023-01-01T${lastShift.endTime}`);
|
|
118
|
+
// Format the new start time
|
|
119
|
+
newStartTime = (0, date_fns_1.format)(lastEndTime, "HH:mm");
|
|
120
|
+
// Set end time 1 hour after start time
|
|
121
|
+
const newEnd = new Date(lastEndTime);
|
|
122
|
+
newEnd.setHours(newEnd.getHours() + 1);
|
|
123
|
+
newEndTime = (0, date_fns_1.format)(newEnd, "HH:mm");
|
|
124
|
+
}
|
|
125
|
+
return { startTime: newStartTime, endTime: newEndTime };
|
|
126
|
+
};
|
|
127
|
+
exports.generateNewShiftTime = generateNewShiftTime;
|
|
128
|
+
/**
|
|
129
|
+
* Convert time string to ISO format
|
|
130
|
+
*/
|
|
131
|
+
const timeStringToISO = (timeString) => {
|
|
132
|
+
return new Date(`2023-01-01T${timeString}`).toISOString();
|
|
133
|
+
};
|
|
134
|
+
exports.timeStringToISO = timeStringToISO;
|
package/dist/utils/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
type Option = {
|
|
2
|
-
label: string;
|
|
3
|
-
value: string;
|
|
4
|
-
};
|
|
5
|
-
export declare function enumToOptions<T extends Record<string, string>>(enumObj: T): Option[];
|
|
6
|
-
export {};
|
|
1
|
+
type Option = {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function enumToOptions<T extends Record<string, string>>(enumObj: T): Option[];
|
|
6
|
+
export {};
|
package/dist/utils/utils.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.enumToOptions = enumToOptions;
|
|
4
|
-
function enumToOptions(enumObj) {
|
|
5
|
-
return Object.values(enumObj).map((value) => ({
|
|
6
|
-
label: value, // Use the enum value for the label
|
|
7
|
-
value: value, // Use the enum value for the value
|
|
8
|
-
}));
|
|
9
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enumToOptions = enumToOptions;
|
|
4
|
+
function enumToOptions(enumObj) {
|
|
5
|
+
return Object.values(enumObj).map((value) => ({
|
|
6
|
+
label: value, // Use the enum value for the label
|
|
7
|
+
value: value, // Use the enum value for the value
|
|
8
|
+
}));
|
|
9
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type VideoProvider = "youtube" | "vimeo" | "loom" | "tiktok";
|
|
2
|
+
export interface VideoValidationResult {
|
|
3
|
+
isValid: boolean;
|
|
4
|
+
provider?: VideoProvider;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Unified video link validation function
|
|
9
|
+
* @param url - The video URL to validate
|
|
10
|
+
* @param allowedProviders - Array of allowed video providers
|
|
11
|
+
* @returns VideoValidationResult object
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateVideoLink(url: string, allowedProviders: VideoProvider[]): VideoValidationResult;
|
|
14
|
+
/**
|
|
15
|
+
* Detect video provider from URL
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectVideoProvider(url: string): VideoProvider | null;
|
|
18
|
+
/**
|
|
19
|
+
* Check if URL is valid YouTube or Vimeo URL
|
|
20
|
+
*/
|
|
21
|
+
export declare function isValidYouTubeOrVimeoUrl(url: string): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Check if URL is valid community video URL (YouTube, Vimeo, Loom, TikTok)
|
|
24
|
+
*/
|
|
25
|
+
export declare function isValidCommunityVideoUrl(url: string): boolean;
|