Skip to content

Improve scheduling algorithm #3126

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

datnguyen-en
Copy link
Collaborator

@datnguyen-en datnguyen-en commented Jun 19, 2025

Summary by CodeRabbit

  • New Features

    • Introduced support for "locked events" in the scheduler, allowing users to mark time blocks as unavailable and manage them via a dedicated interface.
    • Added a lock icon and blue styling to visually distinguish locked events in the schedule.
    • Implemented a toggle to enable or disable task splitting, both in the task list and task creation modal.
    • Enhanced task creation modal with a new layout and an "Allow split" switch, along with improved duration input grouping and descriptions.
  • Improvements

    • Scheduling algorithm now respects locked events and supports splitting eligible tasks into multiple sessions based on user preferences.
    • Updated sample tasks and templates to specify whether splitting is allowed.
  • Bug Fixes

    • Improved handling of scheduling constraints for non-splittable tasks, ensuring correct placement or reporting if unschedulable.
  • Tests

    • Expanded test coverage for scheduling logic, including scenarios for task splitting and locked events.

Copy link

graphite-app bot commented Jun 19, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

Copy link
Contributor

coderabbitai bot commented Jun 19, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This update introduces support for locked events and task splitting within the scheduling application. It modifies the scheduling algorithm, UI components, and data types to handle locked events, allow marking tasks as splittable, and visually distinguish locked events. The changes include new UI controls, updated scheduling logic, and expanded test coverage.

Changes

Files/Paths Change Summary
apps/calendar/src/app/[locale]/(root)/scheduler/components/ScheduleDisplay.tsx Added handling for a locked property on events, including dynamic styling and a lock icon with tooltip for locked events.
apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskList.tsx Introduced a toggle switch for each task to enable or disable the allowSplit property, with a tooltip explaining its purpose.
apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx Refactored to add an allowSplit field to the form, reorganized layout into two columns, updated duration input grouping, and added a toggle switch for splitting tasks.
apps/calendar/src/app/[locale]/(root)/scheduler/page.tsx Added support for managing locked events, including state, modal UI for adding/removing, and integration with scheduling.
packages/ai/src/scheduling/algorithm.test.ts Expanded test suite with cases for non-splittable and splittable tasks, verifying scheduling and error logging.
packages/ai/src/scheduling/algorithm.ts Refactored scheduling logic to support locked events, task splitting, iterative scheduling, and improved logging. Updated function signature to accept locked events.
packages/ai/src/scheduling/default.ts Added allowSplit: true to the default task object.
packages/ai/src/scheduling/templates.ts Added allowSplit property to all template scenario tasks, set appropriately for each scenario.
packages/ai/src/scheduling/types.ts Added locked?: boolean to Event and allowSplit?: boolean to Task interfaces.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SchedulerPage
    participant LockedEventForm
    participant SchedulingAlgorithm

    User->>SchedulerPage: Open "Add Locked Event" modal
    SchedulerPage->>LockedEventForm: Render form
    User->>LockedEventForm: Submit locked event details
    LockedEventForm->>SchedulerPage: Add locked event to state
    User->>SchedulerPage: Click "Schedule"
    SchedulerPage->>SchedulingAlgorithm: Call scheduleTasks(tasks, activeHours, lockedEvents)
    SchedulingAlgorithm->>SchedulerPage: Return schedule including locked events
    SchedulerPage->>User: Display schedule with locked events visually distinguished
Loading
sequenceDiagram
    participant User
    participant TaskModal
    participant SchedulerPage
    participant SchedulingAlgorithm

    User->>TaskModal: Open "Add Task" modal
    TaskModal->>User: Show "Allow split" toggle
    User->>TaskModal: Set allowSplit and submit
    TaskModal->>SchedulerPage: Add task with allowSplit property
    User->>SchedulerPage: Click "Schedule"
    SchedulerPage->>SchedulingAlgorithm: Call scheduleTasks(tasks with allowSplit)
    SchedulingAlgorithm->>SchedulerPage: Return scheduled events (split if allowed)
    SchedulerPage->>User: Display scheduled tasks (split as needed)
Loading

Possibly related PRs

  • Add scheduling algorithm #3062: Introduced the foundational scheduling algorithm and types, which are extended and refined in this PR to support locked events and task splitting.

Suggested labels

enhancement, calendar

Suggested reviewers

  • vhpx

Poem

In the warren where calendars grow,
Rabbits hop and locked events show.
Tasks now split, or stay whole,
Schedules dance, and time’s in control.
With toggles and locks,
We hop through the blocks—
A bunny’s delight in every scroll! 🐇⏰

