Search & Filters — Technical Documentation
Last updated: February 2026
Table of Contents
- Overview
- Architecture
- Repository Map
- Core Flows
- FilterType Enum System
- API Endpoints
- Services & Business Logic
- Frontend Implementation
- Configuration
- Integration Points
1. Overview
Search & Filters provides prospect and company search with a type-safe enum-based filter system. The FilterType enum maps to metadata (label, icon, category), providing centralized filter definitions. The backend exposes search endpoints with filter parameters, autocomplete lookups, and paginated results. Frontend uses React Query hooks with the FilterType system for consistent UI rendering.
Primary repos: data-admin (frontend filter UI, FilterType system) and sopromasterdata (search API endpoints, autocomplete lookups).
2. Architecture
3. Repository Map
| Repository | Layer | Key Files |
|---|---|---|
| data-admin | FilterType Enum | src/types/enums/FilterType.ts |
| data-admin | Filter Metadata | src/types/enums/FilterType.ts (FILTER_METADATA object) |
| data-admin | Metadata Helpers | src/helpers/filterMetadataHelpers.ts |
| data-admin | Filter Hooks | src/hooks/useFilter.ts, useFilterItems.ts, usePinnedFilters.ts |
| data-admin | Search Page | src/pages/search/ |
| data-admin | Search Queries | src/api/search.queries.ts |
| data-admin | Utils Queries | src/api/utils.queries.ts |
| data-admin | Form-to-Params | src/utils/formToFilterParams.ts |
| data-admin | Enum Utils | src/utils/enumUtils.ts |
| sopromasterdata | Prospect Search | API/SoProMasterDBAPI/Controllers/ProspectController.cs |
| sopromasterdata | Company Search | API/SoProMasterDBAPI/Controllers/CompanyController.cs |
| sopromasterdata | Utils/Autocomplete | API/SoProMasterDBAPI/Controllers/UtilsController.cs |
| sopromasterdata | Search Service | SearchServices/SearchService.cs |
4. Core Flows
4.1 Search with Filters
4.2 Autocomplete Flow
5. FilterType Enum System
FilterType Enum
Location: src/types/enums/FilterType.ts
export enum FilterType {
COMPANY_NAME = "companyName",
INDUSTRY = "industry",
COMPANY_SIZE = "companySize",
REVENUE = "revenue",
JOB_TITLE = "jobTitle",
SENIORITY = "seniority",
DEPARTMENT = "department",
COUNTRY = "country",
REGION = "region",
CITY = "city",
TECHNOLOGY = "technology",
TECHNOLOGY_CATEGORY = "technologyCategory",
// ... additional filter types
}
FILTER_METADATA
Each FilterType maps to metadata:
export const FILTER_METADATA: Record<FilterType, FilterMetadata> = {
[FilterType.COMPANY_NAME]: {
label: "Company Names",
icon: "BuildingOfficeIcon",
category: "Company",
description: "Filter by company name",
},
[FilterType.INDUSTRY]: {
label: "Industries",
icon: "BriefcaseIcon",
category: "Company",
description: "Filter by industry classification",
},
// ... metadata for each filter type
};
Helper Functions
Location: src/helpers/filterMetadataHelpers.ts
// Get metadata for a filter
getFilterMetadata(FilterType.COMPANY_NAME);
// → { label: "Company Names", icon: "BuildingOfficeIcon", ... }
// Check if a filter is active
isFilterActive(formData, FilterType.INDUSTRY);
// → true/false
// Get all active filters with metadata
getActiveFilters(formData);
// → [{ type: FilterType.INDUSTRY, metadata: {...}, value: "Technology" }]
Why Enum-Based?
The previous string-based system had:
- No type safety (typos caused silent failures)
- Manual icon mapping in each component
- Inconsistent labels across the UI
- Maintenance headaches when adding filters
The enum-based system provides:
- Type safety — compiler catches invalid filter references
- Centralized metadata — labels, icons, categories defined once
- Consistent UI — every filter rendered the same way
- Easy extension — add a filter type + metadata entry
6. API Endpoints
Prospect Search
| Method | Endpoint | Description |
|---|---|---|
GET | /api/Prospects/Search | Search prospects with filters |
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
q | string | Free-text search query |
industry | string[] | Industry filter values |
jobTitle | string[] | Job title filter values |
seniority | string[] | Seniority level values |
country | string[] | Country filter values |
companySize | string[] | Company size ranges |
revenue | string[] | Revenue ranges |
technology | string[] | Technology filter values |
page | int | Page number (1-based) |
pageSize | int | Results per page |
Company Search
| Method | Endpoint | Description |
|---|---|---|
GET | /api/Companies/Search | Search companies with filters |
GET | /api/Companies/{id} | Get company detail |
Utils / Autocomplete
| Method | Endpoint | Description |
|---|---|---|
GET | /api/Utils/Autocomplete | Autocomplete suggestions for filter values |
GET | /api/Utils/Industries | List all industries |
GET | /api/Utils/Technologies | List all technologies |
GET | /api/Utils/Countries | List all countries |
GET | /api/Utils/RevenueRanges | List revenue range options |
GET | /api/Utils/CompanySizes | List company size options |
GET | /api/Utils/Seniorities | List seniority levels |
7. Services & Business Logic
Backend Services
SearchService
Location: SearchServices/SearchService.cs
Interface: ISearchService
| Method | Description |
|---|---|
SearchProspectsAsync() | Full-text + filter search against prospect database |
SearchCompaniesAsync() | Company search with filter parameters |
GetBreakdownAsync() | Aggregated distribution of results by category |
Frontend Hooks
useFilter
Location: src/hooks/useFilter.ts
Purpose: Manages filter state — adding, removing, and clearing individual filters.
useFilterItems
Location: src/hooks/useFilterItems.ts
Purpose: Fetches available filter options (used for dropdowns and autocomplete).
usePinnedFilters
Location: src/hooks/usePinnedFilters.ts
Purpose: Manages saved filter combinations for quick access.
useCompanySearch
Location: src/hooks/useCompanySearch.ts
Purpose: Encapsulates company search logic with debounced input.
Utility Functions
formToFilterParams
Location: src/utils/formToFilterParams.ts
Purpose: Converts React Hook Form data into API-compatible filter parameters.
// Transforms form state → URL query parameters
const params = formToFilterParams(formData);
// { industry: ["Technology"], seniority: ["VP", "Director"], country: ["UK"] }
enumUtils
Location: src/utils/enumUtils.ts
Purpose: Generic enum serialization/deserialization utilities.
8. Frontend Implementation
Component Structure
Import Pattern
import { FilterType, FILTER_METADATA } from "@enums";
import { getFilterMetadata, isFilterActive, getActiveFilters } from "@helpers/filterMetadataHelpers";
import { useFilter } from "@hooks/useFilter";
import { formToFilterParams } from "@utils/formToFilterParams";
9. Configuration
Frontend DI
Enum exports: src/types/enums/index.ts — barrel export for FilterType and FILTER_METADATA
Endpoints: src/api/endpoints.ts
endpoints: {
prospects: { search: "/Prospects/Search" },
companies: { search: "/Companies/Search", getById: "/Companies" },
utils: {
autocomplete: "/Utils/Autocomplete",
industries: "/Utils/Industries",
technologies: "/Utils/Technologies",
// ...
}
}
Backend DI
DataApi: API/SoProMasterDBAPI/Extensions/ApiServiceExtensions.cs
services.AddScoped<ISearchService, SearchService>();
10. Integration Points
Upstream (data flows in)
| Source | Data | Mechanism |
|---|---|---|
| Prospect Database | Prospect records for search indexing | SQL Server queries |
| Company Database | Company records with metadata | SQL Server queries |
| Lookup Tables | Industries, technologies, locations, sizes | Utils API endpoints |
| ClickHouse | Fast analytical queries for breakdowns | Dapper ClickHouse service |
Downstream (data flows out)
| Target | Data | Mechanism |
|---|---|---|
| Data Admin UI | Search results, autocomplete suggestions | REST API → React Query |
| Audience Management | Filter definitions reused for audience targeting | Shared FilterType system |
Cross-Feature Dependencies
| Feature | Relationship |
|---|---|
| Audience Management | Audience targeting uses the same filter concepts |
| Verification Pipeline | Verification status appears as a searchable property |
| Campaign Management | Campaign prospects are searchable with the same filters |