Files
intotheeast-com/services/travel-memories/app/routes/nav.py
T
m038 bcfee45bd7 feat: add base shell, notes panel, back-navigation with stale propagation
Implements Task 4: base.html DaisyUI/Alpine shell, notes autosave panel,
nav.py phase switching with downstream stale marking, notes.py save/get
endpoints, state debug endpoint, and stub /triage route for test support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 16:08:21 +02:00

52 lines
1.6 KiB
Python

from flask import Blueprint, current_app, jsonify, redirect, request
from app.state import load_state, save_state
bp = Blueprint("nav", __name__)
STALE_DOWNSTREAM = {
"triage": ["curate", "group", "write"],
"curate": ["group", "write"],
"group": ["write"],
"write": [],
"export": [],
}
@bp.post("/nav/phase")
def goto_phase():
body = request.get_json()
target = body["target_phase"]
state = load_state(body["album_id"], current_app)
if state is None:
return jsonify({"error": "no state"}), 404
# Mark downstream completed phases and the current phase as stale
downstream = STALE_DOWNSTREAM.get(target, [])
candidates = set(downstream) & (set(state.phases_completed) | {state.phase})
newly_stale = [p for p in candidates if p not in state.phase_stale]
state.phase_stale = list(set(state.phase_stale + newly_stale))
state.phase = target
save_state(state, current_app)
return jsonify({"ok": True, "phase": target})
@bp.post("/nav/dismiss-stale")
def dismiss_stale():
album_id = request.form["album_id"]
phase = request.form["phase"]
state = load_state(album_id, current_app)
if state:
state.phase_stale = [p for p in state.phase_stale if p != phase]
save_state(state, current_app)
return redirect(f"/{phase}?album_id={album_id}")
@bp.get("/state/<album_id>")
def get_state(album_id):
"""Debug/test endpoint — returns full state JSON."""
state = load_state(album_id, current_app)
if state is None:
return jsonify({"error": "no state"}), 404
from dataclasses import asdict
return jsonify(asdict(state))