@lyxa.ai/core 1.1.58 → 1.1.60
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/types/README.md
CHANGED
package/dist/types/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import dayjs, { Dayjs } from 'dayjs';
|
|
2
|
+
import { HolidayHour, NormalHour, StartEndTime } from '../libraries/mongo/models/shared/work-hour.model';
|
|
3
|
+
import { WeekDay } from './enum';
|
|
4
|
+
export declare const getDaysOfWeek: () => string[];
|
|
5
|
+
export declare const getFullDayHours: () => StartEndTime[];
|
|
6
|
+
export declare const parseTimeString: (timeHHMM: string, zone: string) => dayjs.Dayjs;
|
|
7
|
+
export declare const calculateIntersection: (opening: StartEndTime, valid: StartEndTime, timeZone: string) => StartEndTime | null;
|
|
8
|
+
export declare const getIntersectedHours: (openingHours: StartEndTime[], validHours: StartEndTime[], timeZone?: string) => StartEndTime[];
|
|
9
|
+
export declare const checkWithinNormalHours: (hours: StartEndTime[], normalTimings: NormalHour[], day: keyof typeof WeekDay) => StartEndTime[];
|
|
10
|
+
export declare const checkWithinHolidayHours: (hours: StartEndTime[], holidayTimings: HolidayHour[], currentDate: Dayjs) => StartEndTime[];
|
|
11
|
+
export declare const getHolidayIntersectedHours: (openingHours: StartEndTime[], closingHours: StartEndTime[], timeZone?: string) => StartEndTime[];
|
|
12
|
+
export declare const subtractSegment: (segment: {
|
|
13
|
+
start: dayjs.Dayjs;
|
|
14
|
+
end: dayjs.Dayjs;
|
|
15
|
+
}, block: {
|
|
16
|
+
start: dayjs.Dayjs;
|
|
17
|
+
end: dayjs.Dayjs;
|
|
18
|
+
}) => {
|
|
19
|
+
start: dayjs.Dayjs;
|
|
20
|
+
end: dayjs.Dayjs;
|
|
21
|
+
}[];
|
|
22
|
+
export declare const adminAfterHolidayWorkingHours: (workHourSetting: any) => StartEndTime[];
|
|
23
|
+
export declare const isLyxaOpen: (workHourSetting: any) => boolean;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isLyxaOpen = exports.adminAfterHolidayWorkingHours = exports.subtractSegment = exports.getHolidayIntersectedHours = exports.checkWithinHolidayHours = exports.checkWithinNormalHours = exports.getIntersectedHours = exports.calculateIntersection = exports.parseTimeString = exports.getFullDayHours = exports.getDaysOfWeek = void 0;
|
|
7
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
8
|
+
const utc_1 = __importDefault(require("dayjs/plugin/utc"));
|
|
9
|
+
const timezone_1 = __importDefault(require("dayjs/plugin/timezone"));
|
|
10
|
+
const minMax_1 = __importDefault(require("dayjs/plugin/minMax"));
|
|
11
|
+
const enum_1 = require("./enum");
|
|
12
|
+
const time_1 = require("./time");
|
|
13
|
+
dayjs_1.default.extend(utc_1.default);
|
|
14
|
+
dayjs_1.default.extend(timezone_1.default);
|
|
15
|
+
dayjs_1.default.extend(minMax_1.default);
|
|
16
|
+
const getDaysOfWeek = () => {
|
|
17
|
+
return Array.from({ length: 7 }, (_, i) => (0, dayjs_1.default)().day(i).format('dddd'));
|
|
18
|
+
};
|
|
19
|
+
exports.getDaysOfWeek = getDaysOfWeek;
|
|
20
|
+
const getFullDayHours = () => {
|
|
21
|
+
return [{ start: '0000', end: '2359' }];
|
|
22
|
+
};
|
|
23
|
+
exports.getFullDayHours = getFullDayHours;
|
|
24
|
+
const parseTimeString = (timeHHMM, zone) => {
|
|
25
|
+
const hour = Number(timeHHMM.slice(0, 2));
|
|
26
|
+
const minute = Number(timeHHMM.slice(2));
|
|
27
|
+
return (0, dayjs_1.default)().tz(zone).hour(hour).minute(minute).second(0).millisecond(0);
|
|
28
|
+
};
|
|
29
|
+
exports.parseTimeString = parseTimeString;
|
|
30
|
+
const calculateIntersection = (opening, valid, timeZone) => {
|
|
31
|
+
const openingStart = (0, exports.parseTimeString)(opening.start, timeZone);
|
|
32
|
+
const openingEnd = (0, exports.parseTimeString)(opening.end, timeZone);
|
|
33
|
+
const validStart = (0, exports.parseTimeString)(valid.start, timeZone);
|
|
34
|
+
const validEnd = (0, exports.parseTimeString)(valid.end, timeZone);
|
|
35
|
+
const intersectionStart = dayjs_1.default.max(openingStart, validStart);
|
|
36
|
+
const intersectionEnd = dayjs_1.default.min(openingEnd, validEnd);
|
|
37
|
+
return intersectionStart && intersectionEnd && intersectionStart.isBefore(intersectionEnd)
|
|
38
|
+
? {
|
|
39
|
+
start: intersectionStart.format('HHmm'),
|
|
40
|
+
end: intersectionEnd.format('HHmm'),
|
|
41
|
+
}
|
|
42
|
+
: null;
|
|
43
|
+
};
|
|
44
|
+
exports.calculateIntersection = calculateIntersection;
|
|
45
|
+
const getIntersectedHours = (openingHours, validHours, timeZone = 'Asia/Dhaka') => {
|
|
46
|
+
const intersections = [];
|
|
47
|
+
for (const opening of openingHours) {
|
|
48
|
+
for (const valid of validHours) {
|
|
49
|
+
const intersection = (0, exports.calculateIntersection)(opening, valid, timeZone);
|
|
50
|
+
if (intersection !== null) {
|
|
51
|
+
intersections.push(intersection);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return intersections;
|
|
56
|
+
};
|
|
57
|
+
exports.getIntersectedHours = getIntersectedHours;
|
|
58
|
+
const checkWithinNormalHours = (hours, normalTimings, day) => {
|
|
59
|
+
const dayTiming = normalTimings.find(timing => timing.day === enum_1.WeekDay[day]);
|
|
60
|
+
if (!dayTiming)
|
|
61
|
+
return [];
|
|
62
|
+
const statusHandlers = {
|
|
63
|
+
[enum_1.WorkStatus.CLOSED]: () => [],
|
|
64
|
+
[enum_1.WorkStatus.FULL_DAY]: () => (0, exports.getFullDayHours)(),
|
|
65
|
+
[enum_1.WorkStatus.OPEN]: () => dayTiming.openingHours?.length ? (0, exports.getIntersectedHours)(dayTiming.openingHours, hours) : [],
|
|
66
|
+
};
|
|
67
|
+
return statusHandlers[dayTiming.status]?.() || [];
|
|
68
|
+
};
|
|
69
|
+
exports.checkWithinNormalHours = checkWithinNormalHours;
|
|
70
|
+
const checkWithinHolidayHours = (hours, holidayTimings, currentDate) => {
|
|
71
|
+
if (!holidayTimings.length) {
|
|
72
|
+
return hours;
|
|
73
|
+
}
|
|
74
|
+
const currentDateInTimezone = currentDate.tz(time_1.LyxaTimezone);
|
|
75
|
+
const todaysHoliday = holidayTimings.find(holiday => {
|
|
76
|
+
if (!holiday.date)
|
|
77
|
+
return false;
|
|
78
|
+
const holidayDate = (0, dayjs_1.default)(holiday.date).tz(time_1.LyxaTimezone);
|
|
79
|
+
return currentDateInTimezone.isSame(holidayDate, 'day');
|
|
80
|
+
});
|
|
81
|
+
if (!todaysHoliday)
|
|
82
|
+
return hours;
|
|
83
|
+
if (todaysHoliday.status === enum_1.HolidayWorkStatus.FULL_DAY)
|
|
84
|
+
return [];
|
|
85
|
+
if (todaysHoliday.status === enum_1.HolidayWorkStatus.CLOSED &&
|
|
86
|
+
todaysHoliday.closingHour?.start &&
|
|
87
|
+
todaysHoliday.closingHour?.end) {
|
|
88
|
+
return (0, exports.getHolidayIntersectedHours)(hours, [todaysHoliday.closingHour]);
|
|
89
|
+
}
|
|
90
|
+
return hours;
|
|
91
|
+
};
|
|
92
|
+
exports.checkWithinHolidayHours = checkWithinHolidayHours;
|
|
93
|
+
const getHolidayIntersectedHours = (openingHours, closingHours, timeZone = 'Asia/Dhaka') => {
|
|
94
|
+
if (!openingHours.length || !closingHours.length) {
|
|
95
|
+
return openingHours;
|
|
96
|
+
}
|
|
97
|
+
const result = [];
|
|
98
|
+
for (const opening of openingHours) {
|
|
99
|
+
const openingStart = (0, exports.parseTimeString)(opening.start, timeZone);
|
|
100
|
+
const openingEnd = (0, exports.parseTimeString)(opening.end, timeZone);
|
|
101
|
+
let segments = [{ start: openingStart, end: openingEnd }];
|
|
102
|
+
for (const closing of closingHours) {
|
|
103
|
+
const closingStart = (0, exports.parseTimeString)(closing.start, timeZone);
|
|
104
|
+
const closingEnd = (0, exports.parseTimeString)(closing.end, timeZone);
|
|
105
|
+
const block = { start: closingStart, end: closingEnd };
|
|
106
|
+
segments = segments.flatMap(segment => (0, exports.subtractSegment)(segment, block));
|
|
107
|
+
}
|
|
108
|
+
for (const segment of segments) {
|
|
109
|
+
result.push({
|
|
110
|
+
start: segment.start.format('HHmm'),
|
|
111
|
+
end: segment.end.format('HHmm'),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return result;
|
|
116
|
+
};
|
|
117
|
+
exports.getHolidayIntersectedHours = getHolidayIntersectedHours;
|
|
118
|
+
const subtractSegment = (segment, block) => {
|
|
119
|
+
const { start, end } = segment;
|
|
120
|
+
const { start: blockStart, end: blockEnd } = block;
|
|
121
|
+
if (end.isBefore(blockStart) || start.isAfter(blockEnd))
|
|
122
|
+
return [segment];
|
|
123
|
+
if (blockStart.isBefore(start) && blockEnd.isAfter(end))
|
|
124
|
+
return [];
|
|
125
|
+
if (blockStart.isAfter(start) && blockEnd.isBefore(end)) {
|
|
126
|
+
return [
|
|
127
|
+
{ start, end: blockStart },
|
|
128
|
+
{ start: blockEnd, end },
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
if (blockStart.isBefore(end) && blockEnd.isBefore(end) && blockEnd.isAfter(start)) {
|
|
132
|
+
return [{ start: blockEnd, end }];
|
|
133
|
+
}
|
|
134
|
+
if (blockEnd.isAfter(start) && blockStart.isAfter(start) && blockStart.isBefore(end)) {
|
|
135
|
+
return [{ start, end: blockStart }];
|
|
136
|
+
}
|
|
137
|
+
return [];
|
|
138
|
+
};
|
|
139
|
+
exports.subtractSegment = subtractSegment;
|
|
140
|
+
const adminAfterHolidayWorkingHours = (workHourSetting) => {
|
|
141
|
+
const fullDayHours = (0, exports.getFullDayHours)();
|
|
142
|
+
const now = (0, dayjs_1.default)().tz(time_1.LyxaTimezone);
|
|
143
|
+
const currentDayIndex = now.day();
|
|
144
|
+
const currentDay = (0, exports.getDaysOfWeek)()[currentDayIndex];
|
|
145
|
+
const currentDate = (0, dayjs_1.default)().utc().startOf('day');
|
|
146
|
+
const adminNormalWorkingHours = (0, exports.checkWithinNormalHours)(fullDayHours, workHourSetting.normalHours, currentDay);
|
|
147
|
+
return (0, exports.checkWithinHolidayHours)(adminNormalWorkingHours, workHourSetting.holidayHours, currentDate);
|
|
148
|
+
};
|
|
149
|
+
exports.adminAfterHolidayWorkingHours = adminAfterHolidayWorkingHours;
|
|
150
|
+
const isLyxaOpen = (workHourSetting) => {
|
|
151
|
+
const currentTime = new Date().getHours() * 100 + new Date().getMinutes();
|
|
152
|
+
const lyxaOpenHour = (0, exports.adminAfterHolidayWorkingHours)(workHourSetting);
|
|
153
|
+
return lyxaOpenHour.some(timing => parseInt(timing.start) <= currentTime && currentTime <= parseInt(timing.end));
|
|
154
|
+
};
|
|
155
|
+
exports.isLyxaOpen = isLyxaOpen;
|
|
156
|
+
//# sourceMappingURL=workHourSetting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workHourSetting.js","sourceRoot":"/","sources":["utilities/workHourSetting.ts"],"names":[],"mappings":"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","sourcesContent":["import dayjs, { Dayjs } from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport timezone from 'dayjs/plugin/timezone';\nimport minMax from 'dayjs/plugin/minMax';\nimport { HolidayHour, NormalHour, StartEndTime } from '../libraries/mongo/models/shared/work-hour.model';\nimport { HolidayWorkStatus, WeekDay, WorkStatus } from './enum';\nimport { LyxaTimezone } from './time';\n\ndayjs.extend(utc);\ndayjs.extend(timezone);\ndayjs.extend(minMax);\n\nexport const getDaysOfWeek = (): string[] => {\n\treturn Array.from({ length: 7 }, (_, i) => dayjs().day(i).format('dddd'));\n};\n\nexport const getFullDayHours = (): StartEndTime[] => {\n\treturn [{ start: '0000', end: '2359' }];\n};\n\nexport const parseTimeString = (timeHHMM: string, zone: string): dayjs.Dayjs => {\n\tconst hour = Number(timeHHMM.slice(0, 2));\n\tconst minute = Number(timeHHMM.slice(2));\n\treturn dayjs().tz(zone).hour(hour).minute(minute).second(0).millisecond(0);\n};\nexport const calculateIntersection = (\n\topening: StartEndTime,\n\tvalid: StartEndTime,\n\ttimeZone: string\n): StartEndTime | null => {\n\tconst openingStart = parseTimeString(opening.start, timeZone);\n\tconst openingEnd = parseTimeString(opening.end, timeZone);\n\tconst validStart = parseTimeString(valid.start, timeZone);\n\tconst validEnd = parseTimeString(valid.end, timeZone);\n\n\tconst intersectionStart = dayjs.max(openingStart, validStart);\n\tconst intersectionEnd = dayjs.min(openingEnd, validEnd);\n\n\treturn intersectionStart && intersectionEnd && intersectionStart.isBefore(intersectionEnd)\n\t\t? {\n\t\t\t\tstart: intersectionStart.format('HHmm'),\n\t\t\t\tend: intersectionEnd.format('HHmm'),\n\t\t\t}\n\t\t: null;\n};\n\nexport const getIntersectedHours = (\n\topeningHours: StartEndTime[],\n\tvalidHours: StartEndTime[],\n\ttimeZone = 'Asia/Dhaka'\n): StartEndTime[] => {\n\tconst intersections: StartEndTime[] = [];\n\n\tfor (const opening of openingHours) {\n\t\tfor (const valid of validHours) {\n\t\t\tconst intersection = calculateIntersection(opening, valid, timeZone);\n\n\t\t\tif (intersection !== null) {\n\t\t\t\tintersections.push(intersection);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn intersections;\n};\n\nexport const checkWithinNormalHours = (\n\thours: StartEndTime[],\n\tnormalTimings: NormalHour[],\n\tday: keyof typeof WeekDay\n): StartEndTime[] => {\n\tconst dayTiming = normalTimings.find(timing => timing.day === WeekDay[day]);\n\n\tif (!dayTiming) return [];\n\n\tconst statusHandlers = {\n\t\t[WorkStatus.CLOSED]: () => [],\n\t\t[WorkStatus.FULL_DAY]: () => getFullDayHours(),\n\t\t[WorkStatus.OPEN]: () =>\n\t\t\tdayTiming.openingHours?.length ? getIntersectedHours(dayTiming.openingHours, hours) : [],\n\t};\n\n\treturn statusHandlers[dayTiming.status]?.() || [];\n};\n\nexport const checkWithinHolidayHours = (\n\thours: StartEndTime[],\n\tholidayTimings: HolidayHour[],\n\tcurrentDate: Dayjs\n): StartEndTime[] => {\n\tif (!holidayTimings.length) {\n\t\treturn hours;\n\t}\n\n\t/** Find If Today Is Holiday */\n\tconst currentDateInTimezone = currentDate.tz(LyxaTimezone);\n\tconst todaysHoliday = holidayTimings.find(holiday => {\n\t\tif (!holiday.date) return false;\n\t\tconst holidayDate = dayjs(holiday.date).tz(LyxaTimezone);\n\t\treturn currentDateInTimezone.isSame(holidayDate, 'day');\n\t});\n\n\t/** No holiday today - return original hours */\n\tif (!todaysHoliday) return hours;\n\n\t/** Handle holiday status --> Full Day Holiday */\n\tif (todaysHoliday.status === HolidayWorkStatus.FULL_DAY) return [];\n\n\t/** Handle holiday status --> Certain Hour Closed Holiday */\n\tif (\n\t\ttodaysHoliday.status === HolidayWorkStatus.CLOSED &&\n\t\ttodaysHoliday.closingHour?.start &&\n\t\ttodaysHoliday.closingHour?.end\n\t) {\n\t\treturn getHolidayIntersectedHours(hours, [todaysHoliday.closingHour]);\n\t}\n\n\t/** Default fallback - return original hours */\n\treturn hours;\n};\n\nexport const getHolidayIntersectedHours = (\n\topeningHours: StartEndTime[],\n\tclosingHours: StartEndTime[],\n\ttimeZone = 'Asia/Dhaka'\n): StartEndTime[] => {\n\tif (!openingHours.length || !closingHours.length) {\n\t\treturn openingHours;\n\t}\n\n\tconst result: StartEndTime[] = [];\n\n\tfor (const opening of openingHours) {\n\t\tconst openingStart = parseTimeString(opening.start, timeZone);\n\t\tconst openingEnd = parseTimeString(opening.end, timeZone);\n\n\t\tlet segments = [{ start: openingStart, end: openingEnd }];\n\n\t\t/** Applying each closing period to current segments */\n\t\tfor (const closing of closingHours) {\n\t\t\tconst closingStart = parseTimeString(closing.start, timeZone);\n\t\t\tconst closingEnd = parseTimeString(closing.end, timeZone);\n\t\t\tconst block = { start: closingStart, end: closingEnd };\n\n\t\t\tsegments = segments.flatMap(segment => subtractSegment(segment, block));\n\t\t}\n\n\t\t/** Converting segments to result format */\n\t\tfor (const segment of segments) {\n\t\t\tresult.push({\n\t\t\t\tstart: segment.start.format('HHmm'),\n\t\t\t\tend: segment.end.format('HHmm'),\n\t\t\t});\n\t\t}\n\t}\n\n\treturn result;\n};\nexport const subtractSegment = (\n\tsegment: { start: dayjs.Dayjs; end: dayjs.Dayjs },\n\tblock: { start: dayjs.Dayjs; end: dayjs.Dayjs }\n): { start: dayjs.Dayjs; end: dayjs.Dayjs }[] => {\n\tconst { start, end } = segment;\n\tconst { start: blockStart, end: blockEnd } = block;\n\n\t/** Sequence Matter */\n\t/** No Overlap */\n\tif (end.isBefore(blockStart) || start.isAfter(blockEnd)) return [segment];\n\n\t/** Fully Overlapped */\n\tif (blockStart.isBefore(start) && blockEnd.isAfter(end)) return [];\n\n\t/** Block Inside Segment (Middle Cut) */\n\tif (blockStart.isAfter(start) && blockEnd.isBefore(end)) {\n\t\treturn [\n\t\t\t{ start, end: blockStart },\n\t\t\t{ start: blockEnd, end },\n\t\t];\n\t}\n\n\t/** Overlap At Start */\n\tif (blockStart.isBefore(end) && blockEnd.isBefore(end) && blockEnd.isAfter(start)) {\n\t\treturn [{ start: blockEnd, end }];\n\t}\n\n\t/** Overlap At End */\n\tif (blockEnd.isAfter(start) && blockStart.isAfter(start) && blockStart.isBefore(end)) {\n\t\treturn [{ start, end: blockStart }];\n\t}\n\n\treturn [];\n};\n\nexport const adminAfterHolidayWorkingHours = (workHourSetting: any) => {\n\tconst fullDayHours = getFullDayHours();\n\tconst now = dayjs().tz(LyxaTimezone);\n\tconst currentDayIndex = now.day(); // 0 (Sunday) through 6 (Saturday)\n\tconst currentDay = getDaysOfWeek()[currentDayIndex] as keyof typeof WeekDay;\n\tconst currentDate = dayjs().utc().startOf('day');\n\n\t/**Admin Normal Working Hour*/\n\tconst adminNormalWorkingHours = checkWithinNormalHours(\n\t\tfullDayHours,\n\t\tworkHourSetting.normalHours,\n\t\tcurrentDay\n\t);\n\t/**Admin Working Hour After Subtracting From Admin Holiday Hour */\n\treturn checkWithinHolidayHours(adminNormalWorkingHours, workHourSetting.holidayHours, currentDate);\n};\n\nexport const isLyxaOpen = (workHourSetting: any) => {\n\tconst currentTime = new Date().getHours() * 100 + new Date().getMinutes();\n\tconst lyxaOpenHour = adminAfterHolidayWorkingHours(workHourSetting);\n\treturn lyxaOpenHour.some(\n\t\ttiming => parseInt(timing.start) <= currentTime && currentTime <= parseInt(timing.end)\n\t);\n};\n"]}
|