✨ Finishing Touches
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch feat/Enhance-Schedule-Algorithm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @datnguyen-en, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the scheduling functionality by introducing the ability to define and manage 'locked events' that the scheduler must respect, and by providing granular control over whether individual tasks can be split into multiple sessions. These changes improve the flexibility and realism of the scheduling algorithm, supported by corresponding updates to the user interface for task management and event display.

Highlights

  • Core Scheduling Algorithm Enhancement: The scheduleTasks algorithm now supports 'locked events' which are pre-existing, unmovable time blocks that the scheduler must work around. It also introduces a new allowSplit property for tasks, enabling tasks to be scheduled either as a single continuous block or split into multiple sessions based on user preference.
  • User Interface for Locked Events: A new section and modal have been added to the scheduler page allowing users to define and manage 'locked events' directly within the UI. These events are visually represented in the schedule display with a lock icon and specific styling.
  • Task Splittability Control: The task creation/editing modal and the task list display now include a toggle to control whether a task can be split into multiple sessions. This allowSplit property is integrated into the task data model.
  • Improved Scheduling Logic: The algorithm has been refined to handle minimum and maximum duration constraints more effectively for both splittable and non-splittable tasks, including better handling of deadlines and logging of scheduling outcomes (e.g., tasks split, tasks unscheduled).
  • New Test Cases: Comprehensive unit tests have been added for the schedule function to validate the new allowSplit functionality, ensuring non-splittable tasks are scheduled correctly and splittable tasks are split when necessary.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces 'locked events' and 'task splitting control' (allowSplit). The UI has been updated, and the core scheduling algorithm has been refactored to accommodate these new constraints. Overall, the changes are well-implemented and enhance the scheduler's capabilities.

</div>
<div>
<Label>Category</Label>
<Select value={category} onValueChange={(v) => setCategory(v as any)}>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The type assertion v as any for setting the category should be avoided for better type safety. Validate the value before casting.

Comment on lines +229 to +233
event.locked
? 'border-dynamic-blue/30 bg-dynamic-blue/10'
: event.isPastDeadline
? 'border-destructive/30 bg-destructive/5'
: 'hover:bg-accent/5'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The conditional logic for className is becoming complex. Consider extracting this logic into a helper function or using a utility like clsx to improve readability.

<SplitIcon className="h-4 w-4 text-primary" />
<Switch
id={`split-toggle-${task.id}`}
checked={task.allowSplit ?? true}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The default value for task.allowSplit is true using the nullish coalescing operator (??). This is a good default, making tasks splittable unless explicitly set otherwise.

Comment on lines +109 to +111
id: `locked-${Date.now()}`,
locked: true,
taskId: 'locked',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using taskId: 'locked' for locked events might lead to confusion if taskId is generally expected to be an ID of an actual task. Consider using null or undefined.

Comment on lines +217 to +222
<button
className="ml-auto rounded bg-dynamic-blue px-3 py-1 text-xs text-white transition hover:bg-dynamic-blue/80"
onClick={() => setIsLockedEventModalOpen(true)}
>
Add Locked Event
</button>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consider replacing the button element with the imported Button component from @tuturuuu/ui/button for consistency.

<Button
  variant="outline"
  className="ml-auto bg-dynamic-blue px-3 py-1 text-xs text-white transition hover:bg-dynamic-blue/80"
  onClick={() => setIsLockedEventModalOpen(true)}
>
  Add Locked Event
</Button>

Comment on lines +52 to +56
// Start with locked events in the schedule
const scheduledEvents: Event[] = lockedEvents.map((e) => ({
...e,
locked: true,
}));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Initializing scheduledEvents with lockedEvents ensures these events are respected by the algorithm from the start. Marking them with locked: true is also clear.

Comment on lines +59 to +68
// Prepare a working pool of tasks with remaining duration
const taskPool = tasks.map((task) => ({
...task,
duration: hoursToQuarterHours(task.duration),
minDuration: ensureMinimumDuration(task.minDuration),
maxDuration: hoursToQuarterHours(task.maxDuration),
remaining: hoursToQuarterHours(task.duration),
nextPart: 1,
scheduledParts: 0,
}));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The creation of taskPool with pre-calculated quarter-hour durations and tracking properties is a good refactoring, centralizing task state management.

