diff --git a/src/components/campaign/PrimaryContactCombobox.tsx b/src/components/campaign/PrimaryContactCombobox.tsx index 09eb394e..9d33dbca 100644 --- a/src/components/campaign/PrimaryContactCombobox.tsx +++ b/src/components/campaign/PrimaryContactCombobox.tsx @@ -19,24 +19,22 @@ export const PrimaryContactCombobox = ({ name, current, search, -}: PrimaryContactComboboxProps) => { - return ( - { - const result = await search(query) - const limit = result.current ? 99 : 100 - return result.options.slice(0, limit).map((contact) => ({ - id: contact.id, - label: contactLabel(contact), - })) - }} - pinnedOptions={current ? [{ id: current.id, label: contactLabel(current) }] : []} - pinnedGroupHeading="Contato atual" - /> - ) -} +}: PrimaryContactComboboxProps) => ( + { + const result = await search(query) + const limit = result.current ? 99 : 100 + return result.options.slice(0, limit).map((contact) => ({ + id: contact.id, + label: contactLabel(contact), + })) + }} + pinnedOptions={current ? [{ id: current.id, label: contactLabel(current) }] : []} + pinnedGroupHeading="Contato atual" + /> +) diff --git a/src/utilities/supporterListFilters.ts b/src/utilities/supporterListFilters.ts index abcdee72..be0bdb21 100644 --- a/src/utilities/supporterListFilters.ts +++ b/src/utilities/supporterListFilters.ts @@ -1,4 +1,3 @@ -import { sql } from '@payloadcms/db-postgres' import type { Where } from 'payload' import { isContactSearchQueryReady, normalizeContactSearchQuery } from '@/lib/contactSearchQuery' @@ -11,11 +10,6 @@ export type SupporterSearchTerms = { phoneDigits: string | null } -export type AggregateSqlConditions = { - conditions: ReturnType[] - needsContactJoin: boolean -} - export const buildSupporterSearchTerms = (rawQ: string): SupporterSearchTerms | null => { if (!isContactSearchQueryReady(rawQ)) return null @@ -41,21 +35,6 @@ const buildPayloadSearchWhere = (terms: SupporterSearchTerms): Where => { return { or: searchFilters } } -const buildSqlSearchCondition = (terms: SupporterSearchTerms): ReturnType => { - const searchTerms: ReturnType[] = [ - sql`"contact"."name" ILIKE ${`%${terms.q}%`}`, - sql`"contact"."city" ILIKE ${`%${terms.q}%`}`, - ] - - if (terms.normalizedPhone) { - searchTerms.push(sql`"contact"."phone" = ${terms.normalizedPhone}`) - } else if (terms.phoneDigits) { - searchTerms.push(sql`"contact"."phone" ILIKE ${`%${terms.phoneDigits}%`}`) - } - - return sql`(${sql.join(searchTerms, sql` OR `)})` -} - export const toPayloadWhere = (state: SupporterListState): Where => { const filters: Where[] = [] @@ -78,31 +57,3 @@ export const toPayloadWhere = (state: SupporterListState): Where => { return filters.length ? { and: filters } : {} } - -export const toAggregateSqlConditions = (state: SupporterListState): AggregateSqlConditions => { - const conditions: ReturnType[] = [] - let needsContactJoin = false - - if (state.voteIntention) { - conditions.push(sql`"supporter"."vote_intention" = ${state.voteIntention}`) - } - - if (state.nucleus) { - conditions.push(sql`"supporter"."nucleus_id" = ${state.nucleus}`) - } - - if (state.city) { - needsContactJoin = true - conditions.push(sql`"contact"."city" = ${state.city}`) - } - - if (state.q) { - const searchTerms = buildSupporterSearchTerms(state.q) - if (searchTerms) { - needsContactJoin = true - conditions.push(buildSqlSearchCondition(searchTerms)) - } - } - - return { conditions, needsContactJoin } -} diff --git a/src/utilities/supporterListOverviewAggregate.ts b/src/utilities/supporterListOverviewAggregate.ts index 00115ba2..09647e6d 100644 --- a/src/utilities/supporterListOverviewAggregate.ts +++ b/src/utilities/supporterListOverviewAggregate.ts @@ -6,7 +6,7 @@ import type { Payload } from 'payload' import type { CampaignUser } from '@/payload-types' import { getCoordinatorNucleusIds, isCampaignGeneral } from '@/utilities/campaignAccess' import { drizzleResultRows } from '@/utilities/drizzleBulk' -import { toAggregateSqlConditions } from '@/utilities/supporterListFilters' +import { toAggregateSqlConditions } from '@/utilities/supporterListSqlFilters' import type { SupporterListState } from '@/utilities/supporterUi' import type { SupporterListOverviewViewModel } from '@/utilities/supporterViewModels' diff --git a/src/utilities/supporterListSqlFilters.ts b/src/utilities/supporterListSqlFilters.ts new file mode 100644 index 00000000..4963365f --- /dev/null +++ b/src/utilities/supporterListSqlFilters.ts @@ -0,0 +1,57 @@ +import 'server-only' + +import { sql } from '@payloadcms/db-postgres' + +import { + buildSupporterSearchTerms, + type SupporterSearchTerms, +} from '@/utilities/supporterListFilters' +import type { SupporterListState } from '@/utilities/supporterUi' + +export type AggregateSqlConditions = { + conditions: ReturnType[] + needsContactJoin: boolean +} + +const buildSqlSearchCondition = (terms: SupporterSearchTerms): ReturnType => { + const searchTerms: ReturnType[] = [ + sql`"contact"."name" ILIKE ${`%${terms.q}%`}`, + sql`"contact"."city" ILIKE ${`%${terms.q}%`}`, + ] + + if (terms.normalizedPhone) { + searchTerms.push(sql`"contact"."phone" = ${terms.normalizedPhone}`) + } else if (terms.phoneDigits) { + searchTerms.push(sql`"contact"."phone" ILIKE ${`%${terms.phoneDigits}%`}`) + } + + return sql`(${sql.join(searchTerms, sql` OR `)})` +} + +export const toAggregateSqlConditions = (state: SupporterListState): AggregateSqlConditions => { + const conditions: ReturnType[] = [] + let needsContactJoin = false + + if (state.voteIntention) { + conditions.push(sql`"supporter"."vote_intention" = ${state.voteIntention}`) + } + + if (state.nucleus) { + conditions.push(sql`"supporter"."nucleus_id" = ${state.nucleus}`) + } + + if (state.city) { + needsContactJoin = true + conditions.push(sql`"contact"."city" = ${state.city}`) + } + + if (state.q) { + const searchTerms = buildSupporterSearchTerms(state.q) + if (searchTerms) { + needsContactJoin = true + conditions.push(buildSqlSearchCondition(searchTerms)) + } + } + + return { conditions, needsContactJoin } +} diff --git a/tests/int/supporterListFilters.int.spec.ts b/tests/int/supporterListFilters.int.spec.ts index ead64a8c..027a66fa 100644 --- a/tests/int/supporterListFilters.int.spec.ts +++ b/tests/int/supporterListFilters.int.spec.ts @@ -2,11 +2,8 @@ import { describe, expect, it } from 'vitest' -import { - buildSupporterSearchTerms, - toAggregateSqlConditions, - toPayloadWhere, -} from '@/utilities/supporterListFilters' +import { buildSupporterSearchTerms, toPayloadWhere } from '@/utilities/supporterListFilters' +import { toAggregateSqlConditions } from '@/utilities/supporterListSqlFilters' describe('supporterListFilters', () => { it('ignores search terms shorter than the contact search minimum', () => {