Skip to content

fix: clicking on previous step navigates to correct step instead of next #22146

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

subediDarshan
Copy link

@subediDarshan subediDarshan commented Jun 30, 2025

What does this PR do?

This PR ensures that when a user clicks on a previous step's progress bar segment (white bar), they are navigated to that specific step, rather than the next step. This aligns with expected user behavior.

Visual Demo

Before:

Bug-Capture-qyF3Ypn8-wNKkCV3jrjEGbZKBCTI8Xg2iuVoDxqxh0Ew.mp4

After:

Untitled.video.-.Made.with.Clipchamp.1.mp4

Mandatory Tasks (DO NOT REMOVE)

  • I have self-reviewed the code (A decent size PR without self-review might be rejected).
  • I have updated the developer docs in /docs if this PR makes changes that would require a documentation change. (N/A here)
  • I confirm automated tests are in place that prove my fix is effective or that my feature works.

How should this be tested?

  • Run app locally
  • Navigate to http://localhost:3000/getting-started/connected-video.
  • Click on a white progress bar segment representing a previous step (eg: step 2 or 3).
  • Confirm that you are taken to the correct step, not the next one.

Checklist

  • I haven't read the contributing guide
  • My code doesn't follow the style guidelines of this project
  • I haven't commented my code, particularly in hard-to-understand areas
  • I haven't checked if my changes generate no new warnings

Summary by cubic

Clicking on a previous step in the progress bar now takes users to that exact step, instead of moving them to the next step. This makes navigation match what users expect.

@subediDarshan subediDarshan requested review from a team as code owners June 30, 2025 08:08
Copy link

vercel bot commented Jun 30, 2025

@subediDarshan is attempting to deploy a commit to the cal Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant
Copy link

CLAassistant commented Jun 30, 2025

CLA assistant check
All committers have signed the CLA.

@graphite-app graphite-app bot added the community Created by Linear-GitHub Sync label Jun 30, 2025
@github-actions github-actions bot added ui area: UI, frontend, button, form, input 🐛 bug Something isn't working labels Jun 30, 2025
Copy link

graphite-app bot commented Jun 30, 2025

Graphite Automations

"Add community label" took an action on this PR • (06/30/25)

1 label was added to this PR based on Keith Williams's automation.

"Add ready-for-e2e label" took an action on this PR • (07/09/25)

1 label was added to this PR based on Keith Williams's automation.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

cubic found 2 issues across 5 files. Review them in cubic.dev

React with 👍 or 👎 to teach cubic. Tag @cubic-dev-ai to give specific feedback.

Copy link
Contributor

@Devanshusharma2005 Devanshusharma2005 left a comment

Choose a reason for hiding this comment

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

Hey @subediDarshan thanks for the pr , can you please fix the issues suggested by cubic. and also can you make a loom for making sure that the steps only go to previous adjacent one or any step in the previous ?

kart1ka
kart1ka previously approved these changes Jun 30, 2025
Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

LGTM

@subediDarshan
Copy link
Author

subediDarshan commented Jul 1, 2025

Hey @Devanshusharma2005
I have addressed issues suggested by cubic.
And here's the video demo showing steps only go to previous adjacent one or any step in the previous and not to the upcoming ones:

pr-3.mp4

kart1ka
kart1ka previously approved these changes Jul 1, 2025
Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

LGTM

@anikdhabal anikdhabal added the Low priority Created by Linear-GitHub Sync label Jul 4, 2025
sean-brydon
sean-brydon previously approved these changes Jul 9, 2025
Copy link
Contributor

github-actions bot commented Jul 9, 2025

E2E results are ready!

@anikdhabal
Copy link
Contributor

@subediDarshan pls fix the conflicts

