feat: de-duplicate filterable fields by both slug and normalized name, merging options from fields with the same name but different slugs.

This commit is contained in:
pradeepkumar
2026-02-01 16:14:34 +05:30
parent 91d4625fcd
commit b8b26b236d

View File

@@ -234,6 +234,7 @@ export class ProfileFieldsService {
/** /**
* Get all filterable fields (public endpoint for search filters) * Get all filterable fields (public endpoint for search filters)
* Returns fields with CHECKBOX_GROUP, SELECT, MULTI_SELECT types that have options * Returns fields with CHECKBOX_GROUP, SELECT, MULTI_SELECT types that have options
* De-duplicates by both slug AND name to handle duplicate fields with different slugs
*/ */
async getFilterableFields() { async getFilterableFields() {
const filterableTypes: FieldType[] = [FieldType.CHECKBOX_GROUP, FieldType.SELECT, FieldType.MULTI_SELECT]; const filterableTypes: FieldType[] = [FieldType.CHECKBOX_GROUP, FieldType.SELECT, FieldType.MULTI_SELECT];
@@ -265,6 +266,7 @@ export class ProfileFieldsService {
}); });
// Group fields by slug to merge options from different sections (same field in different agent types) // Group fields by slug to merge options from different sections (same field in different agent types)
// Also track by normalized name to de-duplicate fields with same name but different slugs
const mergedFields = new Map<string, { const mergedFields = new Map<string, {
slug: string; slug: string;
name: string; name: string;
@@ -272,25 +274,49 @@ export class ProfileFieldsService {
options: { label: string; value: string }[]; options: { label: string; value: string }[];
}>(); }>();
for (const field of fields) { // Map normalized names to their primary slug for de-duplication
const existingField = mergedFields.get(field.slug); const nameToSlugMap = new Map<string, string>();
const fieldOptions = (field.options as { label: string; value: string }[]) || [];
if (existingField) { for (const field of fields) {
// Merge options, avoiding duplicates by value const fieldOptions = (field.options as { label: string; value: string }[]) || [];
const existingValues = new Set(existingField.options.map(o => o.value)); const normalizedName = field.name.toLowerCase().trim();
for (const opt of fieldOptions) {
if (!existingValues.has(opt.value)) { // Check if we already have a field with this name (different slug, same name)
existingField.options.push(opt); const existingSlugForName = nameToSlugMap.get(normalizedName);
if (existingSlugForName) {
// Merge into existing field with same name
const existingField = mergedFields.get(existingSlugForName);
if (existingField) {
const existingValues = new Set(existingField.options.map(o => o.value));
for (const opt of fieldOptions) {
if (!existingValues.has(opt.value)) {
existingField.options.push(opt);
}
} }
} }
} else { } else {
mergedFields.set(field.slug, { // Check if we have an existing field with same slug
slug: field.slug, const existingFieldBySlug = mergedFields.get(field.slug);
name: field.name,
fieldType: field.fieldType, if (existingFieldBySlug) {
options: [...fieldOptions], // Merge options, avoiding duplicates by value
}); const existingValues = new Set(existingFieldBySlug.options.map(o => o.value));
for (const opt of fieldOptions) {
if (!existingValues.has(opt.value)) {
existingFieldBySlug.options.push(opt);
}
}
} else {
// New field - add to both maps
mergedFields.set(field.slug, {
slug: field.slug,
name: field.name,
fieldType: field.fieldType,
options: [...fieldOptions],
});
nameToSlugMap.set(normalizedName, field.slug);
}
} }
} }