Skip to content

Implement Rush Hour time inputs and logic#218

Open
shay-coding wants to merge 2 commits intomainfrom
shay-coding-patch-4
Open

Implement Rush Hour time inputs and logic#218
shay-coding wants to merge 2 commits intomainfrom
shay-coding-patch-4

Conversation

@shay-coding
Copy link
Collaborator

@shay-coding shay-coding commented Jan 11, 2026

Added a Rush Hour section with AM and PM time inputs and functionality to generate rush hour times.

Summary by CodeRabbit

  • New Features
    • Added Rush Hour (Optional) configuration in the timetable interface with AM/PM period inputs
    • Auto-generates departure times based on specified rush hour intervals
    • Automatically merges generated times with manually entered times, removing duplicates and maintaining chronological order
  • Bug
    • Applying Rush Hours may occasionally produce duplicate generated entries or incorrect counts (known issue)

✏️ Tip: You can customize this high-level summary in your review settings.

Added a Rush Hour section with AM and PM time inputs and functionality to generate rush hour times.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 11, 2026

Walkthrough

Adds a Rush Hour (Optional) UI to the timetable template for specifying AM/PM windows and intervals; client-side logic generates rush-hour departure times, merges/deduplicates them with manual times, updates the departure-times field and refreshes the preview.

Changes

Cohort / File(s) Summary
Rush Hour Feature Implementation
fleet/templates/timetable_add.html
Replaces previous "Step 3 (Stop Offsets)" UI with a new Rush Hour block (AM/PM start, end, every (mins)) and an Apply Rush Hours button. Adds applyRushHours() and generateRushTimes() client-side logic to generate, merge, deduplicate, sort, and update departure times and trigger preview regeneration. ⚠️ The applyRushHours() function is duplicated consecutively in the diff and should be de-duplicated.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 I hopped to the schedule, pen in paw,
AM and PM scattered like seeds on the floor,
I sprouted minutes, merged them with care,
Sorted and tidy — a timetable fair,
Hop, click, apply — now departures prepare!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: implementing a new Rush Hour UI with time inputs and associated logic to generate rush-hour departure times.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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


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.

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: 1

Caution

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

⚠️ Outside diff range comments (1)
fleet/templates/timetable_add.html (1)

148-152: Step number mismatch.

The comment correctly indicates "Step 4" but the displayed step number is still "3". With the new Rush Hour section being Step 3, this should be updated to Step 4 for proper sequencing.

Proposed fix
         <!-- Step 4: Stop Offsets -->
         <div class="config-card">
           <div class="card-header">
-            <span class="step-number">3</span>
+            <span class="step-number">4</span>
             <h3>Journey Times</h3>
           </div>
🤖 Fix all issues with AI agents
In @fleet/templates/timetable_add.html:
- Around line 532-584: The file contains a duplicate applyRushHours() definition
prefixed by a malformed "}function" token (likely a copy-paste), so remove the
duplicate block (the second applyRushHours definition starting at the
"}function" token) leaving only the original applyRushHours() implementation;
ensure you delete the extraneous closing brace and the entire duplicate function
body and then run the page to verify generateStopTimesJSON() and any callers
still work as before.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3cce33 and 303d73f.

📒 Files selected for processing (1)
  • fleet/templates/timetable_add.html
🔇 Additional comments (2)
fleet/templates/timetable_add.html (2)

96-146: LGTM!

The Rush Hour UI section follows the established pattern of other config cards and provides intuitive inputs for AM/PM rush periods.


480-531: Logic looks good.

The rush hour time generation, merging, deduplication, and sorting logic is correctly implemented. However, see the next comment regarding the duplicate function definition that immediately follows.

Comment on lines 532 to 584
}function applyRushHours() {
const amStart = document.getElementById("rush-am-start").value;
const amEnd = document.getElementById("rush-am-end").value;
const amInterval = parseInt(document.getElementById("rush-am-interval").value, 10);

const pmStart = document.getElementById("rush-pm-start").value;
const pmEnd = document.getElementById("rush-pm-end").value;
const pmInterval = parseInt(document.getElementById("rush-pm-interval").value, 10);

const timesInput = document.querySelector('.departure-times');
let existingTimes = timesInput.value.split(',').map(t => t.trim()).filter(Boolean);

// Helper function to generate times for a rush period
function generateRushTimes(start, end, interval) {
if (!start || !end || !interval || interval <= 0) return [];

const times = [];
let [startHour, startMin] = start.split(":").map(Number);
const [endHour, endMin] = end.split(":").map(Number);

while (startHour < endHour || (startHour === endHour && startMin <= endMin)) {
times.push(`${String(startHour).padStart(2, "0")}:${String(startMin).padStart(2, "0")}`);
startMin += interval;
if (startMin >= 60) {
startHour += Math.floor(startMin / 60);
startMin = startMin % 60;
}
}

return times;
}

// Generate AM rush times
const amTimes = generateRushTimes(amStart, amEnd, amInterval);

// Generate PM rush times
const pmTimes = generateRushTimes(pmStart, pmEnd, pmInterval);

// Merge all times and remove duplicates
const allTimes = [...existingTimes, ...amTimes, ...pmTimes];

// Sort times and remove duplicates
const uniqueTimes = [...new Set(allTimes)].sort((a, b) => {
const [aH, aM] = a.split(':').map(Number);
const [bH, bM] = b.split(':').map(Number);
return (aH * 60 + aM) - (bH * 60 + bM);
});

timesInput.value = uniqueTimes.join(", ");
generateStopTimesJSON();

alert(`Added ${amTimes.length} AM rush trips and ${pmTimes.length} PM rush trips.`);
}
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 | 🔴 Critical

