@easyteam/auto-scheduler-modal-ui 0.1.1 → 0.1.2

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/index.cjs CHANGED
@@ -905,6 +905,7 @@ var SCHEDULE_STEPS = [
905
905
  { title: "Finalizing schedule" }
906
906
  ];
907
907
  var STEP_INTERVAL_MS = 1200;
908
+ var POLL_INTERVAL_MS = 2500;
908
909
  var OPTIMIZING_STEP_INDEX = 2;
909
910
  var NETWORK_ERROR_FAILURE = {
910
911
  violatedConstraints: [
@@ -1449,19 +1450,55 @@ async function getToken(fullUrl, headers) {
1449
1450
  });
1450
1451
  return (_a = tokenRes.data) == null ? void 0 : _a.token;
1451
1452
  }
1452
- async function solveSchedule(baseURL, payload, options) {
1453
+ async function submitSolveJob(baseURL, payload, options) {
1453
1454
  const cleanBaseUrl = baseURL.replace(/\/$/, "");
1454
1455
  const headers = {};
1455
1456
  if (options == null ? void 0 : options.authorization) {
1456
1457
  headers.Authorization = options.authorization;
1457
1458
  }
1458
1459
  const response = await axiosInstance.post(
1459
- `${cleanBaseUrl}/api/schedule/solve`,
1460
+ `${cleanBaseUrl}/api/schedule/solve-async`,
1460
1461
  payload,
1461
1462
  { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1462
1463
  );
1463
1464
  return response.data;
1464
1465
  }
1466
+ async function getJobStatus(baseURL, jobId, options) {
1467
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1468
+ const headers = {};
1469
+ if (options == null ? void 0 : options.authorization) {
1470
+ headers.Authorization = options.authorization;
1471
+ }
1472
+ const response = await axiosInstance.get(
1473
+ `${cleanBaseUrl}/api/schedule/status/${jobId}`,
1474
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1475
+ );
1476
+ return response.data;
1477
+ }
1478
+ async function getJobResult(baseURL, jobId, options) {
1479
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1480
+ const headers = {};
1481
+ if (options == null ? void 0 : options.authorization) {
1482
+ headers.Authorization = options.authorization;
1483
+ }
1484
+ const response = await axiosInstance.get(
1485
+ `${cleanBaseUrl}/api/schedule/result/${jobId}`,
1486
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1487
+ );
1488
+ return response.data;
1489
+ }
1490
+ async function getJobSolution(baseURL, jobId, options) {
1491
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1492
+ const headers = {};
1493
+ if (options == null ? void 0 : options.authorization) {
1494
+ headers.Authorization = options.authorization;
1495
+ }
1496
+ const response = await axiosInstance.get(
1497
+ `${cleanBaseUrl}/api/schedule/solution/${jobId}`,
1498
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1499
+ );
1500
+ return response.data;
1501
+ }
1465
1502
 
1466
1503
  // src/utils/violationMessages.ts
1467
1504
  var SYSTEM_CONSTRAINT_MESSAGES = {
@@ -1839,6 +1876,7 @@ function AutoSchedulerModal({
1839
1876
  const [lastFailure, setLastFailure] = (0, import_react3.useState)(null);
1840
1877
  const [selectedLocationIds, setSelectedLocationIds] = (0, import_react3.useState)([]);
1841
1878
  const timersRef = (0, import_react3.useRef)([]);
1879
+ const pollIntervalRef = (0, import_react3.useRef)(null);
1842
1880
  const runIdRef = (0, import_react3.useRef)(0);
1843
1881
  const selectedByJurisdiction = (0, import_react3.useMemo)(
1844
1882
  () => jurisdictions.map((jurisdiction) => ({
@@ -1904,6 +1942,10 @@ function AutoSchedulerModal({
1904
1942
  const clearTimers = () => {
1905
1943
  timersRef.current.forEach((timerId) => clearTimeout(timerId));
1906
1944
  timersRef.current = [];
1945
+ if (pollIntervalRef.current) {
1946
+ clearInterval(pollIntervalRef.current);
1947
+ pollIntervalRef.current = null;
1948
+ }
1907
1949
  };
1908
1950
  const resetProgress = () => {
1909
1951
  setActiveStepIndex(0);
@@ -2037,7 +2079,6 @@ function AutoSchedulerModal({
2037
2079
  });
2038
2080
  const runId = resetBeforeSubmit();
2039
2081
  schedule(STEP_INTERVAL_MS, async () => {
2040
- var _a, _b;
2041
2082
  setCompletedStepIndex(0);
2042
2083
  setActiveStepIndex(1);
2043
2084
  try {
@@ -2045,51 +2086,47 @@ function AutoSchedulerModal({
2045
2086
  if (!token) {
2046
2087
  throw new Error("Failed to get auto-scheduler token");
2047
2088
  }
2048
- const response = await solveSchedule(
2049
- baseURL,
2050
- payload,
2051
- {
2052
- authorization: `Bearer ${token}`
2053
- }
2054
- );
2089
+ const auth = { authorization: `Bearer ${token}` };
2090
+ const { jobId } = await submitSolveJob(baseURL, payload, auth);
2055
2091
  if (runIdRef.current !== runId) {
2056
2092
  return;
2057
2093
  }
2058
- if (!response.explanation.isFeasible) {
2059
- const result = mapViolationsToResult(
2060
- (_a = response.explanation.violations) != null ? _a : [],
2061
- response.explanation.summary
2062
- );
2063
- const selectedLocations = jurisdictions.flatMap((j) => j.locations).filter(
2064
- (l) => selectedLocationIds.includes(l.id)
2065
- );
2066
- const recommendationPayload = generateRecommendationsURLAndHeaders ? {
2067
- context: {
2068
- selectedLocationIds,
2069
- selectedConstraintIds,
2070
- constraintValues,
2071
- selectedOptimizationIds,
2072
- optimizationValues,
2073
- timezone: (_b = selectedLocations[0]) == null ? void 0 : _b.timezone
2074
- },
2075
- locations: selectedLocations,
2076
- employees,
2077
- openShifts: openShifts.filter((s) => !s.employeeId),
2078
- assignedShifts: openShifts.filter((s) => Boolean(s.employeeId)),
2079
- timeOffs: timeOffs != null ? timeOffs : [],
2080
- explanation: response.explanation
2081
- } : void 0;
2082
- setLastFailure({
2083
- ...result,
2084
- recommendedFixes: [],
2085
- recommendationPayload
2086
- });
2087
- setScreen("failed");
2088
- } else {
2089
- setCompletedStepIndex(1);
2090
- setActiveStepIndex(OPTIMIZING_STEP_INDEX);
2091
- afterSuccessSteps(runId, response);
2092
- }
2094
+ setCompletedStepIndex(1);
2095
+ setActiveStepIndex(OPTIMIZING_STEP_INDEX);
2096
+ const pollForResult = async () => {
2097
+ if (runIdRef.current !== runId) return;
2098
+ try {
2099
+ const statusRes = await getJobStatus(baseURL, jobId, auth);
2100
+ if (runIdRef.current !== runId) return;
2101
+ if (statusRes.status === "NOT_SOLVING" || statusRes.status === "TERMINATED_EARLY") {
2102
+ if (pollIntervalRef.current) {
2103
+ clearInterval(pollIntervalRef.current);
2104
+ pollIntervalRef.current = null;
2105
+ }
2106
+ const response = await getJobResult(baseURL, jobId, auth);
2107
+ if (runIdRef.current !== runId) return;
2108
+ let responseForHandling = response;
2109
+ if (response.explanation.isFeasible) {
2110
+ const solution = await getJobSolution(baseURL, jobId, auth);
2111
+ if (runIdRef.current !== runId) return;
2112
+ responseForHandling = { ...response, solution };
2113
+ }
2114
+ handleSolveResult(runId, responseForHandling);
2115
+ return;
2116
+ }
2117
+ } catch (err) {
2118
+ if (runIdRef.current !== runId) return;
2119
+ if (pollIntervalRef.current) {
2120
+ clearInterval(pollIntervalRef.current);
2121
+ pollIntervalRef.current = null;
2122
+ }
2123
+ console.error(err);
2124
+ setLastFailure(NETWORK_ERROR_FAILURE);
2125
+ setScreen("failed");
2126
+ }
2127
+ };
2128
+ pollForResult();
2129
+ pollIntervalRef.current = setInterval(pollForResult, POLL_INTERVAL_MS);
2093
2130
  } catch (err) {
2094
2131
  if (runIdRef.current !== runId) {
2095
2132
  return;
@@ -2100,6 +2137,42 @@ function AutoSchedulerModal({
2100
2137
  }
2101
2138
  }, runId);
2102
2139
  };
2140
+ const handleSolveResult = (runId, response) => {
2141
+ var _a, _b;
2142
+ if (!response.explanation.isFeasible) {
2143
+ const result = mapViolationsToResult(
2144
+ (_a = response.explanation.violations) != null ? _a : [],
2145
+ response.explanation.summary
2146
+ );
2147
+ const selectedLocations = jurisdictions.flatMap((j) => j.locations).filter(
2148
+ (l) => selectedLocationIds.includes(l.id)
2149
+ );
2150
+ const recommendationPayload = generateRecommendationsURLAndHeaders ? {
2151
+ context: {
2152
+ selectedLocationIds,
2153
+ selectedConstraintIds,
2154
+ constraintValues,
2155
+ selectedOptimizationIds,
2156
+ optimizationValues,
2157
+ timezone: (_b = selectedLocations[0]) == null ? void 0 : _b.timezone
2158
+ },
2159
+ locations: selectedLocations,
2160
+ employees,
2161
+ openShifts: openShifts.filter((s) => !s.employeeId),
2162
+ assignedShifts: openShifts.filter((s) => Boolean(s.employeeId)),
2163
+ timeOffs: timeOffs != null ? timeOffs : [],
2164
+ explanation: response.explanation
2165
+ } : void 0;
2166
+ setLastFailure({
2167
+ ...result,
2168
+ recommendedFixes: [],
2169
+ recommendationPayload
2170
+ });
2171
+ setScreen("failed");
2172
+ } else {
2173
+ afterSuccessSteps(runId, response);
2174
+ }
2175
+ };
2103
2176
  const handleAdjustConstraints = () => {
2104
2177
  clearTimers();
2105
2178
  setScreen("configure");