fix: job seekers unable to submit verification documents
All checks were successful
build-and-release / build (push) Successful in 1m51s

The dashboard's Submit for Verification widget checked profile_data for
a documents/documents_data field that GET /api/jobseeker/profile/me never
returns, so the Submit button stayed permanently disabled. Even bypassing
that, it POSTed {document_urls: []}, a field the backend doesn't
recognize, instead of the profile_data shape submit-for-verification
actually expects.

Now fetches the job seeker's real uploaded documents via
GET /api/jobseeker/profile/documents, checks the correct document_type
field, and submits profile_data merged with the uploaded document URLs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Ashwin Kumar Sivakumar 2026-07-23 04:26:13 +05:30
parent 18a9161e4f
commit 070c4bdab1
2 changed files with 25 additions and 12 deletions

View file

@ -13,7 +13,7 @@ import ProfileCompletionWidget from './widgets/ProfileCompletionWidget';
import VerificationWidget from './widgets/VerificationWidget';
import AiUsageWidget from './widgets/AiUsageWidget';
import VerificationSubmissionGuide from './VerificationSubmissionGuide';
import { fetchProfile } from '~/lib/api';
import { fetchProfile, fetchDocuments } from '~/lib/api';
import {
getBasicFields,
getDocFields,
@ -101,6 +101,7 @@ export default function MyDashboardPage(props: Props) {
const [draggingIdx, setDraggingIdx] = createSignal<number | null>(null);
const [visibleWidgets, setVisibleWidgets] = createSignal<Set<string>>(new Set());
const [profileData, setProfileData] = createSignal<Record<string, any>>({});
const [documents, setDocuments] = createSignal<any[]>([]);
const [submitting, setSubmitting] = createSignal(false);
const getRoleType = (): string => {
@ -135,6 +136,11 @@ export default function MyDashboardPage(props: Props) {
const data = await fetchProfile(prefix);
if (data) setProfileData(data);
} catch { /* ignore */ }
if (props.roleKey === 'JOB_SEEKER') {
try {
setDocuments(await fetchDocuments(prefix));
} catch { /* ignore */ }
}
};
const missingBasicLabels = createMemo(() => {
@ -148,12 +154,10 @@ export default function MyDashboardPage(props: Props) {
});
const missingDocLabels = createMemo(() => {
const data = profileData();
if (!data) return [];
const docs = data.documents || data.documents_data || [];
const docs = documents();
return getDocFields(props.roleKey)
.filter((doc) => doc.required)
.filter((doc) => !docs.some((d: any) => d?.doc_type === doc.key))
.filter((doc) => !docs.some((d: any) => d?.document_type === doc.key))
.map((doc) => doc.label);
});
@ -178,14 +182,18 @@ export default function MyDashboardPage(props: Props) {
}
setSubmitting(true);
try {
const res = await apiFetch("/api/profile/submit-for-verification", {
method: "POST",
body: JSON.stringify({ roleKey: props.roleKey, document_urls: [] }),
});
if (res.ok || res.status === 200) {
// Update verification status to PENDING
props.onVerificationStatusChange?.("PENDING");
const data = profileData();
const p = data.profile || data;
const docUrls: Record<string, string> = {};
for (const d of documents()) {
if (d?.document_type && d?.file_url) docUrls[d.document_type] = d.file_url;
}
// apiFetch() throws on a non-2xx response, so reaching this point means the submission succeeded.
await apiFetch("/api/profile/submit-for-verification", {
method: "POST",
body: JSON.stringify({ roleKey: props.roleKey, profile_data: { ...p, ...docUrls } }),
});
props.onVerificationStatusChange?.("PENDING");
} catch {
// silently fail - the profile page handles submission errors
} finally {

View file

@ -70,6 +70,11 @@ export async function saveProfile(rolePrefix: string, payload: any): Promise<any
});
}
export async function fetchDocuments(rolePrefix: string): Promise<any[]> {
const res = await apiFetch(`/api/${rolePrefix}/profile/documents`);
return res?.data ?? [];
}
export async function submitProfileForVerification(rolePrefix: string): Promise<any> {
return apiFetch(`/api/${rolePrefix}/profile/submit`, {
method: 'POST',