refactor: update orphan value filtering and availability type logic in profile data mapper

This commit is contained in:
pradeepkumar
2026-04-15 14:41:28 +05:30
parent 87d8ee389a
commit affaefc29a

View File

@@ -291,21 +291,21 @@ export function mapFieldValuesToAvailability(fieldValues: FieldValueResponse[]):
return trimmed; return trimmed;
}; };
// Use backend-resolved labels only. Drop stale/orphan values whose option is no longer // Drop stale/orphan options. Backend returns `valueLabel[i]` equal to the raw `value[i]`
// defined in the profile field (backend returns no label for them) — prevents old // when no option match is found (admin renamed/removed the option). Those are orphans —
// selections from lingering when admin renames/removes options. // skip them entirely so old selections don't linger on the public profile.
const resolvedLabels: string[] = []; const resolvedLabels: string[] = [];
rawValues.forEach((val, i) => { rawValues.forEach((val, i) => {
const fromBackend = labelValues[i];
if (fromBackend && typeof fromBackend === 'string' && fromBackend.trim()) {
resolvedLabels.push(formatIfSnakeCase(fromBackend));
return;
}
// No backend label → likely a stale option; skip unless it's already a human-readable string
const raw = String(val || '').trim(); const raw = String(val || '').trim();
if (!raw) return; if (!raw) return;
if (/^[a-z0-9]+(_[a-z0-9]+)+$/i.test(raw)) return; // skip snake_case orphans const fromBackend = labelValues[i];
resolvedLabels.push(formatIfSnakeCase(raw)); const hasResolvedLabel =
fromBackend &&
typeof fromBackend === 'string' &&
fromBackend.trim() &&
fromBackend !== raw; // backend-resolved label must DIFFER from raw value
if (!hasResolvedLabel) return; // orphan — drop
resolvedLabels.push(formatIfSnakeCase(fromBackend));
}); });
// Deduplicate by normalized comparison (case/whitespace insensitive) // Deduplicate by normalized comparison (case/whitespace insensitive)
@@ -319,15 +319,18 @@ export function mapFieldValuesToAvailability(fieldValues: FieldValueResponse[]):
} }
} }
// Determine availability type based on values OR resolved labels // Determine availability type from resolved labels only (orphan values were already dropped).
const allValues = [...rawValues.map(v => String(v)), ...resolvedLabels]; // If nothing valid remains, don't fabricate a type.
let type = 'Available'; let type = '';
if (allValues.some(v => matchesKeyword(v, fullTimeKeywords))) { if (resolvedLabels.length > 0) {
type = 'Full-time'; type = 'Available';
} else if (allValues.some(v => matchesKeyword(v, partTimeKeywords))) { if (resolvedLabels.some(v => matchesKeyword(v, fullTimeKeywords))) {
type = 'Part-time'; type = 'Full-time';
} else if (allValues.some(v => matchesKeyword(v, flexibleKeywords))) { } else if (resolvedLabels.some(v => matchesKeyword(v, partTimeKeywords))) {
type = 'Flexible'; type = 'Part-time';
} else if (resolvedLabels.some(v => matchesKeyword(v, flexibleKeywords))) {
type = 'Flexible';
}
} }
return { type, schedule, label }; return { type, schedule, label };