Comment on lines +106 to 163
// Non-splittable: try to schedule as a single block
if (task.allowSplit === false) {
if (task.scheduledParts > 0) continue; // Already tried
let scheduled = false;
let tryTime = availableTimes[task.category];
let blockAttempts = 0;
while (!scheduled && blockAttempts < 50) {
blockAttempts++;
const availableSlots = getAvailableSlots(
tryTime,
categoryHours,
scheduledEvents
);
const slot = availableSlots.find((slot) => {
const slotDuration = slot.end.diff(slot.start, 'hour', true);
return slotDuration >= task.duration;
});
if (slot) {
const partStart = roundToQuarterHour(slot.start, false);
const partEnd = partStart.add(task.duration, 'hour');
const newEvent: Event = {
id: `event-${task.id}`,
name: task.name,
range: { start: partStart, end: partEnd },
isPastDeadline: false,
taskId: task.id,
};
if (task.deadline && partEnd.isAfter(task.deadline)) {
newEvent.isPastDeadline = true;
logs.push({
type: 'warning',
message: `Task "${task.name}" is scheduled past its deadline of ${task.deadline.format('YYYY-MM-DD HH:mm')}.`,
});
}
scheduledEvents.push(newEvent);
availableTimes[task.category] = roundToQuarterHour(partEnd, true);
scheduled = true;
task.remaining = 0;
task.scheduledParts = 1;
anyScheduled = true;
} else {
tryTime = tryTime.add(1, 'day').startOf('day');
tryTime = getNextAvailableTime(categoryHours, tryTime);
logs.push({
type: 'warning',
message: `Moving task "${task.name}" to ${tryTime.format('YYYY-MM-DD')} due to lack of available time slots for non-splittable task.`,
});
}
}
if (!scheduled) {
logs.push({
type: 'error',
message: `Task "${task.name}" could not be scheduled as a single block after 50 attempts.`,
});
task.remaining = 0;
}
continue;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for handling non-splittable tasks (task.allowSplit === false) is well-defined, ensuring that non-splittable tasks are either scheduled whole or not at all.

Comment on lines +165 to 280
logs.push({
type: 'error',
message: `Cannot fit minimum duration for task "${task.name}" part ${task.nextPart}.`,
});
task.remaining = 0;
break;
}
partDuration = hoursToQuarterHours(adjustedDuration);
}
const finalPartEnd = partStart.add(partDuration, 'hour');
// If this part would end after the deadline, skip scheduling
if (task.deadline && finalPartEnd.isAfter(task.deadline)) {
logs.push({
type: 'warning',
message: `Cannot schedule remaining ${remainingDuration}h of task "${task.name}" due to minimum duration constraint (${adjustedTask.minDuration}h).`,
message: `Cannot schedule part of task "${task.name}" because it would end after the deadline (${task.deadline.format('YYYY-MM-DD HH:mm')}). Skipping remaining duration.`,
});
task.remaining = 0;
break;
}
}

// Ensure the part start time is rounded to 15-minute increment
const partStart = roundToQuarterHour(slot.start, false);
const partEnd = partStart.add(partDuration, 'hour');

