Skip to content

Implement role-based project data flow in MulticalendarPage#35

Merged
Ross1116 merged 3 commits into
mainfrom
staging
Feb 25, 2026
Merged

Implement role-based project data flow in MulticalendarPage#35
Ross1116 merged 3 commits into
mainfrom
staging

Conversation

@Ross1116

@Ross1116 Ross1116 commented Feb 25, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Project-aware behavior with automatic project detection based on user role.
    • Project persistence—selected project is saved and restored across sessions and refreshed when user changes.
    • On-demand project fetching and normalization; first available project is auto-selected when none stored.
    • Manual refresh now reloads projects, assets, and bookings independently.
  • Bug Fixes

    • Improved loading/error handling to avoid premature "No project selected" messages during project fetch.

@vercel

vercel Bot commented Feb 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sitespace-app Ready Ready Preview, Comment Feb 25, 2026 8:35am

@coderabbitai

coderabbitai Bot commented Feb 25, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds project-scoped data flow to MulticalendarPage: reads/saves a session-scoped stored project, fetches projects via SWR using role-aware endpoints, normalizes projects with normalizeProjectList, persists the first fetched project when none exists, and resolves projectId before loading assets/bookings.

Changes

Cohort / File(s) Summary
Multicalendar page & project persistence
src/components/multicalendar/MulticalendarPage.tsx
Adds session storedProject state (readStoredProject/saveStoredProject), role-aware SWR project fetch with projectsUrl, normalizes responses via normalizeProjectList to ApiProject[], persists first project to localStorage when absent, updates projectId resolution order, expands error/loading gating, and adds a handleRefresh that revalidates projects, assets, and bookings. New imports: ApiProject, saveStoredProject, StoredProject, normalizeProjectList.

Sequence Diagram(s)

sequenceDiagram
    participant UI as MulticalendarPage
    participant Auth as Auth/UserState
    participant API as Projects API
    participant Storage as localStorage
    participant Assets as Assets/Bookings API

    Auth->>UI: provide userId and role
    UI->>Storage: readStoredProject(userId)
    alt storedProject missing
        UI->>API: fetch projects (role-dependent URL) via SWR
        API-->>UI: return raw project list
        UI->>UI: normalizeProjectList(raw list) -> ApiProject[]
        alt projects exist
            UI->>Storage: saveStoredProject(first project)
            Storage-->>UI: storedProject persisted
        end
    end
    UI->>Assets: fetch assets & bookings using resolved projectId
    Assets-->>UI: return assets & bookings
    UI-->>User: render calendar with assets/bookings
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through projects, fetching each name,

Normalized bits, and stored one to claim.
SWR whispered, localStorage beamed,
Calendars filled like a carrot-lit dream.
Hop, fetch, and render — hooray for the game! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Implement role-based project data flow in MulticalendarPage' accurately reflects the main change: introducing role-aware project fetching (handling subcontractor vs regular users) and project selection logic in the MulticalendarPage component.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch staging

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot changed the title @coderabbitai Implement role-based project data flow in MulticalendarPage Feb 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/multicalendar/MulticalendarPage.tsx (1)

193-197: ⚠️ Potential issue | 🟡 Minor

"No project selected" error card flashes for new users while the project list is still loading.

When a user has no stored project (first-time use), projectId is null while the projects SWR is in-flight. At that point:

  • error evaluates to "No project selected" (line 195)
  • loading is false — the bookings SWR key is null, so SWR never enters a loading state
  • bookings and availableAssets are both empty

All conditions at line 284 are satisfied, so the error card with "No project selected" is shown immediately, before the project fetch even completes.

Consider distinguishing between "no project yet determined" (loading state) and "project confirmed missing" (genuine error):

🛠️ Proposed fix — introduce a projects-loading guard
+  const isProjectResolving = !storedProject?.id && !!projectsUrl;
+
   const error = useMemo(() => {
     if (fetchError) return "Failed to fetch calendar data";
-    if (userId && !projectId) return "No project selected";
+    if (userId && !projectId && !isProjectResolving) return "No project selected";
     return null;
-  }, [fetchError, userId, projectId]);
+  }, [fetchError, userId, projectId, isProjectResolving]);

