diff --git a/backend/routers/seismo_dashboard.py b/backend/routers/seismo_dashboard.py index fde33b9..72cf7f9 100644 --- a/backend/routers/seismo_dashboard.py +++ b/backend/routers/seismo_dashboard.py @@ -3,13 +3,13 @@ Seismograph Dashboard API Router Provides endpoints for the seismograph-specific dashboard """ -from datetime import date +from datetime import date, datetime, timedelta -from fastapi import APIRouter, Request, Depends, Query +from fastapi import APIRouter, Request, Depends, Query, Form, HTTPException from fastapi.responses import HTMLResponse from sqlalchemy.orm import Session from backend.database import get_db -from backend.models import RosterUnit +from backend.models import RosterUnit, UnitHistory, UserPreferences from backend.templates_config import templates router = APIRouter(prefix="/api/seismo-dashboard", tags=["seismo-dashboard"]) @@ -120,3 +120,109 @@ async def get_seismo_units( "today": date.today() } ) + + +def _get_calibration_interval(db: Session) -> int: + prefs = db.query(UserPreferences).first() + if prefs and prefs.calibration_interval_days: + return prefs.calibration_interval_days + return 365 + + +def _row_context(request: Request, unit: RosterUnit) -> dict: + return {"request": request, "unit": unit, "today": date.today()} + + +@router.get("/unit/{unit_id}/view-row", response_class=HTMLResponse) +async def get_seismo_view_row(unit_id: str, request: Request, db: Session = Depends(get_db)): + unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first() + if not unit: + raise HTTPException(status_code=404, detail="Unit not found") + return templates.TemplateResponse("partials/seismo_row_view.html", _row_context(request, unit)) + + +@router.get("/unit/{unit_id}/edit-row", response_class=HTMLResponse) +async def get_seismo_edit_row(unit_id: str, request: Request, db: Session = Depends(get_db)): + unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first() + if not unit: + raise HTTPException(status_code=404, detail="Unit not found") + return templates.TemplateResponse("partials/seismo_row_edit.html", _row_context(request, unit)) + + +@router.post("/unit/{unit_id}/quick-update", response_class=HTMLResponse) +async def quick_update_seismo_unit( + unit_id: str, + request: Request, + db: Session = Depends(get_db), + status: str = Form(...), + last_calibrated: str = Form(""), + note: str = Form(""), +): + unit = db.query(RosterUnit).filter(RosterUnit.id == unit_id).first() + if not unit: + raise HTTPException(status_code=404, detail="Unit not found") + + # --- Status --- + old_deployed = unit.deployed + old_out_for_cal = unit.out_for_calibration + if status == "deployed": + unit.deployed = True + unit.out_for_calibration = False + elif status == "out_for_calibration": + unit.deployed = False + unit.out_for_calibration = True + else: + unit.deployed = False + unit.out_for_calibration = False + + if unit.deployed != old_deployed or unit.out_for_calibration != old_out_for_cal: + old_status = "deployed" if old_deployed else ("out_for_calibration" if old_out_for_cal else "benched") + db.add(UnitHistory( + unit_id=unit_id, + change_type="deployed_change", + field_name="status", + old_value=old_status, + new_value=status, + source="manual", + )) + + # --- Last calibrated --- + old_cal = unit.last_calibrated + if last_calibrated: + try: + new_cal = datetime.strptime(last_calibrated, "%Y-%m-%d").date() + except ValueError: + raise HTTPException(status_code=400, detail="Invalid date format. Use YYYY-MM-DD") + unit.last_calibrated = new_cal + unit.next_calibration_due = new_cal + timedelta(days=_get_calibration_interval(db)) + else: + unit.last_calibrated = None + unit.next_calibration_due = None + + if unit.last_calibrated != old_cal: + db.add(UnitHistory( + unit_id=unit_id, + change_type="calibration_status_change", + field_name="last_calibrated", + old_value=old_cal.strftime("%Y-%m-%d") if old_cal else None, + new_value=last_calibrated or None, + source="manual", + )) + + # --- Note --- + old_note = unit.note + unit.note = note or None + if unit.note != old_note: + db.add(UnitHistory( + unit_id=unit_id, + change_type="note_change", + field_name="note", + old_value=old_note, + new_value=unit.note, + source="manual", + )) + + db.commit() + db.refresh(unit) + + return templates.TemplateResponse("partials/seismo_row_view.html", _row_context(request, unit)) diff --git a/templates/partials/seismo_row_edit.html b/templates/partials/seismo_row_edit.html new file mode 100644 index 0000000..dc0945d --- /dev/null +++ b/templates/partials/seismo_row_edit.html @@ -0,0 +1,63 @@ +