// Verify the end time doesn't exceed the slot
if (partEnd.isAfter(slot.end)) {
const adjustedDuration = slot.end.diff(partStart, 'hour', true);

if (adjustedDuration < adjustedTask.minDuration) {
const totalParts = Math.ceil(task.duration / task.maxDuration);
const newEvent: Event = {
id: `event-${task.id}-part-${task.nextPart}`,
name:
totalParts > 1
? `${task.name} (Part ${task.nextPart}/${totalParts})`
: task.name,
range: { start: partStart, end: finalPartEnd },
isPastDeadline: false,
taskId: task.id,
partNumber: totalParts > 1 ? task.nextPart : undefined,
totalParts: totalParts > 1 ? totalParts : undefined,
};
if (task.deadline && finalPartEnd.isAfter(task.deadline)) {
newEvent.isPastDeadline = true;
logs.push({
type: 'error',
message: `Cannot fit minimum duration for task "${task.name}" part ${partNumber}.`,
type: 'warning',
message: `Part ${task.nextPart} of task "${task.name}" is scheduled past its deadline of ${task.deadline.format('YYYY-MM-DD HH:mm')}.`,
});
break;
}

partDuration = hoursToQuarterHours(adjustedDuration);
scheduledEvents.push(newEvent);
tryTime = roundToQuarterHour(finalPartEnd, true);
availableTimes[task.category] = tryTime;
task.remaining -= partDuration;
task.scheduledParts++;
task.nextPart++;
anyScheduled = true;
scheduledPart = true;
}

const finalPartEnd = partStart.add(partDuration, 'hour');
const totalParts = Math.ceil(
adjustedTask.duration / adjustedTask.maxDuration
);

const newEvent: Event = {
id: `event-${task.id}-part-${partNumber}`,
name:
totalParts > 1
? `${task.name} (Part ${partNumber}/${totalParts})`
: task.name,
range: { start: partStart, end: finalPartEnd },
isPastDeadline: false,
taskId: task.id,
partNumber: totalParts > 1 ? partNumber : undefined,
totalParts: totalParts > 1 ? totalParts : undefined,
};

// Check if this part is past the deadline
if (task.deadline && finalPartEnd.isAfter(task.deadline)) {
newEvent.isPastDeadline = true;
logs.push({
type: 'warning',
message: `Part ${partNumber} of task "${task.name}" is scheduled past its deadline of ${task.deadline.format('YYYY-MM-DD HH:mm')}.`,
});
}

taskParts.push(newEvent);
scheduledEvents.push(newEvent);

remainingDuration -= partDuration;
availableTimes[task.category] = roundToQuarterHour(finalPartEnd, true);
partNumber++;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for splittable tasks is comprehensive, correctly considering minDuration, maxDuration, and task deadlines. Filtering availableSlots by deadline is a crucial improvement.

Comment on lines +251 to +262
const totalParts = Math.ceil(task.duration / task.maxDuration);
const newEvent: Event = {
id: `event-${task.id}-part-${task.nextPart}`,
name:
totalParts > 1
? `${task.name} (Part ${task.nextPart}/${totalParts})`
: task.name,
range: { start: partStart, end: finalPartEnd },
isPastDeadline: false,
taskId: task.id,
partNumber: totalParts > 1 ? task.nextPart : undefined,
totalParts: totalParts > 1 ? totalParts : undefined,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calculating totalParts using Math.ceil(task.duration / task.maxDuration) is correct for determining how many parts a task might be split into, enhancing clarity for the user.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/ai/src/scheduling/templates.ts (1)

89-126: Consider adding allowSplit property consistently across all scenarios.

Several template scenarios don't define the allowSplit property. While this is valid since the property is optional, it creates inconsistency and could lead to unclear behavior expectations.

Consider adding explicit allowSplit values to all tasks for consistency:

 {
   id: 'mixed-1',
   name: 'Team Meeting',
   duration: 1,
   minDuration: 1,
   maxDuration: 1.5,
   category: 'meeting',
   events: [],
+  allowSplit: false,
 },

Also applies to: 141-171, 185-223, 237-256, 271-311, 327-366, 380-417, 432-478, 494-531, 547-583, 599-636, 650-688, 704-741

apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskList.tsx (1)

250-272: LGTM: Well-implemented allowSplit toggle with good UX.

The toggle switch implementation is excellent with proper tooltip, accessibility considerations, and clean integration into the task header. The callback handling correctly updates the task state.

Consider whether defaulting to true with task.allowSplit ?? true is appropriate, as some template scenarios explicitly set this to false. You might want to use a more conservative default or make it explicit:

- checked={task.allowSplit ?? true}
+ checked={task.allowSplit ?? false}
apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx (1)

23-23: Remove unused import.

The Separator component is imported but never used in the component.

-import { Separator } from '@tuturuuu/ui/separator';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 349ce4d and 6ebaf55.

📒 Files selected for processing (9)
  • apps/calendar/src/app/[locale]/(root)/scheduler/components/ScheduleDisplay.tsx (2 hunks)
  • apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskList.tsx (3 hunks)
  • apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx (6 hunks)
  • apps/calendar/src/app/[locale]/(root)/scheduler/page.tsx (7 hunks)
  • packages/ai/src/scheduling/algorithm.test.ts (1 hunks)
  • packages/ai/src/scheduling/algorithm.ts (2 hunks)
  • packages/ai/src/scheduling/default.ts (1 hunks)
  • packages/ai/src/scheduling/templates.ts (6 hunks)
  • packages/ai/src/scheduling/types.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
packages/ai/src/scheduling/algorithm.ts (2)
packages/ai/src/scheduling/types.ts (4)
  • ActiveHours (31-35)
  • Event (8-17)
  • ScheduleResult (42-45)
  • Log (37-40)
packages/ai/src/scheduling/default.ts (1)
  • defaultActiveHours (4-23)
packages/ai/src/scheduling/algorithm.test.ts (2)
packages/ai/src/scheduling/algorithm.ts (1)
  • scheduleTasks (47-303)
packages/ai/src/scheduling/default.ts (1)
  • defaultActiveHours (4-23)
apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx (3)
packages/ui/src/components/ui/dialog.tsx (2)
  • DialogContent (134-134)
  • DialogFooter (136-136)
packages/ui/src/components/ui/textarea.tsx (1)
  • Textarea (17-17)
packages/ui/src/components/ui/select.tsx (5)
  • Select (170-170)
  • SelectTrigger (178-178)
  • SelectValue (179-179)
  • SelectContent (171-171)
  • SelectItem (173-173)
🪛 GitHub Actions: Vercel Calendar Preview Deployment
apps/calendar/src/app/[locale]/(root)/scheduler/page.tsx

[error] 490-490: ESLint: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any)

apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx

[error] 23-23: ESLint: 'Separator' is defined but never used. (@typescript-eslint/no-unused-vars)

🪛 GitHub Check: Run tests and collect coverage
packages/ai/src/scheduling/algorithm.test.ts

[failure] 217-217: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should split a task if allowSplit is true or undefined and needed
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:217:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }


