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

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.d.cts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
  import { ThemeOverride } from '@chakra-ui/react';
3
4
 
4
5
  declare class RequestError extends Error {
@@ -118,6 +119,8 @@ type OpenShift = {
118
119
  };
119
120
  requiredPosition: string;
120
121
  requiredCount: number;
122
+ isDraft?: boolean;
123
+ isPublished?: boolean;
121
124
  employeePreferences: Array<{
122
125
  employeeId: string;
123
126
  level: "PREFERRED" | "AVAILABLE" | "UNAVAILABLE" | string;
@@ -129,8 +132,17 @@ type EmployeeProperties = {
129
132
  worker_type: string;
130
133
  costToRevenueRatio?: number;
131
134
  avgSalesAmount?: number;
135
+ /** Integer basis points (e.g. 1234 = 12.34%). Omit when unknown. */
136
+ conversionRate?: number;
132
137
  [key: string]: object | string | number | boolean | undefined;
133
138
  };
139
+ /** One hourly traffic cell for the solver TrafficForecast fact (location-local). */
140
+ type TrafficForecastEntry = {
141
+ locationId: string;
142
+ date: string;
143
+ hour: number;
144
+ visits: number;
145
+ };
134
146
  type Employee = {
135
147
  id: string;
136
148
  name: string;
@@ -248,10 +260,88 @@ type AutoSchedulerModalTheme = (ThemeOverride & {
248
260
  }) | (EasyTeamThemeOverrides & {
249
261
  autoSchedulerModal?: AutoSchedulerModalStyleOverrides;
250
262
  });
263
+ type SubLocationOption = {
264
+ id: string;
265
+ name: string;
266
+ parentId: string;
267
+ };
268
+ type TeamOption = {
269
+ id: string;
270
+ name: string;
271
+ resources: {
272
+ id: string;
273
+ externalEmployeeId?: string;
274
+ type?: string;
275
+ properties?: {
276
+ name?: string;
277
+ } & Record<string, unknown>;
278
+ [key: string]: unknown;
279
+ }[];
280
+ };
281
+ type HardConstraintOption = {
282
+ id: string;
283
+ name: string;
284
+ /** Shows this option as selected without requiring user interaction. */
285
+ defaultSelected?: boolean;
286
+ /** Prevents changing an implicitly selected option in the scheduler drawer. */
287
+ readOnly?: boolean;
288
+ /** When present, the modal shows a numeric input on selection. */
289
+ defaultValue?: string;
290
+ /** Label next to the input, e.g. 'hours' or 'days'. Defaults to 'hours'. */
291
+ suffix?: string;
292
+ min?: number;
293
+ max?: number;
294
+ /** Used as violation message detail when the solver reports this constraint as violated. */
295
+ description?: string;
296
+ };
297
+ type SoftConstraintOption = {
298
+ id: string;
299
+ title: string;
300
+ /** Shows this option as selected without requiring user interaction. */
301
+ defaultSelected?: boolean;
302
+ /** Prevents changing an implicitly selected option in the scheduler drawer. */
303
+ readOnly?: boolean;
304
+ /** Shown below the title in the picker. Also used as violation message detail. */
305
+ subtitle?: string;
306
+ };
307
+ type SoftConstraintGroup = {
308
+ id: string;
309
+ name: string;
310
+ options: SoftConstraintOption[];
311
+ };
312
+ type BuiltinConstraintOption = {
313
+ id: string;
314
+ title: string;
315
+ subtitle?: string;
316
+ category?: string;
317
+ defaultSelected?: boolean;
318
+ };
319
+ type GenerateScheduleConfig = {
320
+ selectedLocationIds: string[];
321
+ selectedSubLocationIds: string[];
322
+ selectedTeamIds: string[];
323
+ /** IANA timezone resolved from the selected drawer location. */
324
+ schedulerTimezone?: string;
325
+ /** Calendar dates YYYY-MM-DD within the viewed week to include in workflow evaluation and solver optimization */
326
+ selectedScheduleDates: string[];
327
+ selectedConstraintIds: string[];
328
+ constraintValues: Record<string, string>;
329
+ selectedOptimizationIds: string[];
330
+ optimizationValues: Record<string, string>;
331
+ /** Opt-in built-in Timefold constraint slugs (not org visual-rule UUIDs). */
332
+ selectedBuiltinIds?: string[];
333
+ };
251
334
  type AutoSchedulerModalProps = {
252
- baseURL: string;
335
+ /** Controls whether the component renders as a modal or a right-side drawer */
336
+ displayMode?: 'modal' | 'drawer';
337
+ /** Width of the drawer when displayMode="drawer". "sm"=448px, "md"=578px, "lg"=600px. Defaults to "lg". */
338
+ drawerSize?: 'sm' | 'md' | 'lg';
339
+ /** When true, the drawer fills 100% viewport height. Defaults to false. */
340
+ drawerFullHeight?: boolean;
341
+ baseURL?: string;
253
342
  isOpen: boolean;
254
343
  title?: string;
344
+ bannerTitle?: string;
255
345
  bannerText?: string;
256
346
  jurisdictions: JurisdictionGroup[];
257
347
  employees: Employee[];
@@ -268,22 +358,94 @@ type AutoSchedulerModalProps = {
268
358
  };
269
359
  theme?: AutoSchedulerModalTheme;
270
360
  cssVarsRoot?: string;
271
- generateRecommendationsURLAndHeaders: {
361
+ generateRecommendationsURLAndHeaders?: {
272
362
  url: string;
273
363
  headers?: Record<string, string>;
274
364
  };
275
- getTokenURLAndHeaders: {
365
+ getTokenURLAndHeaders?: {
276
366
  url: string;
277
367
  headers?: Record<string, string>;
278
368
  };
279
- onSolution: (solution: ScheduleSolution) => Promise<void>;
369
+ onSolution?: (solution: ScheduleSolution) => Promise<void>;
280
370
  /** When provided, fetches stored config for a location set to prefill the form */
281
371
  getStoredConfigForLocations?: (locationIds: string[]) => AutoSchedulerModalConfig | null;
282
372
  /** When provided, persists config after successful schedule creation */
283
373
  persistConfigForLocations?: (locationIds: string[], config: AutoSchedulerModalConfig) => void;
374
+ errorToast?: (msg: string) => void;
375
+ /** Organization id — required when sending visual rule ids */
376
+ organizationId?: string;
377
+ /** Visual rule ids attached to this solve (production path) */
378
+ constraintDefinitionIds?: string[];
379
+ /** Inline visual rule definitions (sandbox/test path; for unsaved rules) */
380
+ constraintDefinitions?: unknown[];
381
+ /** Replaces the built-in hard constraint list shown in "Required rules". */
382
+ hardConstraintOptions?: HardConstraintOption[];
383
+ /** Replaces the built-in optimization groups shown in "Optimization". */
384
+ softConstraintGroups?: SoftConstraintGroup[];
385
+ /** Optional footer under Optimization (e.g. host-owned Avia attribution). Prefer a render fn when showing in multiple places. */
386
+ optimizationFooter?: ReactNode | (() => ReactNode);
387
+ /**
388
+ * Hourly traffic forecast for the solve week (location-local).
389
+ * When Maximize Sales is selected and this is non-empty, the modal injects
390
+ * traffic-forecast-incentive and serializes this field on the solve payload.
391
+ */
392
+ trafficForecast?: TrafficForecastEntry[];
393
+ /** Opt-in built-in Timefold constraints (solver catalog slugs). */
394
+ builtinConstraintOptions?: BuiltinConstraintOption[];
395
+ /** All sub-locations (with parentId). The component filters them internally based on selected location IDs. */
396
+ subLocations?: SubLocationOption[];
397
+ /** When true, renders the sub-locations multiselect (filtered by selected locations). Defaults to false. */
398
+ showSubLocations?: boolean;
399
+ /** Teams list. The caller should update this reactively in response to onSelectionChange. */
400
+ teams?: TeamOption[];
401
+ /** When true, renders the teams multiselect. Defaults to false. */
402
+ showTeams?: boolean;
403
+ /**
404
+ * Called when the user changes location or sub-location selection.
405
+ * Use this to re-fetch teams filtered by the new selection.
406
+ */
407
+ onSelectionChange?: (locationIds: string[], subLocationIds: string[]) => void;
408
+ /**
409
+ * When provided, replaces the Java solver flow entirely.
410
+ * The component shows the progress animation and calls this function at step 1.
411
+ * Resolving means success (the resolved value is forwarded to onGenerateSolution);
412
+ * throwing means failure (shown in the failed screen).
413
+ */
414
+ onGenerate?: (config: GenerateScheduleConfig) => Promise<unknown>;
415
+ /**
416
+ * Called after onGenerate resolves successfully, just before the drawer/modal closes.
417
+ * Receives the value returned by onGenerate.
418
+ */
419
+ onGenerateSolution?: (result: unknown) => void;
420
+ /**
421
+ * Calendar week-start date YYYY-MM-DD (matches ops weekly schedule / evaluate-range window).
422
+ * When `onGenerate` is used, pass the week currently shown on the schedule grid.
423
+ */
424
+ scheduleWeekStartYmd?: string;
425
+ /**
426
+ * Today's civil date YYYY-MM-DD in `evaluationTimezone`, used to leave past week days unselected by default.
427
+ */
428
+ todayCalendarYmd?: string;
429
+ /**
430
+ * IANA timezone for interpreting today + backend evaluate-range date filtering (defaults to UTC).
431
+ */
432
+ evaluationTimezone?: string;
433
+ /**
434
+ * Live status of the underlying solve job. When set to "QUEUED" while the
435
+ * progress UI is visible, step 2's caption is replaced with "Waiting in queue…".
436
+ * Any other value (or null/undefined) leaves the step copy unchanged.
437
+ */
438
+ solveStatus?: SolveJobStatus | null;
284
439
  };
285
440
  type Screen = "configure" | "creating" | "failed";
286
441
  type StepStatus = "pending" | "active" | "done";
442
+ /**
443
+ * Status of an async solve job, as reported by the scheduler service.
444
+ * QUEUED → waiting for a solver slot
445
+ * SOLVING_ACTIVE → solver is running
446
+ * NOT_SOLVING / TERMINATED_EARLY → terminal
447
+ */
448
+ type SolveJobStatus = "QUEUED" | "SOLVING_ACTIVE" | "NOT_SOLVING" | "TERMINATED_EARLY";
287
449
  type RuleOverrideEntry = {
288
450
  ruleId: string;
289
451
  parameters?: Record<string, unknown>;
@@ -320,10 +482,16 @@ type SchedulePayload = {
320
482
  timezone?: string;
321
483
  jurisdiction?: string;
322
484
  tags?: string[];
485
+ properties?: Record<string, unknown>;
323
486
  }>;
324
487
  timeOffs?: TimeOff[];
325
488
  ruleIds?: string[];
326
489
  ruleOverrides?: RuleOverrideEntry[];
490
+ /** Hourly traffic forecast problem fact (omit when unused). */
491
+ trafficForecast?: TrafficForecastEntry[];
492
+ constraintDefinitionIds?: string[];
493
+ constraintDefinitions?: unknown[];
494
+ organizationId?: string;
327
495
  };
328
496
  type AutoSchedulerModalConfig = {
329
497
  selectedLocationIds: string[];
@@ -331,6 +499,7 @@ type AutoSchedulerModalConfig = {
331
499
  constraintValues: Record<string, string>;
332
500
  selectedOptimizationIds: string[];
333
501
  optimizationValues: Record<string, string>;
502
+ selectedBuiltinIds?: string[];
334
503
  };
335
504
  type SolveApiExplanation = SolveApiResponse["explanation"];
336
505
  /** Full POST body for the getRecommendationURL API (context, locations, employees, shifts, etc.) */
@@ -374,6 +543,7 @@ type ViolatedConstraintsPanelProps = {
374
543
  };
375
544
  styles?: Record<string, Record<string, unknown>>;
376
545
  styleOverrides?: ViolatedConstraintsPanelStyleOverrides;
546
+ errorToast?: (msg: string) => void;
377
547
  };
378
548
  type SolveApiResponse = {
379
549
  problemId: string;
@@ -400,8 +570,12 @@ type ScheduleRecommendation = {
400
570
  recommendation: string;
401
571
  why_this_resolves_it: string;
402
572
  };
573
+ declare class InfeasibleScheduleError extends Error {
574
+ readonly failure: ViolatedConstraintsResult;
575
+ constructor(failure: ViolatedConstraintsResult);
576
+ }
403
577
 
404
- declare function AutoSchedulerModal({ baseURL, isOpen, title, bannerText, jurisdictions, openShifts, employees, timeOffs, locationPlaceholder, onClose, cancelLabel, primaryActionLabel, onPrimaryAction: _onPrimaryAction, onFixManually, initialConfig, theme, cssVarsRoot, generateRecommendationsURLAndHeaders, getTokenURLAndHeaders, onSolution, getStoredConfigForLocations, persistConfigForLocations, }: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
578
+ declare function AutoSchedulerModal({ displayMode, drawerSize, baseURL, isOpen, title, bannerTitle, bannerText, jurisdictions, openShifts, employees, timeOffs, locationPlaceholder, onClose, cancelLabel, primaryActionLabel, onPrimaryAction: _onPrimaryAction, onFixManually, initialConfig, theme, cssVarsRoot, generateRecommendationsURLAndHeaders, getTokenURLAndHeaders, onSolution, getStoredConfigForLocations, persistConfigForLocations, errorToast, organizationId, constraintDefinitionIds, constraintDefinitions, hardConstraintOptions, softConstraintGroups, optimizationFooter, trafficForecast, builtinConstraintOptions, subLocations, showSubLocations, teams, showTeams, onSelectionChange, onGenerate, onGenerateSolution, solveStatus, scheduleWeekStartYmd, todayCalendarYmd, evaluationTimezone, }: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
405
579
 
406
580
  /**
407
581
  * Self-contained AutoSchedulerModal that wraps itself in ChakraProvider.
@@ -410,11 +584,25 @@ declare function AutoSchedulerModal({ baseURL, isOpen, title, bannerText, jurisd
410
584
  */
411
585
  declare function AutoSchedulerModalWithProvider(props: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
412
586
 
413
- declare function ViolatedConstraintsPanel({ violatedConstraints, title, subtitle, showSecondaryButton, secondaryButtonTitle, onSecondaryButtonClick, generateRecommendationsURLAndHeaders, styles: stylesProp, styleOverrides, }: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
587
+ declare function ViolatedConstraintsPanel({ violatedConstraints, title, subtitle, showSecondaryButton, secondaryButtonTitle, onSecondaryButtonClick, generateRecommendationsURLAndHeaders, styles: stylesProp, styleOverrides, errorToast, }: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
414
588
 
415
589
  declare function ViolatedConstraintsPanelWithProvider(props: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
416
590
 
417
- declare function buildRulesPayload(selectedConstraintIds: string[], constraintValues: Record<string, string>, selectedOptimizationIds: string[], optimizationValues: Record<string, string>): {
591
+ /** Soft companion for conversion rate silent inject under Maximize Sales / Cost-to-sales. */
592
+ declare const MAXIMIZE_CONVERSION_RATE_RULE_ID = "maximize-conversion-rate";
593
+ /** Soft companion for traffic × sales — silent inject under Maximize Sales only. */
594
+ declare const TRAFFIC_FORECAST_INCENTIVE_RULE_ID = "traffic-forecast-incentive";
595
+ type SiblingRuleOptions = {
596
+ /** Inject maximize-conversion-rate when sales opts are selected. */
597
+ includeConversionRate?: boolean;
598
+ /** Inject traffic-forecast-incentive when Maximize Sales is selected. */
599
+ includeTrafficIncentive?: boolean;
600
+ };
601
+ /**
602
+ * Build ruleIds / ruleOverrides. Sibling Avia-agnostic rules are appended into
603
+ * whichever structure is returned (Maximize Sales forces the overrides path).
604
+ */
605
+ declare function buildRulesPayload(selectedConstraintIds: string[], constraintValues: Record<string, string>, selectedOptimizationIds: string[], optimizationValues: Record<string, string>, siblings?: SiblingRuleOptions): {
418
606
  ruleIds?: string[];
419
607
  ruleOverrides?: RuleOverrideEntry[];
420
608
  };
@@ -428,6 +616,10 @@ type BuildSchedulePayloadInput = {
428
616
  constraintValues: Record<string, string>;
429
617
  selectedOptimizationIds: string[];
430
618
  optimizationValues: Record<string, string>;
619
+ trafficForecast?: TrafficForecastEntry[];
620
+ constraintDefinitionIds?: string[];
621
+ constraintDefinitions?: unknown[];
622
+ organizationId?: string;
431
623
  };
432
624
  declare function buildSchedulePayload(input: BuildSchedulePayloadInput): SchedulePayload;
433
625
 
@@ -437,4 +629,11 @@ declare function buildSchedulePayload(input: BuildSchedulePayloadInput): Schedul
437
629
  */
438
630
  declare function getFriendlyRuleName(ruleIdOrConstraintName: string): string;
439
631
 
440
- export { AutoSchedulerModal, type AutoSchedulerModalConfig, type AutoSchedulerModalProps, type AutoSchedulerModalStyleOverrides, type AutoSchedulerModalTheme, AutoSchedulerModalWithProvider, type BuildSchedulePayloadInput, type EasyTeamThemeOverrides, type Employee, type EmployeeProperties, type JurisdictionGroup, type LocationOption, type OpenShift, type RecommendationPayload, RequestError, type RuleOverrideEntry, type SchedulePayload, type ScheduleRecommendation, type ScheduleSolution, type ScheduleSolutionAvailability, type ScheduleSolutionEmployee, type ScheduleSolutionLocation, type ScheduleSolutionRuleMetadata, type ScheduleSolutionRuleOverride, type ScheduleSolutionShift, type ScheduleSolutionShiftAssignment, type ScheduleSolutionTimeOff, type ScheduleSolutionWaiver, type Screen, type ShiftAssignmentJustification, type SolveApiExplanation, type SolveApiResponse, type StepStatus, type TimeOff, ViolatedConstraintsPanel, type ViolatedConstraintsPanelProps, type ViolatedConstraintsPanelStyleOverrides, ViolatedConstraintsPanelWithProvider, type ViolatedConstraintsResult, buildRulesPayload, buildSchedulePayload, getFriendlyRuleName };
632
+ /** Seven consecutive calendar days starting at `weekStartYmd` (already aligned to org week start). */
633
+ declare function getSequentialWeekDatesFromWeekStart(weekStartYmd: string): string[];
634
+ /** Calendar-day weekday chip Su … Sa following JS getDay() order (0 = Sun). */
635
+ declare function weekdayTwoLetterFromYmd(ymd: string): string;
636
+ /** Defaults to all week dates strictly on or after `todayYmd` (ISO date string compare). */
637
+ declare function defaultSelectedScheduleDates(orderedWeekYmds: string[], todayYmd: string): string[];
638
+
639
+ export { AutoSchedulerModal, type AutoSchedulerModalConfig, type AutoSchedulerModalProps, type AutoSchedulerModalStyleOverrides, type AutoSchedulerModalTheme, AutoSchedulerModalWithProvider, type BuildSchedulePayloadInput, type BuiltinConstraintOption, type EasyTeamThemeOverrides, type Employee, type EmployeeProperties, type GenerateScheduleConfig, type HardConstraintOption, InfeasibleScheduleError, type JurisdictionGroup, type LocationOption, MAXIMIZE_CONVERSION_RATE_RULE_ID, type OpenShift, type RecommendationPayload, RequestError, type RuleOverrideEntry, type SchedulePayload, type ScheduleRecommendation, type ScheduleSolution, type ScheduleSolutionAvailability, type ScheduleSolutionEmployee, type ScheduleSolutionLocation, type ScheduleSolutionRuleMetadata, type ScheduleSolutionRuleOverride, type ScheduleSolutionShift, type ScheduleSolutionShiftAssignment, type ScheduleSolutionTimeOff, type ScheduleSolutionWaiver, type Screen, type ShiftAssignmentJustification, type SiblingRuleOptions, type SoftConstraintGroup, type SoftConstraintOption, type SolveApiExplanation, type SolveApiResponse, type SolveJobStatus, type StepStatus, type SubLocationOption, TRAFFIC_FORECAST_INCENTIVE_RULE_ID, type TeamOption, type TimeOff, type TrafficForecastEntry, ViolatedConstraintsPanel, type ViolatedConstraintsPanelProps, type ViolatedConstraintsPanelStyleOverrides, ViolatedConstraintsPanelWithProvider, type ViolatedConstraintsResult, buildRulesPayload, buildSchedulePayload, defaultSelectedScheduleDates, getFriendlyRuleName, getSequentialWeekDatesFromWeekStart, weekdayTwoLetterFromYmd };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
  import { ThemeOverride } from '@chakra-ui/react';
3
4
 
4
5
  declare class RequestError extends Error {
@@ -118,6 +119,8 @@ type OpenShift = {
118
119
  };
119
120
  requiredPosition: string;
120
121
  requiredCount: number;
122
+ isDraft?: boolean;
123
+ isPublished?: boolean;
121
124
  employeePreferences: Array<{
122
125
  employeeId: string;
123
126
  level: "PREFERRED" | "AVAILABLE" | "UNAVAILABLE" | string;
@@ -129,8 +132,17 @@ type EmployeeProperties = {
129
132
  worker_type: string;
130
133
  costToRevenueRatio?: number;
131
134
  avgSalesAmount?: number;
135
+ /** Integer basis points (e.g. 1234 = 12.34%). Omit when unknown. */
136
+ conversionRate?: number;
132
137
  [key: string]: object | string | number | boolean | undefined;
133
138
  };
139
+ /** One hourly traffic cell for the solver TrafficForecast fact (location-local). */
140
+ type TrafficForecastEntry = {
141
+ locationId: string;
142
+ date: string;
143
+ hour: number;
144
+ visits: number;
145
+ };
134
146
  type Employee = {
135
147
  id: string;
136
148
  name: string;
@@ -248,10 +260,88 @@ type AutoSchedulerModalTheme = (ThemeOverride & {
248
260
  }) | (EasyTeamThemeOverrides & {
249
261
  autoSchedulerModal?: AutoSchedulerModalStyleOverrides;
250
262
  });
263
+ type SubLocationOption = {
264
+ id: string;
265
+ name: string;
266
+ parentId: string;
267
+ };
268
+ type TeamOption = {
269
+ id: string;
270
+ name: string;
271
+ resources: {
272
+ id: string;
273
+ externalEmployeeId?: string;
274
+ type?: string;
275
+ properties?: {
276
+ name?: string;
277
+ } & Record<string, unknown>;
278
+ [key: string]: unknown;
279
+ }[];
280
+ };
281
+ type HardConstraintOption = {
282
+ id: string;
283
+ name: string;
284
+ /** Shows this option as selected without requiring user interaction. */
285
+ defaultSelected?: boolean;
286
+ /** Prevents changing an implicitly selected option in the scheduler drawer. */
287
+ readOnly?: boolean;
288
+ /** When present, the modal shows a numeric input on selection. */
289
+ defaultValue?: string;
290
+ /** Label next to the input, e.g. 'hours' or 'days'. Defaults to 'hours'. */
291
+ suffix?: string;
292
+ min?: number;
293
+ max?: number;
294
+ /** Used as violation message detail when the solver reports this constraint as violated. */
295
+ description?: string;
296
+ };
297
+ type SoftConstraintOption = {
298
+ id: string;
299
+ title: string;
300
+ /** Shows this option as selected without requiring user interaction. */
301
+ defaultSelected?: boolean;
302
+ /** Prevents changing an implicitly selected option in the scheduler drawer. */
303
+ readOnly?: boolean;
304
+ /** Shown below the title in the picker. Also used as violation message detail. */
305
+ subtitle?: string;
306
+ };
307
+ type SoftConstraintGroup = {
308
+ id: string;
309
+ name: string;
310
+ options: SoftConstraintOption[];
311
+ };
312
+ type BuiltinConstraintOption = {
313
+ id: string;
314
+ title: string;
315
+ subtitle?: string;
316
+ category?: string;
317
+ defaultSelected?: boolean;
318
+ };
319
+ type GenerateScheduleConfig = {
320
+ selectedLocationIds: string[];
321
+ selectedSubLocationIds: string[];
322
+ selectedTeamIds: string[];
323
+ /** IANA timezone resolved from the selected drawer location. */
324
+ schedulerTimezone?: string;
325
+ /** Calendar dates YYYY-MM-DD within the viewed week to include in workflow evaluation and solver optimization */
326
+ selectedScheduleDates: string[];
327
+ selectedConstraintIds: string[];
328
+ constraintValues: Record<string, string>;
329
+ selectedOptimizationIds: string[];
330
+ optimizationValues: Record<string, string>;
331
+ /** Opt-in built-in Timefold constraint slugs (not org visual-rule UUIDs). */
332
+ selectedBuiltinIds?: string[];
333
+ };
251
334
  type AutoSchedulerModalProps = {
252
- baseURL: string;
335
+ /** Controls whether the component renders as a modal or a right-side drawer */
336
+ displayMode?: 'modal' | 'drawer';
337
+ /** Width of the drawer when displayMode="drawer". "sm"=448px, "md"=578px, "lg"=600px. Defaults to "lg". */
338
+ drawerSize?: 'sm' | 'md' | 'lg';
339
+ /** When true, the drawer fills 100% viewport height. Defaults to false. */
340
+ drawerFullHeight?: boolean;
341
+ baseURL?: string;
253
342
  isOpen: boolean;
254
343
  title?: string;
344
+ bannerTitle?: string;
255
345
  bannerText?: string;
256
346
  jurisdictions: JurisdictionGroup[];
257
347
  employees: Employee[];
@@ -268,22 +358,94 @@ type AutoSchedulerModalProps = {
268
358
  };
269
359
  theme?: AutoSchedulerModalTheme;
270
360
  cssVarsRoot?: string;
271
- generateRecommendationsURLAndHeaders: {
361
+ generateRecommendationsURLAndHeaders?: {
272
362
  url: string;
273
363
  headers?: Record<string, string>;
274
364
  };
275
- getTokenURLAndHeaders: {
365
+ getTokenURLAndHeaders?: {
276
366
  url: string;
277
367
  headers?: Record<string, string>;
278
368
  };
279
- onSolution: (solution: ScheduleSolution) => Promise<void>;
369
+ onSolution?: (solution: ScheduleSolution) => Promise<void>;
280
370
  /** When provided, fetches stored config for a location set to prefill the form */
281
371
  getStoredConfigForLocations?: (locationIds: string[]) => AutoSchedulerModalConfig | null;
282
372
  /** When provided, persists config after successful schedule creation */
283
373
  persistConfigForLocations?: (locationIds: string[], config: AutoSchedulerModalConfig) => void;
374
+ errorToast?: (msg: string) => void;
375
+ /** Organization id — required when sending visual rule ids */
376
+ organizationId?: string;
377
+ /** Visual rule ids attached to this solve (production path) */
378
+ constraintDefinitionIds?: string[];
379
+ /** Inline visual rule definitions (sandbox/test path; for unsaved rules) */
380
+ constraintDefinitions?: unknown[];
381
+ /** Replaces the built-in hard constraint list shown in "Required rules". */
382
+ hardConstraintOptions?: HardConstraintOption[];
383
+ /** Replaces the built-in optimization groups shown in "Optimization". */
384
+ softConstraintGroups?: SoftConstraintGroup[];
385
+ /** Optional footer under Optimization (e.g. host-owned Avia attribution). Prefer a render fn when showing in multiple places. */
386
+ optimizationFooter?: ReactNode | (() => ReactNode);
387
+ /**
388
+ * Hourly traffic forecast for the solve week (location-local).
389
+ * When Maximize Sales is selected and this is non-empty, the modal injects
390
+ * traffic-forecast-incentive and serializes this field on the solve payload.
391
+ */
392
+ trafficForecast?: TrafficForecastEntry[];
393
+ /** Opt-in built-in Timefold constraints (solver catalog slugs). */
394
+ builtinConstraintOptions?: BuiltinConstraintOption[];
395
+ /** All sub-locations (with parentId). The component filters them internally based on selected location IDs. */
396
+ subLocations?: SubLocationOption[];
397
+ /** When true, renders the sub-locations multiselect (filtered by selected locations). Defaults to false. */
398
+ showSubLocations?: boolean;
399
+ /** Teams list. The caller should update this reactively in response to onSelectionChange. */
400
+ teams?: TeamOption[];
401
+ /** When true, renders the teams multiselect. Defaults to false. */
402
+ showTeams?: boolean;
403
+ /**
404
+ * Called when the user changes location or sub-location selection.
405
+ * Use this to re-fetch teams filtered by the new selection.
406
+ */
407
+ onSelectionChange?: (locationIds: string[], subLocationIds: string[]) => void;
408
+ /**
409
+ * When provided, replaces the Java solver flow entirely.
410
+ * The component shows the progress animation and calls this function at step 1.
411
+ * Resolving means success (the resolved value is forwarded to onGenerateSolution);
412
+ * throwing means failure (shown in the failed screen).
413
+ */
414
+ onGenerate?: (config: GenerateScheduleConfig) => Promise<unknown>;
415
+ /**
416
+ * Called after onGenerate resolves successfully, just before the drawer/modal closes.
417
+ * Receives the value returned by onGenerate.
418
+ */
419
+ onGenerateSolution?: (result: unknown) => void;
420
+ /**
421
+ * Calendar week-start date YYYY-MM-DD (matches ops weekly schedule / evaluate-range window).
422
+ * When `onGenerate` is used, pass the week currently shown on the schedule grid.
423
+ */
424
+ scheduleWeekStartYmd?: string;
425
+ /**
426
+ * Today's civil date YYYY-MM-DD in `evaluationTimezone`, used to leave past week days unselected by default.
427
+ */
428
+ todayCalendarYmd?: string;
429
+ /**
430
+ * IANA timezone for interpreting today + backend evaluate-range date filtering (defaults to UTC).
431
+ */
432
+ evaluationTimezone?: string;
433
+ /**
434
+ * Live status of the underlying solve job. When set to "QUEUED" while the
435
+ * progress UI is visible, step 2's caption is replaced with "Waiting in queue…".
436
+ * Any other value (or null/undefined) leaves the step copy unchanged.
437
+ */
438
+ solveStatus?: SolveJobStatus | null;
284
439
  };
285
440
  type Screen = "configure" | "creating" | "failed";
286
441
  type StepStatus = "pending" | "active" | "done";
442
+ /**
443
+ * Status of an async solve job, as reported by the scheduler service.
444
+ * QUEUED → waiting for a solver slot
445
+ * SOLVING_ACTIVE → solver is running
446
+ * NOT_SOLVING / TERMINATED_EARLY → terminal
447
+ */
448
+ type SolveJobStatus = "QUEUED" | "SOLVING_ACTIVE" | "NOT_SOLVING" | "TERMINATED_EARLY";
287
449
  type RuleOverrideEntry = {
288
450
  ruleId: string;
289
451
  parameters?: Record<string, unknown>;
@@ -320,10 +482,16 @@ type SchedulePayload = {
320
482
  timezone?: string;
321
483
  jurisdiction?: string;
322
484
  tags?: string[];
485
+ properties?: Record<string, unknown>;
323
486
  }>;
324
487
  timeOffs?: TimeOff[];
325
488
  ruleIds?: string[];
326
489
  ruleOverrides?: RuleOverrideEntry[];
490
+ /** Hourly traffic forecast problem fact (omit when unused). */
491
+ trafficForecast?: TrafficForecastEntry[];
492
+ constraintDefinitionIds?: string[];
493
+ constraintDefinitions?: unknown[];
494
+ organizationId?: string;
327
495
  };
328
496
  type AutoSchedulerModalConfig = {
329
497
  selectedLocationIds: string[];
@@ -331,6 +499,7 @@ type AutoSchedulerModalConfig = {
331
499
  constraintValues: Record<string, string>;
332
500
  selectedOptimizationIds: string[];
333
501
  optimizationValues: Record<string, string>;
502
+ selectedBuiltinIds?: string[];
334
503
  };
335
504
  type SolveApiExplanation = SolveApiResponse["explanation"];
336
505
  /** Full POST body for the getRecommendationURL API (context, locations, employees, shifts, etc.) */
@@ -374,6 +543,7 @@ type ViolatedConstraintsPanelProps = {
374
543
  };
375
544
  styles?: Record<string, Record<string, unknown>>;
376
545
  styleOverrides?: ViolatedConstraintsPanelStyleOverrides;
546
+ errorToast?: (msg: string) => void;
377
547
  };
378
548
  type SolveApiResponse = {
379
549
  problemId: string;
@@ -400,8 +570,12 @@ type ScheduleRecommendation = {
400
570
  recommendation: string;
401
571
  why_this_resolves_it: string;
402
572
  };
573
+ declare class InfeasibleScheduleError extends Error {
574
+ readonly failure: ViolatedConstraintsResult;
575
+ constructor(failure: ViolatedConstraintsResult);
576
+ }
403
577
 
404
- declare function AutoSchedulerModal({ baseURL, isOpen, title, bannerText, jurisdictions, openShifts, employees, timeOffs, locationPlaceholder, onClose, cancelLabel, primaryActionLabel, onPrimaryAction: _onPrimaryAction, onFixManually, initialConfig, theme, cssVarsRoot, generateRecommendationsURLAndHeaders, getTokenURLAndHeaders, onSolution, getStoredConfigForLocations, persistConfigForLocations, }: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
578
+ declare function AutoSchedulerModal({ displayMode, drawerSize, baseURL, isOpen, title, bannerTitle, bannerText, jurisdictions, openShifts, employees, timeOffs, locationPlaceholder, onClose, cancelLabel, primaryActionLabel, onPrimaryAction: _onPrimaryAction, onFixManually, initialConfig, theme, cssVarsRoot, generateRecommendationsURLAndHeaders, getTokenURLAndHeaders, onSolution, getStoredConfigForLocations, persistConfigForLocations, errorToast, organizationId, constraintDefinitionIds, constraintDefinitions, hardConstraintOptions, softConstraintGroups, optimizationFooter, trafficForecast, builtinConstraintOptions, subLocations, showSubLocations, teams, showTeams, onSelectionChange, onGenerate, onGenerateSolution, solveStatus, scheduleWeekStartYmd, todayCalendarYmd, evaluationTimezone, }: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
405
579
 
406
580
  /**
407
581
  * Self-contained AutoSchedulerModal that wraps itself in ChakraProvider.
@@ -410,11 +584,25 @@ declare function AutoSchedulerModal({ baseURL, isOpen, title, bannerText, jurisd
410
584
  */
411
585
  declare function AutoSchedulerModalWithProvider(props: AutoSchedulerModalProps): react_jsx_runtime.JSX.Element;
412
586
 
413
- declare function ViolatedConstraintsPanel({ violatedConstraints, title, subtitle, showSecondaryButton, secondaryButtonTitle, onSecondaryButtonClick, generateRecommendationsURLAndHeaders, styles: stylesProp, styleOverrides, }: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
587
+ declare function ViolatedConstraintsPanel({ violatedConstraints, title, subtitle, showSecondaryButton, secondaryButtonTitle, onSecondaryButtonClick, generateRecommendationsURLAndHeaders, styles: stylesProp, styleOverrides, errorToast, }: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
414
588
 
415
589
  declare function ViolatedConstraintsPanelWithProvider(props: ViolatedConstraintsPanelProps): react_jsx_runtime.JSX.Element;
416
590
 
417
- declare function buildRulesPayload(selectedConstraintIds: string[], constraintValues: Record<string, string>, selectedOptimizationIds: string[], optimizationValues: Record<string, string>): {
591
+ /** Soft companion for conversion rate silent inject under Maximize Sales / Cost-to-sales. */
592
+ declare const MAXIMIZE_CONVERSION_RATE_RULE_ID = "maximize-conversion-rate";
593
+ /** Soft companion for traffic × sales — silent inject under Maximize Sales only. */
594
+ declare const TRAFFIC_FORECAST_INCENTIVE_RULE_ID = "traffic-forecast-incentive";
595
+ type SiblingRuleOptions = {
596
+ /** Inject maximize-conversion-rate when sales opts are selected. */
597
+ includeConversionRate?: boolean;
598
+ /** Inject traffic-forecast-incentive when Maximize Sales is selected. */
599
+ includeTrafficIncentive?: boolean;
600
+ };
601
+ /**
602
+ * Build ruleIds / ruleOverrides. Sibling Avia-agnostic rules are appended into
603
+ * whichever structure is returned (Maximize Sales forces the overrides path).
604
+ */
605
+ declare function buildRulesPayload(selectedConstraintIds: string[], constraintValues: Record<string, string>, selectedOptimizationIds: string[], optimizationValues: Record<string, string>, siblings?: SiblingRuleOptions): {
418
606
  ruleIds?: string[];
419
607
  ruleOverrides?: RuleOverrideEntry[];
420
608
  };
@@ -428,6 +616,10 @@ type BuildSchedulePayloadInput = {
428
616
  constraintValues: Record<string, string>;
429
617
  selectedOptimizationIds: string[];
430
618
  optimizationValues: Record<string, string>;
619
+ trafficForecast?: TrafficForecastEntry[];
620
+ constraintDefinitionIds?: string[];
621
+ constraintDefinitions?: unknown[];
622
+ organizationId?: string;
431
623
  };
432
624
  declare function buildSchedulePayload(input: BuildSchedulePayloadInput): SchedulePayload;
433
625
 
@@ -437,4 +629,11 @@ declare function buildSchedulePayload(input: BuildSchedulePayloadInput): Schedul
437
629
  */
438
630
  declare function getFriendlyRuleName(ruleIdOrConstraintName: string): string;
439
631
 
440
- export { AutoSchedulerModal, type AutoSchedulerModalConfig, type AutoSchedulerModalProps, type AutoSchedulerModalStyleOverrides, type AutoSchedulerModalTheme, AutoSchedulerModalWithProvider, type BuildSchedulePayloadInput, type EasyTeamThemeOverrides, type Employee, type EmployeeProperties, type JurisdictionGroup, type LocationOption, type OpenShift, type RecommendationPayload, RequestError, type RuleOverrideEntry, type SchedulePayload, type ScheduleRecommendation, type ScheduleSolution, type ScheduleSolutionAvailability, type ScheduleSolutionEmployee, type ScheduleSolutionLocation, type ScheduleSolutionRuleMetadata, type ScheduleSolutionRuleOverride, type ScheduleSolutionShift, type ScheduleSolutionShiftAssignment, type ScheduleSolutionTimeOff, type ScheduleSolutionWaiver, type Screen, type ShiftAssignmentJustification, type SolveApiExplanation, type SolveApiResponse, type StepStatus, type TimeOff, ViolatedConstraintsPanel, type ViolatedConstraintsPanelProps, type ViolatedConstraintsPanelStyleOverrides, ViolatedConstraintsPanelWithProvider, type ViolatedConstraintsResult, buildRulesPayload, buildSchedulePayload, getFriendlyRuleName };
632
+ /** Seven consecutive calendar days starting at `weekStartYmd` (already aligned to org week start). */
633
+ declare function getSequentialWeekDatesFromWeekStart(weekStartYmd: string): string[];
634
+ /** Calendar-day weekday chip Su … Sa following JS getDay() order (0 = Sun). */
635
+ declare function weekdayTwoLetterFromYmd(ymd: string): string;
636
+ /** Defaults to all week dates strictly on or after `todayYmd` (ISO date string compare). */
637
+ declare function defaultSelectedScheduleDates(orderedWeekYmds: string[], todayYmd: string): string[];
638
+
639
+ export { AutoSchedulerModal, type AutoSchedulerModalConfig, type AutoSchedulerModalProps, type AutoSchedulerModalStyleOverrides, type AutoSchedulerModalTheme, AutoSchedulerModalWithProvider, type BuildSchedulePayloadInput, type BuiltinConstraintOption, type EasyTeamThemeOverrides, type Employee, type EmployeeProperties, type GenerateScheduleConfig, type HardConstraintOption, InfeasibleScheduleError, type JurisdictionGroup, type LocationOption, MAXIMIZE_CONVERSION_RATE_RULE_ID, type OpenShift, type RecommendationPayload, RequestError, type RuleOverrideEntry, type SchedulePayload, type ScheduleRecommendation, type ScheduleSolution, type ScheduleSolutionAvailability, type ScheduleSolutionEmployee, type ScheduleSolutionLocation, type ScheduleSolutionRuleMetadata, type ScheduleSolutionRuleOverride, type ScheduleSolutionShift, type ScheduleSolutionShiftAssignment, type ScheduleSolutionTimeOff, type ScheduleSolutionWaiver, type Screen, type ShiftAssignmentJustification, type SiblingRuleOptions, type SoftConstraintGroup, type SoftConstraintOption, type SolveApiExplanation, type SolveApiResponse, type SolveJobStatus, type StepStatus, type SubLocationOption, TRAFFIC_FORECAST_INCENTIVE_RULE_ID, type TeamOption, type TimeOff, type TrafficForecastEntry, ViolatedConstraintsPanel, type ViolatedConstraintsPanelProps, type ViolatedConstraintsPanelStyleOverrides, ViolatedConstraintsPanelWithProvider, type ViolatedConstraintsResult, buildRulesPayload, buildSchedulePayload, defaultSelectedScheduleDates, getFriendlyRuleName, getSequentialWeekDatesFromWeekStart, weekdayTwoLetterFromYmd };