@subediDarshan subediDarshan dismissed stale reviews from sean-brydon and kart1ka via b3c3878 July 10, 2025 13:07
@@ -25,7 +25,7 @@ export function useWizardState(defaultStep = 1, maxSteps: number) {

const goToStep = useCallback(
(newStep: number) => {
setStep(Math.min(Math.max(newStep, 1), maxSteps));
setStep(Math.min(Math.max(newStep + 1, 1), maxSteps));
Copy link
Author

Choose a reason for hiding this comment

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

In 'Steps' component (where this 'goToStep' function is passed as prop),
0-based indexes are passed in goToFunction as newStep,
but 1-based indexes is being used in URL query param (?step=1),
So, +1 conversion is needed here

Copy link
Contributor

Choose a reason for hiding this comment

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

pls add a comment in the code mentioning the same

Copy link
Author

Choose a reason for hiding this comment

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

Comment added c999b7e

kart1ka
kart1ka previously approved these changes Jul 10, 2025
Copy link
Contributor

@kart1ka kart1ka left a comment

Choose a reason for hiding this comment

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

Looks good. Thanks for the PR.

stepLabel={stepLabel}
data-testid="wizard-step-component"
disableNavigation={disableNavigation}
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the reason for removal of this props?

Copy link
Author

Choose a reason for hiding this comment

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

By not passing this prop, disableNavigation=false is set by default (default parameter set in Steps component), which is what we need since we are navigating between previous steps here through 'navigateToStep' function.

Copy link
Contributor

This PR is being marked as stale due to inactivity.

@github-actions github-actions bot added the Stale label Jul 25, 2025
Copy link
Contributor

coderabbitai bot commented Jul 25, 2025

Walkthrough

This set of changes refactors the navigation logic for multi-step forms and wizards across several components and modules. The primary update replaces the previous "next step" navigation pattern with a more general "go to step" approach, allowing direct navigation to any step by index. This involves renaming props and types from nextStep to navigateToStep and updating their signatures to accept a step index parameter. The internal logic for handling step indices is adjusted to ensure correct mapping between zero-based and one-based indices. Related tests and usages are updated accordingly, and redundant code (such as a no-op function) is removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Complexity label: Moderate
Rationale:
The changes are spread across multiple files, including core logic, type definitions, component usage, and test updates. The review involves verifying correct prop renaming, function signature changes, navigation logic adjustments, and ensuring consistency across components. While not highly complex, attention to detail is required to confirm correct step index handling and to ensure the bug fix is robust.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/app-store/googlecalendar/lib/CalendarService.ts

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

packages/ui/components/form/step/Steps.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the plugin "eslint-plugin-playwright".

(The package "eslint-plugin-playwright" was not found when loaded as a Node module from the directory "".)

It's likely that the plugin isn't installed correctly. Try reinstalling by running the following:

npm install eslint-plugin-playwright@latest --save-dev

The plugin "eslint-plugin-playwright" was referenced from the config file in ".eslintrc.js".

If you still can't figure out the problem, please stop by https://eslint.org/chat/help to chat with the team.

  • 4 others
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 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 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
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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c316721 and f8203f7.

📒 Files selected for processing (7)
  • apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx (2 hunks)
  • packages/app-store/googlecalendar/lib/CalendarService.ts (1 hunks)
  • packages/ui/components/form/step/Steps.tsx (3 hunks)
  • packages/ui/components/form/step/steps.test.tsx (1 hunks)
  • packages/ui/components/form/wizard/WizardForm.tsx (2 hunks)
  • packages/ui/components/form/wizard/useWizardState.ts (1 hunks)
  • packages/ui/components/layout/WizardLayout.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code. Functions like .add, .diff, .isBefore, and .isAfter are slow, especially in timezone mode. Prefer .utc() for better performance. Where possible, replace with native Date and direct .valueOf() comparisons for faster execution. Recommend using native methods or Day.js .utc() consistently in hot paths like loops.

Files:

  • packages/ui/components/layout/WizardLayout.tsx
  • packages/ui/components/form/step/steps.test.tsx
  • packages/ui/components/form/wizard/useWizardState.ts
  • apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx
  • packages/ui/components/form/wizard/WizardForm.tsx
  • packages/app-store/googlecalendar/lib/CalendarService.ts
  • packages/ui/components/form/step/Steps.tsx
🧠 Learnings (4)
packages/ui/components/form/wizard/useWizardState.ts (1)

Learnt from: alishaz-polymath
PR: #22304
File: packages/features/eventtypes/components/MultiplePrivateLinksController.tsx:92-94
Timestamp: 2025-07-16T06:42:27.024Z
Learning: In the MultiplePrivateLinksController component (packages/features/eventtypes/components/MultiplePrivateLinksController.tsx), the currentLink.maxUsageCount ?? 1 fallback in the openSettingsDialog function is intentional. Missing maxUsageCount values indicate old/legacy private links that existed before the expiration feature was added, and they should default to single-use behavior (1) for backward compatibility.

apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx (1)

Learnt from: Anshumancanrock
PR: #22570
File: apps/web/modules/signup-view.tsx:253-253
Timestamp: 2025-07-21T21:33:23.371Z
Learning: In signup-view.tsx, when checking if redirectUrl contains certain strings, using explicit && checks (redirectUrl && redirectUrl.includes()) is preferred over optional chaining (redirectUrl?.includes()) to ensure the result is always a boolean rather than potentially undefined. This approach provides cleaner boolean contracts for downstream conditional logic.

packages/ui/components/form/wizard/WizardForm.tsx (1)

Learnt from: eunjae-lee
PR: #22106
File: packages/features/insights/components/FailedBookingsByField.tsx:65-71
Timestamp: 2025-07-15T12:59:34.389Z
Learning: In the FailedBookingsByField component (packages/features/insights/components/FailedBookingsByField.tsx), although routingFormId is typed as optional in useInsightsParameters, the system automatically enforces a routing form filter, so routingFormId is always present in practice. This means the data always contains only one entry, making the single-entry destructuring approach safe.

packages/app-store/googlecalendar/lib/CalendarService.ts (1)

Learnt from: CR
PR: calcom/cal.com#0
File: .cursor/rules/review.mdc:0-0
Timestamp: 2025-07-21T13:54:11.770Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Flag excessive Day.js use in performance-critical code. Functions like .add, .diff, .isBefore, and .isAfter are slow, especially in timezone mode. Prefer .utc() for better performance. Where possible, replace with native Date and direct .valueOf() comparisons for faster execution. Recommend using native methods or Day.js .utc() consistently in hot paths like loops.

🧬 Code Graph Analysis (1)
packages/ui/components/form/wizard/WizardForm.tsx (1)
packages/ui/components/form/wizard/useWizardState.ts (1)
  • useWizardState (22-55)
🔇 Additional comments (10)
packages/ui/components/form/step/steps.test.tsx (1)

16-16: LGTM! Test prop updated to match component interface.

The prop rename from nextStep to navigateToStep correctly aligns with the component interface changes while maintaining the same test coverage.

packages/ui/components/layout/WizardLayout.tsx (1)

60-60: LGTM! Using disableNavigation is cleaner than noop functions.

Explicitly disabling navigation is more intentional and readable than passing a no-operation function. This change aligns well with the component's purpose in the wizard layout.

packages/ui/components/form/wizard/useWizardState.ts (1)

28-29: LGTM! Index conversion is correctly implemented.

The conversion from 0-based component interface to 1-based URL parameters is properly handled with appropriate bounds checking. The added comment clearly explains the conversion logic.

apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx (1)

167-167: LGTM! Navigation prop correctly updated.

The change from nextStep to navigateToStep with the new goToStep function properly enables navigation to any previous step, which aligns with the PR objective of fixing the navigation behavior.

packages/ui/components/form/wizard/WizardForm.tsx (2)

49-49: LGTM! Correctly extracting goToStep for navigation.

Adding goToStep to the destructured return enables the step navigation functionality that was previously unused.


74-74: LGTM! Navigation prop updated consistently with the refactor.

The change from nextStep to navigateToStep with goToStep function enables direct navigation to any step, which aligns with the PR objective and the broader refactor pattern across the codebase.

packages/ui/components/form/step/Steps.tsx (4)

6-6: LGTM - Type definition correctly updated.

The function signature change from nextStep to navigateToStep: (step: number) => void properly supports navigation to any step by index, aligning with the PR objective.


14-14: LGTM - Maintains type safety for disabled navigation.

The optional undefined type correctly excludes navigation functionality when disableNavigation is true.


26-26: LGTM - Prop destructuring updated consistently.

The prop name change from nextStep to navigateToStep is consistent with the type definition updates.


38-38: LGTM - Click handler correctly passes step index.

The navigation logic now correctly passes the clicked step's index to navigateToStep. This fixes the issue described in the PR where clicking previous steps would navigate to the next step instead.

Note: The handler passes zero-based indices - ensure consuming components handle this correctly.

Comment on lines +127 to +132
const goToStep = (step: number) => {
const newStep = steps[step];
startTransition(() => {
router.push(`/getting-started/${stepTransform(newStep)}`);
});
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add bounds checking for step parameter.

The goToStep function should validate that the step parameter is within valid bounds before accessing steps[step]. Currently, if step is out of bounds, it will cause steps[step] to return undefined, leading to unexpected navigation to INITIAL_STEP.

  const goToStep = (step: number) => {
+   if (step < 0 || step >= steps.length) {
+     return; // or throw an error, or handle gracefully
+   }
    const newStep = steps[step];
    startTransition(() => {
      router.push(`/getting-started/${stepTransform(newStep)}`);
    });
  };
📝 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
const goToStep = (step: number) => {
const newStep = steps[step];
startTransition(() => {
router.push(`/getting-started/${stepTransform(newStep)}`);
});
};
const goToStep = (step: number) => {
if (step < 0 || step >= steps.length) {
return; // or throw an error, or handle gracefully
}
const newStep = steps[step];
startTransition(() => {
router.push(`/getting-started/${stepTransform(newStep)}`);
});
};
🤖 Prompt for AI Agents
In apps/web/modules/getting-started/[[...step]]/onboarding-view.tsx around lines
127 to 132, the goToStep function lacks bounds checking for the step parameter,
which can cause steps[step] to be undefined and lead to incorrect navigation.
Add a check to ensure step is within the valid range of the steps array indices
before accessing steps[step]. If step is out of bounds, handle it gracefully,
for example by returning early or defaulting to a valid step, to prevent
unexpected navigation.

Comment on lines 679 to 681
const oneDayMs = 1000 * 60 * 60 * 24;
const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / (oneDayMs));
const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / oneDayMs);

Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Reuse existing MS_PER_DAY constant and guard against over-90-day edge case

You redeclare the day-length constant and still rely on Math.floor().
Two issues arise:

  1. Duplication/maintainability – MS_PER_DAY (line 38) already captures the same value.
  2. Off-by-one risk – Math.floor() lets a range of “90 days + ε” (e.g. 90 days 23 h) slip through as 90, provoking a 400 error from Google’s 90-day cap.

Consider:

-const oneDayMs = 1000 * 60 * 60 * 24;
-const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / oneDayMs);
+// Use the shared constant for consistency and avoid silent “90 days + ε” passes.
+const diff = (toDate.getTime() - fromDate.getTime()) / MS_PER_DAY;
+
+// Google API allows *up to* 90 full days
+if (diff > 90) {
+  // fall-back to chunking logic below
+} else {
+  ...
+}

This eliminates duplication and relies on a direct millisecond check, preventing borderline ranges from bypassing the limit.


🏁 Script executed:

#!/bin/bash
set -e

echo "🔍 Searching for MS_PER_DAY occurrences..."
rg -n "MS_PER_DAY" packages/app-store/googlecalendar/lib/CalendarService.ts || true

echo
echo "📄 Showing top of file (lines 1–100) to locate the constant definition..."
sed -n '1,100p' packages/app-store/googlecalendar/lib/CalendarService.ts

echo
echo "📋 Showing lines 670–720 around the oneDayMs/diff snippet..."
sed -n '670,720p' packages/app-store/googlecalendar/lib/CalendarService.ts

Length of output: 6691


Use shared MS_PER_DAY and prevent “90 days + ε” slip

Rather than redeclaring a local oneDayMs and flooring to truncate, reuse the existing MS_PER_DAY constant and compare the raw millisecond difference against 90 * MS_PER_DAY. This removes duplication and avoids allowing 90 days plus fractional hours to be treated as exactly 90 days.

• File: packages/app-store/googlecalendar/lib/CalendarService.ts
Lines ~675–680

Suggested diff:

-    const oneDayMs = 1000 * 60 * 60 * 24;
-    const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / oneDayMs);
+    const diffMs = toDate.getTime() - fromDate.getTime();
+
+    // Google API allows up to 90 full days
+    if (diffMs <= 90 * MS_PER_DAY) {
+      // single-range freebusy call
+      const freeBusyData = await this.getCacheOrFetchAvailability(
+        { timeMin: dateFrom, timeMax: dateTo, items: calendarIds.map((id) => ({ id })) },
+        shouldServeCache
+      );
+
+      if (!freeBusyData) throw new Error("No response from google calendar");
+      return freeBusyData.map((b) => ({ start: b.start, end: b.end }));
+    }
+
+    // chunk into multiple 90-day windows
     // …