projectsUrl being non-null signals that a fetch is in-progress/pending, so the "no project" message is suppressed until the fetch settles.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/multicalendar/MulticalendarPage.tsx` around lines 193 - 197,
The "No project selected" message is shown too early because useMemo for error
only checks projectId and not whether the projects request is still in-flight;
update the error computation in the error useMemo (the const error =
useMemo(...) block) to also check the projects fetch guard (e.g., projectsUrl or
a projects-loading boolean) and return null while projectsUrl is non-null (fetch
pending), so the "No project selected" message is suppressed until the projects
SWR settles; keep existing checks for fetchError and the confirmed absence of
projectId when projects are not loading.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/multicalendar/MulticalendarPage.tsx`:
- Around line 98-134: Replace the useMemo-storedProject with a stateful,
lazy-initialized value so writes to localStorage update in-session: change
storedProject from useMemo(() => readStoredProject(userId), [userId]) to
useState(() => readStoredProject(userId)) (or useState<ApiProject|null>(() =>
readStoredProject(userId))). After calling saveStoredProject(userId,
firstProject) inside the effect, call setStoredProject(firstProject) so the
component re-renders and projectsUrl (which currently reads storedProject?.id)
becomes null and stops SWR from refetching; also update any places that read
storedProject (projectsUrl, projectId, effect guards) to use the new state
variable and ensure hooks' dependency arrays reference the state variable (e.g.,
storedProject?.id) not the old memo.

---

Outside diff comments:
In `@src/components/multicalendar/MulticalendarPage.tsx`:
- Around line 193-197: The "No project selected" message is shown too early
because useMemo for error only checks projectId and not whether the projects
request is still in-flight; update the error computation in the error useMemo
(the const error = useMemo(...) block) to also check the projects fetch guard
(e.g., projectsUrl or a projects-loading boolean) and return null while
projectsUrl is non-null (fetch pending), so the "No project selected" message is
suppressed until the projects SWR settles; keep existing checks for fetchError
and the confirmed absence of projectId when projects are not loading.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8dbdfa0 and ee5154a.

📒 Files selected for processing (1)
  • src/components/multicalendar/MulticalendarPage.tsx

Comment thread src/components/multicalendar/MulticalendarPage.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/multicalendar/MulticalendarPage.tsx`:
- Around line 121-125: The useSWR call that defines projectsRaw/projectsLoading
must also return the projects error and mutate so failures are surfaced and
retryable: update the hook invocation to destructure { data: projectsRaw, error:
projectsError, isLoading: projectsLoading, mutate: mutateProjects } from
useSWR(projectsUrl, swrFetcher, SWR_CONFIG); then update the UI branch that
currently shows "No project selected" to render the projectsError when present
(use projectsError to show the real fetch failure), and modify handleRefresh to
call mutateProjects() as part of the retry path so projects are refetched when
the user clicks Retry.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee5154a and 8e16ed8.

📒 Files selected for processing (1)
  • src/components/multicalendar/MulticalendarPage.tsx

Comment thread src/components/multicalendar/MulticalendarPage.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/components/multicalendar/MulticalendarPage.tsx (2)

207-214: Previous silent-failure bug correctly remediated — projectsError is now surfaced and loading state is correctly guarded.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/multicalendar/MulticalendarPage.tsx` around lines 207 - 214,
The useMemo block should surface projectsError and avoid showing "No project
selected" while projects are loading; ensure the conditional order and
dependency array on useMemo include fetchError, projectsError, projectsUrl,
projectsLoading, userId, and projectId (as currently in the useMemo) so that
projectsError is returned when present and the projectsLoading guard prevents
the "No project selected" message while projects are still loading; keep the
conditions in useMemo exactly as written to preserve this behavior.

101-109: Previous perpetual-revalidation bug correctly resolved.

Both the lazy-init state and the userId-change effect are in place.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/multicalendar/MulticalendarPage.tsx` around lines 101 - 109,
Remove the redundant useEffect that re-reads localStorage on userId change: the
lazy-initialized useState with readStoredProject handles initial load, so delete
the useEffect block referencing setStoredProject/readStoredProject and userId to
avoid duplicate reads; keep the state variables (storedProject,
setStoredProject) and the readStoredProject call only in the lazy initializer.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/components/multicalendar/MulticalendarPage.tsx`:
- Around line 207-214: The useMemo block should surface projectsError and avoid
showing "No project selected" while projects are loading; ensure the conditional
order and dependency array on useMemo include fetchError, projectsError,
projectsUrl, projectsLoading, userId, and projectId (as currently in the
useMemo) so that projectsError is returned when present and the projectsLoading
guard prevents the "No project selected" message while projects are still
loading; keep the conditions in useMemo exactly as written to preserve this
behavior.
- Around line 101-109: Remove the redundant useEffect that re-reads localStorage
on userId change: the lazy-initialized useState with readStoredProject handles
initial load, so delete the useEffect block referencing
setStoredProject/readStoredProject and userId to avoid duplicate reads; keep the
state variables (storedProject, setStoredProject) and the readStoredProject call
only in the lazy initializer.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8e16ed8 and 5d17198.

📒 Files selected for processing (1)
  • src/components/multicalendar/MulticalendarPage.tsx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant