feat: Route tab overhaul + work order filters + Next Stop + Google Maps

- Added work order filter bar to Route tab matching the Work Orders tab UX:
  status, priority, work type dropdowns + date range selector
- Filter params passed to /api/workorders/today endpoint (backend updated
  with new query params: status, priority, work_type, date_range)
- Added Google Maps Navigate button on every route stop
- Added Mark Done & Next Stop button — tracks current stop index,
  marks completed stops with green check, advances to next with
  auto-prompt to open Google Maps navigation
- Animated stop progress: done stops dimmed with green ✓, current
  stop highlighted with accent border
- Updated /api/workorders/today to support date_range (week/month/all)
  and additional filter WHERE clauses
This commit is contained in:
2026-06-01 13:10:37 -04:00
parent 2d232941da
commit 03cf4b9281
2 changed files with 221 additions and 12 deletions
+36 -3
View File
@@ -3311,11 +3311,16 @@ async def workorders_lookup(body: WorkorderLookupRequest):
async def workorders_today(
tech: list[str] = Query([], description="Filter by technician names"),
limit: int = Query(100, ge=1, le=500),
status: str = Query("", description="Filter by work order status"),
priority: str = Query("", description="Filter by priority (Urgent/High/Medium/Low)"),
work_type: str = Query("", description="Filter by work type (Install/Repair/PM/Emergency)"),
date_range: str = Query("today", description="Date range: today, week, month, all"),
):
"""Fetch today's active work orders via bookableresourcebooking.
Pass ?tech=Shawn+Canada&tech=John+Doe to filter by one or more technicians.
Omit tech entirely to return all technicians.
Supports optional ?status=, ?priority=, ?work_type=, ?date_range= filters.
"""
conn = _get_extraction_db()
if not conn:
@@ -3323,20 +3328,47 @@ async def workorders_today(
try:
cur = conn.cursor()
today = date.today().isoformat()
today_start = f"{today}T00:00:00Z"
today_end = f"{today}T23:59:59Z"
# Determine date window
date_window_start = f"{today}T00:00:00Z"
date_window_end = f"{today}T23:59:59Z"
if date_range == "week":
from datetime import timedelta
week_ago = (date.today() - timedelta(days=7)).isoformat()
date_window_start = f"{week_ago}T00:00:00Z"
elif date_range == "month":
from datetime import timedelta
month_ago = (date.today() - timedelta(days=30)).isoformat()
date_window_start = f"{month_ago}T00:00:00Z"
elif date_range == "all":
date_window_start = "2000-01-01T00:00:00Z"
date_window_end = "2099-12-31T23:59:59Z"
active_booking_statuses = ",".join(
f"'{s}'"
for s in ["Scheduled", "Unscheduled", "On Site", "Traveling", "On Break", "Hold", "Committed"]
)
params = [today_start, today_end]
params = [date_window_start, date_window_end]
tech_clause = ""
if tech:
placeholders_t = ",".join(["?" for _ in tech])
tech_clause = f'AND b."resource!name" IN ({placeholders_t})'
params.extend(tech)
# Additional filters
filter_clauses = []
if status:
filter_clauses.append("w.msdyn_systemstatus = ?")
params.append(status)
if priority:
filter_clauses.append('w."msdyn_priority!name" = ?')
params.append(priority)
if work_type:
filter_clauses.append('w."msdyn_workordertype!name" = ?')
params.append(work_type)
filter_sql = " ".join(filter_clauses)
params.append(limit)
cur.execute(
@@ -3365,6 +3397,7 @@ async def workorders_today(
AND b.starttime <= ?
AND b."bookingstatus!name" IN ({active_booking_statuses})
{tech_clause}
{filter_sql}
ORDER BY b.starttime ASC
LIMIT ?
""",