Files
intotheeast-com/services/travel-memories/app/routes/write.py
T
m038 fade38e7a0 fix: enforce write phase completion gate and wire done endpoint
- GET /write now checks all groups are written/skipped before showing
  the completion screen; incomplete sessions are redirected to the first
  draft group
- POST /write/done now accepts form data (not JSON) and redirects to
  /export; wired up from the completion screen via a <form> POST button
- phase5.html extra_scripts block wrapped in {% if group %} to prevent
  Jinja errors when group is None on the completion screen

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

104 lines
3.8 KiB
Python

from flask import Blueprint, current_app, jsonify, redirect, render_template, request, url_for
from app.state import load_state, save_state
bp = Blueprint("write", __name__)
@bp.get("/write")
def write():
album_id = request.args["album_id"]
group_idx = int(request.args.get("group_idx", 0))
state = load_state(album_id, current_app)
active_groups = [g for g in state.groups if g.status != "exported"]
total = len(active_groups)
group = active_groups[group_idx] if group_idx < total else None
done_count = sum(1 for g in active_groups if g.status in ("written", "skipped"))
if group is None:
all_done = all(g.status in ("written", "skipped", "exported") for g in active_groups)
if not all_done:
first_incomplete = next(i for i, g in enumerate(active_groups) if g.status == "draft")
return redirect(url_for("write.write", album_id=album_id, group_idx=first_incomplete))
photos = []
if group:
by_id = {p.id: p for p in state.photos}
photos = [by_id[pid] for pid in group.photo_ids if pid in by_id]
return render_template(
"phase5.html",
state=state,
group=group,
photos=photos,
group_idx=group_idx,
total=total,
done_count=done_count,
current_phase="write",
album_id=album_id,
phase_stale=state.phase_stale,
notes_content=state.notes,
)
@bp.post("/write/autosave")
def autosave():
body = request.get_json()
state = load_state(body["album_id"], current_app)
for g in state.groups:
if g.id == body["group_id"] and g.status != "exported":
g.title = body.get("title", g.title)
g.body = body.get("body", g.body)
g.location_city = body.get("location_city", g.location_city)
g.location_country = body.get("location_country", g.location_country)
g.date = body.get("date", g.date)
g.hero_photo_id = body.get("hero_photo_id", g.hero_photo_id)
g.shortcode_hints = body.get("shortcode_hints", g.shortcode_hints)
if body.get("entry_type"):
g.entry_type = body["entry_type"]
break
save_state(state, current_app)
return jsonify({"ok": True})
@bp.post("/write/save")
def save():
body = request.get_json()
state = load_state(body["album_id"], current_app)
for g in state.groups:
if g.id == body["group_id"] and g.status != "exported":
g.title = body.get("title", g.title)
g.body = body.get("body", g.body)
g.location_city = body.get("location_city", g.location_city)
g.location_country = body.get("location_country", g.location_country)
g.date = body.get("date", g.date)
g.hero_photo_id = body.get("hero_photo_id", g.hero_photo_id)
g.shortcode_hints = body.get("shortcode_hints", g.shortcode_hints)
if body.get("entry_type"):
g.entry_type = body["entry_type"]
g.status = "written"
break
save_state(state, current_app)
return jsonify({"ok": True})
@bp.post("/write/skip")
def skip():
body = request.get_json()
state = load_state(body["album_id"], current_app)
for g in state.groups:
if g.id == body["group_id"] and g.status != "exported":
g.status = "skipped"
break
save_state(state, current_app)
return jsonify({"ok": True})
@bp.post("/write/done")
def write_done():
album_id = request.form["album_id"]
state = load_state(album_id, current_app)
if state is None:
return jsonify({"ok": False, "error": "not found"}), 404
if "write" not in state.phases_completed:
state.phases_completed.append("write")
state.phase = "export"
save_state(state, current_app)
return redirect(f"/export?album_id={album_id}")