Remove duplicate applyRushHours() function.

This is an exact duplicate of the function defined on lines 480-531. The malformed }function on line 532 indicates this was likely a copy-paste error. The duplicate should be removed.

Proposed fix
   alert(`Added ${amTimes.length} AM rush trips and ${pmTimes.length} PM rush trips.`);
-}function applyRushHours() {
-  const amStart = document.getElementById("rush-am-start").value;
-  const amEnd = document.getElementById("rush-am-end").value;
-  const amInterval = parseInt(document.getElementById("rush-am-interval").value, 10);
-  
-  const pmStart = document.getElementById("rush-pm-start").value;
-  const pmEnd = document.getElementById("rush-pm-end").value;
-  const pmInterval = parseInt(document.getElementById("rush-pm-interval").value, 10);
-  
-  const timesInput = document.querySelector('.departure-times');
-  let existingTimes = timesInput.value.split(',').map(t => t.trim()).filter(Boolean);
-  
-  // Helper function to generate times for a rush period
-  function generateRushTimes(start, end, interval) {
-    if (!start || !end || !interval || interval <= 0) return [];
-    
-    const times = [];
-    let [startHour, startMin] = start.split(":").map(Number);
-    const [endHour, endMin] = end.split(":").map(Number);
-
-    while (startHour < endHour || (startHour === endHour && startMin <= endMin)) {
-      times.push(`${String(startHour).padStart(2, "0")}:${String(startMin).padStart(2, "0")}`);
-      startMin += interval;
-      if (startMin >= 60) {
-        startHour += Math.floor(startMin / 60);
-        startMin = startMin % 60;
-      }
-    }
-    
-    return times;
-  }
-  
-  // Generate AM rush times
-  const amTimes = generateRushTimes(amStart, amEnd, amInterval);
-  
-  // Generate PM rush times
-  const pmTimes = generateRushTimes(pmStart, pmEnd, pmInterval);
-  
-  // Merge all times and remove duplicates
-  const allTimes = [...existingTimes, ...amTimes, ...pmTimes];
-  
-  // Sort times and remove duplicates
-  const uniqueTimes = [...new Set(allTimes)].sort((a, b) => {
-    const [aH, aM] = a.split(':').map(Number);
-    const [bH, bM] = b.split(':').map(Number);
-    return (aH * 60 + aM) - (bH * 60 + bM);
-  });
-  
-  timesInput.value = uniqueTimes.join(", ");
-  generateStopTimesJSON();
-  
-  alert(`Added ${amTimes.length} AM rush trips and ${pmTimes.length} PM rush trips.`);
 }
