mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
Merge client-side recent visits and last-acted municipality storage into wizard municipality suggest idle list ahead of B92 server rankings. - Add campaignLastActedMunicipality + wizardMunicipalitySuggestMerge libs - Extend wizard-municipality-suggest with scopeMunicipalities for hit lookup - Record last-acted on wizard write success (votes, signal, trend, leadership) - Clear last-acted on logout alongside recent visits Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
75 lines
2.5 KiB
TypeScript
75 lines
2.5 KiB
TypeScript
import 'server-only'
|
|
|
|
import type { Payload } from 'payload'
|
|
|
|
import {
|
|
toHomeSearchMunicipalityHit,
|
|
type WizardMunicipalitySearchSuccessResponse,
|
|
} from '@/lib/campaignHomeSearchHits'
|
|
import { HOME_SEARCH_STAFF_ONLY_MESSAGE } from '@/lib/campaignHomeSearchMessages'
|
|
import { isStaffCampaignRole } from '@/lib/campaignRoles'
|
|
import { DEFAULT_VOTE_RANK_YEAR, getMunicipalityVoteRank } from '@/lib/municipalityVoteRank'
|
|
import {
|
|
rankWizardMunicipalitySuggestions,
|
|
type WizardMunicipalitySuggestInput,
|
|
} from '@/lib/wizardMunicipalitySuggest'
|
|
import type { CampaignUser } from '@/payload-types'
|
|
import { loadMunicipalityScope } from '@/utilities/municipality/campaignMunicipalityScope'
|
|
import { resolveMunicipalityLastSignalAt } from '@/utilities/municipality/municipalitySignal'
|
|
import { computeMunicipalityTerritorialClass } from '@/utilities/municipality/municipalityTerritorialClass'
|
|
|
|
export const loadWizardMunicipalitySuggestions = async (
|
|
payload: Payload,
|
|
user: CampaignUser,
|
|
): Promise<WizardMunicipalitySearchSuccessResponse> => {
|
|
if (!isStaffCampaignRole(user.role)) {
|
|
throw new Error(HOME_SEARCH_STAFF_ONLY_MESSAGE)
|
|
}
|
|
|
|
const { municipalities, pledgeAggregates } = await loadMunicipalityScope(
|
|
payload,
|
|
user,
|
|
{},
|
|
{
|
|
extraSelect: {
|
|
lastUpdateAt: true,
|
|
engagementLevel: true,
|
|
politicalTrend: true,
|
|
},
|
|
},
|
|
)
|
|
|
|
const inputs: WizardMunicipalitySuggestInput[] = municipalities.map((doc) => {
|
|
const aggregate = pledgeAggregates.get(doc.id)
|
|
const lastSignalAt = resolveMunicipalityLastSignalAt(
|
|
doc.lastUpdateAt ?? null,
|
|
aggregate?.lastPledgeAt ?? null,
|
|
)
|
|
const voteRank = getMunicipalityVoteRank(doc.slug, DEFAULT_VOTE_RANK_YEAR)
|
|
|
|
return {
|
|
slug: doc.slug,
|
|
name: doc.name,
|
|
lastSignalAt,
|
|
engagementLevel: doc.engagementLevel ?? null,
|
|
politicalTrend: doc.politicalTrend?.status ?? null,
|
|
territorialClass: computeMunicipalityTerritorialClass(doc.slug).class,
|
|
votes2022: voteRank?.votes ?? null,
|
|
}
|
|
})
|
|
|
|
const ranked = rankWizardMunicipalitySuggestions(inputs)
|
|
const docBySlug = new Map(municipalities.map((doc) => [doc.slug, doc]))
|
|
|
|
return {
|
|
status: 'success',
|
|
resultKind: 'wizard-suggest',
|
|
municipalities: ranked.map((input) => toHomeSearchMunicipalityHit(docBySlug.get(input.slug)!)),
|
|
scopeMunicipalities: municipalities.map((doc) => ({
|
|
slug: doc.slug,
|
|
name: doc.name,
|
|
region: doc.region,
|
|
priority: doc.priority ?? null,
|
|
})),
|
|
}
|
|
}
|