fix
This commit is contained in:
@@ -503,9 +503,17 @@ export class AgentsService {
|
|||||||
|
|
||||||
const matchingIds = matchingValues
|
const matchingIds = matchingValues
|
||||||
.filter((fv) => {
|
.filter((fv) => {
|
||||||
const jsonVal = fv.jsonValue as string[] | null;
|
const jsonVal = fv.jsonValue as unknown;
|
||||||
if (!jsonVal || !Array.isArray(jsonVal)) return false;
|
if (!Array.isArray(jsonVal)) return false;
|
||||||
return selectedValues.some((sv) => jsonVal.includes(sv));
|
// Direct match (normalized option values stored in jsonVal)
|
||||||
|
if (selectedValues.some((sv) => jsonVal.includes(sv))) return true;
|
||||||
|
// TAG_INPUT fallback: strip " - N yrs" suffix and normalize
|
||||||
|
const normalized = (jsonVal as unknown[])
|
||||||
|
.map((item) => typeof item === 'string' ? item : '')
|
||||||
|
.map((s) => s.replace(/\s*[-–]\s*\d+\s*(yrs?|years?)\s*$/i, '').trim())
|
||||||
|
.map((s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, ''))
|
||||||
|
.filter(Boolean);
|
||||||
|
return selectedValues.some((sv) => normalized.includes(sv));
|
||||||
})
|
})
|
||||||
.map((fv) => fv.agentProfileId);
|
.map((fv) => fv.agentProfileId);
|
||||||
|
|
||||||
@@ -664,11 +672,17 @@ export class AgentsService {
|
|||||||
const agentFieldValues = (agent.fieldValues || []) as any[];
|
const agentFieldValues = (agent.fieldValues || []) as any[];
|
||||||
const fieldMatch = agentFieldValues.some((fv: any) => {
|
const fieldMatch = agentFieldValues.some((fv: any) => {
|
||||||
if (fv.field?.slug !== filterSlug) return false;
|
if (fv.field?.slug !== filterSlug) return false;
|
||||||
const jsonVal = fv.jsonValue as string[] | null;
|
const jsonVal = fv.jsonValue as unknown;
|
||||||
if (jsonVal && Array.isArray(jsonVal)) {
|
if (!Array.isArray(jsonVal)) return false;
|
||||||
return selectedValues.some(sv => jsonVal.includes(sv));
|
// Direct match (normalized option values already stored in jsonVal)
|
||||||
}
|
if (selectedValues.some(sv => jsonVal.includes(sv))) return true;
|
||||||
return false;
|
// TAG_INPUT fallback: strip " - N yrs" suffix and normalize to match aggregated expertise values
|
||||||
|
const normalized = (jsonVal as unknown[])
|
||||||
|
.map((item) => typeof item === 'string' ? item : '')
|
||||||
|
.map((s) => s.replace(/\s*[-–]\s*\d+\s*(yrs?|years?)\s*$/i, '').trim())
|
||||||
|
.map((s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, ''))
|
||||||
|
.filter(Boolean);
|
||||||
|
return selectedValues.some(sv => normalized.includes(sv));
|
||||||
});
|
});
|
||||||
if (fieldMatch) matchedFilters++;
|
if (fieldMatch) matchedFilters++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -298,8 +298,16 @@ export class ProfileFieldsService {
|
|||||||
// Map normalized names to their primary slug for de-duplication
|
// Map normalized names to their primary slug for de-duplication
|
||||||
const nameToSlugMap = new Map<string, string>();
|
const nameToSlugMap = new Map<string, string>();
|
||||||
|
|
||||||
|
// Options to exclude from search filters (still available on profile forms via admin)
|
||||||
|
const EXCLUDED_OPTION_VALUES = new Set(['prefer_not_to_say', 'prefer-not-to-say', 'preferNotToSay']);
|
||||||
|
const isExcludedOption = (opt: { label: string; value: string }) => {
|
||||||
|
if (EXCLUDED_OPTION_VALUES.has(opt.value)) return true;
|
||||||
|
return opt.label.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '') === 'prefer_not_to_say';
|
||||||
|
};
|
||||||
|
|
||||||
for (const field of fields) {
|
for (const field of fields) {
|
||||||
const fieldOptions = (field.options as { label: string; value: string }[]) || [];
|
const rawOptions = (field.options as { label: string; value: string }[]) || [];
|
||||||
|
const fieldOptions = rawOptions.filter((opt) => !isExcludedOption(opt));
|
||||||
const normalizedName = field.name.toLowerCase().trim();
|
const normalizedName = field.name.toLowerCase().trim();
|
||||||
|
|
||||||
// Check if we already have a field with this name (different slug, same name)
|
// Check if we already have a field with this name (different slug, same name)
|
||||||
@@ -341,6 +349,61 @@ export class ProfileFieldsService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append TAG_INPUT expertise_areas as a dynamic filter — options aggregated from agent-entered values
|
||||||
|
const expertiseField = await this.prisma.profileField.findFirst({
|
||||||
|
where: {
|
||||||
|
slug: 'expertise_areas',
|
||||||
|
isActive: true,
|
||||||
|
fieldType: FieldType.TAG_INPUT,
|
||||||
|
section: {
|
||||||
|
isActive: true,
|
||||||
|
OR: [
|
||||||
|
{ isGlobal: true },
|
||||||
|
{ agentTypeSections: { some: {} } },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
select: { id: true, name: true, slug: true, fieldType: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (expertiseField && !mergedFields.has(expertiseField.slug)) {
|
||||||
|
const fieldValues = await this.prisma.profileFieldValue.findMany({
|
||||||
|
where: {
|
||||||
|
fieldId: expertiseField.id,
|
||||||
|
jsonValue: { not: Prisma.JsonNull },
|
||||||
|
},
|
||||||
|
select: { jsonValue: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
// value → label (preserve first-seen label casing)
|
||||||
|
const areaMap = new Map<string, string>();
|
||||||
|
for (const fv of fieldValues) {
|
||||||
|
const arr = fv.jsonValue as unknown;
|
||||||
|
if (!Array.isArray(arr)) continue;
|
||||||
|
for (const item of arr) {
|
||||||
|
if (typeof item !== 'string') continue;
|
||||||
|
// Strip " - N yrs" / " – N years" suffix used in the profile UI
|
||||||
|
const areaName = item.replace(/\s*[-–]\s*\d+\s*(yrs?|years?)\s*$/i, '').trim();
|
||||||
|
if (!areaName) continue;
|
||||||
|
const value = areaName.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');
|
||||||
|
if (!value) continue;
|
||||||
|
if (!areaMap.has(value)) areaMap.set(value, areaName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (areaMap.size > 0) {
|
||||||
|
const options = Array.from(areaMap.entries())
|
||||||
|
.map(([value, label]) => ({ label, value }))
|
||||||
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
|
mergedFields.set(expertiseField.slug, {
|
||||||
|
slug: expertiseField.slug,
|
||||||
|
name: expertiseField.name,
|
||||||
|
fieldType: expertiseField.fieldType,
|
||||||
|
options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Array.from(mergedFields.values());
|
return Array.from(mergedFields.values());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user