think
16px
820px

Scroll Specimens in Compare Modal + Verifikator Decision-Panel Fixes

Date: 2026-07-14 · Branch: refactor/tidyup-foundation · Deploy: web ahu-ai-ocr:2601c04c (@192.168.83.20:3520) — FE-only (the /crop endpoint shipped in K.17)

Efran's 5-item follow-up on the Darsani (b01bb469) review page:

  1. Multi-match officers (Darsani) — let the verifikator scroll through their specimens to compare each against the document's signature.
  2. Konfirmasi cocok / Tidak cocok should be the modal's action buttons, not "tandai ulang" / "gambar ulang kotak".
  3. Remove "(wajib sebelum menyetujui — skor AI hanya advisori)".
  4. Add a warning of why "Setujui" is disabled.
  5. "Minta Perbaikan" and "Tolak" should be enabled so a verifikator can actually reject an invalid-signature permohonan.

Compare modal (asks 1–2)

Ask 1 — scroll the officer's specimens. The Spesimen side now cycles ‹ › through the officer's same-officer registrations (shared nameKey, has a file), selected one first — "Spesimen 1/4 · ✓ Spesimen terpilih". The Dokumen side stays fixed. A non-selected specimen shows its detected crop (via /api/apostille/spesimen/:id/signature-crop), a slate badge "Spesimen ini belum dianalisis AI — bandingkan manual", and a "Jadikan spesimen terpilih" button (→ /signer/set, which re-runs the AI against it). Score + heatmaps apply only to the analysed/selected specimen.

This is the direct answer to the contamination: on b01bb469 the selected specimen (1/4 = 291063455) is the blue successor signature; scrolling to 2/4 = 2655 shows the genuine black Darsani signature that matches the document. The verifikator sees it and can switch to it (or just record the verdict).

Ask 2 — verdict is the primary action. Konfirmasi cocok / Tandai tidak cocok (+ Reset) are now the modal's footer buttons; "Tandai tanda tangan di dokumen" and "Gambar ulang kotak" are demoted to the muted secondary row. The separate "Penilaian manual verifikator" box is gone (redundant with the footer).

Decision panel — "Keputusan Verifikator" (asks 3–5)

The gating, spelled out (backend POST …/decide):

Decision Requires
Setujui (APPROVE) note + signature-comparison attestation + no unoverridden FAIL (bypassable)
Minta Perbaikan (REVISE) note only
Tolak (REJECT) note only
  • Ask 3: removed "(wajib sebelum menyetujui — skor AI hanya advisori)" from the attestation checkbox.
  • Ask 4: Setujui stays disabled until its prerequisites are met, but now says why — an amber line "Setujui belum aktif — isi Catatan Keputusan dan centang konfirmasi perbandingan tanda tangan" (computed from what's actually missing).
  • Ask 5: Minta Perbaikan and Tolak are clickable (the backend never gated them on signature/validations — only APPROVE carries those). Clicking without a note focuses the Catatan field and shows an inline "Catatan keputusan wajib diisi" instead of a mysterious greyed-out button. The footer help clarifies: "Menolak/meminta perbaikan cukup dengan catatan — konfirmasi tanda tangan hanya untuk Setujui." So an invalid-signature permohonan can be rejected with a reason, without first confirming a signature the verifikator doesn't believe.

Verification

  • Suites: FE 990 green (new apostille-decision-panel suite for asks 3/4/5; compare-modal gains specimen-scroll + switch tests; verdict-controls assertion moved to the footer). Typecheck clean. FE-only wave — no backend change.
  • Live on b01bb469 (admin persona, staging shadow-enforce): decision panel shows the removed parenthetical, the "Setujui belum aktif" reason, and enabled Minta Perbaikan/Tolak; the compare modal shows the footer verdict bar and scrolls "Spesimen 1/4" → "2/4" (contaminated blue 291063455 → genuine black 2655) with the "Jadikan spesimen terpilih" affordance.

Files

  • frontend/src/components/apostille/signature-compare-modal.tsx — specimen scroll + footer verdict
  • frontend/src/components/apostille/apostille-decision-panel.tsx — asks 3/4/5
  • frontend/src/pages/apostille/ApostilleReviewPage.tsx — wire onSelectSpecimen
  • tests: apostille-decision-panel.test.tsx (new), signature-compare-modal.test.tsx