[failure] 198-198: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should not schedule a non-splittable task if no single block is available
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:198:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }


[failure] 178-178: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should schedule a non-splittable task as a single block if possible
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:178:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }

🪛 GitHub Actions: Run tests and upload coverage
packages/ai/src/scheduling/algorithm.test.ts

[error] 178-217: Scheduling Algorithm test failures: Cannot find module './algorithm' causing 3 test failures in schedule function tests.

⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Prettier Check (23)
  • GitHub Check: Deploy-Preview
  • GitHub Check: Deploy-Preview
  • GitHub Check: Deploy-Preview
  • GitHub Check: Deploy-Preview
  • GitHub Check: Deploy-Preview
  • GitHub Check: Verify generated types
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Deploy-Preview
  • GitHub Check: Deploy-Preview
🔇 Additional comments (26)
packages/ai/src/scheduling/default.ts (1)

34-34: LGTM: Clean addition of allowSplit property.

The addition of allowSplit: true to the default task is well-implemented and aligns with the new task splitting functionality.

packages/ai/src/scheduling/templates.ts (2)

17-17: LGTM: Appropriate allowSplit values for Basic Work Day scenario.

Setting allowSplit: false for Basic Work Day tasks is logical as these represent focused, non-splittable activities like standups and meetings.

Also applies to: 27-27, 37-37


53-53: LGTM: Correct allowSplit configuration for splitting scenario.

Setting allowSplit: true for Task Splitting Challenge tasks is appropriate as this scenario is specifically designed to test task splitting functionality.

Also applies to: 63-63, 73-73

packages/ai/src/scheduling/types.ts (2)

16-16: LGTM: Well-designed optional locked property.

The locked?: boolean property is appropriately optional and clearly indicates its purpose for marking events as non-reschedulable.


28-28: LGTM: Clean allowSplit property addition.

The allowSplit?: boolean property follows good TypeScript practices by being optional and maintaining backward compatibility.

apps/calendar/src/app/[locale]/(root)/scheduler/components/ScheduleDisplay.tsx (3)

16-16: LGTM: Appropriate icon import.

The LockIcon import is correctly added to support the new locked event visualization.


229-234: LGTM: Well-structured conditional styling.

The conditional styling logic properly prioritizes locked events over past deadline styling, with appropriate blue theming for locked events.


240-251: LGTM: Excellent user experience with lock icon and tooltip.

The lock icon with descriptive tooltip provides clear visual feedback for locked events. The conditional rendering and accessibility considerations are well-implemented.

apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskList.tsx (1)

21-21: LGTM: Correct UI component imports.

The SplitIcon and Switch imports are properly added to support the new allowSplit toggle functionality.

Also applies to: 32-32

apps/calendar/src/app/[locale]/(root)/scheduler/page.tsx (5)

59-60: Well-implemented state management for locked events.

The addition of locked events state variables follows the existing pattern and integrates well with the component's state management.


104-118: Clean implementation of locked event management functions.

Both addLockedEvent and deleteLockedEvent functions follow good practices:

  • Proper event structure with required fields
  • Consistent ID generation pattern
  • Immutable state updates

125-126: Correct integration of locked events into scheduling.

The updated handleSchedule function properly passes locked events to the scheduling algorithm, maintaining the expected function signature.


212-251: Excellent UI implementation for locked events management.

The locked events section provides:

  • Clear visual indicators with lock icons
  • Intuitive add/remove functionality
  • Proper styling that distinguishes locked events
  • Good user experience with empty state handling

428-536: Well-structured LockedEventForm component with proper validation.

The form implementation includes:

  • Comprehensive form validation
  • Good error handling and user feedback
  • Proper date/time constraints
  • Clean separation of concerns

The validation logic correctly prevents past dates and invalid time ranges.

apps/calendar/src/app/[locale]/(root)/scheduler/components/TaskModal.tsx (3)

67-67: Good integration of allowSplit property.

The addition of allowSplit to the form state with a sensible default value of true aligns well with the scheduling algorithm's expectations.


144-149: Properly typed updateFormData function.

The function signature correctly accepts boolean values alongside string and number types, enabling proper type safety for the allowSplit toggle.


