# backend/app/routers/dashboard.py from fastapi import APIRouter, Depends from sqlmodel import Session, select from ..db import get_session from ..models import Approval, Briefing, Event, Goal, InboxItem, Person, Project, Task from ..routers.inbox import latest_cls from ..schemas import ( ApprovalSummaryOut, BadgesOut, BriefingOut, DashboardOut, EventOut, GoalOut, InboxRecentOut, TaskSummaryItem, TaskSummaryOut, UserOut, WeatherOut, ) router = APIRouter() # prefix 없음. main.py 에서 prefix="/api" 등록. # 날씨 아이콘 저장값 → 표시값 매핑(cloudSun 저장 → sun 표시) WEATHER_ICON_MAP = {"cloudSun": "sun"} @router.get("/dashboard", response_model=DashboardOut) def dashboard(s: Session = Depends(get_session)): me = s.exec(select(Person).where(Person.is_me == True)).first() # noqa: E712 user = UserOut(name=me.name, initial=me.initial) if me else UserOut(name="", initial="") br = s.exec(select(Briefing)).first() if br: weather = WeatherOut( temp=br.weather_temp, cond=br.weather_cond, icon=WEATHER_ICON_MAP.get(br.weather_icon, br.weather_icon), ) briefing = BriefingOut( today=br.today, weather=weather, commute=br.commute, sleep=br.sleep, note=br.note ) saved_today, today_routed = br.saved_today, br.today_routed else: briefing = BriefingOut( today="", weather=WeatherOut(temp=0, cond="", icon="sun"), commute="", sleep="", note="", ) saved_today, today_routed = "", 0 schedule = [ EventOut( id=e.id, time=e.time, title=e.title, tag=e.tag, dur=e.dur, tone=e.tone, soon=e.soon ) for e in s.exec(select(Event).order_by(Event.sort_order)).all() ] tasks = s.exec(select(Task)).all() proj_name = {p.id: p.name for p in s.exec(select(Project)).all()} # 요약은 최상위(parent_id=None) 미완료 작업만, 상위 5건. open_count=최상위 미완료 수. open_tasks = sorted( [t for t in tasks if t.parent_id is None and t.status.value != "done"], key=lambda t: t.sort_order, ) items = [ TaskSummaryItem( id=t.id, title=t.title, prio=t.prio.value, project=proj_name.get(t.project_id, "") ) for t in open_tasks[:5] ] task_summary = TaskSummaryOut(open_count=len(open_tasks), items=items) goals = [ GoalOut(id=g.id, title=g.title, pct=g.pct, sub=g.sub, tone=g.tone) for g in s.exec(select(Goal).order_by(Goal.sort_order)).all() ] apprs = s.exec(select(Approval).order_by(Approval.sort_order)).all() high = [a for a in apprs if a.risk == "high"] approvals_summary = [ ApprovalSummaryOut(id=a.id, icon=a.icon, tone=a.tone, title=a.title, time=a.time) for a in high[:3] ] # high-risk 만, 최대 3건 recent = s.exec(select(InboxItem).order_by(InboxItem.created_at.desc()).limit(3)).all() # 평탄화: 각 항목의 최신 classification 에서 type/proj_label/tone 을 끌어와 채운다. inbox_recent = [] for it in recent: c = latest_cls(s, it.id) inbox_recent.append( InboxRecentOut( id=it.id, kind=it.kind.value if hasattr(it.kind, "value") else it.kind, raw=it.raw, type=(c.type.value if c and hasattr(c.type, "value") else (c.type if c else "")), proj_label=c.proj_label if c else "", tone=c.tone if c else "ink", ) ) badges = BadgesOut(appr=len(high), task=len(open_tasks), noti=6) return DashboardOut( user=user, briefing=briefing, saved_today=saved_today, today_routed=today_routed, schedule=schedule, task_summary=task_summary, goals=goals, approvals_summary=approvals_summary, inbox_recent=inbox_recent, badges=badges, )