feat: Sprint 3 frontend dashboards with Alpine.js + Jinja2
- Login page with JWT auth and role-based redirect - CS Dashboard: KPI cards, priority breakdown, recent tickets - FM Dashboard: tech workload, aging analysis, emergency alerts - CEO Dashboard: executive KPIs, charts, risk indicators - All Issues: filterable/sortable ticket table with pagination - Create Issue: form with category tree, property/unit selector, photo uploads - Issue Detail: full timeline, photo gallery, SLA status, action modals - Role-based nav bar: CS/FM/Executive links adapt to user role - Base template: shared Alpine.js app state, toast notifications, loading overlay
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Frontend page routes — serve Jinja2 HTML templates for the SPA-like dashboard."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
router = APIRouter(tags=["pages"])
|
||||
|
||||
templates = Jinja2Templates(directory=str(Path(__file__).resolve().parent.parent / "templates"))
|
||||
|
||||
|
||||
@router.get("/login", response_class=HTMLResponse)
|
||||
async def login_page(request: Request):
|
||||
return templates.TemplateResponse(request, "login.html")
|
||||
|
||||
|
||||
@router.get("/dashboard/cs", response_class=HTMLResponse)
|
||||
async def cs_dashboard(request: Request):
|
||||
return templates.TemplateResponse(request, "dashboard/cs.html")
|
||||
|
||||
|
||||
@router.get("/dashboard/fm", response_class=HTMLResponse)
|
||||
async def fm_dashboard(request: Request):
|
||||
return templates.TemplateResponse(request, "dashboard/fm.html")
|
||||
|
||||
|
||||
@router.get("/dashboard/ceo", response_class=HTMLResponse)
|
||||
async def ceo_dashboard(request: Request):
|
||||
return templates.TemplateResponse(request, "dashboard/ceo.html")
|
||||
|
||||
|
||||
@router.get("/tickets", response_class=HTMLResponse)
|
||||
async def ticket_list(request: Request):
|
||||
return templates.TemplateResponse(request, "tickets/list.html")
|
||||
|
||||
|
||||
@router.get("/tickets/new", response_class=HTMLResponse)
|
||||
async def create_ticket_page(request: Request):
|
||||
return templates.TemplateResponse(request, "tickets/new.html")
|
||||
|
||||
|
||||
@router.get("/tickets/{ticket_id}", response_class=HTMLResponse)
|
||||
async def ticket_detail_page(request: Request, ticket_id: int):
|
||||
return templates.TemplateResponse(request, "tickets/detail.html", context={"ticket_id": ticket_id})
|
||||
Reference in New Issue
Block a user