fix: dead Add Note buttons and no-op row click in admin review pages
Some checks failed
build-and-release / build (push) Failing after 1m16s

- verification/[id].tsx: "Add Note" in the Reviewer Notes panel had no
  onClick — wired to the existing POST /api/admin/verifications/:id/notes
  endpoint.
- approval/index.tsx: Decision Notes textarea was uncontrolled and its
  "Add Note" button was a no-op; there's no standalone notes endpoint
  for approval_requests, so the textarea is now bound to state and its
  value is sent as the rejection reason when the reviewer rejects
  (the only channel the backend currently supports).
- support.tsx: removed a no-op onClick={() => {}} on the case row —
  the row isn't actually clickable, only the adjacent "View" link is
  (though that link's target route doesn't exist yet — flagged
  separately, out of scope here).
This commit is contained in:
Ashwin Kumar Sivakumar 2026-07-12 17:59:03 +05:30
parent e78b7c2642
commit ef8f4410c7
3 changed files with 30 additions and 5 deletions

View file

@ -252,6 +252,7 @@ export default function ApprovalManagementPage() {
const [filterMenuOpen, setFilterMenuOpen] = createSignal(false); const [filterMenuOpen, setFilterMenuOpen] = createSignal(false);
const [error, setError] = createSignal(''); const [error, setError] = createSignal('');
const [isActing, setIsActing] = createSignal(false); const [isActing, setIsActing] = createSignal(false);
const [decisionNote, setDecisionNote] = createSignal('');
const selectedDocuments = createMemo<ApprovalDocument[]>(() => { const selectedDocuments = createMemo<ApprovalDocument[]>(() => {
const row = viewingCase(); const row = viewingCase();
@ -449,7 +450,7 @@ export default function ApprovalManagementPage() {
}, },
credentials: 'include', credentials: 'include',
body: action === 'reject' body: action === 'reject'
? JSON.stringify({ reason: 'Rejected by admin from approval management' }) ? JSON.stringify({ reason: decisionNote().trim() || 'Rejected by admin from approval management' })
: JSON.stringify({}), : JSON.stringify({}),
}); });
if (!res.ok) { if (!res.ok) {
@ -581,8 +582,8 @@ export default function ApprovalManagementPage() {
<div style="border:1px solid #E5E7EB;border-radius:12px;padding:20px;background:#F9FAFB"> <div style="border:1px solid #E5E7EB;border-radius:12px;padding:20px;background:#F9FAFB">
<h3 style="font-size:14px;font-weight:700;color:#111827;margin-bottom:16px">Decision Notes</h3> <h3 style="font-size:14px;font-weight:700;color:#111827;margin-bottom:16px">Decision Notes</h3>
<textarea placeholder="Add decision note..." style="width:100%;height:100px;border-radius:8px;border:1px solid #E5E7EB;padding:10px;font-size:13px;resize:none;margin-bottom:12px" /> <textarea value={decisionNote()} onInput={(e) => setDecisionNote(e.currentTarget.value)} placeholder="Add decision note..." style="width:100%;height:100px;border-radius:8px;border:1px solid #E5E7EB;padding:10px;font-size:13px;resize:none;margin-bottom:12px" />
<button type="button" style="width:100%;height:34px;background:#0D0D2A;color:white;border-radius:8px;font-size:12px;font-weight:600;border:none">Add Note</button> <p style="margin:0;font-size:12px;color:#6B7280">This note is included as the rejection reason when you reject below.</p>
</div> </div>
</div> </div>
</Show> </Show>

View file

@ -512,7 +512,7 @@ export default function SupportPage() {
<Show when={!cases.loading && !cases.error && filteredCases().length > 0}> <Show when={!cases.loading && !cases.error && filteredCases().length > 0}>
<For each={filteredCases()}> <For each={filteredCases()}>
{(item) => ( {(item) => (
<tr class="hover:bg-slate-50" style="cursor:pointer" onClick={() => {}}> <tr class="hover:bg-slate-50">
<td> <td>
<div class="font-semibold text-slate-900">{item.title}</div> <div class="font-semibold text-slate-900">{item.title}</div>
<div style="font-size:12px;color:#64748b;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"> <div style="font-size:12px;color:#64748b;max-width:260px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">

View file

@ -210,6 +210,30 @@ export default function VerificationReviewDetailPage() {
} }
}; };
const addNote = async () => {
const note = reviewerNote().trim();
if (!note) return;
setActionLoading(true);
setActionMsg('');
try {
const res = await adminFetch(`/api/admin/verifications/${params.id}/notes`, {
method: 'POST',
body: JSON.stringify({ notes: note }),
});
if (res.ok) {
setActivityNotes((prev) => [...prev, `Reviewer note: ${note}`]);
setActionMsg('Note added.');
} else {
const d = await res.json().catch(() => ({}));
setActionMsg(d.error ?? 'Failed to add note. Please try again.');
}
} catch {
setActionMsg('Network error. Please try again.');
} finally {
setActionLoading(false);
}
};
const rejectSubmission = async () => { const rejectSubmission = async () => {
if (!rejectReason().trim()) { setShowRejectInput(true); return; } if (!rejectReason().trim()) { setShowRejectInput(true); return; }
setActionLoading(true); setActionLoading(true);
@ -533,7 +557,7 @@ export default function VerificationReviewDetailPage() {
<div class="table-card" style="border-radius:14px;padding:14px"> <div class="table-card" style="border-radius:14px;padding:14px">
<p style="margin:0;font-size:12px;font-weight:700;color:#64748B;letter-spacing:0.06em;text-transform:uppercase">Reviewer Notes</p> <p style="margin:0;font-size:12px;font-weight:700;color:#64748B;letter-spacing:0.06em;text-transform:uppercase">Reviewer Notes</p>
<textarea value={reviewerNote()} onInput={(e) => setReviewerNote(e.currentTarget.value)} style="margin-top:8px;width:100%;min-height:110px;border:1px solid #E5E7EB;border-radius:10px;padding:10px;font-size:13px;color:#374151;resize:vertical" /> <textarea value={reviewerNote()} onInput={(e) => setReviewerNote(e.currentTarget.value)} style="margin-top:8px;width:100%;min-height:110px;border:1px solid #E5E7EB;border-radius:10px;padding:10px;font-size:13px;color:#374151;resize:vertical" />
<button type="button" style="margin-top:8px;height:36px;width:100%;border-radius:10px;border:none;background:#0D0D2A;color:white;font-size:13px;font-weight:700">Add Note</button> <button type="button" onClick={addNote} disabled={actionLoading() || !reviewerNote().trim()} style="margin-top:8px;height:36px;width:100%;border-radius:10px;border:none;background:#0D0D2A;color:white;font-size:13px;font-weight:700">Add Note</button>
</div> </div>
<A href="/admin/approval" style="height:36px;border-radius:10px;border:none;background:#0D0D2A;padding:0 12px;font-size:13px;font-weight:700;color:white;display:inline-flex;align-items:center;justify-content:center;text-decoration:none"> <A href="/admin/approval" style="height:36px;border-radius:10px;border:none;background:#0D0D2A;padding:0 12px;font-size:13px;font-weight:700;color:white;display:inline-flex;align-items:center;justify-content:center;text-decoration:none">