teqo-backup/src/components/campaign/MunicipalityStrategyCard.tsx
Francisco Ignácio Fontoura Solla c07969f4a7 Remove duplicated voteGoals; seed projection sheet into expectedVotes.
Meta Bom/Regular/Mínimo duplicated the estimate scenarios — keep a single municipality series (pessimista/média/otimista), backfill then drop the old columns, and map the spreadsheet onto expectedVotes.
2026-07-24 14:04:44 -03:00

141 lines
4.9 KiB
TypeScript

import { PencilIcon } from 'lucide-react'
import Link from 'next/link'
import { StaffMunicipalityVotesDisplay } from '@/components/campaign/StaffMunicipalityVotesDisplay'
import { StateDeputyChips } from '@/components/campaign/StateDeputyChips'
import { Badge } from '@/components/ui/Badge'
import { Button } from '@/components/ui/button'
import {
municipalityPriorityLabels,
politicalTrendBadgeVariant,
politicalTrendLabels,
} from '@/utilities/municipalityUi'
import type { MunicipalityDetailViewModel } from '@/utilities/municipalityViewModels'
import type { MunicipalityPledgeCoverageView } from '@/utilities/votePledgeData'
const dateFormatter = new Intl.DateTimeFormat('pt-BR')
export const MunicipalityStrategyCard = ({
strategy,
municipalitySlug,
canEdit,
pledgeCoverage,
}: {
strategy: NonNullable<MunicipalityDetailViewModel['strategy']>
municipalitySlug: string
canEdit: boolean
pledgeCoverage: MunicipalityPledgeCoverageView | null
}) => {
const trend = strategy.politicalTrend
return (
<section
aria-labelledby="municipality-strategy-title"
className="flex flex-col gap-4 rounded-xl border p-4"
>
<div className="flex items-start justify-between gap-2">
<div className="flex flex-col gap-1">
<h2 id="municipality-strategy-title" className="text-base font-medium">
Estratégia do município
</h2>
<div className="flex flex-wrap items-center gap-2">
{strategy.priority === 'alta' ? (
<Badge variant="destructive">{municipalityPriorityLabels.alta}</Badge>
) : (
<Badge variant="secondary">Prioridade normal</Badge>
)}
{trend.status ? (
<Badge variant={politicalTrendBadgeVariant[trend.status]}>
Tendência {politicalTrendLabels[trend.status].toLowerCase()}
</Badge>
) : (
<Badge variant="outline">Tendência não registrada</Badge>
)}
</div>
</div>
{canEdit ? (
<Button asChild variant="outline" className="min-h-11">
<Link href={`/campanha/municipios/${municipalitySlug}/editar`}>
<PencilIcon data-icon="inline-start" aria-hidden="true" />
Editar
</Link>
</Button>
) : null}
</div>
<div className="rounded-lg bg-muted/40 px-3 py-2">
<p className="text-xs font-medium text-muted-foreground">Votos estimados</p>
<StaffMunicipalityVotesDisplay
expectedVotes={strategy.expectedVotes}
pledgeCoverage={pledgeCoverage}
/>
</div>
{trend.status || trend.note ? (
<div className="flex flex-col gap-1">
<h3 className="text-sm font-medium">Tendência política</h3>
{trend.note ? (
<p className="whitespace-pre-wrap text-sm text-muted-foreground">{trend.note}</p>
) : null}
{trend.recordedAt ? (
<p className="text-xs text-muted-foreground">
Registrada {trend.recordedByName ? `por ${trend.recordedByName} ` : ''}em{' '}
{dateFormatter.format(new Date(trend.recordedAt))}
</p>
) : null}
</div>
) : null}
{strategy.strengths.length > 0 || strategy.risks.length > 0 ? (
<div className="grid gap-4 sm:grid-cols-2">
{strategy.strengths.length > 0 ? (
<div>
<h3 className="text-sm font-medium">Forças</h3>
<ul className="mt-1 list-inside list-disc text-sm text-muted-foreground">
{strategy.strengths.map((text) => (
<li key={text}>{text}</li>
))}
</ul>
</div>
) : null}
{strategy.risks.length > 0 ? (
<div>
<h3 className="text-sm font-medium">Riscos</h3>
<ul className="mt-1 list-inside list-disc text-sm text-muted-foreground">
{strategy.risks.map((text) => (
<li key={text}>{text}</li>
))}
</ul>
</div>
) : null}
</div>
) : null}
{strategy.stateDeputies.length > 0 ? (
<div>
<h3 className="text-sm font-medium">Dobradinhas</h3>
<div className="mt-2">
<StateDeputyChips deputies={strategy.stateDeputies} />
</div>
</div>
) : null}
{strategy.dobradinhaNotes ? (
<div>
<h3 className="text-sm font-medium">Dobradinhas (notas)</h3>
<p className="mt-1 whitespace-pre-wrap text-sm text-muted-foreground">
{strategy.dobradinhaNotes}
</p>
</div>
) : null}
{strategy.nextSteps ? (
<div>
<h3 className="text-sm font-medium">Encaminhamentos</h3>
<p className="mt-1 whitespace-pre-wrap text-sm text-muted-foreground">
{strategy.nextSteps}
</p>
</div>
) : null}
</section>
)
}