feat: scope filterable fields by agent type and update filters dynamically on selection change
This commit is contained in:
@@ -460,14 +460,11 @@ function ProfilesPageContent() {
|
|||||||
}
|
}
|
||||||
}, [typeFromUrl, nameFromUrl, filtersFromUrl]);
|
}, [typeFromUrl, nameFromUrl, filtersFromUrl]);
|
||||||
|
|
||||||
// Fetch agent types and filter fields on mount
|
// Fetch agent types on mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchInitialData = async () => {
|
const fetchAgentTypesOnly = async () => {
|
||||||
try {
|
try {
|
||||||
const [types, fields] = await Promise.all([
|
const types = await agentsService.getAgentTypes();
|
||||||
agentsService.getAgentTypes(),
|
|
||||||
profileSectionsService.getFilterableFields(),
|
|
||||||
]);
|
|
||||||
setAgentTypes(types);
|
setAgentTypes(types);
|
||||||
|
|
||||||
// If listing param is set, auto-select the matching agent type
|
// If listing param is set, auto-select the matching agent type
|
||||||
@@ -478,8 +475,19 @@ function ProfilesPageContent() {
|
|||||||
setActiveTypeId(matchedType.id);
|
setActiveTypeId(matchedType.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch agent types:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAgentTypesOnly();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Convert FilterableField to FilterField format
|
// Re-fetch filter fields whenever the selected agent type changes so the Filters modal
|
||||||
|
// only shows options relevant to that agent type (plus globals).
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchFilters = async () => {
|
||||||
|
try {
|
||||||
|
const fields = await profileSectionsService.getFilterableFields(activeTypeId);
|
||||||
const filterFieldsData: FilterField[] = fields.map((f: FilterableField) => ({
|
const filterFieldsData: FilterField[] = fields.map((f: FilterableField) => ({
|
||||||
slug: f.slug,
|
slug: f.slug,
|
||||||
name: f.name,
|
name: f.name,
|
||||||
@@ -487,12 +495,21 @@ function ProfilesPageContent() {
|
|||||||
options: f.options,
|
options: f.options,
|
||||||
}));
|
}));
|
||||||
setFilterFields(filterFieldsData);
|
setFilterFields(filterFieldsData);
|
||||||
|
// Drop any selected filter keys that no longer exist in the new field list
|
||||||
|
setFilters((prev) => {
|
||||||
|
const validSlugs = new Set(filterFieldsData.map((f) => f.slug));
|
||||||
|
const next: typeof prev = {};
|
||||||
|
for (const [k, v] of Object.entries(prev)) {
|
||||||
|
if (validSlugs.has(k)) next[k] = v;
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch initial data:', error);
|
console.error('Failed to fetch filter fields:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchInitialData();
|
fetchFilters();
|
||||||
}, []);
|
}, [activeTypeId]);
|
||||||
|
|
||||||
// Fetch agents based on filters
|
// Fetch agents based on filters
|
||||||
const fetchAgents = useCallback(async () => {
|
const fetchAgents = useCallback(async () => {
|
||||||
|
|||||||
@@ -128,10 +128,13 @@ class ProfileSectionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all filterable fields with options (for search filters)
|
* Get all filterable fields with options (for search filters).
|
||||||
|
* When `agentTypeId` is provided, filters are scoped to that agent type's sections plus globals.
|
||||||
*/
|
*/
|
||||||
async getFilterableFields(): Promise<FilterableField[]> {
|
async getFilterableFields(agentTypeId?: string | null): Promise<FilterableField[]> {
|
||||||
const response = await api.get<ApiResponse<FilterableField[]>>('/profile-fields/filterable');
|
const response = await api.get<ApiResponse<FilterableField[]>>('/profile-fields/filterable', {
|
||||||
|
params: agentTypeId ? { agentTypeId } : undefined,
|
||||||
|
});
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user