Skip to content

Improve calendar event display + MUI TimePicker#173

Open
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1782111070-event-display-improvements
Open

Improve calendar event display + MUI TimePicker#173
devin-ai-integration[bot] wants to merge 3 commits into
mainfrom
devin/1782111070-event-display-improvements

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Two changes to the Planner calendar UX:

1. Event blocks show course + location instead of time

Time is already encoded by the block's vertical position on the grid — redundant to show it inside the block. Now events display the course number + room location, which is actually useful:

// before: "Ma 1 a Section 1 10:00 AM"
// after:  "Ma 1 a §1" + "387 LINDE" (via _customContent.timeGrid)
  • shortLocation() extracts the first room-number entry from SectionData.locations (newline-separated, messy format)
  • Regex /^[A-Z]?\d+\w*\s+[A-Z]/ handles regular rooms (387 LINDE), basement rooms (B280 MRE), and letter-suffix rooms (240A CNRB)
  • Events with no location data (e.g. CS 1) render title only
  • HTML is escaped via escapeHtml() before injection

2. Time pickers replaced with MUI TimePicker

Old: native <input type="time"> — visually inconsistent with MUI design system, 12hr format (browser-dependent), while course data uses 24hr.

New: @mui/x-date-pickers TimePicker with ampm={false} — MUI outlined styling, 24hr format matching course catalog data, consistent with other MUI components in the app.

  • Added LocalizationProvider + AdapterDayjs at app root (index.tsx)
  • Clock icon hidden via MuiInputAdornment-root { display: none } for compact layout
  • New deps: @mui/x-date-pickers@9.6.0, dayjs@1.11.21

Note: NODE_VERSION=22 may need to be set in Cloudflare Workers Builds dashboard.

Link to Devin session: https://app.devin.ai/sessions/2a1e057e9b584456bf6c5009f6573070
Requested by: @rchalamala


Open in Devin Review

Co-Authored-By: Rahul Chalamala <22563365+rchalamala@users.noreply.github.com>
@rchalamala rchalamala self-assigned this Jun 22, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 22, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
caltech-dev 6659257 Commit Preview URL

Branch Preview URL
Jun 22 2026, 07:12 AM

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Devin Review found 3 potential issues.

Open in Devin Review

Comment thread src/Planner.tsx Outdated
Comment thread src/Planner.tsx
start: toZonedDateTime(event.start),
end: toZonedDateTime(event.end),
calendarId: `course-${event.id}`,
_customContent: { timeGrid: html },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🚩 _customContent usage with Schedule-X v4 cannot be verified without node_modules

The PR uses _customContent: { timeGrid: html } at line 140 to inject custom HTML into calendar events. This is a Schedule-X feature for custom event rendering, but with @schedule-x/calendar: ^4.6.0 specified in package.json, I cannot verify whether this specific API shape is supported in the installed version since node_modules are not available. The CSS at src/css/planner.css:45-47 hides the default time label (.sx__time-grid-event-time) which suggests the custom content is intended to fully replace the default event rendering. If _customContent is not recognized, events would still render (using the title field which is still set), but without the location info or custom styling.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Verified locally — _customContent.timeGrid works correctly with @schedule-x/calendar@^4.6.0. Events render with the custom HTML (title + location), and the title field is preserved as fallback. Build passes, and the custom content is visible in the running app.

Comment thread src/Planner.tsx
id: course.courseData.id,
title: course.courseData.number + " Section " + section.number,
title: course.courseData.number + " §" + section.number,
location: shortLocation(section.locations),

@devin-ai-integration devin-ai-integration Bot Jun 22, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🚩 shortLocation always returns the first room for multi-location sections

When a section has multiple newline-separated locations (e.g. "142 KCK\nB280 MRE" or "Lecture Hall\nBAX\n103 DWN"), shortLocation returns only the first matching room. This is a single location label applied to all time intervals of the section, even though different intervals may meet in different rooms. The existing code in src/Workspace.tsx:154-158 zips locations with time entries, suggesting the data model supports per-interval locations. This means the planner might show the wrong room for some time slots of multi-location sections.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Acknowledged — the location data format isn't a clean 1:1 zip with time entries. E.g., Ma 1a §1 has 3 time entries but 5 location lines ("Lecture Hall BAX 387 LINDE Lecture Hall BAX"). The existing zip approach in Workspace.tsx:154-158 is also imprecise for the same reason. Per-interval location mapping would require heuristic parsing of multi-line location blocks — not worth the complexity for this PR. Showing the first room match is a reasonable default (better than no location at all).