153-340: Excellent UI restructure with improved user experience.

The two-column layout significantly improves the modal's organization:

  • Left column: Basic task information (name, description, category, deadline)
  • Right column: Technical constraints (duration settings, split toggle)
  • Proper spacing and visual hierarchy
  • Clear labeling and help text for duration semantics

The allowSplit toggle is well-integrated with appropriate icons and explanatory text.

packages/ai/src/scheduling/algorithm.ts (9)

49-56: Excellent addition of locked events support.

The function signature update and initialization of locked events in the schedule provides a solid foundation for respecting pre-existing commitments during scheduling.


60-68: Well-designed task pool architecture.

The normalization of tasks to quarter-hour increments and addition of tracking metadata (remaining, nextPart, scheduledParts) enables sophisticated multi-part scheduling while maintaining data integrity.


87-89: Good safeguard against infinite loops.

The attempt counter with a reasonable maximum (2000) prevents infinite loops while allowing sufficient iterations for complex scheduling scenarios.


107-163: Robust non-splittable task scheduling logic.

The implementation correctly:

  • Attempts to find single continuous blocks for non-splittable tasks
  • Includes multiple retry attempts with different start times
  • Provides appropriate error logging when scheduling fails
  • Respects deadline constraints

176-182: Smart deadline filtering for splittable tasks.

The deadline-aware slot filtering prevents scheduling parts that would extend beyond task deadlines, maintaining scheduling integrity.


202-226: Sophisticated duration constraint handling.

The logic for handling minimum duration constraints when remaining time is small is well thought out:

  • Attempts to extend duration to meet minimum requirements
  • Falls back gracefully when constraints cannot be satisfied
  • Provides clear warning messages

251-263: Intelligent part naming and metadata.

The dynamic calculation of total parts and conditional part numbering creates clear event names while avoiding unnecessary part numbers for tasks that don't actually get split.


283-284: Important deadlock prevention.

The check for anyScheduled prevents infinite loops when no progress can be made, ensuring the algorithm terminates gracefully even in complex scheduling scenarios.


287-300: Comprehensive logging and reporting.

The final logging phase provides valuable feedback about:

  • Tasks that were split into multiple parts
  • Tasks that couldn't be fully scheduled
  • Clear quantification of remaining unscheduled time

This will be very helpful for users to understand scheduling decisions.