+
 function autoFillOffsets() {
🤖 Prompt for AI Agents
In @fleet/templates/timetable_add.html around lines 532 - 584, The file contains
a duplicate applyRushHours() definition prefixed by a malformed "}function"
token (likely a copy-paste), so remove the duplicate block (the second
applyRushHours definition starting at the "}function" token) leaving only the
original applyRushHours() implementation; ensure you delete the extraneous
closing brace and the entire duplicate function body and then run the page to
verify generateStopTimesJSON() and any callers still work as before.

Removed the duplicate applyRushHours function that generated rush hour times based on user inputs.
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: 1

🤖 Fix all issues with AI agents
In @fleet/templates/timetable_add.html:
- Around line 148-151: The step number in the Journey Times/Stop Offsets card is
wrong: update the span with class "step-number" inside the card header (the <div
class="config-card"> / <div class="card-header"> block) to display "4" instead
of "3" so the steps read sequentially after Rush Hour (which is now step 3).
🧹 Nitpick comments (1)
fleet/templates/timetable_add.html (1)

480-532: LGTM! Rush hour logic is solid.

The applyRushHours() function correctly:

  • Validates inputs and handles empty fields gracefully
  • Generates rush hour times for both AM and PM periods
  • Merges with existing times, deduplicates, and sorts chronologically
  • Updates the UI and triggers preview regeneration

The user feedback via alert is a nice UX touch.

Consider extracting the time generation logic to reduce duplication.

The generateRushTimes helper (lines 493-510) contains logic nearly identical to the time generation in autoFillTimes() (lines 463-474). Consider extracting this into a shared utility function to follow the DRY principle.

♻️ Suggested refactor

Extract a reusable function before autoFillTimes:

+function generateTimeRange(start, end, interval) {
+  if (!start || !end || !interval || interval <= 0) return [];
+  
+  const times = [];
+  let [startHour, startMin] = start.split(":").map(Number);
+  const [endHour, endMin] = end.split(":").map(Number);
+
+  while (startHour < endHour || (startHour === endHour && startMin <= endMin)) {
+    times.push(`${String(startHour).padStart(2, "0")}:${String(startMin).padStart(2, "0")}`);
+    startMin += interval;
+    if (startMin >= 60) {
+      startHour += Math.floor(startMin / 60);
+      startMin = startMin % 60;
+    }
+  }
+  
+  return times;
+}
+
 function autoFillTimes() {
   const start = document.getElementById("autofill-start").value;
   const end = document.getElementById("autofill-end").value;
   const interval = parseInt(document.getElementById("autofill-interval").value, 10);
   const input = document.querySelector('.departure-times');

   if (!start || !end || !interval || interval <= 0) {
     alert("Please enter valid start, end times and interval.");
     return;
   }

-  const times = [];
-  let [startHour, startMin] = start.split(":").map(Number);
-  const [endHour, endMin] = end.split(":").map(Number);
-
-  while (startHour < endHour || (startHour === endHour && startMin <= endMin)) {
-    times.push(`${String(startHour).padStart(2, "0")}:${String(startMin).padStart(2, "0")}`);
-    startMin += interval;
-    if (startMin >= 60) {
-      startHour += Math.floor(startMin / 60);
-      startMin = startMin % 60;
-    }
-  }
+  const times = generateTimeRange(start, end, interval);

   input.value = times.join(", ");
   generateStopTimesJSON();
 }

Then update applyRushHours to use the shared function:

 function applyRushHours() {
   const amStart = document.getElementById("rush-am-start").value;
   const amEnd = document.getElementById("rush-am-end").value;
   const amInterval = parseInt(document.getElementById("rush-am-interval").value, 10);
   
   const pmStart = document.getElementById("rush-pm-start").value;
   const pmEnd = document.getElementById("rush-pm-end").value;
   const pmInterval = parseInt(document.getElementById("rush-pm-interval").value, 10);
   
   const timesInput = document.querySelector('.departure-times');
   let existingTimes = timesInput.value.split(',').map(t => t.trim()).filter(Boolean);
   
-  // Helper function to generate times for a rush period
-  function generateRushTimes(start, end, interval) {
-    if (!start || !end || !interval || interval <= 0) return [];
-    
-    const times = [];
-    let [startHour, startMin] = start.split(":").map(Number);
-    const [endHour, endMin] = end.split(":").map(Number);
-
-    while (startHour < endHour || (startHour === endHour && startMin <= endMin)) {
-      times.push(`${String(startHour).padStart(2, "0")}:${String(startMin).padStart(2, "0")}`);
-      startMin += interval;
-      if (startMin >= 60) {
-        startHour += Math.floor(startMin / 60);
-        startMin = startMin % 60;
-      }
-    }
-    
-    return times;
-  }
-  
   // Generate AM rush times
-  const amTimes = generateRushTimes(amStart, amEnd, amInterval);
+  const amTimes = generateTimeRange(amStart, amEnd, amInterval);
   
   // Generate PM rush times
-  const pmTimes = generateRushTimes(pmStart, pmEnd, pmInterval);
+  const pmTimes = generateTimeRange(pmStart, pmEnd, pmInterval);
   
   // Merge all times and remove duplicates
   const allTimes = [...existingTimes, ...amTimes, ...pmTimes];
   
   // Sort times and remove duplicates
   const uniqueTimes = [...new Set(allTimes)].sort((a, b) => {
     const [aH, aM] = a.split(':').map(Number);
     const [bH, bM] = b.split(':').map(Number);
     return (aH * 60 + aM) - (bH * 60 + bM);
   });
   
   timesInput.value = uniqueTimes.join(", ");
   generateStopTimesJSON();
   
   alert(`Added ${amTimes.length} AM rush trips and ${pmTimes.length} PM rush trips.`);
 }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 303d73f and 6fd7510.

📒 Files selected for processing (1)
  • fleet/templates/timetable_add.html
🔇 Additional comments (1)
fleet/templates/timetable_add.html (1)

96-146: LGTM! Clean implementation of the Rush Hour UI.

The optional Rush Hour section is well-structured and follows the existing form patterns consistently. The default 10-minute interval for rush hours is appropriate, and the empty time defaults properly support the optional nature of this feature.

Comment on lines +148 to 151
<!-- Step 4: Stop Offsets -->
<div class="config-card">
<div class="card-header">
<span class="step-number">3</span>
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 | 🟡 Minor

Fix the step number inconsistency.

The Journey Times section still shows step number "3", but it should be "4" since Rush Hour is now step 3.

🔢 Proposed fix
-        <!-- Step 4: Stop Offsets -->
         <div class="config-card">
           <div class="card-header">
-            <span class="step-number">3</span>
+            <span class="step-number">4</span>
             <h3>Journey Times</h3>
           </div>
🤖 Prompt for AI Agents
In @fleet/templates/timetable_add.html around lines 148 - 151, The step number
in the Journey Times/Stop Offsets card is wrong: update the span with class
"step-number" inside the card header (the <div class="config-card"> / <div
class="card-header"> block) to display "4" instead of "3" so the steps read
sequentially after Rush Hour (which is now step 3).

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