…etc.)

Co-Authored-By: Rahul Chalamala <22563365+rchalamala@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Testing Results

Tested locally on localhost:5173 against the feature branch. All 3 tests passed.

Devin session

Test 1: Event blocks show course + location, NOT time — PASSED
  • Ma 1a: "Ma 1 a §1" + "387 LINDE" ✅
  • Ph 1a: "Ph 1 a §1" + "201 BRG" ✅
  • Ch 1a: "Ch 1 a §1" + "151 CRL" ✅
  • CS 1: "CS 1 §1" + no location (empty locations field) ✅
  • No "AM"/"PM" time text in any event block ✅

Calendar events

Test 2: Basement room regex fix (B-prefix) — PASSED

Added EE 152 (location: B280 MRE). Old regex /^\d+\s+[A-Z]/ would miss this. New regex /^[A-Z]?\d+\w*\s+[A-Z]/ catches it.

  • Event shows "EE 152 §1" with "B280 MRE" below ✅

Basement room

Test 3: Time picker width — PASSED
  • All 10 time pickers show full "08:00 AM" / "11:00 PM" text, centered, no clipping ✅

CI: 6/6 green (verify, CodeQL, Analyze x2, Workers Builds, Devin Review)

…gn system)

Co-Authored-By: Rahul Chalamala <22563365+rchalamala@users.noreply.github.com>
@devin-ai-integration devin-ai-integration Bot changed the title Improve calendar event display: show course + location, hide redundant time Improve calendar event display + MUI TimePicker Jun 22, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread src/Planner.tsx
Comment on lines +46 to 50
onChange={(newVal) => {
if (!newVal) return;
const day = new Date(value);
day.setHours(hours, minutes, 0, 0);
day.setHours(newVal.hour(), newVal.minute(), 0, 0);
onChange(day);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

🟡 Missing dayjs isValid() check allows NaN to corrupt state

MUI's TimePicker (v9.6.0) can fire onChange with an invalid Dayjs object when the user partially edits or clears a time section in the field. The code only guards against null (if (!newVal) return;) but doesn't check newVal.isValid(). When an invalid Dayjs is used, .hour() and .minute() return NaN, causing day.setHours(NaN, NaN, 0, 0) to produce an Invalid Date. This corrupted Date propagates through updateAvailableTimes (src/useAppState.ts:474) into localStorage, and breaks the scheduler at src/scheduler.ts:87-88 where availableTimes[j][0].getTime() returns NaN, making all availability comparisons fail and preventing any valid arrangements from being generated.

Suggested change
onChange={(newVal) => {
if (!newVal) return;
const day = new Date(value);
day.setHours(hours, minutes, 0, 0);
day.setHours(newVal.hour(), newVal.minute(), 0, 0);
onChange(day);
onChange={(newVal) => {
if (!newVal || !newVal.isValid()) return;
const day = new Date(value);
day.setHours(newVal.hour(), newVal.minute(), 0, 0);
onChange(day);
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/Planner.tsx
.map((l) => l.trim())
.filter(Boolean);
// room entries: "387 LINDE", "B280 MRE", "115c BAX", "240A CNRB"
const rooms = lines.filter((l) => /^[A-Z]?\d+\w*\s+[A-Z]/.test(l));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

📝 Info: The shortLocation regex won't match rooms with multi-letter prefixes

The regex /^[A-Z]?\d+\w*\s+[A-Z]/ uses [A-Z]? which matches zero or one uppercase letter before the digits. Room codes with two-letter prefixes (e.g., "AB123 BUILDING") would not match. The comments indicate this is intentional based on the known data format ("387 LINDE", "B280 MRE", "115c BAX", "240A CNRB"), but if new room formats appear in the catalog, they would silently fall through to the building code fallback or return empty string — a graceful degradation rather than an error.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/css/planner.css
Comment on lines +29 to 31
.sx__time-grid-event .sx__time-grid-event-time {
display: none;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

📝 Info: CSS hides Schedule-X event time labels globally

The rule .sx__time-grid-event .sx__time-grid-event-time { display: none; } hides the default time label that Schedule-X renders inside all time-grid events. This is presumably intentional since the custom content (_customContent) replaces the default rendering. However, if any events are added without _customContent in the future, they'll lose their time labels with no visual indication of when they occur within the grid cell.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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