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>
This commit is contained in:
2026-06-21 16:58:03 +02:00
parent 02c772f321
commit fade38e7a0
2 changed files with 17 additions and 5 deletions
+10 -4
View File
@@ -13,6 +13,11 @@ def write():
total = len(active_groups) total = len(active_groups)
group = active_groups[group_idx] if group_idx < total else None 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")) 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 = [] photos = []
if group: if group:
by_id = {p.id: p for p in state.photos} by_id = {p.id: p for p in state.photos}
@@ -86,12 +91,13 @@ def skip():
@bp.post("/write/done") @bp.post("/write/done")
def done(): def write_done():
body = request.get_json() album_id = request.form["album_id"]
album_id = body["album_id"]
state = load_state(album_id, current_app) 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: if "write" not in state.phases_completed:
state.phases_completed.append("write") state.phases_completed.append("write")
state.phase = "export" state.phase = "export"
save_state(state, current_app) save_state(state, current_app)
return jsonify({"ok": True, "redirect": f"/export?album_id={album_id}"}) return redirect(f"/export?album_id={album_id}")
@@ -7,7 +7,11 @@
</div> </div>
{% if not group %} {% if not group %}
<div class="alert alert-success">All groups written or skipped. <a href="/export?album_id={{ album_id }}" class="link">Continue to export →</a></div> <div class="alert alert-success mb-4">All groups written or skipped.</div>
<form method="post" action="/write/done">
<input type="hidden" name="album_id" value="{{ album_id }}">
<button type="submit" class="btn btn-primary">Export →</button>
</form>
{% else %} {% else %}
<div class="flex gap-4"> <div class="flex gap-4">
@@ -101,6 +105,7 @@
{% endblock %} {% endblock %}
{% block extra_scripts %} {% block extra_scripts %}
{% if group %}
<script> <script>
(function() { (function() {
var albumId = {{ album_id | tojson }}; var albumId = {{ album_id | tojson }};
@@ -193,4 +198,5 @@
} }
})(); })();
</script> </script>
{% endif %}
{% endblock %} {% endblock %}