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
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:
parent
e78b7c2642
commit
ef8f4410c7
3 changed files with 30 additions and 5 deletions
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue