@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.js CHANGED
@@ -889,6 +889,7 @@ var SCHEDULE_STEPS = [
889
889
  { title: "Finalizing schedule" }
890
890
  ];
891
891
  var STEP_INTERVAL_MS = 1200;
892
+ var POLL_INTERVAL_MS = 2500;
892
893
  var OPTIMIZING_STEP_INDEX = 2;
893
894
  var NETWORK_ERROR_FAILURE = {
894
895
  violatedConstraints: [
@@ -1433,19 +1434,55 @@ async function getToken(fullUrl, headers) {
1433
1434
  });
1434
1435
  return (_a = tokenRes.data) == null ? void 0 : _a.token;
1435
1436
  }
1436
- async function solveSchedule(baseURL, payload, options) {
1437
+ async function submitSolveJob(baseURL, payload, options) {
1437
1438
  const cleanBaseUrl = baseURL.replace(/\/$/, "");
1438
1439
  const headers = {};
1439
1440
  if (options == null ? void 0 : options.authorization) {
1440
1441
  headers.Authorization = options.authorization;
1441
1442
  }
1442
1443
  const response = await axiosInstance.post(
1443
- `${cleanBaseUrl}/api/schedule/solve`,
1444
+ `${cleanBaseUrl}/api/schedule/solve-async`,
1444
1445
  payload,
1445
1446
  { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1446
1447
  );
1447
1448
  return response.data;
1448
1449
  }
1450
+ async function getJobStatus(baseURL, jobId, options) {
1451
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1452
+ const headers = {};
1453
+ if (options == null ? void 0 : options.authorization) {
1454
+ headers.Authorization = options.authorization;
1455
+ }
1456
+ const response = await axiosInstance.get(
1457
+ `${cleanBaseUrl}/api/schedule/status/${jobId}`,
1458
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1459
+ );
1460
+ return response.data;
1461
+ }
1462
+ async function getJobResult(baseURL, jobId, options) {
1463
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1464
+ const headers = {};
1465
+ if (options == null ? void 0 : options.authorization) {
1466
+ headers.Authorization = options.authorization;
1467
+ }
1468
+ const response = await axiosInstance.get(
1469
+ `${cleanBaseUrl}/api/schedule/result/${jobId}`,
1470
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1471
+ );
1472
+ return response.data;
1473
+ }
1474
+ async function getJobSolution(baseURL, jobId, options) {
1475
+ const cleanBaseUrl = baseURL.replace(/\/$/, "");
1476
+ const headers = {};
1477
+ if (options == null ? void 0 : options.authorization) {
1478
+ headers.Authorization = options.authorization;
1479
+ }
1480
+ const response = await axiosInstance.get(
1481
+ `${cleanBaseUrl}/api/schedule/solution/${jobId}`,
1482
+ { headers: Object.keys(headers).length > 0 ? headers : void 0 }
1483
+ );
1484
+ return response.data;
1485
+ }
1449
1486
 
1450
1487
  // src/utils/violationMessages.ts
1451
1488
  var SYSTEM_CONSTRAINT_MESSAGES = {
@@ -1831,6 +1868,7 @@ function AutoSchedulerModal({
1831
1868
  const [lastFailure, setLastFailure] = useState2(null);
1832
1869
  const [selectedLocationIds, setSelectedLocationIds] = useState2([]);
1833
1870
  const timersRef = useRef([]);
1871
+ const pollIntervalRef = useRef(null);
1834
1872
  const runIdRef = useRef(0);
1835
1873
  const selectedByJurisdiction = useMemo2(
1836
1874
  () => jurisdictions.map((jurisdiction) => ({
@@ -1896,6 +1934,10 @@ function AutoSchedulerModal({
1896
1934
  const clearTimers = () => {
1897
1935
  timersRef.current.forEach((timerId) => clearTimeout(timerId));
1898
1936
  timersRef.current = [];
1937
+ if (pollIntervalRef.current) {
1938
+ clearInterval(pollIntervalRef.current);
1939
+ pollIntervalRef.current = null;
1940
+ }
1899
1941
  };
1900
1942
  const resetProgress = () => {
1901
1943
  setActiveStepIndex(0);
@@ -2029,7 +2071,6 @@ function AutoSchedulerModal({
2029
2071
  });
2030
2072
  const runId = resetBeforeSubmit();
2031
2073
  schedule(STEP_INTERVAL_MS, async () => {
2032
- var _a, _b;
2033
2074
  setCompletedStepIndex(0);
2034
2075
  setActiveStepIndex(1);
2035
2076
  try {
@@ -2037,51 +2078,47 @@ function AutoSchedulerModal({
2037
2078
  if (!token) {
2038
2079
  throw new Error("Failed to get auto-scheduler token");
2039
2080
  }
2040
- const response = await solveSchedule(
2041
- baseURL,
2042
- payload,
2043
- {
2044
- authorization: `Bearer ${token}`
2045
- }
2046
- );
2081
+ const auth = { authorization: `Bearer ${token}` };
2082
+ const { jobId } = await submitSolveJob(baseURL, payload, auth);
2047
2083
  if (runIdRef.current !== runId) {
2048
2084
  return;
2049
2085
  }
2050
- if (!response.explanation.isFeasible) {
2051
- const result = mapViolationsToResult(
2052
- (_a = response.explanation.violations) != null ? _a : [],
2053
- response.explanation.summary
2054
- );
2055
- const selectedLocations = jurisdictions.flatMap((j) => j.locations).filter(
2056
- (l) => selectedLocationIds.includes(l.id)
2057
- );
2058
- const recommendationPayload = generateRecommendationsURLAndHeaders ? {
2059
- context: {
2060
- selectedLocationIds,
2061
- selectedConstraintIds,
2062
- constraintValues,
2063
- selectedOptimizationIds,
2064
- optimizationValues,
2065
- timezone: (_b = selectedLocations[0]) == null ? void 0 : _b.timezone
2066
- },
2067
- locations: selectedLocations,
2068
- employees,
2069
- openShifts: openShifts.filter((s) => !s.employeeId),
2070
- assignedShifts: openShifts.filter((s) => Boolean(s.employeeId)),
2071
- timeOffs: timeOffs != null ? timeOffs : [],
2072
- explanation: response.explanation
2073
- } : void 0;
2074
- setLastFailure({
2075
- ...result,
2076
- recommendedFixes: [],
2077
- recommendationPayload
2078
- });
2079
- setScreen("failed");
2080
- } else {
2081
- setCompletedStepIndex(1);
2082
- setActiveStepIndex(OPTIMIZING_STEP_INDEX);
2083
- afterSuccessSteps(runId, response);
2084
- }
2086
+ setCompletedStepIndex(1);
2087
+ setActiveStepIndex(OPTIMIZING_STEP_INDEX);
2088
+ const pollForResult = async () => {
2089
+ if (runIdRef.current !== runId) return;
2090
+ try {
2091
+ const statusRes = await getJobStatus(baseURL, jobId, auth);
2092
+ if (runIdRef.current !== runId) return;
2093
+ if (statusRes.status === "NOT_SOLVING" || statusRes.status === "TERMINATED_EARLY") {
2094
+ if (pollIntervalRef.current) {
2095
+ clearInterval(pollIntervalRef.current);
2096
+ pollIntervalRef.current = null;
2097
+ }
2098
+ const response = await getJobResult(baseURL, jobId, auth);
2099
+ if (runIdRef.current !== runId) return;
2100
+ let responseForHandling = response;
2101
+ if (response.explanation.isFeasible) {
2102
+ const solution = await getJobSolution(baseURL, jobId, auth);
2103
+ if (runIdRef.current !== runId) return;
2104
+ responseForHandling = { ...response, solution };
2105
+ }
2106
+ handleSolveResult(runId, responseForHandling);
2107
+ return;
2108
+ }
2109
+ } catch (err) {
2110
+ if (runIdRef.current !== runId) return;
2111
+ if (pollIntervalRef.current) {
2112
+ clearInterval(pollIntervalRef.current);
2113
+ pollIntervalRef.current = null;
2114
+ }
2115
+ console.error(err);
2116
+ setLastFailure(NETWORK_ERROR_FAILURE);
2117
+ setScreen("failed");
2118
+ }
2119
+ };
2120
+ pollForResult();
2121
+ pollIntervalRef.current = setInterval(pollForResult, POLL_INTERVAL_MS);
2085
2122
  } catch (err) {
2086
2123
  if (runIdRef.current !== runId) {
2087
2124
  return;
@@ -2092,6 +2129,42 @@ function AutoSchedulerModal({
2092
2129
  }
2093
2130
  }, runId);
2094
2131
  };
2132
+ const handleSolveResult = (runId, response) => {
2133
+ var _a, _b;
2134
+ if (!response.explanation.isFeasible) {
2135
+ const result = mapViolationsToResult(
2136
+ (_a = response.explanation.violations) != null ? _a : [],
2137
+ response.explanation.summary
2138
+ );
2139
+ const selectedLocations = jurisdictions.flatMap((j) => j.locations).filter(
2140
+ (l) => selectedLocationIds.includes(l.id)
2141
+ );
2142
+ const recommendationPayload = generateRecommendationsURLAndHeaders ? {
2143
+ context: {
2144
+ selectedLocationIds,
2145
+ selectedConstraintIds,
2146
+ constraintValues,
2147
+ selectedOptimizationIds,
2148
+ optimizationValues,
2149
+ timezone: (_b = selectedLocations[0]) == null ? void 0 : _b.timezone
2150
+ },
2151
+ locations: selectedLocations,
2152
+ employees,
2153
+ openShifts: openShifts.filter((s) => !s.employeeId),
2154
+ assignedShifts: openShifts.filter((s) => Boolean(s.employeeId)),
2155
+ timeOffs: timeOffs != null ? timeOffs : [],
2156
+ explanation: response.explanation
2157
+ } : void 0;
2158
+ setLastFailure({
2159
+ ...result,
2160
+ recommendedFixes: [],
2161
+ recommendationPayload
2162
+ });
2163
+ setScreen("failed");
2164
+ } else {
2165
+ afterSuccessSteps(runId, response);
2166
+ }
2167
+ };
2095
2168
  const handleAdjustConstraints = () => {
2096
2169
  clearTimers();
2097
2170
  setScreen("configure");