Comment on lines 197 to 214
it('should not schedule a non-splittable task if no single block is available', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'single-block-fail',
name: 'Non-splittable Task',
duration: 10, // longer than any available slot
minDuration: 1,
maxDuration: 10,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(0);
expect(result.logs.some((log: any) => log.type === 'error')).toBe(true);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Apply the same import fix and improve test assertion.

The same module import issue exists here. Additionally, the error log assertion could be more specific.

-    it('should not schedule a non-splittable task if no single block is available', () => {
-      const { scheduleTasks } = require('./algorithm');
+    it('should not schedule a non-splittable task if no single block is available', async () => {
+      const { scheduleTasks } = await import('./algorithm');
       const tasks = [
         {
           id: 'single-block-fail',
           name: 'Non-splittable Task',
           duration: 10, // longer than any available slot
           minDuration: 1,
           maxDuration: 10,
           category: 'work',
           events: [],
           allowSplit: false,
         },
       ];
       const result = scheduleTasks(tasks, defaultActiveHours);
       expect(result.events.length).toBe(0);
-      expect(result.logs.some((log: any) => log.type === 'error')).toBe(true);
+      expect(result.logs.some((log) => log.type === 'error' && log.message.includes('could not be scheduled as a single block'))).toBe(true);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should not schedule a non-splittable task if no single block is available', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'single-block-fail',
name: 'Non-splittable Task',
duration: 10, // longer than any available slot
minDuration: 1,
maxDuration: 10,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(0);
expect(result.logs.some((log: any) => log.type === 'error')).toBe(true);
});
it('should not schedule a non-splittable task if no single block is available', async () => {
const { scheduleTasks } = await import('./algorithm');
const tasks = [
{
id: 'single-block-fail',
name: 'Non-splittable Task',
duration: 10, // longer than any available slot
minDuration: 1,
maxDuration: 10,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(0);
expect(
result.logs.some(
(log) =>
log.type === 'error' &&
log.message.includes('could not be scheduled as a single block')
)
).toBe(true);
});
🧰 Tools
🪛 GitHub Check: Run tests and collect coverage

[failure] 198-198: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should not schedule a non-splittable task if no single block is available
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:198:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }

🤖 Prompt for AI Agents
In packages/ai/src/scheduling/algorithm.test.ts around lines 197 to 214, the
test imports the scheduleTasks function inside the test case, which is
inconsistent with best practices. Move the import statement for scheduleTasks to
the top of the file to ensure it is imported once. Also, improve the error log
assertion by checking for a specific error message or error type in the logs
array instead of just verifying the presence of any error type, making the test
more precise.

Comment on lines 216 to 233
it('should split a task if allowSplit is true or undefined and needed', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'splittable',
name: 'Splittable Task',
duration: 6,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: true,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBeGreaterThan(1);
expect(result.events[0].name).toContain('Part 1');
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix import and enhance splittable task test validation.

Same import issue plus the test could validate more aspects of task splitting behavior.

-    it('should split a task if allowSplit is true or undefined and needed', () => {
-      const { scheduleTasks } = require('./algorithm');
+    it('should split a task if allowSplit is true or undefined and needed', async () => {
+      const { scheduleTasks } = await import('./algorithm');
       const tasks = [
         {
           id: 'splittable',
           name: 'Splittable Task',
           duration: 6,
           minDuration: 1,
           maxDuration: 2,
           category: 'work',
           events: [],
           allowSplit: true,
         },
       ];
       const result = scheduleTasks(tasks, defaultActiveHours);
       expect(result.events.length).toBeGreaterThan(1);
       expect(result.events[0].name).toContain('Part 1');
+      // Validate that all parts belong to the same task
+      expect(result.events.every(event => event.taskId === 'splittable')).toBe(true);
+      // Validate total scheduled duration doesn't exceed task duration
+      const totalScheduled = result.events.reduce((sum, event) => 
+        sum + event.range.end.diff(event.range.start, 'hour', true), 0);
+      expect(totalScheduled).toBeLessThanOrEqual(6);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should split a task if allowSplit is true or undefined and needed', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'splittable',
name: 'Splittable Task',
duration: 6,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: true,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBeGreaterThan(1);
expect(result.events[0].name).toContain('Part 1');
});
it('should split a task if allowSplit is true or undefined and needed', async () => {
const { scheduleTasks } = await import('./algorithm');
const tasks = [
{
id: 'splittable',
name: 'Splittable Task',
duration: 6,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: true,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBeGreaterThan(1);
expect(result.events[0].name).toContain('Part 1');
// Validate that all parts belong to the same task
expect(result.events.every(event => event.taskId === 'splittable')).toBe(true);
// Validate total scheduled duration doesn't exceed task duration
const totalScheduled = result.events.reduce((sum, event) =>
sum + event.range.end.diff(event.range.start, 'hour', true), 0);
expect(totalScheduled).toBeLessThanOrEqual(6);
});
🧰 Tools
🪛 GitHub Check: Run tests and collect coverage

[failure] 217-217: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should split a task if allowSplit is true or undefined and needed
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:217:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }

🤖 Prompt for AI Agents
In packages/ai/src/scheduling/algorithm.test.ts around lines 216 to 233, fix the
import of scheduleTasks by using an ES module import statement at the top
instead of requiring it inside the test. Enhance the test by adding assertions
to verify that all split parts have durations within minDuration and
maxDuration, and that the total duration equals the original task duration,
ensuring the splitting logic is correctly validated.

Comment on lines 177 to 195
it('should schedule a non-splittable task as a single block if possible', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'single-block',
name: 'Non-splittable Task',
duration: 2,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(1);
expect(result.events[0].name).toBe('Non-splittable Task');
expect(result.events[0].partNumber).toBeUndefined();
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix module import issue and use consistent import syntax.

The test is failing because it cannot find the './algorithm' module. Use ES6 import syntax consistently with the rest of the file instead of require().

-    it('should schedule a non-splittable task as a single block if possible', () => {
-      const { scheduleTasks } = require('./algorithm');
+    it('should schedule a non-splittable task as a single block if possible', async () => {
+      const { scheduleTasks } = await import('./algorithm');

Alternatively, add the import at the top of the file:

+import { scheduleTasks } from './algorithm';
 import { defaultActiveHours, defaultTasks } from './default';
 import dayjs from 'dayjs';
 import { describe, expect, it } from 'vitest';

Then remove the require statements from individual tests.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should schedule a non-splittable task as a single block if possible', () => {
const { scheduleTasks } = require('./algorithm');
const tasks = [
{
id: 'single-block',
name: 'Non-splittable Task',
duration: 2,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(1);
expect(result.events[0].name).toBe('Non-splittable Task');
expect(result.events[0].partNumber).toBeUndefined();
});
it('should schedule a non-splittable task as a single block if possible', async () => {
const { scheduleTasks } = await import('./algorithm');
const tasks = [
{
id: 'single-block',
name: 'Non-splittable Task',
duration: 2,
minDuration: 1,
maxDuration: 2,
category: 'work',
events: [],
allowSplit: false,
},
];
const result = scheduleTasks(tasks, defaultActiveHours);
expect(result.events.length).toBe(1);
expect(result.events[0].name).toBe('Non-splittable Task');
expect(result.events[0].partNumber).toBeUndefined();
});
🧰 Tools
🪛 GitHub Check: Run tests and collect coverage

[failure] 178-178: src/scheduling/algorithm.test.ts > Scheduling Algorithm > schedule function > should schedule a non-splittable task as a single block if possible
Error: Cannot find module './algorithm'
Require stack:

  • /home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts
    ❯ src/scheduling/algorithm.test.ts:178:33

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 'MODULE_NOT_FOUND', requireStack: [ '/home/runner/work/platform/platform/packages/ai/src/scheduling/algorithm.test.ts' ] }

🤖 Prompt for AI Agents
In packages/ai/src/scheduling/algorithm.test.ts around lines 177 to 195, replace
the require('./algorithm') call inside the test with a consistent ES6 import
statement at the top of the file. Import scheduleTasks using `import {
scheduleTasks } from './algorithm';` and remove the require statement from the
test to fix the module import issue and ensure consistent import syntax
throughout the file.

</div>
<div>
<Label>Category</Label>
<Select value={category} onValueChange={(v) => setCategory(v as any)}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace explicit 'any' type with proper typing.

ESLint is correctly flagging the use of any. Use the proper union type instead.

-          <Select value={category} onValueChange={(v) => setCategory(v as any)}>
+          <Select value={category} onValueChange={(v) => setCategory(v as 'work' | 'personal' | 'meeting')}>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Select value={category} onValueChange={(v) => setCategory(v as any)}>
<Select value={category} onValueChange={(v) => setCategory(v as 'work' | 'personal' | 'meeting')}>
🧰 Tools
🪛 GitHub Actions: Vercel Calendar Preview Deployment

[error] 490-490: ESLint: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any)

🤖 Prompt for AI Agents
In apps/calendar/src/app/[locale]/(root)/scheduler/page.tsx at line 490, the use
of 'any' in the type assertion for setCategory is flagged by ESLint. Replace
'any' with the correct union type that matches the expected values for category,
ensuring type safety and compliance with linting rules.

@vhpx vhpx changed the title optimize algo for scheduling Improve scheduling algorithm Jun 19, 2025
Copy link
Member

@vhpx vhpx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix all CI/CD errors before changing to ready mode.

@vhpx vhpx marked this pull request as draft June 19, 2025 11:44
@vhpx vhpx added the AI label Jun 20, 2025
Copy link

codecov bot commented Jun 20, 2025

Codecov Report

Attention: Patch coverage is 21.68874% with 473 lines in your changes missing coverage. Please review.

Project coverage is 0.88%. Comparing base (05e6eda) to head (f8da07b).
Report is 95 commits behind head on main.

Files with missing lines Patch % Lines
...alendar/src/app/[locale]/(root)/scheduler/page.tsx 0.00% 197 Missing ⚠️
...[locale]/(root)/scheduler/components/TaskModal.tsx 0.00% 161 Missing ⚠️
packages/ai/src/scheduling/algorithm.ts 66.32% 66 Missing ⚠️
.../[locale]/(root)/scheduler/components/TaskList.tsx 0.00% 25 Missing ⚠️
[...e]/(root)/scheduler/components/ScheduleDisplay.tsx](https://app.codecov.io/gh/tutur3u/platform/pull/3126?src=pr&el=tree&filepath=apps%2Fcalendar%2Fsrc%2Fapp%2F%5Blocale%5D%2F%28root%29%2Fscheduler%2Fcomponents%2FScheduleDisplay.tsx&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=tutur3u#diff-YXBwcy9jYWxlbmRhci9zcmMvYXBwL1tsb2NhbGVdLyhyb290KS9zY2hlZHVsZXIvY29tcG9uZW50cy9TY2hlZHVsZURpc3BsYXkudHN4) 0.00% 18 Missing ⚠️
packages/ai/src/scheduling/templates.ts 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3126      +/-   ##
==========================================
+ Coverage    0.80%    0.88%   +0.07%     
==========================================
  Files        2542     2542              
  Lines      323788   324107     +319     
  Branches     3043     3095      +52     
==========================================
+ Hits         2621     2872     +251     
- Misses     318998   319067      +69     
+ Partials     2169     2168       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vhpx vhpx added the calendar label Jun 21, 2025
@datnguyen-en datnguyen-en deleted the feat/Enhance-Schedule-Algorithm branch June 22, 2025 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants