diff --git a/docs/plans/0003-copy-close-on-case-page.md b/docs/plans/0003-copy-close-on-case-page.md new file mode 100644 index 0000000..8540a48 --- /dev/null +++ b/docs/plans/0003-copy-close-on-case-page.md @@ -0,0 +1,487 @@ +# Copy + Close on the Case Page — Implementation Plan + +> **Parent spec:** `docs/specs/0002-copy-close-on-case-page.md` +> +> **For agentic workers:** REQUIRED SUB-SKILL: use the `implement` +> skill to run this plan. Steps use `- [ ]` checkboxes for tracking. + +**Goal:** Replace the case page's icon-only trash-can close with a text +"Kopieren + Schließen" control below the document that copies the +document text then closes the case (landing on `/cases`), keeping a bare +"Schließen" control for documentless open cases. + +**Architecture:** Frontend-only. One Askama template +(`server/templates/case_page.html`) and its inline ` +``` + +Replace it with: + +```html + +``` + +- [ ] **Step 5: Run tests to verify they pass** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 --test case_page_test` +Expected: the whole `case_page_test` target PASSes — in particular the new +`case_page_open_document_has_copy_close_button` (form present on open+doc), +`case_page_closed_document_hides_copy_close` (absent on closed), and the +pre-existing `case_page_document_has_copy_button` (icon `#copy-btn` + +`#doc-content` survive the refactor). + +--- + +### Task 2: Bare "Schließen" control for documentless open cases + +**Files:** +- Modify: `server/templates/case_page.html` (the `{% when None %}` arm of `{% match document_html %}`, ~line 746) +- Test: `server/tests/case_page_test.rs:270` (`case_page_empty_case_shows_placeholder`, extended) + +- [ ] **Step 1: Extend the empty-case test with the label assertion** + +In `server/tests/case_page_test.rs`, in `case_page_empty_case_shows_placeholder`, +after the existing close-form assertion (the block ending at the +`"close form missing on empty case"` message), add: + +```rust + assert!( + body.contains(r#">Schließen"#), + "documentless open case must offer a bare Schließen button" + ); +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 case_page_empty_case_shows_placeholder` +Expected: FAIL with "documentless open case must offer a bare Schließen button" (today the empty case has only the icon trash-can in the H1, no text `>Schließen`). + +- [ ] **Step 3: Insert the bare close form in the no-document branch** + +In `server/templates/case_page.html`, find this exact line (the two +`{% endmatch %}` that close the inner `analysis_failed` match and the +outer `document_html` match): + +```html + {% endif %} {% endmatch %} {% endmatch %} +``` + +Replace it with (split: bare form lands inside the `document_html` +`None` arm, after the inner match resolves, before the outer match +closes — so it renders for both the failure-banner and the +placeholder/analyzing sub-cases of a documentless open case): + +```html + {% endif %} {% endmatch %} + {% if !is_closed %} + + {% endif %} + {% endmatch %} +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 case_page_empty_case_shows_placeholder` +Expected: PASS (placeholder text, the close action, and the bare `>Schließen` are all present). + +--- + +### Task 3: Remove the H1 trash-can close button (open-case arm) + +**Files:** +- Modify: `server/templates/case_page.html:439–473` (the `{% else %}` close arm of the H1 title-row form) +- Test: `server/tests/case_page_test.rs` + +- [ ] **Step 1: Write the failing test** + +Append at the end of `server/tests/case_page_test.rs`: + +```rust +/// Property: the icon-only trash-can close button in the H1 title row is +/// gone — closing now happens via the text control below the document. +/// (The closed-case reopen affordance in the same slot is untouched.) +#[tokio::test] +async fn case_page_open_case_has_no_trashcan_close() { + let cfg = TestConfig::new() + .with_label("cp-no-trash") + .with_user(test_user("dr_a")) + .with_llm("http://unused") + .build(); + let case_id = "11111111-1111-1111-1111-111111111111"; + let case_dir = seed_case(&cfg.data_path, "dr_a", case_id); + write_document_for_test(&case_dir, "fertiger Brief", "1970-01-01T00:00:00Z"); + + let app = doctate_server::create_router(cfg); + let cookie = login_dr_a(&app).await; + + let resp = app + .oneshot(get_with_cookie(paths::case_detail(case_id), &cookie)) + .await + .unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + let body = body_string(resp).await; + + assert!( + !body.contains(r#"title="Fall schließen""#), + "the H1 trash-can close button must be gone" + ); +} +``` + +- [ ] **Step 2: Run test to verify it fails** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 case_page_open_case_has_no_trashcan_close` +Expected: FAIL with "the H1 trash-can close button must be gone" (the title-row close form still carries `title="Fall schließen"`). + +- [ ] **Step 3: Delete the H1 close arm** + +In `server/templates/case_page.html`, find this exact block (the +`{% else %}` close arm and the `{% endif %}` that closes the H1 +reopen/close conditional): + +```html + {% else %} +
+ {% call csrf::field(csrf_token) %} + +
+ {% endif %} +``` + +Replace it with (drop the entire `{% else %}` arm; keep `{% endif %}`): + +```html + {% endif %} +``` + +- [ ] **Step 4: Run test to verify it passes** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 case_page_open_case_has_no_trashcan_close` +Expected: PASS (no `title="Fall schließen"` on the open case page). + +- [ ] **Step 5: Run the full case-page + close-redirect suites to confirm no regression** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4 --test case_page_test` +Expected: PASS — in particular `case_page_empty_case_shows_placeholder` (close action now served by the Task 2 bare form), `case_page_renders_for_closed_case_without_show_closed`, and `case_page_hides_mutation_actions_when_closed` (H1 reopen arm untouched) all stay green. + +--- + +### Task 4: Whole-suite + lint/format gate + +**Files:** (none — verification only) + +- [ ] **Step 1: Run the full server test suite** + +Run: `cargo test --manifest-path server/Cargo.toml -j 4` +Expected: PASS (no failures, no regressions). + +- [ ] **Step 2: Clippy** + +Run: `cargo clippy --manifest-path server/Cargo.toml --all-targets` +Expected: no warnings (CLAUDE.md: "cargo clippy hat immer Recht"). + +- [ ] **Step 3: Format** + +Run: `cargo fmt --manifest-path server/Cargo.toml` +Expected: no diff (or only the newly added test code reflowed).