This ensures consistency with the shared constant and prevents borderline ranges (e.g. 90 days + 23 h) from bypassing the cap.

📝 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
const oneDayMs = 1000 * 60 * 60 * 24;
const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / (oneDayMs));
const diff = Math.floor((toDate.getTime() - fromDate.getTime()) / oneDayMs);
const diffMs = toDate.getTime() - fromDate.getTime();
// Google API allows up to 90 full days
if (diffMs <= 90 * MS_PER_DAY) {
// single-range freebusy call
const freeBusyData = await this.getCacheOrFetchAvailability(
{ timeMin: dateFrom, timeMax: dateTo, items: calendarIds.map((id) => ({ id })) },
shouldServeCache
);
if (!freeBusyData) throw new Error("No response from google calendar");
return freeBusyData.map((b) => ({ start: b.start, end: b.end }));
}
// chunk into multiple 90-day windows
// …
🤖 Prompt for AI Agents
In packages/app-store/googlecalendar/lib/CalendarService.ts around lines 679 to
681, replace the local declaration of oneDayMs with the shared MS_PER_DAY
constant. Instead of flooring the day difference, compare the raw millisecond
difference directly against 90 times MS_PER_DAY to avoid counting fractional
days as full days. This removes duplication and ensures the 90-day cap is
enforced precisely.

@github-actions github-actions bot removed the Stale label Jul 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working community Created by Linear-GitHub Sync Low priority Created by Linear-GitHub Sync ready-for-e2e ui area: UI, frontend, button, form, input
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Clicking on previous step indicator navigates to next step instead of selected step
6 participants