mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-14 08:53:11 +00:00
Collection actionPlan -> activity (labels "Atividade"/"Atividades"), campo
campaignDemand.actionPlan -> activity, rota /campanha/planos ->
/campanha/atividades (criacao em atividades/nova), sidebar "Atividades" e
rotulos alinhados a entidade ("Tipo de atividade", "Origem da atividade",
"Resultado da atividade"). Valores de enum kind/status/origin inalterados.
Schema movido por migration data-preserving escrita a mao
(20260725_213000_rename_action_plan_to_activity): 4 tabelas, 3 enums, 2
colunas, 39 indices (4 pkeys inclusos), 14 FKs e 2 sequences, cada statement
guardado na existencia do objeto de origem, com down() simetrico. O gerador do
Payload emitiria DROP+CREATE e nao ve o indice parcial escrito a mao
action_plan_upcoming_start_at_idx, entao a lista veio de
pg_indexes/pg_constraint/pg_type/pg_sequences e o snapshot .json foi derivado
do anterior por transformacao textual -- validado por migrate:create __probe
sem mudanca de schema. A mesma migration alinha os 8 indices fosseis %plaza%
que a remodelagem de municipios deixou (renomeou as colunas plaza_id, nao os
indices).
Guard: o describe "banned campaign terminology" de
codebaseConventions.unit.spec.ts virou tabela de termos varrendo src+tests+
scripts (migrations fora -- historia congelada), banindo os compostos
actionPlan, a copy "plano de acao" e a rota antiga, mas nao plan/plano isolado
(colidiria com os planos de assinatura da Fase 2). Allowlist: o proprio spec,
scripts/generate-remodel-municipalities-migration.mjs e o comentario historico
em campaignMigrationReconciliation.int.spec.ts.
Plano: docs/plans/renomear-plano-acao-para-atividade.md
50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
import { MessageSquareTextIcon } from 'lucide-react'
|
|
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
|
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/Empty'
|
|
import type { ActivityUpdateViewModel } from '@/utilities/activityViewModels'
|
|
import { formatBahiaDateTimeLabel } from '@/utilities/campaignTime'
|
|
|
|
const UpdateCard = ({ update }: { update: ActivityUpdateViewModel }) => (
|
|
<article>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="text-base">{update.authorName ?? 'Autor removido'}</CardTitle>
|
|
<p className="text-sm text-muted-foreground">
|
|
{update.createdAt ? formatBahiaDateTimeLabel(update.createdAt) : ''}
|
|
</p>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<p className="whitespace-pre-wrap">{update.body}</p>
|
|
</CardContent>
|
|
</Card>
|
|
</article>
|
|
)
|
|
|
|
export const ActivityUpdateFeed = ({ updates }: { updates: ActivityUpdateViewModel[] }) => {
|
|
if (!updates.length) {
|
|
return (
|
|
<Empty className="border">
|
|
<EmptyHeader>
|
|
<EmptyMedia variant="icon">
|
|
<MessageSquareTextIcon aria-hidden="true" />
|
|
</EmptyMedia>
|
|
<EmptyTitle>Nenhuma atualização registrada</EmptyTitle>
|
|
<EmptyDescription>
|
|
Envie o primeiro reporte para iniciar o histórico cronológico desta atividade.
|
|
</EmptyDescription>
|
|
</EmptyHeader>
|
|
</Empty>
|
|
)
|
|
}
|
|
|
|
const sortedUpdates = [...updates].reverse()
|
|
|
|
return (
|
|
<div className="flex flex-col gap-4">
|
|
{sortedUpdates.map((update, index) => (
|
|
<UpdateCard key={update.id ?? index} update={update} />
|
|
))}
|
|
</div>
|
|
)
|
|
}
|