Sobre

Historico de atualizacoes do GerenciApp

v1.0998 entradas

27 de Maio de 2026

46 itens
16723
CorrecaoCRM Deals (/crm/deals) — visao Kanban: todas as colunas (e portanto todos os cards, que sao `w-full` dentro das colunas) agora tem a mesma largura. As colunas usavam `min-w-65 max-w-75` (largura variavel entre 260px e 300px conforme o conteudo), o que fazia os cards de colunas diferentes terem larguras distintas. Substituido por `w-72` (largura fixa de 288px) mantendo `shrink-0`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
CorrecaoCRM Commissions (/crm/commissions): deals com `vertical_negocio === 'AMS'` deixaram de exibir o icone `BadgeCheck` regular/irregular (verde/vermelho) na coluna de comparacao de valores e PEPs — a celula fica vazia para esses casos, ja que AMS nao segue a mesma logica de bater itens vs recebiveis. Implementacao: no `useMemo` de `dealPepStatus`, novo set `amsDealIds` populado a partir de `dealsState.data` filtrando `(d.vertical_negocio ?? '').trim().toUpperCase() === 'AMS'`. No loop sobre `itemsState.data`, deals AMS sao excluidos antes de adicionar a `allDealIds`/`dealsWithPep`/`itemSumByDeal`. No loop sobre `receivablesState.data`, deals AMS tambem sao ignorados. Resultado: `dealPepStatus.get(amsDealId)` retorna `undefined`, e a celula da tabela renderiza `null` (sem icone). Dependencias do useMemo atualizadas: `[dealsState.data, itemsState.data, receivablesState.data]`. Arquivo: app/(app)/_components/crm-commissions-section.tsx.
NovidadeCRM Deals (/crm/deals/[id]): campo `Data Fechamento` (`close_date`) agora e editavel no modo edicao (antes era readonly fora do modo criacao). Removidos os props `readOnly={!isCreating}` e `inputClassName={!isCreating ? 'bg-slate-50 dark:bg-slate-800/50' : ''}` do `DatePickerInput` — agora o campo aceita edicao sempre. Save logic ja existia (no `changedPayload` o `close_date` ja era enviado via `if (formCloseDate !== iv.closeDate) changedPayload.close_date = formCloseDate || null`) e o `hasChanged` ja comparava contra `initialFormValues.current.closeDate`, entao a edicao agora ativa o botao Salvar e dispara PUT parcial corretamente. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: campo `Canal` reposicionado para a direita de `Contato` no painel de detalhes. Antes a Row 1 era `Titulo + Canal` (grid `[1fr_9rem]`) e a Row 2 era stack vertical de `Empresa / Contato / Oportunidade`. Agora: Row 1 = `Titulo` (ocupando 100% da largura, sem grid); Row 2 = stack com `Empresa` em cima, depois um sub-grid 2-col `[1fr_9rem]` com `Contato + Canal` lado a lado, e por fim `Oportunidade` embaixo. Justificativa: o canal e atributo do contato/conversa, fica mais coeso ao lado do nome do contato; libera o titulo para usar a largura cheia da coluna estreita. Wrapper do Contato ganhou `wrapperClassName="min-w-0"` para o truncate funcionar dentro do grid. Estilo do Select de Canal preservado (`w-full rounded-md bg-white text-[13px]`). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: header do card de Mensagens removido e Status pill movido para o header da conversa. O `<div className="flex items-center justify-between gap-2 border-b ...">` que englobava o icone `MessageCircle`, label `Mensagens`, contador de mensagens e Select de Status foi excluido por completo do bloco MESSAGES — o card agora vai direto da borda superior `rounded-2xl` para a area de mensagens (scrollarea). O Select de Status (`<Select value={formStatus} ...>` com pill `rounded-full uppercase` colorido por estado open/snoozed/closed/archived + ring cyan quando alterado) agora vive dentro do `Right cluster` do header da conversa, antes do quick-save pill, posicionado entre a subtitle e o CopyId/toggle. Altura ajustada de `h-7` para `h-8` para casar com os outros botoes do cluster (size-9 e h-8). A info de contagem (`{conversationMessages.length}`) e o icone `MessageCircle` foram descontinuados — redundantes com o badge do canal no avatar e com a subtitle do header. Resultado: o card de Mensagens fica `cleaner` (sem cromo de header), e o Status passa a viver junto da identidade da conversa. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: header redesenhado para visual mais clean, com cantos arredondados como cartao flutuante e fade de transparencia nos cantos. Mudancas adicionais (apos as descritas a seguir): (a) **Cartao flutuante arredondado**: header virou um cartao independente `rounded-2xl border border-slate-200/40 shadow-sm` com `mx-3` (sem margem superior — usa o `pt-3` do main para o gap com o site header), removida a strip de acento horizontal antiga (substituida por um acento vertical de 3px na borda esquerda com gradient do brand `linear-gradient(180deg, brand, brand55)`). (b) **Fade de transparencia nos cantos** (glass effect): camada de background dedicada (`absolute inset-0 bg-white dark:bg-slate-900`) com `mask-image: radial-gradient(ellipse 110% 95% at 50% 50%, #000 45%, rgba(0,0,0,0.55) 80%, rgba(0,0,0,0.20) 100%)` (+ `-webkit-mask-image` para Safari) — o centro do header e opaco e os cantos arredondados ficam progressivamente transparentes, deixando o pageBg/orbs do layout vazarem pelas pontas para um glassmorphism mais autoral. Children (texto/botoes) ficam fora da mascara, mantendo legibilidade total. `backdrop-blur-md` -> `backdrop-blur-xl` para reforcar o efeito. Borda do cartao suavizada para `slate-200/40`. (c) **Padding interno** ajustado para `px-4 py-2.5` (antes `px-5 py-3`) — proporcional ao novo container card. (d) **Body wrapper** passou de `p-3` para `px-3 pb-3 pt-2` — corte do gap entre header e mensagens (de 12px para 8px). (e) **Duplicacao removida**: o `· atualizada {lastMessageRelative}` que aparecia no header do card de Mensagens foi excluido (info agora vive apenas na subtitle do header da conversa). Mudancas anteriores (mantidas): (1) **Fundo simplificado**: substituido `bg-gradient-to-br from-[brand]/10 via-white to-[brand]/10` (channelMeta.headerBg) por `bg-white/95 backdrop-blur-md` puro, com apenas um wash radial sutil do brand na direita (`opacity-[0.06]`) — fica clean sem perder a identidade do canal. (2) **Borda inferior**: substituida a strip de gradiente fullbleed no topo (`h-1 bg-gradient-to-r [headerGradient]`) por uma hairline `h-px` no rodape do header com fade horizontal do brand (`linear-gradient(90deg, transparent, brand99 30%, brand99 70%, transparent)`) sobreposta a uma linha `bg-slate-200/80` — acento sutil sem peso visual. (3) **Botao Voltar minimalista**: deixou de ser chip com label `Voltar` (`h-8 px-2.5 border bg-white/80`) e virou icon-button circular `size-9 rounded-full text-slate-500 hover:bg-slate-100` sem borda/sombra — mais leve. Tooltip preserva acessibilidade. (4) **Avatar 3D refinado**: tamanho `size-9` -> `size-10`, removida a borda branca `border-2` substituida por `ring-2 ring-white` + halo do brand via `box-shadow: 0 0 0 2px brand33` (efeito vidro mais elegante). Fallback de iniciais agora usa gradient `135deg, brand, brand cc` no lugar do `from-emerald-400 via-teal-500 to-cyan-500` generico — assume cor do canal. Badge do canal: `size-4` -> `size-[18px]`, `border-2 border-white` -> `ring-1 ring-slate-200` + `shadow-md`. (5) **Hierarquia tipografica**: titulo `text-sm` -> `text-[15px] font-semibold tracking-tight text-slate-900`. Removido o channel chip ao lado do titulo (info redundante com o badge no avatar e com a nova subtitle). Adicionada **subtitle inline** `text-[11.5px] text-slate-500` com 3 segmentos opcionais separados por `·`: (a) nome do canal em cor do brand com dot pulsante `0 0 6px brand80` (presenca visual delicada); (b) nome da empresa via `companyMap.get(formCompanyId)?.name`; (c) `atualizada X` (`lastMessageRelative` ja existente, movido do header do card de Mensagens para o header principal). (6) **Cluster de acoes a direita** agrupado em `flex gap-1.5`: Quick-save pill virou `rounded-full h-8 text-[11.5px]` (antes `rounded-xl text-xs`) com label apenas `Salvar` (antes `Salvar alteracoes`); CopyIdButton perdeu borda/fundo (`border-0 bg-transparent`) e ficou icon ghost circular `size-9 rounded-full hover:bg-slate-100`; toggle de detalhes tambem virou `size-9 rounded-full` ghost, com fundo emerald-500/15 quando ativo (mesma linguagem visual). (7) **Padding e altura**: `px-4 py-2` -> `px-5 py-3` (header mais respiravel, mais perto do padrao iOS/macOS de chat headers). Variavel `headerCompany` adicionada para resolver o nome da empresa via `companyMap`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
CorrecaoCRM Activities (/crm/activities/[id]) — conversation: ao abrir uma conversa, a area de mensagens agora rola automaticamente para o final (mensagem mais recente visivel). O useEffect que ajusta `messagesScrollRef.current.scrollTop = scrollHeight` passou a (1) condicionar-se a `isConversationActivity && !loadingMessages` (so dispara apos o load completar), (2) incluir `loadingMessages`, `selectedActivity?.id` e `detailsOpen` como dependencias (cobre troca de conversa, fim do loading e re-layout ao recolher/expandir detalhes), e (3) diferir o scroll em dois `requestAnimationFrame` consecutivos (primeiro para apos layout inicial, segundo para capturar conteudo assincrono como avatares/imagens que afetam `scrollHeight`). Cleanup cancela ambos os RAFs ao desmontar/re-disparar. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: painel `Detalhes da conversa` agora e colapsavel para dar largura total a area de mensagens (mais area de leitura, UI mais clean). Mudancas: (1) Novo state `detailsOpen` (default `false`, persistido em `localStorage['crm-conversation-details-open']` como `'1'`/`'0'`). (2) Toggle adicionado no header da conversa (apos `CopyIdButton`): botao `size-8 rounded-lg` com icones `PanelRightOpen` (fechado) / `PanelRightClose` (aberto), `aria-pressed={detailsOpen}`, tinta emerald quando ativo. (3) Layout reestruturado: grid muda dinamicamente entre `lg:grid-cols-1` (quando colapsado — mensagens ocupam 100%) e `lg:grid-cols-[minmax(0,1fr)_minmax(320px,22rem)]` (quando aberto — detalhes vai para a direita, mais estreito que antes — 22rem vs 24rem anteriores). (4) Coluna de detalhes ganhou `order-2` (vai para a direita) e classe `hidden` quando colapsado; coluna de mensagens ganhou `order-1` (mantem-se a esquerda). (5) Padding externo do container reduzido `p-4` -> `p-3` e gap do grid `gap-4` -> `gap-3` para menos cromos visuais. (6) Quick-save: quando o painel esta colapsado e existem `hasFormChanges` pendentes (`detailsOpen === false && hasFormChanges && permWrite`), aparece um pill compacto `h-8 px-3 text-xs` no header (entre status pill e CopyId) com gradiente amber/orange + icone `Save`, label `Salvar alteracoes`. Estados respeitam `isSaving`/`justSaved` (Loader2/Check). Permite salvar status/canal alterados sem reabrir os detalhes. Imports `PanelRightOpen`/`PanelRightClose` adicionados a `lucide-react`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: header da conversa enxugado para liberar altura ao painel de mensagens. Removidos do header: (1) linha de subtitulo composta (`headerSecondaryBits`) que mostrava titulo da conversa + empresa + email/telefone + `ultima mensagem X`; (2) Status pill (movido de volta para o header do card `Mensagens`, ao lado direito do contador). Avatar reduzido de `size-11` para `size-9` e badge do canal de `size-5` para `size-4`. Padding vertical do header passou de `pt-3 pb-3` para `py-2`. Header agora exibe apenas: `[Voltar][Avatar com badge][Nome do contato + chip do canal][CopyId]`, em linha unica. Atualizada relativa (`atualizada X min atras`) foi incorporada inline no header `Mensagens` (apos o badge de contagem, prefixada por `· `). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: campo `Enviada em` do painel de opcoes do composer dividido em `Data` + `Horario`, seguindo o padrao das atividades tipo task. Substituido o `<LabeledInput type="datetime-local">` unico por: (1) `DatePickerInput` (label `Data`, wrapper `w-32`) para a data; (2) `LabeledInput type="time"` (label `Horario`, wrapper `w-28`, leftIcon `<Clock>` cyan-600, classe `[&::-webkit-calendar-picker-indicator]:hidden`) para o horario. State quebrado em dois: `msgSentDate` (YYYY-MM-DD) e `msgSentTime` (HH:MM), substituindo o `msgSentAt`. `handleSendMessage` compoe o ISO via `new Date(\`${msgSentDate}T${msgSentTime}\`).toISOString()` (com fallback para `T00:00` quando so a data e informada, ou `new Date()` quando ambos vazios). Reset apos envio limpa os dois states. `optionsAreNonDefault` e o hint `Enviando como X · agora/data-hora` consideram ambos os campos. Grid do painel de opcoes mudou de `grid md:grid-cols-[1fr_1fr]` para `flex flex-wrap items-end gap-2` (sender ocupa `min-w-[180px] flex-1`). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: removida a linha de subtitulo do remetente (email - telefone) que aparecia logo abaixo do nome em mensagens inbound dentro do balao. A constante `senderSubtitle = [msg.sender_email, msg.sender_phone].filter(Boolean).join(' - ')` e o `<div>` que a renderizava foram removidos do bloco de bubble. O nome do remetente (primeira linha do balao) e as iniciais/avatar do contato continuam suficientes para identificar quem enviou. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: tela de conversa repaginada com identidade visual por canal (WhatsApp / Microsoft Teams). Novidades: (1) Header dedicado para conversation com strip de gradiente do canal no topo, fundo tintado por canal (`headerBg`), avatar grande do contato (size-11) com profile_picture_url ou iniciais, ring colorido pelo canal e badge do icone do canal no canto inferior direito do avatar. Nome do contato aparece como titulo principal; titulo da conversa + empresa + telefone/email + ultima-mensagem viram subtitulo composto. Status pill agora vive no header (removida do card de mensagens). (2) Card de mensagens com fundo tintado pelo canal e textura de pontos sutil (background-image radial-gradient) imitando wallpaper de chat. Header do card mostra contagem em badge pill e horario da ultima atualizacao. Empty state com icone do canal e copy contextual (`Inicie esta conversa enviando a primeira mensagem pelo WhatsApp/Teams...`). (3) Baloes de mensagem: outbound usa cor de marca do canal (WhatsApp `#dcf8c6`/`#005c4b` dark, Teams `#e8ebfa`/`#4b53bd` dark); ultimo balao de cada grupo de mesmo remetente ganha canto inferior diminuido (`rounded-br-md` / `rounded-bl-md`) emulando "rabicho"; avatares se repetem apenas no ultimo balao do grupo (invisible nos demais). Outbound ganha double-check decorativo ao lado do horario. Hover do balao adiciona `shadow-md`. (4) Composer redesenhado: textarea + botao opcoes + botao enviar agrupados em um unico container `rounded-2xl border` com ring teal quando o remetente esta como contato. Botao enviar usa cor de marca do canal (`bg-[#25D366]` / `bg-[#4B53BD]`). Botao opcoes vira icon-button minimalista (sem moldura colorida). Hint `Enviando como X · sentAt` ganha dot de status. (5) `CHANNEL_META` estendido com `headerGradient`, `headerBg`, `avatarRing`, `outboundBubble`, `outboundMeta`, `sendBtn`, `messagesBg` e `iconColor`. (6) Coluna de detalhes (esquerda) ganha label de secao `Detalhes da conversa` + data de atualizacao. Layout do grid passa de `[minmax(360px,28rem)_minmax(0,1fr)]` para `[minmax(340px,24rem)_minmax(0,1fr)]` (coluna de mensagens com mais espaco). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: removido o container de edicao (card flutuante com borda, sombra, backdrop-blur e header com gradiente colorido). Os campos agora ficam diretamente na pagina. Mudancas: (1) `<section>` externa deixa de centralizar/scrollar quando `formType === 'conversation'` (vira `flex flex-1 min-h-0 flex-col overflow-hidden`, sem `items-center justify-center overflow-y-auto py-6`). (2) Outer max-w div ganha `flex-1` e `max-w-none` (antes ja era `max-w-none` mas faltava flex-1). (3) Card div interno perde `overflow-hidden rounded-2xl border shadow-xl backdrop-blur-xl md:h-[80vh] md:max-h-[calc(100vh-140px)]` + todas as classes condicionais de borda/shadow vermelho/ambar (priority/overdue). Vira so `flex flex-1 min-h-0 flex-col`. (4) Header gradiente substituido por barra simples: `relative px-4 border-b border-slate-200 bg-transparent py-2.5` (antes `overflow-hidden rounded-t-2xl border-b-0 px-5 py-3 crm-header-gradient`). Blurs decorativos (white/12 e theme.blur) nao sao renderizados. (5) Botao Voltar: classe `border-white/20 bg-white/10 text-white` → `border-slate-200 bg-white text-slate-600` (estilo neutro). (6) Titulo h2: `text-white` → `text-slate-700 dark:text-slate-100`. (7) Channel chip: `bg-white/15 text-white` → `bg-white text-slate-600` (borda colorida do brand mantida). (8) Texto `Ultima mensagem X`: `text-white/65` → `text-slate-400 dark:text-slate-500`. (9) `CopyIdButton`: classes glass `border-white/20 bg-white/10 text-white/70` → `border-slate-200 bg-white text-slate-400`. (10) Form body (`<div bg-white/50>`) tambem perde o background quando conversation. Para task/meeting o card original e o header com gradiente sao preservados integralmente. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — campos editaveis com fundo branco solido para melhor contraste. `LabeledInput` (componente compartilhado): `bg-white/40` / `dark:bg-slate-900/70` → `bg-white` / `dark:bg-slate-900`. `DatePickerInput`: input editavel ganhou `bg-white dark:bg-slate-900` (antes ficava transparente herdando do shadcn Input). `SelectTrigger` dos campos `Canal`, `Tipo Local`, `Prioridade` (task/meeting/conversation) e `Status` (task/meeting): adicionado `bg-white dark:bg-slate-900` no className. Wrapper do campo `Notas` (Markdown): `bg-white/40 backdrop-blur-sm` → `bg-white` (removido o blur). Mudancas se propagam para LabeledAutocomplete (que renderiza via LabeledInput). Status pill no header do card de mensagens e msg-sender do composer mantidos com seu estilo proprio. Arquivos: app/(app)/_components/labeled-input.tsx, components/ui/date-picker-input.tsx, app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — campo `Notas` (task/meeting): linha do label simplificada. Removida a hint italica `Clique para editar` / `Markdown - clique fora para pre-visualizar` (estado obvio pelo cursor + comportamento). Botao de expandir notas (`AlignLeft`) movido para a **esquerda** do `<Label>` (antes ficava `ml-auto` a direita). Gap da linha reduzido de `gap-2` para `gap-1.5`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — campo `Notas` (task/meeting) padronizado com label fora do input, igual aos demais campos do formulario. Removido o header interno do card (`<div className="border-b ...">` com span `Notas` em uppercase cyan-600 + botao `AlignLeft`) e substituido por uma linha externa acima do textarea/preview: `<Label htmlFor="activity-notes" className={labelOutsideClass}>Notas</Label>` a esquerda, hint italico (`Markdown - clique fora para pre-visualizar` / `Clique para editar`) e botao `AlignLeft` (expandir modal) `ml-auto` a direita. Card interno simplificado de `rounded-xl` para `rounded-md` e mantem a borda cyan quando ha mudanca (mesma classe dos demais campos: `border-cyan-400/60 shadow-[0_0_0_1px_rgba(6,182,212,0.1)]`). Wrapper externo mudou de `relative min-w-0` para `flex min-w-0 flex-col gap-1`. `id="activity-notes"` adicionado ao textarea e ao button-preview para o `htmlFor` da Label funcionar corretamente. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — avatar do header ganhou efeito 3D (vidro/relevo). Substituido `bg-white shadow-lg` plano por: (1) **base** com gradiente vertical `bg-gradient-to-b from-white via-white to-slate-200` (sombreado inferior para sensacao de volume); (2) **multi-layer box-shadow** inset (`inset_0_1px_1px_rgba(255,255,255,0.95)` highlight superior + `inset_0_-2px_3px_rgba(15,23,42,0.18)` sombra inferior interna) combinada com sombra externa `0_2px_5px_rgba(15,23,42,0.35)` e halo `0_0_0_1px_rgba(255,255,255,0.25)`; (3) **ring-1 ring-black/5** para definir contorno; (4) **dois overlays pseudo-spec**: gradient `from-white/70` no topo (luz difusa) e barra blur `bg-white/60 blur-[2px]` no terco superior (specular highlight). Icone interno (`Calendar`/`ClipboardList`/`MessageCircle`/img Teams) ganhou `drop-shadow-[0_1px_1px_rgba(0,0,0,0.25)]` e `relative` para sobrepor as camadas de luz. Border `border-white/50` -> `border-white/60`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — header do formulario (task/meeting): padding vertical reduzido de `pt-4 pb-4` (16px+16px) para `py-3` (12px+12px). Conversation mantem `py-2`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — header do formulario (task/meeting): avatar circular reduzido de `size-11` (44px) para `size-9` (36px). Conversation mantem `size-7` (28px). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — header do formulario: titulo (`<h2>`) reduzido para `text-sm` (14px) tambem em task/meeting (antes era `text-base`/16px so para conversation). Removida a condicional `formType === 'conversation' ? 'text-sm' : 'text-base'`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — header do formulario (task/meeting): subtitulo removido. O `<p>` que mostrava o local da reuniao ou o `activityTypeLabel` da tarefa logo abaixo do titulo do header gradiente foi excluido. Os badges `Tarefa vencida` e prioridade (que ficavam na mesma linha) sao preservados. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — campo `Notas` (inline e modal expandido): removidos os botoes de toggle `Pencil` (editar) e `Eye` (pre-visualizar). Agora o campo opera em modo focus-driven: o estado inicial e sempre **preview renderizado** (Markdown com remark-gfm + remark-breaks); clicar na area transforma-a em textarea com auto-focus (`notesTextareaRef.current?.focus()` via `setTimeout(..., 0)`); ao perder o foco (`onBlur`) volta para preview. Mesma logica no modal expandido (`notesModalTextareaRef` + `notesModalEditing`). States renomeados: `notesPreview` → `notesEditing` (semantica invertida — `true` = textarea visivel), `notesModalPreview` → `notesModalEditing`. Defaults sao `false` (preview sempre primeiro). Empty state mudou de `Nenhuma nota` para `Clique para adicionar notas em Markdown...` (hint do click). Label do header reduzido de `Notas (Markdown)` para `Notas`, com hint contextual a direita: `Clique para editar` quando preview, `Markdown - clique fora para pre-visualizar` quando editando. Botao `AlignLeft` (expandir para modal) preservado. Imports `Pencil`/`Eye` ainda usados em outros lugares do arquivo (mensagens), mantidos. Arquivo: app/(app)/_components/crm-activities-section.tsx.
CorrecaoCRM Activities (/crm/activities/[id]) — campo `Oportunidade` (LabeledAutocomplete): deals em estagios fechados/ganhos/perdidos/cancelados nao aparecem mais nas sugestoes. Novo state `allStages: CRMPipelineStage[]` populado via `fetchCrmPipelineStages()` adicionado aos dois `Promise.all` (modo criacao e modo edicao). O useMemo de `dealItems` agora monta um `stageMap` (id → stage) e filtra deals onde `stage.is_closed === true || stage.is_won === true` OU o nome do estagio (lower) esta em `EXCLUDED_STAGE_NAMES = ['fechado','fechada','perdido','perdida','cancelado','cancelada']`. Excecao: se o deal corresponder ao `formDealId` atual (ja vinculado a atividade aberta), ele continua sendo exibido para nao sumir do select durante a edicao — `(d) => d.id === formDealId || !isExcludedDeal(d)`. Imports: `CRMPipelineStage`/`fetchCrmPipelineStages` de `lib/api/crm-pipelines`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: pacote de melhorias de UX/UI no chat. (1) **Channel chip no header gradiente**: chip arredondado ao lado do titulo mostra o canal selecionado com favicon do provider (WhatsApp via google s2 favicons em `whatsapp.com`, Teams via `teams.microsoft.com`) e borda colorida com o brand (`#25D366` WhatsApp / `#4B53BD` Teams) via `style={{ borderColor: brand+80 }}`. Identidade imediata sem precisar abrir o Select Canal. (2) **Linha de tempo relativo da ultima mensagem**: sob o titulo do header aparece `Ultima mensagem 5 min atras` quando ha mensagens (computado de `conversationMessages[length-1]` via novo helper `formatRelativeTime` — agora/Ns/Nmin/Nh/ontem/Nd/data completa). (3) **Status pill no header do card de Mensagens**: o Select de Status saiu do form (Row 3 reduzida de 3 para 2 colunas: Responsavel + Prioridade) e virou uma pill clicavel arredondada (`h-7 rounded-full px-3`) no header do card de mensagens (`flex justify-between`), com cor da borda conforme estado (emerald=open, amber=snoozed, slate=closed/archived), dot colorido e ring cyan quando ha change pendente. SelectContent abre com `align=end` para nao estourar a area. (4) **Separadores de data nas mensagens**: lista agora itera sobre `groupedConversationMessages` (novo useMemo que agrupa por `getMessageDateKey(YYYY-MM-DD)`), renderizando uma pilula central `Hoje`/`Ontem`/`27 de maio` (helper `formatMessageDateSeparator`) antes de cada grupo. Bolha de mensagem mudou o label de hora completa (`dateStyle:short,timeStyle:short`) para apenas hora (`HH:MM` via `toLocaleTimeString`), ja que a data esta no separador. (5) **Avatares com paridade outbound/inbound**: cada balao agora tem um avatar size-7 do lado externo. **Inbound**: foto do contato (`contactMap.get(formContactId)?.profile_picture_url`) ou fallback com iniciais (helper `getInitials`) em circulo gradient teal/emerald. **Outbound**: iniciais do owner (lookup por `sender_external_id` ou fallback para `formOwnerId`/session) em circulo gradient emerald/teal solido com texto branco. Linha do balao virou `gap-1.5 items-end` para alinhar avatar com base da mensagem. Nome agora aparece tambem em outbound (era so inbound antes). (6) **Composer slim com opcoes recolhidas**: antes era grid 2-col com Remetente+EnviadaEm sempre visiveis (~14rem permanentes). Agora rodape e uma unica linha `[botao Opcoes][Textarea slim rows=1 min-h-[40px]][Enviar h-9]` com hint visual `Enviando como Eu / agora` + kbd `Ctrl+Enter para enviar`. Botao `Settings2` (size-9) alterna painel collapsivel acima do textarea com os campos Remetente e Enviada em (so visivel quando `composerOptionsOpen`). Dot cyan no botao indica que opcoes diferem do default (Eu/agora). (7) **Auto-focus**: novo useEffect foca o textarea (`composerTextareaRef`) 80ms apos o load das mensagens, ao entrar na conversa. (8) **Provider info enxuto**: removida a linha `Ultima mensagem: ...` da barra read-only de provider/thread (info redundante agora que esta no header). Helpers/states adicionados: `formatRelativeTime`, `getMessageDateKey`, `formatMessageDateSeparator`, `getInitials`, `CHANNEL_META`, `conversationStatusLabel`, `conversationStatusOptions`, `composerOptionsOpen`, `composerTextareaRef`, `groupedConversationMessages`, `lastMessageRelative`. Imports adicionados: `ChevronDown`, `Settings2` (lucide-react). Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Companies > aba Atividades > edicao da atividade: campos `Titulo`, `Responsavel`, `Contato` e `Oportunidade` agora sao editaveis (antes eram readonly). `Titulo` virou `FloatingInput` editavel com `hasChanged` (ring cyan quando alterado vs `editingActivity.title`). Os 3 campos de referencia (`Responsavel`/`Contato`/`Oportunidade`) trocaram `FloatingInput readOnly` por `FloatingSelect` (componente `components/ui/floating-select.tsx`, mesmo visual de label flutuante) populados respectivamente por `users`, `companyContacts` e `companyDeals`, com `hasChanged` comparando contra `editingActivity.owner_id|contact_id|deal_id`. Tambem adicionado `FormFooter` proprio para a aba `activities && activityFormOpen` (antes nao havia rodape de save quando o form era do tipo atividade-base, so para task/meeting): botoes Salvar (chama `handleSaveActivity`, ja existente — faz PUT parcial so dos campos alterados) e Excluir (chama `handleDeleteActivity`), respeitando `permWrite`/`permDelete`, exibe `updatedAt` e usa tema amber consistente com task/meeting. Import `FloatingSelect` adicionado. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies > aba Atividades > edicao de atividade do tipo `conversation`: agora exibe historico de mensagens e permite enviar nova mensagem inline. Apos clicar em uma conversa existente, abre-se o formulario padrao (campos readonly Titulo/Responsavel/Contato/Oportunidade + timestamp Criado em) e, abaixo, um card emerald com cabecalho `Mensagens (N)`, area de scroll com baloes estilo chat (mensagens `outbound` alinhadas a direita com fundo emerald-500 texto branco, `inbound` a esquerda com fundo branco/slate e nome do remetente em emerald uppercase), data/hora curta abaixo de cada balao e empty state quando ainda nao ha mensagens. Footer com `Textarea` + botao `Enviar` (icone `Send`): Enter envia, Shift+Enter quebra linha, botao desabilitado enquanto vazio ou enviando (mostra `Loader2`). Implementacao: novos states `conversationMessages: CRMMessage[]`, `loadingConversationMessages`, `newMessageBody`, `sendingMessage` e ref `messagesScrollRef`. `useEffect` carrega via `fetchCrmConversationMessages(activityId)` quando `activityFormType === 'conversation' && editingActivity?.id`, ordenando por `sent_at|received_at|created_at`. Outro `useEffect` faz auto-scroll para o final ao atualizar a lista. `handleSendMessage` chama `createCrmConversationMessage(activityId, { direction: 'outbound', body, sent_at: now })` e faz append otimista. `closeActivityForm` reseta a lista e o input. Botao Enviar so aparece com `permWrite`. Imports: `Send` (lucide), `createCrmConversationMessage`, `fetchCrmConversationMessages`, `CRMMessage` de `lib/api/crm-messages.ts`. Arquivo: app/(app)/_components/crm-companies-section.tsx.
CorrecaoCRM Activities (/crm/activities/[id]): campos `Empresa`, `Contato` e `Oportunidade` (LabeledAutocomplete) deixaram de exibir o dropdown de sugestoes do navegador (historico de valores digitados anteriormente). Mudancas no componente `LabeledAutocomplete`: `autoComplete` alterado de `new-password` para `off`, `name` agora inclui sufixo aleatorio por instancia (`ac-{scrubbedId}-{randomSuffix}`) gerado via `useMemo` para invalidar a cache de historico do Chrome, e adicionados `data-form-type="other"` e `data-bwignore="true"` para suprimir tambem extensoes Bitwarden e heuristicas adicionais. Arquivo: app/(app)/_components/labeled-autocomplete.tsx.
MelhoriaCRM Companies (/crm/companies/[id]): campo `Status` na Row 1 do formulario padronizado para usar o componente compartilhado `StatusToggleField` (mesmo estilo Glassmorphism Pro ja usado em /fin/partners/[id]) — chip `rounded-2xl border px-5 py-2.5` com dot pulsante `animate-ping` emerald/red e blur decorativo. Substituido o bloco custom anterior (Label + container `h-9 rounded-md` + `<Switch>` + texto Ativo/Inativo) por `<StatusToggleField active onToggle disabled hasChanged />`, mantendo o espacador invisivel (`<span className={cn(labelOutsideClass, 'invisible select-none')}>`) para alinhamento vertical com os LabeledInputs vizinhos. Import `StatusToggleField` adicionado em `app/(app)/_components/crm-companies-section.tsx`.
MelhoriaCRM Companies > aba Contatos > edicao de contato (/crm/companies/[id], `editingContact`): campo `Status` na Row 1 (ao lado direito do HubSpot ID, via `ml-auto`) tambem padronizado para usar `StatusToggleField`. Substituido o mesmo bloco custom (Label + container `h-9 rounded-md` + `<Switch id=ct-active>` + texto Ativo/Inativo + change dot manual) por `<StatusToggleField active={ctIsActive} onToggle={() => setCtIsActive(prev => !prev)} disabled={ctSaving} hasChanged={!!editingContact && ctIsActive !== (editingContact.is_active ?? true)} />` com o espacador invisivel mantendo o alinhamento. Arquivo: app/(app)/_components/crm-companies-section.tsx.
CorrecaoCRM Companies > Status (formulario principal e formulario de contato): chip `StatusToggleField` agora recebe `className="h-9 py-0"` para casar a altura com os `LabeledInput` da mesma linha (h-9 = 36px). Antes o chip ficava ~4px mais alto que os inputs vizinhos por causa do `py-2.5` default do componente, criando um leve desalinhamento visual. O `h-9` sobrescreve via `cn()` no componente compartilhado (que aceita `className` extra) e o `py-0` neutraliza o padding vertical default. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies > aba Contatos > edicao de contato: campo `LinkedIn` agora salva apenas o slug do perfil, mesmo quando o usuario cola a URL completa. Ao colar `https://www.linkedin.com/in/joaopaulo-castro-pmo/` (ou variantes sem scheme/com query string/com fragment) o campo armazena apenas `joaopaulo-castro-pmo`. Implementacao: novo helper `extractLinkedinUsername(value)` em `lib/format-helpers.ts` que aplica regex `linkedin\.com\/in\/([^/?#\s]+)` para capturar o slug, retornando o valor original se nenhum padrao de URL casar (preserva digitacao manual do slug). Aplicado no `onChange` do `LabeledInput#ct-linkedin` via `setCtLinkedinUrl(extractLinkedinUsername(e.target.value))`. O helper `buildLinkedinUrl` ja existente continua sendo usado para abrir o link no botao do avatar, entao a navegacao para o LinkedIn segue funcionando normalmente a partir do slug. Arquivos: lib/format-helpers.ts (novo helper), app/(app)/_components/crm-companies-section.tsx (import + uso).
MelhoriaCRM > campo `HubSpot ID` (readonly) ampliado de `w-29` (116px) para `w-35` (140px) para evitar truncamento do ID em telas. Aplicado em duas telas: `app/(app)/_components/crm-companies-section.tsx` (aba Contatos da empresa, `#ct-hubspot-id`) e `app/(app)/_components/crm-contacts-section.tsx` (pagina standalone do contato, `#contact-hubspot-id`). No Tailwind v4 (spacing dinamico) `w-35` = `35 * 0.25rem` = 8.75rem.
MelhoriaCRM Companies > aba Solucoes (/crm/companies/[id]): coluna `Categoria` reposicionada para a esquerda de `Fornecedor`. Nova ordem das colunas: `Categoria → Fornecedor → Solucao → Notas` (antes era `Fornecedor → Solucao → Categoria → Notas`). Aplicado tanto no `TableHeader` (botoes de sort `solutionSortIcon` preservados, sem alteracao em `SolutionSortKey` ou `sortedCompanySolutions`) quanto nas `TableCell` do `TableBody`. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies > aba Atividades: dropdown `+ Nova Atividade` agora inclui terceira opcao `Conversa` (icone `MessageCircle` emerald-500, hover emerald-50/emerald-700). Click abre Dialog (`max-w-md`) com header gradiente emerald e dois campos: `Canal *` (Select com `whatsapp` default + `teams`) e `Titulo *` (LabeledInput). Botao `Criar` chama `createCrmConversation({ channel, title, company_id: selectedCompany.id })` (do novo `lib/api/crm-conversations.ts`) e em sucesso fecha o dialog, recarrega activities via `loadCompanyActivities` e exibe toast `Conversa criada`. Erros mostram toast com `resolveErrorMessage`. State: `conversationDialogOpen`, `conversationChannel`, `conversationTitle`, `conversationSaving`. Botao desabilitado enquanto `!conversationTitle.trim()` ou `conversationSaving`. Conversation ID retornado e `activity_id` (1:1 com CRMActivity), entao aparece na lista de atividades junto com task/meeting. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Activities: adicionado suporte ao novo recurso `conversations` (e `messages` aninhadas) baseado no `swagger.json`. Criados dois novos modulos de API client: (1) **`lib/api/crm-conversations.ts`** com tipos `CRMConversation` (chave primaria `activity_id`, campos `channel: 'teams'|'whatsapp'`, `priority: LOW|MEDIUM|HIGH|URGENT`, `title`, `status`, `owner_id`, `company_id`, `contact_id`, `deal_id`, `provider`, `provider_thread_id`, `notes`, `last_message_at`, `completed_at`, `metadata`), `CreateCRMConversationPayload` (required: `channel`, `title`), `UpdateCRMConversationPayload` (todos opcionais), `FetchCrmConversationsParams` (filtros do GET: `owner_id`/`company_id`/`contact_id`/`deal_id`/`priority`/`status`/`channel`/`provider`/`provider_thread_id`) e funcoes `fetchCrmConversations(params)` → `GET /crm/conversations`, `fetchCrmConversation(activityId)` → `GET /crm/conversations/{activity_id}`, `createCrmConversation(payload)` → `POST /crm/conversations`, `updateCrmConversation(activityId, payload)` → `PUT /crm/conversations/{activity_id}`, `deleteCrmConversation(activityId)` → `DELETE /crm/conversations/{activity_id}`. (2) **`lib/api/crm-messages.ts`** com tipos `CRMMessage` (`id`, `conversation_activity_id`, `direction: 'inbound'|'outbound'`, `message_type`, `body`, `provider_message_id`, `sender_name/email/phone/external_id`, `sent_at`, `received_at`, `metadata`), `CreateCRMMessagePayload` (required: `direction`), `UpdateCRMMessagePayload` e funcoes `fetchCrmConversationMessages(activityId)` → `GET /crm/conversations/{activity_id}/messages`, `createCrmConversationMessage(activityId, payload)` → `POST /crm/conversations/{activity_id}/messages`, `fetchCrmMessage(id)` → `GET /crm/messages/{id}`, `updateCrmMessage(id, payload)` → `PUT /crm/messages/{id}`, `deleteCrmMessage(id)` → `DELETE /crm/messages/{id}`. Os tipos usam `FlexibleTime` de `lib/date-helpers` para campos de data flexivel. Conversations sao um tipo de activity (1:1 com `CRMActivity` via `activity_id`), entao o backend cria a activity automaticamente no POST.
NovidadeCRM Deals (/crm/deals/new): adicionados campos `Pipeline` e `Estagio` (Select shadcn) no formulario de criacao de oportunidade. O state `formPipelineId`/`formStageId` ja existia e era validado no save, mas faltava a UI para o usuario escolher esses valores ao criar. Inseridos como uma nova linha (so renderizada quando `isCreating`) acima da linha `Empresa | Contato`, com layout `flex items-end gap-3` (cada select com `flex-1`). Comportamento: pipeline lista todos `pipelines` do `useCrmReferenceData`; ao mudar pipeline, `formStageId` e resetado para `""`; o select de estagio fica desabilitado enquanto nenhum pipeline esta selecionado e exibe placeholder `Selecione um pipeline`; estagios ordenados por `stage_order` via `filteredStages` (ja filtrado pelo pipeline atual). Em modo edicao a linha nao aparece (mantem-se o badge de stage atual a direita da linha 1). Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Activities (/crm/activities): adicionado terceiro botao de filtro `Conversas` na barra de filtros do header, ao lado de `Tarefas` e `Reunioes`. Mesmo estilo glass (`h-7 rounded-lg px-2.5`, fundo `bg-white/20` quando ativo, `text-white/50` quando inativo) com icone `MessageCircle` (balao circular, size-3.5). Toggle on/off (volta para `all` ao clicar de novo). O filtro reaproveita o `activityTypeFilter` existente (`a.activity_type === activityTypeFilter`), agora tipado como `'all' | 'task' | 'meeting' | 'conversation'`, e a regra de persistencia em sessionStorage (`crm-activities-filters`) tambem foi estendida para aceitar `conversation`. Adicionalmente, nas listas de atividades (variantes `overdue`/`upcoming`/`done`) as linhas com `activity_type === 'conversation'` agora exibem o icone `MessageCircle` (balao de conversa) ao lado do titulo — overdue: `text-red-400`; upcoming: `text-emerald-500 drop-shadow-[0_0_3px_rgba(16,185,129,0.5)]` (URGENT vermelho/HIGH amber); done: `text-slate-400`. Novo derivado `isConversation = activity.activity_type === 'conversation'`. Import `MessageCircle` adicionado em `lucide-react`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: `FormFooter` removido por completo do branch de conversation; botoes `Excluir` e `Salvar` movidos para uma nova Row 4 inline dentro da coluna esquerda (logo abaixo de Status/Prioridade), alinhados a direita (`flex items-center justify-end gap-2`). Botoes replicam o estilo do FormFooter (Excluir = `h-9 px-3` ghost com hover red-500/10, icone `Trash2` com `group-hover:-rotate-[8deg]`; Salvar = `h-9 px-5` gradiente emerald-teal-green com shimmer + estados `Loader2`/`Check`/`Save` e textos `Salvando...`/`Salvo!`/`Salvar`). Salvar desabilitado quando `isSaving || justSaved || !hasFormChanges || !formTitle.trim()`. Excluir aparece so com `permDelete && selectedActivity`; Salvar aparece so com `permWrite`. Isso libera toda a altura do card para a coluna de mensagens (sem footer fixo de 56px no rodape). Imports `Save` e `Check` adicionados a `lucide-react`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: header gradiente compactado e composer reorganizado. (1) Header compacto quando `formType === 'conversation'`: padding `pt-4 pb-4` → `py-2`, avatar circular `size-11` → `size-7` (icone `MessageCircle` `size-5` → `size-4`), titulo `text-base` → `text-sm`, botao Voltar `h-8 px-3 text-sm` → `h-7 px-2.5 text-xs`, gap entre itens `gap-3` → `gap-2`. Outros tipos (task/meeting) mantem header original. (2) Linha de subtitulo + badges abaixo do titulo so renderiza para task/meeting agora — quando conversation, o bloco inteiro (`<div className="mt-0.5 ...">`) some, liberando ainda mais espaco vertical. (3) Campo Notas removido completamente do formulario de conversation (`{/* CONVERSATION Row 4: Notas */}` + textarea + header com botao expandir): a coluna esquerda agora tem so Titulo+Canal / Empresa/Contato/Oportunidade / Responsavel+Status+Prioridade. (4) Composer de mensagens reorganizado em grid 2 colunas (`md:grid-cols-[14rem_minmax(0,1fr)]`): **coluna esquerda** com `Remetente` (Select) empilhado sobre `Enviada em` (LabeledInput datetime-local); **coluna direita** com Textarea (`flex-1`, `rows=3`, `min-h-[80px]`) a esquerda do botao Enviar (que agora ocupa altura cheia via `self-stretch` e fica como bloco vertical com icone + label). Antes era 2 linhas (`Row 1: remetente|enviada em`, `Row 2: textarea|enviar`); agora os campos de contexto ficam ao lado da mensagem, nao acima dela. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: layout reotimizado para dar maximo espaco ao chat. (1) Container agora usa `max-w-none` quando `formType === 'conversation'` (antes ficava em `lg:w-[92vw] lg:max-w-[1500px]`), ocupando 100% da largura disponivel dentro do main; outros tipos (task/meeting) seguem com `max-w-[88rem] lg:w-[60vw] lg:max-w-[1100px]`. (2) Subtitulo `Conversa` removido do header gradiente (o `<p>` abaixo do titulo so renderiza para task/meeting agora — `formType !== 'conversation' && (...)`); o icone `MessageCircle` ja indica o tipo. (3) Coluna esquerda passa a ter largura fixa de `minmax(360px,28rem)` (antes era `minmax(0,1.05fr)`), liberando todo o restante para a coluna de mensagens (`minmax(0,1fr)`). (4) Campos da esquerda compactados: `gap-3` → `gap-2`, Row 1 Canal de `12rem` para `9rem`, Row 2 (Empresa/Contato/Oportunidade) virou stack vertical (`flex flex-col gap-2`, antes era grid 3 cols), Row 3 Status/Prioridade de `11rem` para `8rem` cada, padding do body `p-5` → `p-4`. (5) Textarea Notas de `rows={8}` para `rows={4}` (suficiente em coluna estreita). (6) Fix de scroll: `min-h-[160px]` da area de mensagens trocado por `min-h-0` para permitir shrink correto; `shrink-0` adicionado ao header do card, ao composer e a linha de provider info para garantir que so o scroll-area absorva o overflow. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: mensagens salvas agora podem ser editadas e excluidas. Em cada balao de mensagem, ao fazer hover, aparecem 2 botoes (size-6 rounded-md, `opacity-0 group-hover/msg:opacity-100`): `Pencil` (editar) e `Trash2` (excluir, hover red-50/red-600). Posicao dos botoes: a esquerda do balao para outbound (alinhados com o lado externo), a direita para inbound. Editar: o body do balao vira uma Textarea inline com mesmo tema de cor (outbound = fundo translucido branco sobre emerald, inbound = fundo branco/slate), Ctrl/Cmd+Enter salva, Esc cancela; abaixo da textarea ha botoes `Cancelar` e `Salvar` (loader `Loader2` quando salvando). `saveEditMessage` chama `updateCrmMessage(id, { body })` e faz merge otimista na lista (`prev.map(m => m.id === id ? { ...m, ...updated } : m)`). Excluir: abre `ConfirmDeleteDialog` (entityLabel=`a mensagem`, itemName=primeiros 60 chars do body); confirmacao chama `deleteCrmMessage(id)` e remove da lista (`prev.filter(m => m.id !== id)`). Botoes ficam ocultos no balao em modo edicao (`!isEditing`) e tambem para mensagens sem `id`. Novos states: `editingMessageId`, `editingMessageBody`, `savingMessageEdit`, `deleteMessageTarget`, `deletingMessage`. Imports `updateCrmMessage`/`deleteCrmMessage` adicionados de `lib/api/crm-messages`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: composer de mensagens simplificado para o fluxo real (mensagens manuais sao do usuario logado ou do contato da conversa, sempre texto, mesma data para envio/recebimento). UI final no rodape do card de Mensagens: Row 1 = `Remetente` (Select com 2 opcoes — `Eu (nome/email do usuario logado, lido de `getSession()`)` ou `Contato (nome do contato vinculado a conversa, lido de `contactMap.get(formContactId)`)`; opcao Contato fica desabilitada e o botao Enviar tambem quando nao ha contato selecionado na conversa) + `Enviada em` (LabeledInput `datetime-local`, opcional — vazio = `new Date()`); Row 2 = Textarea do body + botao Enviar. `handleSendMessage` deriva `direction` automaticamente: `Eu → outbound`, `Contato → inbound`. `received_at` sempre igual a `sent_at` (mesmo ISO). `message_type` fixado em `'text'`. Sender fields preenchidos automaticamente da fonte selecionada: quando `Eu` → `sender_name`=session.userName||userEmail, `sender_email`=session.userEmail, `sender_external_id`=session.userId; quando `Contato` → `sender_name`=`first_name last_name`, `sender_email`=contact.email, `sender_phone`=contact.phone. Atalho: Ctrl/Cmd+Enter envia (antes era Enter simples). States consolidados em apenas `msgSender` (`'me'`/`'contact'`, default `'me'`) e `msgSentAt` (datetime-local) — removidos `msgDirection`, `msgMessageType`, `msgSenderName`/`msgSenderEmail`/`msgSenderPhone`/`msgSenderExternalId`, `msgProviderMessageId`, `msgReceivedAt`. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/[id]) — conversation: layout do formulario reorganizado em duas colunas para aproveitar a largura adicional. Container externo agora usa `lg:w-[92vw] lg:max-w-[1500px]` quando `formType === 'conversation'` (antes ficava com a mesma largura compacta de task/meeting, `lg:w-[60vw] lg:max-w-[1100px]`). Body interno virou `grid lg:grid-cols-[minmax(0,1.05fr)_minmax(0,1fr)] gap-5`: coluna **esquerda** com scroll proprio (`overflow-y-auto scrollbar-premium`) contendo Row 1 (Titulo + Canal), Row 2 (Empresa + Contato + Oportunidade), Row 3 (Responsavel + Status + Prioridade) e Row 4 (Notas Markdown — `rows` aumentado de 3 para 8 para preencher melhor a coluna); coluna **direita** (flex-col, sem scroll proprio — o card de mensagens cuida do scroll interno) contendo a linha read-only `Provider / Thread ID / Ultima mensagem` (quando ha dados) e o card de Mensagens que ocupa `flex-1` da altura disponivel. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/[id]) — conversation: formulario expandido para cobrir todos os campos relevantes do `models.CRMConversation` (swagger.json). Antes so havia Titulo + Canal + Empresa/Contato/Oportunidade + lista de mensagens. Adicionados: (1) **Row 3**: `Responsavel` (LabeledInput com autocomplete portaled, reusando `acOwnerRef`/`acOwnerInput`/`handleAcOwnerInput`/`filteredAcOwners`/`handleSelectAcOwner` ja existentes para task/meeting), `Status` (Select com `open`/`snoozed`/`closed`/`archived` + dot colorido — `statusDotClass` estendido com cores para esses 4 valores) e `Prioridade` (Select LOW/MEDIUM/HIGH/URGENT com dot, identico aos forms de task/meeting). (2) **Row 4 Notas**: textarea (rows=3) com header `Notas (Markdown)`, change indicator (borda cyan + dot quando difere de init), botao para abrir modal expandido (reusa `notesModalOpen`). (3) **Provider info read-only** (visivel quando ha dados): linha com `Provider`, `Thread ID` e `Ultima mensagem` formatados em fonte mono para os IDs e data localizada para `last_message_at`. Mudancas no payload: `channel` foi adicionado ao `initialFormValues.current` (default `'whatsapp'`) e ao `hasFormChanges` (gated por `formType === 'conversation' || init.type === 'conversation'`), entao mudancas no campo Canal agora ativam o botao Salvar e sao enviadas no PUT. Os demais campos (priority/notes/owner_id/status) ja faziam parte do payload compartilhado e agora sao realmente editaveis. Bolhas de mensagem enriquecidas: alem de `sender_name`, agora mostram (4) **`sender_email`/`sender_phone`** concatenados (separados por hifen) em uma linha menor abaixo do nome para mensagens inbound, e (5) badge **`message_type`** (uppercase, fundo emerald-100) quando o tipo nao for `text` (ex: `image`, `audio`, `video`, `file`). Arquivo: app/(app)/_components/crm-activities-section.tsx.
CorrecaoCRM Activities (/crm/activities/[id]): edicao de atividades do tipo `conversation` deixou de exibir tela em branco. Antes o `loadEntity` so tentava `fetchCrmTask`/`fetchCrmMeeting` (ambos 404 para uma conversation), caia no `catch` e zerava `selectedActivity` — a UI renderizava o empty state mas pelo timing parecia branco. Mudancas: (1) `inferredType` agora reconhece `'conversation'` quando `listedActivity?.activity_type === 'conversation'`; (2) `loadEntity` busca via `fetchCrmConversation(editingId)` quando o tipo e conversation, e o fallback final tambem cai em conversation se task+meeting falharem; (3) `setSelectedActivity({ activity_type: 'conversation', ... })` ja popula o tipo corretamente. Nova UI dedicada para conversation: Row 1 com `Titulo` (LabeledInput) + `Canal` (Select WhatsApp/Teams via `formChannel` state), Row 2 com Empresa/Contato/Oportunidade (LabeledAutocomplete reusando os items existentes), e um card emerald com cabecalho `Mensagens (N)`, area de baloes estilo chat (outbound emerald-500 texto branco a direita, inbound branco/slate a esquerda com nome do remetente em emerald uppercase), data/hora curta, empty state e footer com `Textarea` + botao `Enviar` (Enter envia, Shift+Enter quebra linha). `useEffect` carrega via `fetchCrmConversationMessages(activityId)` quando `formType === 'conversation' && selectedActivity?.id` ordenando por `sent_at|received_at|created_at`. `handleSendMessage` chama `createCrmConversationMessage(activityId, { direction: 'outbound', body, sent_at: now })` com append otimista. Save (`handleSaveActivity`) ganhou branch `formType === 'conversation'` que faz `updateCrmConversation` com partial payload incluindo `channel`. Delete (`handleDeleteActivity`) chama `deleteCrmConversation`. Icone do header do form mostra `MessageCircle` emerald-600 quando conversation. Toasts adaptados (`Conversa atualizada`/`Conversa excluida`). Imports adicionados: `Send` (lucide), `Textarea` (`components/ui/textarea`), `fetchCrmConversation`/`updateCrmConversation`/`deleteCrmConversation`/`CRMConversation`/`CRMConversationChannel` (`lib/api/crm-conversations`), `fetchCrmConversationMessages`/`createCrmConversationMessage`/`CRMMessage` (`lib/api/crm-messages`). Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Contatos: adicionado campo booleano `is_linkedin_connected` (`Conectado no LinkedIn`) no CRUD, conforme `models.CRMContact`/`models.CreateCRMContactPayload`/`models.UpdateCRMContactPayload` do `swagger.json`. (1) **Types**: novo `is_linkedin_connected?: boolean` em `CRMContact` (`lib/api/crm-contacts.ts`), `CreateCRMContactPayload` (`lib/api/crm-contacts-create.ts`) e `UpdateCRMContactPayload` (`lib/api/crm-contacts-update.ts`). (2) **UI**: botao com icone `Link2` (conectado, emerald-300/emerald-50/emerald-600) ou `Link2Off` (nao conectado, red-300/red-50/red-600) renderizado **a direita do input LinkedIn** (size-9 square, alinhado ao final do input via `items-end`). Click alterna o estado, tooltip explica o significado, `aria-pressed` reflete o estado. Change indicator (dot cyan) no canto superior direito quando difere do valor inicial. Substituido o checkbox inferior por essa abordagem mais compacta. IDs `#ct-linkedin-connected` (companies tab) e `#contact-linkedin-connected` (standalone) preservados via `title`/`aria-pressed`. Aplicado em ambas as telas: `crm-companies-section.tsx` e `crm-contacts-section.tsx`. Novos icones `Link2Off` adicionados aos imports de `lucide-react`. (3) **State management**: novos `ctIsLinkedinConnected`/`setCtIsLinkedinConnected` (companies) e `formIsLinkedinConnected`/`setFormIsLinkedinConnected` (contacts). Populados em `openEditContact`/`populateForm` via `contact.is_linkedin_connected ?? false`. Reset em `openNewContact`/`resetForm` para `false`. (4) **Change tracking + save**: incluido em `hasContactFormChanges`/`hasFormChanges` e no payload PUT (`if (ctIsLinkedinConnected !== ...) payload.is_linkedin_connected = ...`) e POST (`is_linkedin_connected: ctIsLinkedinConnected`). Em `crm-contacts-section.tsx` o `initialFormValues` (tipo `Record<string, string>`) guarda como `String(value)` consistente com o padrao do arquivo.

26 de Maio de 2026

48 itens
19722
MelhoriaFin - Recurrences (/fin/recurrences): coluna `Status` agora alinhada ao centro (header com `text-center` + `justify-center` no botao de sort, celula com `text-center` mantendo o pill `inline-flex` Ativo/Inativo centralizado). Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
MelhoriaFin - Recurrences (/fin/recurrences): coluna `Frequencia` removida da tabela. Header e celula da coluna (que usava `frequencyBadge` com pills coloridos DAILY=violet/WEEKLY=sky/MONTHLY=cyan/YEARLY=purple) excluidos. Limpeza associada: chave `frequency` removida do `SortKey` e do switch de `sortedRecs` (nao havia mais botao para acionar), e o helper `frequencyBadge` + constante `FREQUENCY_LABELS` deletados por nao terem mais consumidor na tela. O campo `frequency` continua no data model do `FinRecurrence` e e exibido/editado normalmente no formulario (`/fin/recurrences/[id]` → Row 2 → `<Select>` Frequencia) e ainda participa do filtro de busca textual. Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
MelhoriaFin - Recurrences (/fin/recurrences): coluna `Vigencia` (range `start_date - end_date` em formato dd/mm/aaaa) substituida por **duas colunas separadas** `Inicio` e `Fim` em formato **dd/MM/yy** (compacto, via `formatFlexibleDateShort`), alinhadas ao centro. Cada coluna e ordenavel: nova chave de sort `end_date` adicionada ao `SortKey` e ao `switch` de `sortedRecs` (usa `extractFlexibleTime` + `localeCompare` consistente com `start_date`). Coluna `Fim` exibe em-dash slate-300 quando `end_date` esta vazio (recorrencia em vigor indefinidamente), e usa texto mais claro (slate-500) que `Inicio` (slate-600) para reforcar visualmente que e secundario. Import `formatFlexibleDate` removido (nao mais usado). Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
NovidadeFin - Recurrences (/fin/recurrences): listagem alinhada ao mesmo modelo do Installment Groups. (1) **Filtros no header**: `HeaderOwnerFilter` + `HeaderAccountFilter` populados via novo `accountOwnerMap` (owner derivado de `account.owner_id`), com filtragem cruzada entre owner/conta. Toggle pill `Ativas/Todas` (emerald quando ativo via `Clock3`, white quando todos via `Layers`) substituindo o filtro implicito anterior — default `Ativas`. (2) **Selecao multipla** com Checkbox shadcn: nova primeira coluna com select-all em 3 estados (unchecked/checked/indeterminate) e checkboxes por linha. Linhas selecionadas com fundo cyan-50/70 (dark: cyan-500/10). Click no checkbox usa `stopPropagation` no TableCell para nao abrir a edicao. (3) **Badges de totais** abaixo do header: `Receita` (emerald, soma de `amount` de categorias INCOME/TRANSFER_IN/INVESTMENT_IN) e `Despesa` (red, demais). Quando ha selecao, badges intensificam (ring-1) e aparece terceiro badge cyan `Selecionados N` clicavel para limpar. Sem selecao: somam toda a lista filtrada. (4) Imports adicionados: `Checkbox`, `Clock3`, `Layers`, `HeaderAccountFilter`, `HeaderOwnerFilter`, `AuthUser`, `fetchAuthUsers`. Novos states: `selectedOwnerId`, `selectedAccountId`, `showOnlyActive`, `selectedIds: Set<string>`, `allAuthUsers`. Helpers: `accountOwnerMap`, `ownerOptions`, `accountOptions`, `headerTotals`, `visibleSelectedCount`, `selectAllState`, `toggleSelectAll`, `toggleRowSelected`, `clearSelection`, `isIncomeCategory`. Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
NovidadeFin - Installment Groups (/fin/installment-groups): selecao multipla de itens na tabela que recalcula em tempo real os badges de `Pendente` e `Parcela` no topo. Nova coluna inicial com `Checkbox` shadcn (header com select-all em 3 estados: unchecked/checked/indeterminate cobrindo todos os grupos visiveis na lista filtrada; linhas com checkbox individual). State `selectedIds: Set<string>` mantido em memoria. `headerTotals` (useMemo) agora retorna `{ pending, installment, count, hasSelection }` — se ha selecao, soma apenas os grupos selecionados que estao na lista filtrada; sem selecao, comportamento original (soma toda a lista filtrada). Quando ha selecao, badges ganham borda/fundo intensificados (amber-100 ring-1 amber-200 / slate-100 ring-1 slate-200) e aparece um terceiro badge cyan **Selecionados N** clicavel que limpa a selecao (icone XCircle). Linhas selecionadas usam fundo cyan-50/70 (dark: cyan-500/10) sobrescrevendo o zebra striping. Click no checkbox usa `stopPropagation` no TableCell para nao abrir a edicao do grupo. Imports adicionados: `Checkbox` de `@/components/ui/checkbox`. Helpers adicionados: `toggleSelectAll`, `toggleRowSelected`, `clearSelection`, `selectAllState` (com indeterminate). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Recurrences (/fin/recurrences/[id]): formulario alinhado ao mesmo modelo de layout do Installment Groups. Header compactado (px-4 pt-2.5, botao Voltar h-8 text-xs, avatar size-8 mostrando favicon/logo do parceiro com fallback RefreshCw violet, titulo text-sm leading-tight, subtitulo de frequencia removido). Tabs compactas (px-3 py-1.5 text-xs, icones size-3.5, rounded-t-lg). Campos do formulario migrados de Floating* para padrao shadcn label-outside: `FloatingInput` (Valor, Intervalo, Dif.mes, Dia do mes) -> `LabeledInput` com `leftIcon`; `FloatingSelect` (Frequencia, Dia Transacao) -> `<Label>` + `<Select>` shadcn com SelectTrigger h-9 bg-white/40 e ring cyan no hasChanged; `FloatingDateInput` (Vencimento Inicio/Fim) -> `DatePickerInput`; `<textarea>` (Notas) -> `<Label>` + `Textarea` shadcn. Autocompletes Row 1 (Parceiro/Categoria/Conta) com `labelOutside id="rec-..."`. Linhas reorganizadas: Row 1 Parceiro/Categoria/Conta/Status; Row 2 Valor/Frequencia/Intervalo/Vencimento Inicio/Vencimento Fim; Row 3 Dia Transacao/Dif.mes/Dia do mes; Row 4 Notas (flex-1). Imports `FloatingInput`/`FloatingDateInput`/`FloatingSelect` e icones `Tag`/`Type` removidos. Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): header do formulario com 3 ajustes. (1) **Subtitulo removido** — antes mostrava `{N} parcelas` abaixo do titulo; agora so o titulo. (2) **Avatar do header** trocado de icone fixo `CreditCard` violet para o **logo do parceiro selecionado** (`formPartnerId` → `allPartners.find()`): favicon do `domain` via Google s2 → fallback `logo_url` → fallback icone `Users` violet quando nenhum dos dois esta disponivel. Mesma cadeia de fallback usada em outras telas. Usa `object-fill` (stretch) e `overflow-hidden` para preencher o circulo. (3) **Espacamento maior entre botao Voltar e avatar** — adicionado `ml-3` (+12px) no container do avatar, separando visualmente o botao de navegacao da identidade do registro. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
CorrecaoFin Autocompletes (Parceiro, Categoria, Conta) + Textarea de Notas (Installment Groups): font-size 13px que nao estava sendo aplicada em telas md+ porque o `Input`/`Textarea` shadcn tem `md:text-sm` (14px) que vence sobre `text-[13px]` quando ha breakpoint responsivo. Solucao: adicionar `md:text-[13px]` ao lado de `text-[13px]` (mesma estrategia que ja era usada em `LabeledInput`). Aplicado em fin-partner-autocomplete.tsx, fin-category-autocomplete.tsx, fin-account-autocomplete.tsx (input do modo `labelOutside`) e no textarea de Notas em fin-installment-groups-section.tsx. Agora os campos exibem 13px consistentemente em todas as larguras.
NovidadeFin - Installment Groups (/fin/installment-groups/[id]): direcao do calculo automatico invertida — agora `Valor Total` e tratado como entrada e `Valor Parcela` e a saida via formula **`Valor Parcela = Total / Parcelas - Encargos + Desconto`**. Antes, mudar `Encargos`/`Desconto` recalculava o Total (mantendo Parcela fixa). Agora recalcula a Parcela (mantendo Total fixo) — `onChange` desses dois campos chama `calcInstallmentAmount(formTotalAmount, formInstallmentTotal, v, ...)` em vez de `calcTotalFromInstallment`. `populateForm` tambem atualizado para inicializar `Valor Parcela` ja com encargos/desconto aplicados ao carregar dados existentes do backend. Os helpers `calcInstallmentAmount`/`calcTotalFromInstallment` continuam aceitando `charges`/`discount` como parametros explicitos (passados pelo caller antes do React aplicar o setState). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Autocompletes (Parceiro, Categoria, Conta) + Installment Groups Details: padronizada a `font-size` em **13px** em todos os campos. Selects `Modo de Data` e `Dia da Transacao` agora aplicam `text-[13px]` em cada `SelectItem` do dropdown (eram 14px por padrao do shadcn). Itens do dropdown dos autocompletes (linhas de sugestoes de parceiro/categoria/conta) tambem migrados de `text-sm` para `text-[13px]`. Inputs ja estavam 13px via `LabeledInput`, `DatePickerInput`, `Textarea` shadcn override e o input label-outside dos autocompletes. Arquivos: app/(app)/_components/fin-installment-groups-section.tsx, fin-partner-autocomplete.tsx, fin-category-autocomplete.tsx, fin-account-autocomplete.tsx.
NovidadeFin Autocompletes (Parceiro, Categoria, Conta): nova prop opcional `labelOutside?: boolean` (+ `id?: string`) que troca a renderizacao do label flutuante (FloatingInput) por um `<Label>` shadcn acima de um `<Input>` shadcn normal, mantendo todo o resto da logica (icone/avatar clicavel a esquerda, dropdown com createPortal, botao X de limpar, navegacao por teclado, Sheet de edicao). Default `false` — comportamento inalterado para todos os usos existentes (FinTransactionForm, FinRecurrencesSection, ConciliacaoBancaria, etc.). Container de label-outside reusa `labelOutsideClass` de `labeled-input.tsx` para consistencia tipografica. Aplicado em `fin-installment-groups-section.tsx` Row 1 (Parceiro/Categoria/Conta) com `labelOutside id="ig-..."`, completando a padronizacao shadcn da aba Detalhes. Arquivos: app/(app)/_components/fin-partner-autocomplete.tsx, fin-category-autocomplete.tsx, fin-account-autocomplete.tsx, fin-installment-groups-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id], aba `Detalhes`): campos do formulario migrados do padrao `Floating*` (label dentro do input que flutua) para o padrao **shadcn com label fora** (Label acima do controle), alinhado ao restante do app (CRM Companies/Deals, Useful Links, Safe Vaults). Conversoes: (1) `FloatingInput` (Valor Total, Parcelas, Valor Parcela, Encargos, Desconto, Dia do Mes, Valor Pago, Valor Pendente) → `LabeledInput` (`app/(app)/_components/labeled-input.tsx`) com icones movidos para `leftIcon`; (2) `FloatingSelect` (Modo de Data, Dia da Transacao) → `<Label className={labelOutsideClass}>` + `<Select>` shadcn com `SelectTrigger h-9 bg-white/40` e ring cyan no `hasChanged`; (3) `FloatingDateInput` (Data Transacao, Primeiro Vencimento) → `DatePickerInput` (`components/ui/date-picker-input.tsx`) que ja segue o padrao label-outside e tem popover de calendario; (4) `<textarea>` com label flutuante (Notas) → `<Label>` + `Textarea` shadcn (`components/ui/textarea.tsx`). Imports `FloatingInput`, `FloatingDateInput`, `FloatingSelect` removidos (ficaram sem uso). Visual mais consistente com outras telas; menos componentes custom, mais shadcn padrao. Autocompletes da Row 1 (Parceiro/Categoria/Conta) mantidos como `Fin*Autocomplete` (sao componentes proprios reutilizaveis). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): header do formulario compactado, liberando espaco vertical para o conteudo. Padding: `px-5 pt-4 pb-4` → `px-4 pt-2.5 pb-2.5` (ou `pb-0` quando ha tabs). Icone do parceiro: circulo `size-11` (44px) → `size-8` (32px), icone `size-5` → `size-4`. Botao Voltar: `size=sm` default → `h-8 text-xs px-2.5` com icone `size-3.5`. Titulo: `text-base` → `text-sm leading-tight`; subtitulo `text-xs` → `text-[11px] leading-tight`. Gap entre elementos: `gap-3` → `gap-2`. Tabs: separador `h-px bg-white/20` mantido entre o header e as abas para separacao visual clara; espacamento `mt-3 mt-2` → `mt-2 mt-1.5`; botoes das tabs `px-4 py-2 text-sm` → `px-3 py-1.5 text-xs` com icones `size-3.5`. Visual permanece elegante com gradiente, blurs decorativos e shimmer mantidos. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin - Installment Groups (/fin/installment-groups/[id]): formula de calculo automatico do `Valor Total` ajustada para considerar encargos e desconto. Antes: `Total = Parcela * N`. Agora: **`Total = (Parcela + Encargos - Desconto) * N`**. Helpers `calcTotalFromInstallment` e `calcInstallmentAmount` (inversa: `Parcela = Total/N - Enc + Desc`) atualizados para aceitar `charges` e `discount` como parametros (default puxa do state atual, mas o caller pode passar valores novos antes do React render). Os onChange dos campos `Encargos` e `Desconto` agora disparam `calcTotalFromInstallment` passando o novo valor explicitamente — assim o `Valor Total` se atualiza imediatamente, mesmo que o React ainda nao tenha aplicado o setState. Comportamento ao editar Parcela ou Parcelas continua igual (mantem total quando ha total e parcelas, ou recalcula total da parcela). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): campo `Primeiro Vencimento` movido da Row 2 para a Row 2.4, posicionado **a direita de `Data Transacao`**. Junto com `Modo de Data`, `Data Transacao` e os campos condicionais `Dia da Transacao`/`Dia do Mes`, todos os campos relacionados a datas das parcelas ficam agrupados na mesma linha. Row 2 fica so com Valor Total, Parcelas, Valor Parcela, Encargos, Desconto. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): campo `Data Transacao` movido da Row 2 (Valor Total / Parcelas / Valor Parcela / ...) para a Row 2.4, posicionado **a direita de `Modo de Data`**. Faz sentido conceitualmente porque os dois campos definem juntos quando as transacoes do grupo acontecem (a data base e o modo de propagacao). Row 2 fica mais leve com Valor Total, Parcelas, Valor Parcela, Primeiro Vencimento, Encargos, Desconto. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): rearranjo da Row 3 do formulario. `Valor Pago` e `Valor Pendente` (readonly) saem da Row 2.4 (`Modo de Data`) e passam a ficar **a direita do textarea de Notas**, empilhados verticalmente (`Valor Pago` em cima, `Valor Pendente` embaixo) numa coluna `flex-col w-48 shrink-0`. Notas continua ocupando o espaco restante (`flex-1`) com `h-full` para acompanhar a altura da coluna direita. Row 2.4 fica focada so nos campos de modo de data. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin - Installment Groups (/fin/installment-groups/[id]): CRUD sincronizado com novo schema do swagger. Dois novos campos `number` adicionados ao `models.CreateFinSchemaInstallmentGroupPayload`, `models.UpdateFinSchemaInstallmentGroupPayload` e `models.FinSchemaInstallmentGroup`: (1) **`charges_amount`** — encargos/taxas; (2) **`discount_amount`** — desconto aplicado ao grupo. Implementacao em `lib/api/fin-installment-groups.ts`: campos opcionais no type `FinInstallmentGroup` e no payload de `createFinInstallmentGroup`. Implementacao em `app/(app)/_components/fin-installment-groups-section.tsx`: 2 novos states `formChargesAmount`/`formDiscountAmount`, integrados ao `hasFormChanges`, `populateForm` (formatando via `fmtMonetary`), `resetForm`, payload de create (via `currencyToNumber`) e de update (envia `null` quando limpo). Novos `FloatingInput` currency com `w-40` na Row 2 do form, apos `Primeiro Vencimento`: **Encargos** (icone R$ amber) e **Desconto** (icone R$ emerald), ambos com `hasChanged` indicator. Arquivos: lib/api/fin-installment-groups.ts, app/(app)/_components/fin-installment-groups-section.tsx.
CorrecaoFin - Partners (/fin/partners/new): rota mostrava a listagem de parceiros em vez do formulario de criacao. Causa: `isCreating` era setado para `true` apenas dentro de um `useEffect` que dispara depois do primeiro render, entao a primeira pintura sempre mostrava o modo lista; em renders subsequentes, dependendo da ordem de execucao de effects (especialmente sob React Strict Mode e quando `loading` do `useEntityList` flip-flopa), o effect podia bailar antes de aplicar o modo `new` (gate `if (initialModeAppliedRef.current || loading) return;`). Solucao: inicializar `isCreating` sincronamente a partir da prop `initialMode` via `useState(initialMode === "new")` em vez de depender do effect. Form de inclusao agora aparece imediatamente no primeiro paint, sem flicker da lista. O effect `Apply initial mode` permanece para o caso `edit` (que precisa esperar `partners` carregar para fazer o `populateForm`). Arquivo: app/(app)/_components/fin-partners-section.tsx.
MelhoriaFin - Installment Groups (/fin/installment-groups/[id]): campos `Valor Pago` e `Valor Pendente` (readonly) movidos da Row 2.5 standalone para a mesma linha do `Modo de Data` (Row 2.4), alinhados a direita via `ml-auto` no `wrapperClassName` do primeiro. Aproveita o espaco horizontal do formulario, reduzindo uma linha quando os campos opcionais `Dia da Transacao`/`Dia do Mes` nao estao visiveis. Row 2.5 antiga removida. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin - Installment Groups (/fin/installment-groups/[id]): CRUD atualizado com tres novos campos do swagger (POST e PUT) que controlam como o backend calcula as datas das transacoes geradas pelo grupo de parcelamento. (1) **`transaction_date_mode`** (`FIXED` | `MONTHLY`) — `FIXED` usa a mesma `transaction_date` em todas as parcelas; `MONTHLY` espalha uma por mes. Default FIXED. (2) **`transaction_day_mode`** (`SAME_DAY` | `FIRST_DAY` | `LAST_DAY` | `EXACT_DAY`) — so faz sentido em MONTHLY: replicar o dia da `transaction_date`, primeiro dia do mes, ultimo dia, ou um dia especifico. Default SAME_DAY. (3) **`transaction_day_of_month`** (1-31) — so usado quando `transaction_day_mode === EXACT_DAY`. Implementacao em `lib/api/fin-installment-groups.ts`: novos types exportados `FinInstallmentTransactionDateMode` e `FinInstallmentTransactionDayMode`, campos opcionais adicionados ao `FinInstallmentGroup` e ao payload de `createFinInstallmentGroup`. Implementacao em `app/(app)/_components/fin-installment-groups-section.tsx`: 3 novos states, integrados ao `hasFormChanges`, `populateForm` (com defaults FIXED/SAME_DAY), `resetForm` e payload de create/update (no PUT, campos enviados como `null` quando limpos). Nova Row 2.4 no formulario com `FloatingSelect` para os modos (labels em pt-BR: 'Fixa (mesma data em todas)', 'Mensal (uma por mes)', 'Mesmo dia da data de transacao', 'Primeiro dia do mes', 'Ultimo dia do mes', 'Dia especifico do mes') e `FloatingInput` numerico para o dia do mes — dropdowns aparecem condicionalmente (Dia da Transacao so em MONTHLY; Dia do Mes so em MONTHLY + EXACT_DAY). Validacao do input restringe 1-31. Arquivos: lib/api/fin-installment-groups.ts, app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin - Conciliacao de Cartao (/fin/conciliacao-cartao): coluna `REC` (recorrencia) removida da tabela `Sistema`. Grid atualizado de `grid-cols-[28px_70px_1fr_1fr_80px_22px_36px_28px]` para `grid-cols-[28px_70px_1fr_1fr_80px_36px_28px]` tanto no header quanto nas linhas; cabecalho `Rec` removido, div com icone `Repeat2` removida das linhas, import `Repeat2` removido da lista de `lucide-react`. Tabela agora tem 7 colunas: status (28px), data (70px), parceiro (1fr), categoria (1fr), valor (80px), parcela (36px) e pgto (28px). Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: redesenho com foco em UI/UX para o usuario final. (1) **Summary card** no topo (violet-50 rounded, 22mm) com `R$ TOTAL` em 18pt violet-900 a esquerda, contagem `N lancamentos em M categorias`, e grid de meta (PERIODO/OWNER/CONTA) a direita com labels SMALLCAPS gray + valores slate. Data de geracao no canto superior direito do card. (2) **Ordenacao por valor DESC** — categorias e parceiros agora aparecem do maior para o menor gasto (empates por nome), em vez de alfabetica; muito mais acionavel ao revisar onde o dinheiro foi. (3) **Percentuais** — cada categoria mostra `XX,X%` do total geral (texto violet-light dentro da barra colorida); cada parceiro mostra `XX,X%` da categoria (slate-400 sutil ao lado do total). (4) **Linha do parceiro sem fill** — antes era uma barra violet-claro; agora e uma linha limpa com logo + nome slate-700 + % + total slate-900 bold, mais leve visualmente e melhor para escanear. Body table agora indenta sob o logo do parceiro (margem esquerda +7mm) com hairline divider entre linhas (sem zebra), date column slate-500, valor slate-900. (5) **Total geral** com linha violet-border acima e amount grande em 14pt violet-900 (era barra slate-900 5mm). Mais elegante e claro. (6) **Footer por pagina** com `Pagina X de Y` centralizado, `Relatorio Segmentado` a esquerda e `gerenciapp` a direita, linha divisora slate-200 acima — renderizado em loop final via `doc.getNumberOfPages()` + `doc.setPage()`. (7) Helpers de cor extraidos em constantes nomeadas (`VIOLET`, `SLATE_900`, etc.) para legibilidade. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
MelhoriaFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: barras de categoria voltaram a usar cor unica (violet-600) em vez da paleta deterministica de 10 cores — removido o helper `colorFor()` e o array `catPalette` que ficaram sem uso. Identidade visual da categoria continua via o icone (emoji) renderizado no circulo branco. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
MelhoriaFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: layout ainda mais compacto para caber em menos paginas. Page header consolidado em 2 linhas (era 3): Periodo/Owner/Conta/Gerado em/contagem juntos. Inicio do conteudo Y=16 (era 25). Barras de categoria 5.5→4.4mm (fonte 9→8pt), barras de parceiro 4.6→3.6mm (fonte 8→7pt), body do autoTable 7→6.5pt com `minCellHeight: 0` e padding vertical 0.5→0.3mm. Espacamento entre parceiros 1.2→0.6mm; entre categorias 1.5→0.8mm. Avatar circle das categorias/parceiros 1.7→1.4mm. `TOTAL GERAL` 7→5.2mm (10→9pt). `pageBottom` 285→290. Resultado: aprox 35-45% menos altura vertical por grupo, divide muito menos paginas. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
CorrecaoFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: tres correcoes no layout segmentado. (1) **Favicons via `domain` agora carregam** — Google `s2/favicons` nao envia headers CORS, entao `<img crossOrigin=anonymous>` + canvas falhava silenciosamente. Solucao: novo helper `corsImageUrl()` que proxia qualquer URL atraves de `images.weserv.nl` (proxy publico gratuito que reenvia com `Access-Control-Allow-Origin: *`). Aplicado tanto no favicon do `domain` quanto no `logo_url` direto. (2) **Icones de categoria (emojis) agora aparecem** — fonte padrao do jsPDF (Helvetica) nao tem glyph para emoji. Solucao: novo helper `renderEmojiToDataURL()` que desenha o emoji num canvas usando as fontes do browser (`Apple Color Emoji`, `Segoe UI Emoji`, `Noto Color Emoji`, `Twemoji Mozilla`), converte para PNG dataURL e embarca via `doc.addImage`. Cache `categoryIconCache` por string de icone evita re-render. Fallback continua sendo a inicial do nome da categoria. (3) **Removido o `Nx`** (contagem de lancamentos) da barra do parceiro — informacao redundante com as linhas do body que ja listam cada lancamento. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: layout reformatado, mais compacto, com icones/logos. (1) **Mais compacto** — titulo 14→12pt, subheaders 9→7.5pt, barras de categoria 7→5.5mm de altura, barras de parceiro 6→4.6mm, linhas do body autoTable 8→7pt com padding 1.2→0.5mm e `lineWidth: 0` (sem bordas internas); alternateRowStyles slate-50 para separacao visual; coluna `Valor` em bold. (2) **Logos dos parceiros** — pre-carregados em paralelo via `<img crossOrigin=anonymous>` + canvas → dataURL (com timeout 4s) usando `partner.domain` (favicon Google s2 `sz=64`) ou `partner.logo_url` como fallback; renderizados a esquerda da barra do parceiro com `doc.addImage` num circulo branco de 3.4mm. Quando o load falha por CORS/timeout, cai para circulo violet-300 com a inicial do nome. (3) **Icones das categorias** — circulo branco a esquerda da barra com o `category.icon` (emoji ou texto curto) ou inicial; cor de fundo da barra agora segue uma paleta deterministica de 10 cores (violet/blue/emerald/orange/rose/amber/teal/fuchsia/indigo/cyan) hashada pelo nome da categoria, dando identidade visual sem precisar de campo `color` na FinCategory. (4) Refatorada a estrutura interna: agrupamento agora usa `category_id`/`partner_id` como chaves para conseguir lookup dos records (necessario para domain/logo_url/icon). `TOTAL GERAL` mantido em barra slate-900 ao final. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
CorrecaoFin - Conciliacao de Cartao (/fin/conciliacao-cartao) - PDF `Relatorio Segmentado`: barra do parceiro nao quebra mais em duas linhas quando o nome e longo (ex.: `Posto de Combustivel`, `Mais que Make`). Antes a barra era o `head` do `autoTable` com `cellWidth: 22` na primeira coluna (largura da data), forcando wrap; agora a barra do parceiro e desenhada manualmente como `rect` violet-100 full-width (mesma estrategia da barra de categoria), com nome a esquerda, contagem de lancamentos ao centro-direita e total a direita. O nome usa novo helper local `fitTextToWidth` (busca binaria com `doc.getTextWidth`) que adiciona `...` se ultrapassar o espaco disponivel ate a coluna de info, garantindo sempre uma unica linha. Mesma protecao aplicada ao nome da categoria. Body do autoTable mantem 3 colunas (data 22mm, descricao auto, valor 28mm right). Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`handleExportSegmentedPdf`).
CorrecaoFin - Conciliacao de Cartao (/fin/conciliacao-cartao): avatar do parceiro no `InlinePartnerAutocomplete` (usado tanto na tabela `Fatura Excel` quanto na tabela `Sistema`) agora cai para `partner.logo_url` quando nao ha `partner.domain` em vez de pular direto para o icone `Users`. Cadeia de fallback: (1) `domain` → favicon do Google s2; (2) `logo_url` → `<img>` direto; (3) sem nenhum dos dois → icone `Users` em fundo indigo. O anel branco do container so e ativado quando ha imagem (`domain || logo_url`), igual ao comportamento ja consolidado nas outras telas de parceiros. Imagens passaram a usar `object-fill` (stretch) consistente com o ajuste recente em `/fin/transactions`. Aplicado no botao selecionado e em cada item do dropdown. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx (`InlinePartnerAutocomplete`).
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): botao `Exportar PDF` simples no header virou um `DropdownMenu` (`components/ui/dropdown-menu.tsx`) chamado `Exportar` com duas opcoes: (1) **Conciliacao (Fatura)** — mantem o `handleExportPdf` ja existente (tabela landscape com lancamentos da fatura Excel, status e cores), habilitado somente quando ha `statementData` carregado; (2) **Relatorio Segmentado** — novo `handleExportSegmentedPdf` que gera um PDF A4 retrato agrupando `systemTxs` por **Categoria → Parceiro**, com subtotais por parceiro e por categoria, mais um `TOTAL GERAL` em barra slate-900 no fim. O cabecalho do PDF traz Periodo (dos filtros de vencimento), Owner, Conta (`Todas do owner` quando ha owner sem conta especifica), data de geracao e contagem total de lancamentos; usa `jspdf` + `jspdf-autotable` (mesmas libs do export ja existente). Container das acoes do header agora abre com `statementData || systemTxs.length > 0` (em vez de exigir `statementData`), permitindo exportar o segmentado mesmo sem fatura Excel; stats badges, `Incluir Pendentes` e `Baixar Lancamentos` continuam gated por `statementData`. Novos imports: `FileText` (lucide) e o conjunto do `DropdownMenu`. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): com `Owner Account` selecionado e nenhuma `Conta` especifica, a tabela `Sistema` agora carrega as transacoes de TODAS as contas ativas do owner (preferindo `CREDIT_CARD`; fallback para qualquer conta ativa). Implementacao via novo `useMemo effectiveAccountIds` que resolve a lista de account_ids a usar em `searchFinTransactions({ account_id: effectiveAccountIds })`: prioridade `[selectedAccountId]` quando explicito; caso contrario, contas do `selectedOwnerId`; caso contrario, vazio (e o painel exibe `Selecione um owner ou uma conta para carregar as transacoes`). `loadSystemTxs` e a recarga apos `handleBulkPay` passaram a usar essa lista. Mantem o filtro de periodo (`start_due_date`/`end_due_date`) e a derivacao a partir do `statementData.summary.dueDate` quando nao ha filtro manual. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): novo filtro `Owner Account` no header principal, posicionado a esquerda do filtro `Conta` ja existente. Reutiliza `HeaderOwnerFilter` (`app/(app)/_components/header-owner-filter.tsx`) — autocomplete glass com busca normalizada por `full_name`/`email`, avatar via `image_url` (fallback icone `User`), navegacao por teclado (ArrowUp/Down + Enter) e X para limpar. Implementacao em `app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx`: (1) nova state `selectedOwnerId` + `authUsers`, populado via `fetchAuthUsers()` (`lib/api/auth-users.ts`) junto com os outros fetches do mount; (2) `ownerOptions` lista apenas usuarios que sao `owner_id` de alguma conta ativa (preferindo donos de contas `CREDIT_CARD`; se nenhum dono de cartao for encontrado cai para todos os donos de contas ativas), ordenado alfabeticamente em pt-BR; (3) `creditCardAccounts` e `allAccounts` agora filtram tambem por `a.owner_id === selectedOwnerId` quando ha owner escolhido, encadeando os dois filtros (selecionar owner restringe contas visiveis); (4) `useEffect` limpa `selectedAccountId` automaticamente quando o owner selecionado deixa de bater com o owner da conta atual, evitando estado invalido. Headers usados: `Authorization` + `tenant_id` ja injetados pelo interceptor do axios em `lib/api/client.ts`.
NovidadeFin - Installment Groups (/fin/installment-groups/[id], aba `Transacoes`): (1) colunas `Vencimento` e `Pago` da tabela de transacoes passam a usar `formatFlexibleDateShort` (formato `dd/MM/yy`) em vez de `formatFlexibleDate` (formato `dd/MM/yyyy`), economizando espaco horizontal e mantendo consistencia visual com outras tabelas curtas; (2) coluna `Valor` deixou de exibir o prefixo `R$ ` (apenas o numero monetario, ja com tabular-nums e cor por tipo de categoria); (3) **nova coluna `Referencia`** adicionada a esquerda de `Vencimento`, exibindo `tx.transaction_date` no mesmo formato `dd/MM/yy` e tambem clicavel para ordenar (a chave `transaction_date` ja existia em `txSortKey` e estava sem botao). Import de `formatFlexibleDate` removido (ficou sem uso); `formatFlexibleDateShort` ja era importado. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin - Transactions (/fin/transactions): ordenacao padrao da tabela alterada de `due_date ASC` (Vencimento) para `transaction_date DESC` (Referencia descendente), fazendo as transacoes mais recentes aparecerem primeiro no carregamento inicial. Mudanca em uma unica linha do `useSortable<SortKey>(...)` em `app/(app)/_components/fin-transactions-section.tsx` (linha 154). O usuario pode continuar reordenando livremente clicando nos cabecalhos.
MelhoriaFin - Transactions (/fin/transactions): avatar do parceiro na tabela passa a usar `object-fill` (stretch) em vez de `object-cover`, fazendo o favicon/logo preencher totalmente o circulo de `size-7` sem deixar borda branca em cima/baixo nem cortar laterais. Aplicado nas duas `<img>` (favicon do `partner.domain` via Google s2 e `partner.logo_url` proprio). Arquivo: app/(app)/_components/fin-transactions-table.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): filtros de `Vencimento Inicial` e `Vencimento Final` no header agora sao inicializados com o primeiro e o ultimo dia do mes atual (via `getCurrentMonthRange()` de `lib/date-helpers.ts`) em vez de comecarem vazios, alinhado com o comportamento padrao do extrato bancario. O reset (`handleReset`) tambem volta para esse mesmo intervalo do mes corrente, e o upload de uma fatura continua sobrescrevendo o intervalo com `statementData.summary.dueDate` quando disponivel. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): filtros de `Vencimento Inicial` e `Vencimento Final` no header passaram a ser campos de data editaveis (em vez de botoes que abriam o date picker nativo). Agora aceitam digitacao livre com os mesmos atalhos do restante do app via `parseReferenceInput` de `lib/date-helpers.ts`: ao digitar `12` + Enter completa para 12/MM/AAAA do mes atual, `1205` + Enter para 12/05/AAAA, `120526` para 12/05/2026, ou `+5`/`-3` para deslocar dias uteis. Mantida a aparencia (pill glass com label `VENCIMENTO INICIAL/FINAL` em cima e valor abaixo), o icone do calendario virou botao que abre o `<input type="date">` nativo escondido, e o commit acontece em Enter ou blur (revertendo para o ultimo valor valido quando a entrada nao puder ser parseada). Novo componente local `HeaderDueDateField` (mesmo padrao do `CompactDateField` ja usado em `extrato-bancario-screen.tsx`); removidos refs `startDueDatePickerRef`/`endDueDatePickerRef` e helper `openDatePicker` que ficaram sem uso. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
CorrecaoFin - Parceiros (/fin/partners): avatares dos parceiros na listagem (tabela) e nos cards expandidos do painel lateral tambem passam a usar `object-contain` em vez de `object-cover`, para nao cortar logos com proporcao diferente de quadrado. Aplicado em todas as quatro `<img>` que carregavam favicon do `domain` ou `logo_url` do partner (2 na tabela `size-8 rounded-full` + 2 no card `size-12 rounded-2xl`). Arquivo: app/(app)/_components/fin-partners-section.tsx.
CorrecaoFin - Parceiros (/fin/partners/[id]): avatar do parceiro no header da aba Detalhes nao corta mais o logo quando o partner tem um `logo_url` proprio enviado pelo usuario. A `<img>` do logo trocou `object-cover` (que cortava o logo para preencher o circulo de `size-[96px]`) por `object-contain p-1` (mantem a proporcao e adiciona um respiro de 4px para o logo nao encostar nas bordas do circulo). Comportamento de fallback para favicon (`formDomain`) e icone `Users` permanece igual. Arquivo: app/(app)/_components/fin-partners-section.tsx.
NovidadeFin - Conciliacao de Cartao (/fin/conciliacao-cartao): tabela `Sistema` ganhou duas novas colunas de status a esquerda da coluna `Pgto`, na ordem (Rec - Parc - Pgto). (1) **Rec** (22px, rotulo `Rec` no header) exibe um circulo violet com icone `Repeat2` (size-3) quando `recurrence_id` esta preenchido; (2) **Parc** (36px, rotulo `Parc` no header) exibe a parcela atual no formato `N/total` (ex.: `1/3`) com pill violet (`rounded-full border-violet-200 bg-violet-50 text-violet-700`, `text-[10px] tabular-nums`) quando `installment_number` esta preenchido. Grid atualizado de `grid-cols-[28px_70px_1fr_1fr_80px_28px]` para `grid-cols-[28px_70px_1fr_1fr_80px_22px_36px_28px]` tanto no header quanto nas linhas. Import `Repeat2` adicionado de `lucide-react`. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeAdmin - Safe Vault (/admin/safe-vaults): avatar na tabela passa a exibir o favicon do dominio extraido do campo `url` em vez das iniciais quando a URL esta preenchida. Implementacao em `app/(app)/_components/safe-vaults-section.tsx`: novo helper `extractDomain(url)` (mesmo padrao usado em `useful-links-section.tsx`) e novo componente local `VaultAvatar` que tenta renderizar `<img src='https://www.google.com/s2/favicons?domain=...&sz=128' />` dentro de um circulo com borda rose e fallback automatico para as iniciais quando (a) a URL nao existe, (b) o `onError` dispara, ou (c) `naturalWidth < 20` (favicon generico do Google). A celula `Nome` da tabela agora usa `<VaultAvatar vault={item} />` no lugar do span com iniciais. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults/[id]): formulario migrado para o mesmo padrao visual usado em `/travel/trips/[id]` e demais resources de Travel — labels em `text-[12px] font-semibold text-slate-400` (`labelOutsideClass`), inputs `h-9 rounded-md border-slate-200 bg-white/40 text-[13px] shadow-none`, icones a esquerda em `size-4 text-sky-500`, change indicator com borda cyan + bolinha cyan no canto superior direito. Os campos simples (Nome, Tipo, Usuario, URL) usam `LabeledInput` diretamente; Senha e Access Key usam novo componente local `SecretField` que replica o estilo do `LabeledInput` adicionando o botao `Eye/EyeOff` a direita e reposiciona o dot de change para `right-8` (para nao colidir com o botao). A textarea de Observacoes ganhou `rows={4}`, `field-sizing-fixed resize-none rounded-md border-slate-200 bg-white/40 text-[13px]` e o mesmo dot cyan. O const local `inputClass` (usado antes para todos os inputs) foi removido. Novo helper `fieldIconClass = 'size-4 text-sky-500 dark:text-sky-400'`. Imports adicionados: `LabeledInput`, `labelOutsideClass`, `Label`, `Tag`. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults/[id]): campo `Status` (toggle Ativo/Inativo) movido para a direita do campo `Tipo`, compartilhando a mesma linha. A celula direita do grid `lg:grid-cols-2` foi substituida por um `flex items-end gap-3` com Tipo (`flex-1`) a esquerda e Status (largura auto) a direita. O bloco isolado de Status que ficava abaixo do grid foi removido. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults/[id]): campo `is_active` movido do header (par de botoes pill Ativo/Inativo no canto direito) para dentro do corpo do formulario, logo apos a linha de Senha/Access Key e antes de Observacoes. Renderizado com o componente compartilhado `StatusToggleField` (mesmo usado em `/travel/cities/[id]` e demais resources de Travel) — botao glassmorphism com bolinha pulsante emerald/red, label `Ativo/Inativo` (default), `hasChanged` dot cyan quando o valor difere de `initialRef.current.isActive`, altura `h-11` para alinhar com os inputs. O label uppercase 'Status' acima segue o padrao dos outros campos do form. Os dois `<button>` antigos no header (Ativo/Inativo) foram removidos; o `CopyIdButton` permanece. Arquivos: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults/[id]): tamanho de fonte dos inputs e da textarea de Observacoes ajustado de `text-sm` (14px) para `text-[13px]` para um visual ligeiramente mais compacto. Aplicado em `inputClass` (compartilhado por Nome, Tipo, Usuario, URL, Senha, Access Key) e no `<Textarea>` de Observacoes. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults/[id]): removidos os dois cards do rodape do formulario de edicao (`Auditoria` com criado_em/atualizado_em/criado_por/atualizado_por e `Resumo` com status/tipo/usuario/tenant_id). As informacoes ja estao disponiveis no proprio formulario (status no toggle do header, tipo/usuario como campos editaveis) e o `FormFooter` ja mostra o updated_at, entao os cards eram redundantes. Limpeza acompanhada: imports `CalendarClock` (lucide-react) e helper local `formatDateTime` removidos, ja que so eram usados nos cards excluidos. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
NovidadeAdmin - Safe Vault (/admin/safe-vaults/[id]): avatar circular no header do formulario de edicao tambem passa a exibir o favicon do dominio extraido do campo `url` (sincronizado com `formUrl` em tempo real conforme o usuario edita o campo URL), com fallback automatico para o icone `Shield` rose quando a URL e vazia, invalida, ou o favicon falha ao carregar (`onError` ou `naturalWidth < 20`). Implementacao em `app/(app)/_components/safe-vaults-section.tsx`: novo componente local `VaultHeaderAvatar({ url })` que reaproveita o helper `extractDomain` e segue o mesmo padrao do `VaultAvatar` da tabela, mas dimensionado para o circulo `size-12` do header (`<img className='size-7 object-contain'>`). `useEffect` reseta o estado `failed` quando o dominio muda. Substitui o `<span>` antigo que renderizava Shield diretamente. Arquivo: app/(app)/_components/safe-vaults-section.tsx.
MelhoriaAdmin - Safe Vault (/admin/safe-vaults): contador de registros migrou da pill solta a direita do header para dentro do avatar a esquerda do titulo, substituindo o icone `Shield`. O avatar (`rounded-xl bg-white/20 backdrop-blur`) agora exibe `{sortedItems.length}` em texto branco bold `tabular-nums` quando `hasSearched` e verdadeiro; antes da primeira busca, mantem o icone `Shield` como placeholder. A `<span>` antiga que renderizava `{sortedItems.length} registros` no flex `ml-auto` foi removida, deixando o lado direito do header apenas com o botao `Novo Safe Vault`. Tambem foi removido o subtitulo `CRUD vinculado ao swagger.json` que ficava abaixo do titulo, deixando apenas o `h1` Safe Vault. Arquivo: app/(app)/_components/safe-vaults-section.tsx.

25 de Maio de 2026

3 itens
3
NovidadeCRM - Calculadora (/crm/calculadora): novo botao 'Exportar' no header (glass style branco, icone `Download` + `ChevronDown`) abre `Popover` shadcn com duas opcoes — 'PDF' (badge red, icone `FileText`, gera relatorio paisagem A4 via `jspdf` + `jspdf-autotable`) e 'Excel' (badge emerald, icone `FileSpreadsheet`, gera .xlsx via `xlsx`). O export e contextual ao tab ativo: na aba Licencas exporta a composicao do preco (6 linhas) + manutencao anual + pro-rata; na aba Alocacao exporta a tabela de alocacoes com Perfil/Custo-h/UF/Imposto/Margem/Valor-h/Horas/Valor mensal + linha TOTAL destacada (no PDF a linha total ganha fundo amber via `didParseCell`). Para acessar os dados da aba Alocacao, o handle exposto pelo `forwardRef` ganhou novo metodo `getExportData()` que retorna `{ rows, totalHoras, totalValor, valorMedioHora }` — tipos exportados como `AlocacaoExportRow` e `AlocacaoExportData`. Em ambos os formatos o arquivo gerado segue o padrao `calculadora-{licencas|alocacao}-YYYY-MM-DD.{pdf|xlsx}` (data ISO). Feedback via `useToast` para sucesso/erro. Tabela vazia em Alocacao mostra toast de erro 'Nada para exportar'. Arquivos: app/(app)/features/crm/calculadora/calculadora-screen.tsx, app/(app)/features/crm/calculadora/alocacao-recursos-section.tsx.
NovidadeCRM - Calculadora (/crm/calculadora): adicionado filtro de tipo de calculadora no header principal via abas no padrao consolidado (Abas no Header do CLAUDE.md). Duas opcoes: `Licencas On-Premise` (icone `KeyRound`, calculadora existente com Custo SAP NET, impostos, margem e manutencao) e `Alocacao de Recursos` (icone `Users`). Implementacao em `app/(app)/features/crm/calculadora/calculadora-screen.tsx`: novo type `CalcType = 'licencas' | 'alocacao'`, constante `CALC_TABS` com `{ key, label, icon, subtitle }`, novo state `activeTab` (default `licencas`). Header agora exibe titulo generico 'Calculadora' e subtitulo dinamico vindo do tab ativo. Abas seguem `theme.tabActive`/`tabShadow`/`tabLine`/`tabIcon` do `sectionThemes.crm` (paleta amber): aba ativa com `bg-white text-amber-700` + linha amber no topo via gradient; aba inativa em `text-white/60`. Botao 'Restaurar padroes' agora delega para a aba ativa via `alocacaoRef` (handle `{ reset }` exposto via `forwardRef`/`useImperativeHandle`). Arquivo: app/(app)/features/crm/calculadora/calculadora-screen.tsx.
NovidadeCRM - Calculadora -> Alocacao de Recursos (/crm/calculadora aba Alocacao): nova calculadora implementada conforme modelo Excel `Alocacao Recurso.xlsx`. Layout em `xl:grid-cols-[300px_1fr]`: coluna esquerda com card editavel 'Imposto por UF' (defaults SP 9,05%, RJ 11,15%, BH 8,65%) + helper amber explicando as formulas; coluna direita com card 'Alocacoes' contendo tabela dinamica + linha de totais. Tabela: cada linha tem input livre de texto para Perfil (placeholder 'Ex.: ABAP Senior'), input mono com prefixo `R$` para Custo/h editavel por linha, `Select` do shadcn para UF (resolve imposto via lookup), inputs inline mono para Margem (%) e Horas mensais, celulas calculadas para Imposto (% do lookup), Valor/h (`custo / (1 - imposto - margem)`) e Valor mensal (`valor_h * horas`); botao `Trash2` rose por linha + botao 'Adicionar' amber no header do card. Sticky thead com fundo amber/yellow gradient. Tres cards de totais embaixo: Total Horas (slate), Total Valor mensal (amber, destaque), Valor medio por hora (emerald). Reset restaura defaults via `useImperativeHandle({ reset })` exposto pelo `forwardRef` do `AlocacaoRecursosSection`. Arquivos: app/(app)/features/crm/calculadora/alocacao-recursos-section.tsx (novo), app/(app)/features/crm/calculadora/calculadora-screen.tsx.

22 de Maio de 2026

33 itens
12219
NovidadeTravel - Viagens (/travel/trips/[id]): novo bloco de cards-resumo abaixo do formulario de edicao mostrando agregados de reservas vinculadas a viagem. Quatro cards lado a lado (`grid grid-cols-4 gap-3`): (1) **Reservas** (tom indigo, icone `CreditCard`) — total geral somando passagens + hoteis + locacoes, com contagem total de registros; (2) **Passagens** (tom sky, icone `Plane`) — soma de `amount_per_person * passengers_count` de todas as `TravelAirTicket` da viagem; (3) **Hotel** (tom violet, icone `BedDouble`) — soma de `total_amount` de `TravelHotelReservation`; (4) **Aluguel de carro** (tom emerald, icone `Car`) — soma de `total_amount` de `TravelVehicleRental`. Implementacao em `app/(app)/features/travel/travel-resource-screen.tsx`: novos states `tripAirTickets`, `tripHotels`, `tripRentals`; `useEffect` (condicional a `config.resource === 'trips' && !isCreating && selectedItem?.id`) faz `Promise.all` de `fetchTravelAirTickets({ trip_id })`, `fetchTravelHotelReservations({ trip_id })`, `fetchTravelVehicleRentals({ trip_id })` com `.catch(() => [])` por chamada; memo `tripBookingsSummary` calcula totais e contagens; novo helper component `TripBookingCard` com paleta `TRIP_BOOKING_CARD_TONES` (indigo/sky/violet/emerald) — cada card tem icone em badge colorido, label mono uppercase, valor em currency `pt-BR/BRL` e sublinha com contagem (`N registros`). Renderizado apos o grid de fields, antes do `FormFooter`. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets): tabela da listagem foi substituida por versao dedicada com colunas especificas (no lugar das colunas genericas Companhia | Localizador | Criado | Atualizado | Status). Nova ordem: **Companhia** (logo via `AirlineLogo` + `airline_name` + IATA mono em sublinha; sortable por `primary`); **Viagem** (nome da `TravelTrip` via lookup por `trip_id`); **Rota** (badge de direcao usando `DIRECTION_VISUAL` + IATA origem `Plane` IATA destino em mono via lookups de `TravelAirport`); **Partida** (data + hora de `departure_at` via novo helper `formatDateTimeLabel`; sortable por `date`); **Voo / PNR** (flight_number na linha de cima, booking_code mono menor na linha de baixo; sortable por `secondary`); **Valor** (total = `amount_per_person * passengers_count` em currency BRL, com sublinha `R$ X x N`); **Status** (StatusPill; sortable por `status`). Para alimentar os lookups na list view, novos derivados `isAirTicketsList = config.resource === 'air-tickets' && !isFormMode` e `shouldLoadTrips/Airlines/Airports` foram extraidos dos `useEffect` originais — agora as chamadas `fetchTravelTrips/Airlines/Airports` rodam tanto em form mode quanto em list mode de air-tickets. Novos memos `airlineById`, `tripById`, `airportById` (Map<id, entity>) usados para hidratar cada linha. Busca tambem foi enriquecida: alem dos `config.searchKeys`, em air-tickets a busca tambem matcheia o nome da viagem (via tripById) e os codigos IATA dos aeroportos de origem/destino (via airportById). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Viagens (/travel/trips/[id]): removido o banner amber 'Esta viagem ainda esta em planejamento — campos podem mudar ate a reserva' que aparecia no topo do formulario quando `status === 'PLANNING'`. O sinal de planejamento ja esta presente via status pill no header, entao a faixa era ruido visual. Limpeza acompanhada: a variavel local `isTripPlanning` (usada apenas pelo banner) tambem foi removida; `tripStatusValue` permanece pois ainda alimenta o pill do header. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): layout de campos reorganizado — `passengers_count` (Passageiros) movido para a direita do campo `trip_id` (Viagem) na primeira linha do formulario, e `amount_per_person` ficou pareado com `purchased_at` na segunda. Spans em `AIR_TICKET_FIELD_SPANS` atualizados: Linha 1 `trip_id` (4) + `passengers_count` (2) + `direction` (3) + `status` (3); Linha 2 `airline_id` (3) + `cabin_class` (3) + `amount_per_person` (3) + `purchased_at` (3). Ordem do array `fields` em `RESOURCE_CONFIGS['air-tickets']` reordenada para refletir o layout. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
CorrecaoTravel - Passagens aereas: campo `purchased_at` agora e somente data (sem horario) para acompanhar swagger — o backend mudou a tipagem do campo de `FlexibleTime` para `FlexibleDate` em `models.TravelAirTicket`, `models.CreateTravelAirTicketPayload` e `models.UpdateTravelAirTicketPayload`. Em `lib/api/travel.ts`, o tipo de `purchased_at` em `TravelAirTicket` foi alterado de `FlexibleTime` para `FlexibleDate`. Em `app/(app)/features/travel/travel-resource-screen.tsx`, a config do field em `RESOURCE_CONFIGS['air-tickets']` mudou de `kind: 'datetime'` para `kind: 'date'`, fazendo o componente renderizar apenas `DatePickerInput` (sem `LabeledDateTimeInput`). Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): sincronizacao do CRUD com o swagger atual. O campo `total_amount` (Valor total) foi removido do modelo `TravelAirTicket` e dos payloads de Create/Update no backend; em seu lugar foram adicionados dois novos campos: `amount_per_person` (number, R$) e `passengers_count` (integer). Em `lib/api/travel.ts`: removido `total_amount` e adicionados `amount_per_person?: number` e `passengers_count?: number` em `TravelAirTicket` e `CreateTravelAirTicketPayload`. Em `app/(app)/features/travel/travel-resource-screen.tsx`: (1) `AIR_TICKET_FIELD_SPANS` substitui `total_amount: 'md:col-span-3'` por `amount_per_person: 'md:col-span-2'` + `passengers_count: 'md:col-span-2'` e ajusta `purchased_at` de col-span-3 para col-span-2 (mantendo 12 colunas: airline 3 + cabin 3 + valor 2 + passageiros 2 + compra 2); (2) na configuracao de fields do resource `air-tickets`, o item `{ key: 'total_amount', label: 'Valor total', kind: 'money' }` foi substituido por dois: `{ key: 'amount_per_person', label: 'Valor por pessoa', kind: 'money' }` e `{ key: 'passengers_count', label: 'Passageiros', kind: 'number' }`. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Aeroportos (/travel/airports): layout do formulario reorganizado para a grade de 4 colunas. Novo mapa `AIRPORT_FIELD_SPANS` (com `name: 'md:col-span-2'`) faz o campo Nome ocupar duas colunas na primeira linha, deixando IATA e Cidade ao lado e empurrando Website + Ativo juntos para a segunda linha (Website fica a esquerda de Ativo). Notas permanece em col-span-4 como textarea na linha 3. `renderTravelField` agora consulta `AIRPORT_FIELD_SPANS` no mesmo pipeline de `CITY_FIELD_SPANS` e `TRIP_FIELD_SPANS`, e o `AIRPORT_FIELD_SPANS[field.key]` tambem foi aplicado ao `<div>` wrapper da branch especial do `OpenFlightsAirportAutocomplete` (que retorna seu proprio div, fora do pipeline padrao). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Aeroportos (/travel/airports): campo `Nome` virou autocomplete com busca na base publica OpenFlights (`airports.dat` em raw.githubusercontent.com/jpatokal/openflights/master/data, ~7000 aeroportos com IATA/ICAO/cidade/pais/lat-lon/timezone). Implementacao em tres arquivos: (1) novo `lib/api/openflights-airports.ts` — espelha o padrao do `openflights-airlines.ts`: type `OpenFlightsAirport` (id, name, city, country, iata, icao, latitude, longitude, timezone), parser CSV in-house, `loadOpenFlightsAirports()` com cache em memoria + `localStorage` (chave `openflights-airports-v1`), throttle via `inFlight` promise. (2) novo `app/(app)/_components/openflights-airport-autocomplete.tsx` — componente especializado (nao reaproveita `LabeledAutocomplete` porque o `value` precisa ser texto livre, nao um id). Renderiza `LabeledInput` com icone `Search` indigo + dropdown em `createPortal` filtrado por digitar >= 2 letras; itens com pill IATA mono, nome (com `PlaneTakeoff` mini), `cidade, pais`; navegacao por ArrowUp/Down/Enter/Escape. (3) `app/(app)/features/travel/travel-resource-screen.tsx`: novo state `openFlightsAirports` + `useEffect` que carrega via `loadOpenFlightsAirports()` quando `isFormMode && config.resource === 'airports'`. Branch novo no topo de `renderTravelField` (`if (config.resource === 'airports' && field.key === 'name')`) que renderiza o `OpenFlightsAirportAutocomplete` em lugar do `TravelField`. Ao selecionar um aeroporto, popula tres campos: `name`, `iata_code` (upper) e tenta resolver `city_id` fazendo `cities.find(c => normalizeText(c.name) === normalizeText(airport.city))` — se encontra, vincula e emite toast com sucesso + nome da cidade; se nao encontra, emite toast pedindo selecao manual. O usuario pode tambem digitar livremente sem selecionar (modo texto puro continua funcionando). Arquivos: lib/api/openflights-airports.ts, app/(app)/_components/openflights-airport-autocomplete.tsx, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Aeroportos (/travel/airports): sincronizacao do CRUD com o swagger atual — campos texto livre `city`, `state`, `country` e `timezone` foram removidos de `models.TravelAirport`, `CreateTravelAirportPayload`, `UpdateTravelAirportPayload` e dos filtros do GET `/travel/airports`. O backend agora expoe apenas o FK `city_id` (referencia para `/cities`), que resolve hierarquicamente cidade -> UF -> pais via tabela de Cidades. Em `lib/api/travel.ts`: `TravelAirport`, `CreateTravelAirportPayload` e `FetchTravelAirportsParams` simplificados para `{ name, iata_code, city_id?, website?, notes?, is_active? }` (+ filtros equivalentes no GET). Em `app/(app)/features/travel/travel-resource-screen.tsx`: (1) `RESOURCE_CONFIGS['airports'].fields` agora tem 6 campos no lugar de 9 — Nome (req), Codigo IATA (req), Cidade (kind `city`, autocomplete reaproveitando o que ja existe em trips.destination_id), Website, Ativo, Notas; ordem reorganizada (Nome -> IATA -> Cidade -> Website -> Ativo -> Notas); (2) `searchKeys` enxutos para `['name', 'iata_code', 'notes']`; (3) memo `airportItems` (autocomplete de aeroportos usado em air-tickets) agora resolve `a.city_id` contra a lista de cidades carregada para montar `sublabel` = `nome, UF, pais` e `searchableTexts` correspondentes; (4) `needsCityList` estendido para tambem disparar quando o resource atual tem campos do tipo `airport` (assim air-tickets carrega cidades automaticamente para enriquecer o autocomplete de aeroporto). Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Viagens (/travel/trips): redesign do formulario de edicao com 10 melhorias de UI/UX. (1) **Reorganizacao em 4-col grid**: Linha 1 Nome(2)/Destino(2); Linha 2 Tipo(1)/Status(1)/Orcamento(2); Linha 3 Inicio(2)/Fim(2); Linha 4 Descricao(4). Implementado via novo mapa `TRIP_FIELD_SPANS` em `app/(app)/features/travel/travel-resource-screen.tsx` (segue o mesmo padrao de `CITY_FIELD_SPANS`). (2) **Secoes visuais**: novo array `TRIP_SECTIONS` agrupa os campos em quatro blocos (Identificacao, Detalhes, Periodo, Notas), cada um com header tipografico uppercase + separador horizontal sutil. Renderizado via path dedicado `config.resource === 'trips'` que itera `TRIP_SECTIONS` (extrai `renderTravelField` como helper local reutilizado entre os dois caminhos para nao duplicar a logica de col-span/gating/autocomplete). (3) **Header com resumo dinamico**: para trips em edit mode, o subtitulo `config.title` cinza foi substituido por uma linha rica com `MapPin + nome do destino`, `Clock + N dias`, `DollarSign + orcamento formatado em pt-BR/BRL` e um **status pill glassy** branco com o label traduzido (PLANNING → 'Planejando' etc., via `STATUS_LABELS`). (4) **Card de destino contextual** entre header e fields (apenas trips com `destination_id` preenchido): card sky com icone, nome da cidade, sublabel (estado/pais) e chips de dias + orcamento a direita. (5) **Banner de planejamento** (apenas trips com `status === 'PLANNING'`): faixa amber acima do card de destino com `Sparkles` + mensagem 'Esta viagem ainda esta em planejamento — campos podem mudar ate a reserva'. (6) **Chip de duracao** ao lado do header da secao 'Periodo': `Clock + N dias` calculado por novo helper `computeTripDuration(start, end)` que faz `Date.parse` das datas YYYY-MM-DD e calcula `Math.floor((e - s) / 86400000) + 1`. (7) **Validacao de data**: `handleSave` agora aborta com toast 'Data final invalida' quando `start_date > end_date` no resource trips (comparacao lexicografica de strings YYYY-MM-DD funciona). (8) **Atalho Ctrl/Cmd+S**: novo `useEffect` global (ativo quando `isFormMode`) com listener `keydown` que faz `preventDefault` em Ctrl+S e dispara save via `handleSaveRef.current` (ref atualizado a cada render para evitar re-bind do listener). (9) **Tooltip Ctrl+S** no botao Salvar (via prop `saveTitle` ja existente no `FormFooter`). (10) **Contador de mudancas nao salvas**: novo memo `changedFieldsCount` conta fields com `formValues[k] !== initialValues.current[k]`; renderizado como chip cyan glassy com bolinha pulsante dentro do slot `children` do `FormFooter` (visivel apenas em modo edit com mudancas pendentes). Adicionado import `Clock` ao lucide-react e novo type-import `ReactNode`. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Viagens (/travel/trips): campo `Destino` reintroduzido como autocomplete de cidades. O `destination_id` em `models.TravelTrip` agora e chave estrangeira para `public.cities` (tabela do CRUD Cidades em `/travel/cities`). Implementacao em `app/(app)/features/travel/travel-resource-screen.tsx`: novo `FieldKind` `city`; novo estado `cities` + flag `needsCityList` (`config.resource !== 'cities' && config.fields.some(f => f.kind === 'city')`) + `useEffect` que chama `fetchCities()` quando o form abre; memo `cityItems` que mapeia para `LabeledAutocompleteItem` (label = nome da cidade, sublabel = `state_code - country_code`, searchableTexts cobrindo name/state_code/country_code/ibge_code); branch novo no `TravelField` que renderiza `LabeledAutocomplete` com icone `MapPin` quando `field.kind === 'city'`; `cityItems` agora e passado como prop. Entrada `{ key: 'destination_id', label: 'Destino', kind: 'city' }` adicionada logo apos `name` no `RESOURCE_CONFIGS['trips'].fields`. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Viagens (/travel/trips): campo `is_active` REMOVIDO em sincronizacao com o swagger. O backend nao expoe mais `is_active` em `models.TravelTrip`, `CreateTravelTripPayload`, `UpdateTravelTripPayload` e o filtro `is_active` tambem foi retirado do GET `/travel/trips`. Em `lib/api/travel.ts`: `is_active?: boolean` removido de `TravelTrip`, `CreateTravelTripPayload` e `FetchTravelTripsParams`. Em `app/(app)/features/travel/travel-resource-screen.tsx`: entrada `{ key: 'is_active', label: 'Ativo', kind: 'boolean' }` removida do array `fields` em `RESOURCE_CONFIGS['trips']`. A coluna de status na lista continua usando `status` (PLANNING/BOOKED/ONGOING/COMPLETED/CANCELLED) como `statusKey` — o `booleanStatus` helper so e invocado quando `displayValue(item, statusKey)` retorna vazio, entao em viagens o `is_active` nunca alimentava aquele fallback. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - modulo Destinos REMOVIDO. O swagger nao tem mais o endpoint `/travel/destinations` nem o modelo `models.TravelDestination` — a tabela foi removida do banco. Remocoes aplicadas: (1) `lib/api/travel.ts`: bloco inteiro `// Destinations` removido (type `TravelDestination`, `FetchTravelDestinationsParams`, `CreateTravelDestinationPayload` e as 5 funcoes `fetchTravelDestinations`, `fetchTravelDestination`, `createTravelDestination`, `updateTravelDestination`, `deleteTravelDestination`). (2) `app/(app)/data/nav-routes.ts`: chave `Travel Destinations` removida do `NavItemKey` e do `navItemBasePaths`. (3) `app/(app)/data/nav.ts`: removida da lista de items e da secao Cadastros do grupo Viagem. (4) `lib/auth/permissions.ts`: binding `Travel Destinations` removido. (5) `app/(app)/_components/nav-hub-grid.tsx`: entrada `navMeta['Travel Destinations']` removida e import de `MapPin` excluido (ja nao era usado em outras entradas do nav-meta). (6) `app/(app)/features/travel/travel-resource-screen.tsx`: a) imports de destinos (`TravelDestination`, payload e 5 funcoes) excluidos; b) `TravelResource` e `TravelEntity` deixaram de incluir `destinations` e `TravelDestination`; c) `FieldKind` deixou de incluir `destination`; d) entrada `destinations` do `RESOURCE_CONFIGS` removida por completo; e) campo `destination_id` removido dos fields de `trips`, `expenses`, `hotel-reservations` e `vehicle-rentals` — em compensacao, o `destination_id` continua presente nos tipos TS (`TravelTrip.destination_id`, `TravelExpense.destination_id`, etc.) e nos `FetchTravel*Params`, ja que o swagger ainda expoe esses campos/filtros como string opcional, apenas sem UI para resolver UUID a nome; f) state `destinations`, `useEffect` que chamava `fetchTravelDestinations`, memo `destinationItems`, `needsDestinationList` e o branch `if (field.kind === 'destination')` do `TravelField` removidos; g) `secondaryKey` do resource `trips` mudou de `destination_id` para `trip_type`, e o `secondaryColumnLabel` agora retorna `Tipo` em vez de `Destino` para a coluna secundaria da lista de viagens. (7) Pastas/arquivos de rotas removidos: `app/(app)/travel/destinations/page.tsx`, `new/page.tsx`, `[id]/page.tsx`. Arquivos modificados: lib/api/travel.ts, app/(app)/data/nav-routes.ts, app/(app)/data/nav.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx, app/(app)/features/travel/travel-resource-screen.tsx; rotas deletadas: app/(app)/travel/destinations/*.
NovidadeTravel - novo modulo Cidades (/travel/cities): CRUD completo integrado ao endpoint global `/cities` do swagger (tag `Cities`, modelo `models.City` — campos name (req), country_code (req, ex.: `BR`), state_code (ex.: `SP`), ibge_code, latitude, longitude, timezone, is_capital, is_active). Como o endpoint nao esta sob `/travel/*`, foi criado um novo modulo isolado `lib/api/cities.ts` (com `City`, `FetchCitiesParams`, `CreateCityPayload`, `fetchCities`, `fetchCity`, `createCity`, `updateCity`, `deleteCity` — usa o mesmo `api` axios instance, entao envia `Authorization` + `tenant_id`). UI surge sob a secao Cadastros do menu Viagem (junto de Destinos, Companhias, Aeroportos), com rotas em `/travel/cities`, `/travel/cities/new` e `/travel/cities/{id}`. Em `app/(app)/data/nav-routes.ts`: nova chave `Travel Cities` em `NavItemKey` com base path `/travel/cities`. Em `app/(app)/data/nav.ts`: incluido em items do grupo Viagem e na secao Cadastros. Em `lib/auth/permissions.ts`: binding `Travel Cities → cities` (resource sem prefixo travel, alinhado ao endpoint global). Em `app/(app)/_components/nav-hub-grid.tsx`: novo `navMeta['Travel Cities']` com icone `Building`, gradiente fuchsia→purple, label `Cidades` (import de `Building` adicionado). Em `app/(app)/features/travel/travel-resource-screen.tsx`: (1) `TravelResource` e `TravelEntity` estendidos para incluir `cities` / `City`; (2) novo `FieldKind` `decimal` — sanitize permite digito/ponto/virgula/sinal de menos (`/[^\d.,-]/g`), e `convertFieldValue` faz `Number.parseFloat(text.replace(',', '.'))` retornando number (usado por latitude/longitude); (3) nova entrada `cities` em `RESOURCE_CONFIGS` com fields name (req) - country_code (req, ex. BR) - state_code - ibge_code - timezone - latitude (decimal) - longitude (decimal) - is_capital - is_active. `secondaryColumnLabel` retorna `Estado` para o resource cities; (4) o autocomplete de UFs brasileiras (criado anteriormente para o campo `state` em Destinos/Aeroportos) foi generalizado para tambem ativar quando `field.key === 'state_code'` — agora a deteccao do pais consulta tanto `formValues.country` quanto `formValues.country_code`. Assim, ao preencher `country_code = BR` em uma cidade, o campo `state_code` vira autocomplete das 27 UFs. Novas rotas: `app/(app)/travel/cities/page.tsx`, `new/page.tsx` e `[id]/page.tsx`. Arquivos: lib/api/cities.ts, app/(app)/data/nav-routes.ts, app/(app)/data/nav.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx, app/(app)/features/travel/travel-resource-screen.tsx, app/(app)/travel/cities/page.tsx, app/(app)/travel/cities/new/page.tsx, app/(app)/travel/cities/[id]/page.tsx.
MelhoriaTravel - segunda sincronizacao com o swagger atual: campos removidos dos schemas `Airport` e `Destination`. (1) `models.TravelAirport`, `CreateTravelAirportPayload`, `UpdateTravelAirportPayload` e o filtro do GET `/travel/airports` NAO tem mais o campo `icao_code` — removido de `TravelAirport`, `CreateTravelAirportPayload` e `FetchTravelAirportsParams` em `lib/api/travel.ts`; tambem removido do array `fields` e de `searchKeys` em `RESOURCE_CONFIGS['airports']`; o memo `airportItems` (autocomplete de aeroportos usado em air-tickets) deixou de usar `a.icao_code` no fallback de codigo, no label e em `searchableTexts`. (2) `models.TravelDestination`, `CreateTravelDestinationPayload`, `UpdateTravelDestinationPayload` e o filtro do GET `/travel/destinations` NAO tem mais os campos `iata_code`, `currency_code` e `description` — todos removidos de `TravelDestination`, `CreateTravelDestinationPayload` e `FetchTravelDestinationsParams`; em `RESOURCE_CONFIGS['destinations']` removidos os 3 fields correspondentes (`iata_code`, `currency_code`, `description`) e os termos retirados de `searchKeys`; o memo `destinationItems` deixou de usar `d.iata_code` no sublabel e em `searchableTexts`. (3) Bonus: a ordem dos campos do form de Aeroportos foi alinhada com a de Destinos (Nome → Pais → Estado → Cidade → IATA → Fuso → Website → Ativo → Notas), e como o campo `state` em ambos os modulos passa pela conversao automatica em autocomplete de UFs quando o pais for Brasil/Brazil/BR (helper `isBrazil`), a mudanca tambem habilita o autocomplete de UFs no form de Aeroportos. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Destinos (/travel/destinations): campo `Estado` vira autocomplete de UFs quando `Pais` esta preenchido com Brasil/Brazil/BR. Implementacao em `app/(app)/features/travel/travel-resource-screen.tsx`: nova constante `BRAZILIAN_STATES` (27 entradas com `code` UF e `name`); helper `isBrazil(value)` que normaliza via `normalizeText` e compara com `brasil`/`brazil`/`br`; novo memo `brazilianStateItems` que mapeia para `LabeledAutocompleteItem` (id = UF, label = `UF - Nome`, searchableTexts = UF + nome). O componente `TravelField` recebeu duas novas props opcionais (`brazilianStateItems` e `countryValue`). Quando `field.key === 'state' && isBrazil(countryValue)`, renderiza `LabeledAutocomplete` com icone `MapPin` em vez do `LabeledInput` default — caso contrario, mantem o input livre (suporta paises sem padrao definido). O valor selecionado e o codigo da UF (ex.: `SP`). Tambem foi reorganizada a ordem dos campos em `RESOURCE_CONFIGS['destinations']`: Nome → Pais → Estado → Cidade → Codigo IATA → ... (Pais agora vem antes de Estado, e Estado antes de Cidade, alinhado com a hierarquia geografica). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - sincronizacao completa de todos os schemas com o swagger atual. (1) `models.TravelTrip`, `CreateTravelTripPayload` e `UpdateTravelTripPayload` nao tem mais os campos `currency` nem `destination_summary` — ambos removidos de `TravelTrip` e `CreateTravelTripPayload` em `lib/api/travel.ts` e do array de fields do `RESOURCE_CONFIGS['trips']`. `searchKeys` de trips reduzido para `['name', 'description']`; `secondaryKey` mudou de `destination_summary` para `destination_id` (a coluna `Destino` da lista agora exibe o UUID — uma resolucao para nome do destino fica como melhoria futura). O memo `tripItems` (usado por autocompletes em outros recursos) passou a usar `t.description` como sublabel/searchableText no lugar de `t.destination_summary`. (2) Em `models.TravelExpense`, `models.TravelHotelReservation` e `models.TravelVehicleRental` (alem dos respectivos Create/Update payloads e GET filters), o swagger expoe agora o campo `destination_id`. Em `lib/api/travel.ts`: `destination_id?: string` adicionado em `TravelExpense`, `CreateTravelExpensePayload`, `FetchTravelExpensesParams`, `TravelHotelReservation`, `CreateTravelHotelReservationPayload`, `FetchTravelHotelReservationsParams`, `TravelVehicleRental`, `CreateTravelVehicleRentalPayload`, `FetchTravelVehicleRentalsParams`. (3) Em `RESOURCE_CONFIGS` foi adicionado o field `{ key: 'destination_id', label: 'Destino', kind: 'destination' }` em expenses (apos `trip_id`), hotel-reservations (apos `trip_id`) e vehicle-rentals (apos `trip_id`) — usando o autocomplete `destination` ja criado anteriormente; o trigger `needsDestinationList` foi escrito de forma generica (`config.resource !== 'destinations' && config.fields.some(f => f.kind === 'destination')`), ou seja, ja carrega a lista de destinos automaticamente nesses novos cenarios sem precisar de nenhum codigo adicional. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Viagens (/travel/trips): sincronizacao do CRUD com o swagger — campo `destination_id` adicionado em `models.TravelTrip`, `models.CreateTravelTripPayload` e `models.UpdateTravelTripPayload` (alem do filtro `destination_id` em GET /travel/trips). Em `lib/api/travel.ts`: `destination_id?: string` adicionado em `TravelTrip`, `CreateTravelTripPayload` e `FetchTravelTripsParams`. Em `app/(app)/features/travel/travel-resource-screen.tsx`: novo `FieldKind` `destination` (autocomplete que carrega destinos via `fetchTravelDestinations` quando `config.resource !== 'destinations' && config.fields.some(f => f.kind === 'destination')` — replica o padrao `needsTripList`/`needsAirlineList`/`needsAirportList`). Novo estado `destinations` + `useEffect` de carregamento condicional ao montar o form. Novo memo `destinationItems` que mapeia para `LabeledAutocompleteItem` (label = nome, sublabel = cidade/estado/pais ou IATA, searchableTexts cobrindo nome/cidade/estado/pais/IATA). Novo render no `TravelField` (icone `MapPin`). No `RESOURCE_CONFIGS['trips']` foi inserido `{ key: 'destination_id', label: 'Destino', kind: 'destination' }` logo apos `name`, antes de `destination_summary` (que continua como texto livre para fallback). Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - novo modulo Aeroportos (/travel/airports): CRUD completo de aeroportos integrado ao swagger (`/travel/airports`, `/travel/airports/{id}`). Em `lib/api/travel.ts`: adicionados `CreateTravelAirportPayload`, `fetchTravelAirport`, `createTravelAirport`, `updateTravelAirport`, `deleteTravelAirport` (o type `TravelAirport` e `fetchTravelAirports` ja existiam para uso como autocomplete em air-tickets). Em `app/(app)/data/nav-routes.ts`: nova chave `Travel Airports` em `NavItemKey` com base path `/travel/airports`. Em `app/(app)/data/nav.ts`: incluido em `items` do grupo Viagem e na secao Cadastros (ao lado de Destinos e Companhias). Em `lib/auth/permissions.ts`: novo binding `Travel Airports → travel/airports`. Em `app/(app)/_components/nav-hub-grid.tsx`: novo `navMeta['Travel Airports']` com icone `PlaneTakeoff`, gradiente indigo→violet e label `Aeroportos` (import de `PlaneTakeoff` adicionado). Em `app/(app)/features/travel/travel-resource-screen.tsx`: `TravelResource` e `TravelEntity` estendidos para incluir `airports` / `TravelAirport`; nova entrada `airports` em `RESOURCE_CONFIGS` com fields name (req) - iata_code (req) - icao_code - city - state - country - timezone - website - is_active - notes (textarea); `secondaryColumnLabel` retorna `IATA` para o resource airports (mesmo padrao de airlines). Novas rotas: `app/(app)/travel/airports/page.tsx`, `new/page.tsx` e `[id]/page.tsx`. Arquivos: lib/api/travel.ts, app/(app)/data/nav-routes.ts, app/(app)/data/nav.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx, app/(app)/features/travel/travel-resource-screen.tsx, app/(app)/travel/airports/page.tsx, app/(app)/travel/airports/new/page.tsx, app/(app)/travel/airports/[id]/page.tsx.
NovidadeTravel - novo modulo Destinos (/travel/destinations): CRUD completo de destinos de viagem integrado ao swagger (`/travel/destinations`, `/travel/destinations/{id}`). Em `lib/api/travel.ts`: adicionados `CreateTravelDestinationPayload`, `fetchTravelDestination`, `createTravelDestination`, `updateTravelDestination`, `deleteTravelDestination` (o type `TravelDestination` e `fetchTravelDestinations` ja existiam). Em `app/(app)/data/nav-routes.ts`: nova chave `Travel Destinations` em `NavItemKey` com base path `/travel/destinations`. Em `app/(app)/data/nav.ts`: incluido em `items` do grupo Viagem e na secao Cadastros (ao lado de Companhias). Em `lib/auth/permissions.ts`: novo binding `Travel Destinations → travel/destinations` no mapa de permissoes. Em `app/(app)/_components/nav-hub-grid.tsx`: novo `navMeta['Travel Destinations']` com icone `MapPin`, gradiente rose-to-pink e label `Destinos` (e import de `MapPin` adicionado). Em `app/(app)/features/travel/travel-resource-screen.tsx`: `TravelResource` e `TravelEntity` estendidos para incluir `destinations` / `TravelDestination`; nova entrada `destinations` em `RESOURCE_CONFIGS` com fields name (req) - iata_code - city - state - country - timezone - currency_code - cover_image_url - is_international - is_favorite - is_active - description (textarea) - notes (textarea); secondaryColumnLabel retorna `Cidade` para o resource destinations. Novas rotas: `app/(app)/travel/destinations/page.tsx` (lista), `new/page.tsx` (criar) e `[id]/page.tsx` (editar). Arquivos: lib/api/travel.ts, app/(app)/data/nav-routes.ts, app/(app)/data/nav.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx, app/(app)/features/travel/travel-resource-screen.tsx, app/(app)/travel/destinations/page.tsx, app/(app)/travel/destinations/new/page.tsx, app/(app)/travel/destinations/[id]/page.tsx.
MelhoriaTravel - todos os resources (/travel/*): largura maxima do container do formulario reduzida de 1100px para 960px e a parcela viewport de 72vw para 70vw (`w-[min(72vw,1100px)]` → `w-[min(70vw,960px)]`). Com 4 colunas no grid, cada coluna fica em torno de ~210px — mais compacto e melhor centralizado na tela. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets): validacao condicional de obrigatoriedade — quando o `status` da passagem e `BOOKED` (Reservada), todos os campos (exceto `notes`) passam a ser obrigatorios para salvar. Implementacao: novo helper `isFieldRequired(config, field, values)` que centraliza a regra; retorna `true` se `field.required === true` (config estatica) OU se `config.resource === 'air-tickets' && values.status === 'BOOKED' && field.key !== 'notes'`. `validateRequired` agora usa esse helper em vez de ler `field.required` direto, e tambem ignora campos do tipo `boolean` (que nunca sao validados como vazios). O componente `TravelField` recebeu uma nova prop opcional `required?: boolean`; quando informada, ela sobrepoe o `field.required` no calculo do label (asterisco visual). Isso significa que em BOOKED o asterisco aparece dinamicamente ao lado de Direcao, Aero. origem/destino, Saida/Chegada, Classe, Valor total, Compra, Localizador, Nº voo, Bagagem e Assento — alem dos ja obrigatorios Viagem e Companhia aerea. Em PLANNING continua so com os obrigatorios da config (Viagem, Companhia). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): ordem dos campos reorganizada — `flight_number` (Numero do voo), `baggage_info` (Bagagem) e `seat_info` (Assento) movidos para depois de `arrival_at` no array `fields`, de modo que ocupam a linha do grid imediatamente abaixo da linha de rota (com `departure_at`/Saida). `total_amount` migrou para a linha de booking junto com Companhia/Classe/Compra. Posteriormente `booking_code` (Localizador) e `purchased_at` (Compra) trocaram de posicao no array: Compra agora fica na linha de booking ao lado da Companhia, e Localizador desce para a linha dos detalhes pos-reserva — posicionado a esquerda de Nº voo. Nova grade do form (status ≠ PLANNING, 4 colunas com Viagem em col-span-2): Linha 1 - Viagem (2) - Direcao - Status; Linha 2 - Companhia - Classe - Valor total - Compra; Linha 3 - Aero. origem - Saida - Aero. destino - Chegada; Linha 4 - Localizador - Nº voo - Bagagem - Assento; Linha 5 - Notas (col-span-4). Em PLANNING os campos `booking_code`, `flight_number`, `baggage_info`, `seat_info` e `purchased_at` ficam ocultos via `AIR_TICKET_PLANNING_HIDDEN_FIELDS` (Bagagem adicionada ao set — em PLANNING ainda nao se sabe a politica de bagagem); adicionalmente o campo `airline_id` (Companhia aerea) passa a ocupar `md:col-span-2` apenas em PLANNING (via condicional inline `config.resource === 'air-tickets' && formValues.status === 'PLANNING' && field.key === 'airline_id'`), de modo que a Linha 2 em PLANNING fica Companhia (col-span-2) - Classe - Valor total. Em PLANNING a Linha 4 (Localizador, Nº voo, Bagagem, Assento) some inteira. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): re-sincronizacao com o swagger — campo `currency` foi removido dos schemas `models.TravelAirTicket`, `models.CreateTravelAirTicketPayload` e `models.UpdateTravelAirTicketPayload`. Em `lib/api/travel.ts`: `currency?: string` removido de `TravelAirTicket` e `CreateTravelAirTicketPayload`. Em `travel-resource-screen.tsx`: entrada `{ key: 'currency', label: 'Moeda', kind: 'text', placeholder: 'BRL' }` removida do `RESOURCE_CONFIGS['air-tickets']`. O default `'BRL'` em `createEmptyValues` (`else if (field.key === 'currency')`) continua valendo para os outros recursos que ainda tem o campo (trips, hotel-reservations, vehicle-rentals, expenses). Arquivo: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): ajustes de ordem/largura dos campos no formulario. (1) `Direcao` e `Status` trocados — nova primeira linha do grid: Viagem (col-span-2) - Direcao - Status; (2) Campo `Companhia aerea` (kind `airline`) volta para uma coluna apos breve experimento com `md:col-span-2` — col-span-2 fica restrito ao kind `trip`; (3) `Valor total` movido para logo apos `Bagagem` na lista de fields (era depois de `Compra`). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - todos os resources (/travel/*): grid do formulario passou de 3 para 4 colunas (`md:grid-cols-3` → `md:grid-cols-4`); textarea de notas tambem passou de `md:col-span-3` para `md:col-span-4` para continuar ocupando a linha inteira. Como o container ja era `w-[min(72vw,1100px)]` (largo), 4 colunas aproveitam melhor o espaco horizontal e reduzem a altura de todos os formularios (especialmente air-tickets, hotel-reservations e vehicle-rentals, que tem 13-16 campos). Adicionalmente, o campo `Viagem` (kind `trip`) passa a ocupar duas colunas (`md:col-span-2`) — o autocomplete de viagem mostra nome + resumo do destino, entao se beneficia do espaco extra. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): re-sincronizacao com o swagger — campo `destination_id` foi removido dos schemas `models.TravelAirTicket`, `models.CreateTravelAirTicketPayload` e `models.UpdateTravelAirTicketPayload` no backend (o conceito de destino agora vive em outros recursos: trips, hotel-reservations, vehicle-rentals e expenses). Em `lib/api/travel.ts`: `destination_id?: string` removido de `TravelAirTicket` e `CreateTravelAirTicketPayload`. Em `travel-resource-screen.tsx`: entrada `{ key: 'destination_id', label: 'Destino', kind: 'destination' }` removida do `RESOURCE_CONFIGS['air-tickets']`; toda a plumbing especifica do kind `destination` removida ja que nenhum resource a utiliza atualmente — `FieldKind` perdeu a opcao `destination`, o ramo correspondente no `TravelField` foi excluido, e a prop `destinationItems` saiu da assinatura; state/effect/useMemo de `destinations`/`destinationItems`/`needsDestinationList` removidos; imports de `fetchTravelDestinations`, `TravelDestination` e do icone `Compass` removidos (os tipos e a funcao continuam exportados em `lib/api/travel.ts` para uso futuro em outros resources). Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
CorrecaoTravel - todos os resources (/travel/*): barra de scroll vertical indesejada na pagina (em qualquer formulario new/edit) removida. Diagnostico: a `<section>` em `isFormMode` tinha `overflow-y-auto` combinada com `py-3`, e o card interno usava altura fixa `h-[calc(100vh-5.5rem)]` (88px de margem) — somando com o `pt-3 pb-4` (28px) do `<main>` global mais o TopBar + linha decorativa (~65px), o card ficava ~28px maior do que o espaco disponivel na viewport, forcando a section a scrollar. Correcao: (a) `overflow-y-auto` removido do `isFormMode` da section (fica apenas o `overflow-hidden` da classe base); (b) altura do card trocada de `h-[calc(100vh-5.5rem)]` para `h-full` — o card agora preenche exatamente a altura disponivel da section, sem premissas sobre o chrome do layout. O scroll interno do conteudo do formulario continua funcionando via o `overflow-y-auto p-5 scrollbar-premium` do body do card. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): CRUD atualizado para acompanhar mudancas do backend (`models.TravelAirTicket` / `CreateTravelAirTicketPayload` / `UpdateTravelAirTicketPayload`). Campos texto livre `departure_airport`, `departure_city`, `arrival_airport` e `arrival_city` foram removidos e substituidos por duas FKs: `departure_airport_id` e `arrival_airport_id` (referencias para `/travel/airports`). Adicionado novo campo `destination_id` (FK para `/travel/destinations`). Em `lib/api/travel.ts`: tipos `TravelAirTicket` e `CreateTravelAirTicketPayload` ajustados; novos tipos `TravelAirport` + `TravelDestination` com seus respectivos `fetchTravelAirports`/`fetchTravelDestinations` (so list, ja que esses CRUDs sao usados aqui apenas como autocomplete-source). Em `travel-resource-screen.tsx`: novos `FieldKind` `airport` e `destination`; ramos correspondentes em `TravelField` usando `LabeledAutocomplete` (igual ao padrao ja consolidado para `trip` e `airline`). Aeroporto de origem usa icone `PlaneTakeoff`, de destino usa `PlaneLanding`, e destino usa `Compass`. Items do autocomplete de aeroporto formatam `IATA - Nome` no label e `Cidade, Pais` no sublabel; destinos mostram nome + `Cidade, Estado, Pais`. Estado/fetch novos: `airports`, `destinations`, `needsAirportList`, `needsDestinationList` (lazy: so carrega quando entra em form mode de resource que possui campos do tipo). `searchKeys` de air-tickets limpos (removidos `departure_city`, `arrival_city`, `departure_airport`, `arrival_airport`) — busca local agora cobre `airline_name`, `booking_code`, `flight_number`, `notes`, `trip_id`. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets): enquanto o `status` da passagem for `PLANNING` (Planejando), os campos `booking_code` (Localizador), `flight_number` (Numero do voo), `seat_info` (Assento) e `purchased_at` (Compra) ficam ocultos no formulario — fazem sentido apenas apos a reserva/compra. Implementacao: nova constante `AIR_TICKET_PLANNING_HIDDEN_FIELDS` (Set) e um filtro no `.map(config.fields)` que verifica `config.resource === "air-tickets" && formValues.status === "PLANNING"`. Os valores em formValues nao sao apagados ao ocultar (continuam la, prontos para reaparecer quando o status mudar). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets/new e /travel/air-tickets/{id}): formulario revertido ao padrao consolidado do projeto. Removido o header customizado "Boarding Pass" (a faixa horizontal com fonte mono, tracking-[0.18em] e tag Boarding Pass) — agora air-tickets usa o mesmo gradient header padrao dos demais resources do modulo travel (Voltar + icone + titulo + ID copiavel). Removida a renderizacao do `BoardingPassHeader` no body do formulario (o cartao de embarque visual estilo IATA), substituido pelo grid generico `grid-cols-1 md:grid-cols-3` que percorre `config.fields` e renderiza cada campo via `TravelField`. A guard `config.resource !== "air-tickets"` que pulava o grid foi removida. Import de `BoardingPassHeader` removido (o componente em `app/(app)/_components/boarding-pass-header.tsx` permanece no projeto para reuso futuro, apenas nao e mais consumido). Helper `stringValue` (usado exclusivamente para serializar formValues para o BoardingPassHeader) tambem removido. Os ajustes de config (campos de air-tickets, ordem) e o sizing geral do container (`h-[calc(100vh-5.5rem)]` + `w-[min(72vw,1100px)]`) ficam preservados — sao compartilhados com os outros resources. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaUseful Links (/useful-links): logica do avatar (logo) unificada em um unico componente `LinkAvatar` com precedencia estrita e explicita — (1) tenta o campo `icon` em todas as suas formas (favicon-de-dominio, depois nome react-icons, depois emoji/texto literal); (2) so cai no favicon do `url` quando o icone esta vazio ou eh irresoluvel; (3) por ultimo, icone generico (`LinkIcon` no header gradient, `Globe` nos cards). Durante o carregamento dinamico do react-icons, o avatar agora segura um `Loader2` discreto em vez de exibir momentaneamente o favicon da URL — isso elimina o flicker em que o favicon da URL piscava antes do icone customizado aparecer. Comportamento extra: nomes que parecem ser tentativa de react-icon mas nao resolvem (`looksLikeIconNameAttempt`) nao sao renderizados como texto cru, caindo para o favicon da URL. O componente atende dois variants (`header` e `card`) com classes proprias de tamanho/cor. Aplicado no avatar do header do formulario e nos cards do Kanban — antes eram duas implementacoes paralelas (`LinkCardIcon` + JSX inline no header) com pequenas divergencias; `LinkCardIcon` foi removido. Estados `previewFaviconFailed`/`iconFaviconFailed` saem do escopo de `UsefulLinksSection` e ficam encapsulados dentro do proprio `LinkAvatar`. Arquivo: app/(app)/_components/useful-links-section.tsx.
MelhoriaUseful Links (/useful-links): redesign da tela de listagem em formato Kanban — cada categoria virou uma coluna vertical com scroll proprio, e a area toda rola horizontalmente. Layout: container externo em `overflow-x-auto` + `overflow-y-hidden`; cada coluna e uma `<section>` com `w-72 shrink-0`, altura cheia (`h-full`), border `rounded-2xl`, fundo em gradient slate sutil (`from-slate-50/80 to-slate-50/20`) e `backdrop-blur-sm` para diferenciar do background da pagina. Cabecalho da coluna tem ponto-accent emerald com halo, nome da categoria em uppercase `tracking-[0.14em]` (com `truncate` e `title` para nomes longos), e contador como pill branca com ring emerald. Corpo da coluna em `overflow-y-auto` com `scrollbar-premium`, cards empilhados em `flex-col gap-2`. Cards reconstruidos em layout vertical: toda a area e um `<a>` que abre o link em nova aba; barra-accent horizontal animada no topo (scaleX + glow emerald) como assinatura de hover; favicon `size-11` em rounded-xl com background gradient (com ring emerald e leve scale no hover); titulo `line-clamp-2`; dominio em peso medium; `notes` em italico `line-clamp-2` quando presente. Badge de access_count fica amber quando `>= 10` ("link quente"); botao de editar e `ArrowUpRight` so aparecem no hover, ambos com `stopPropagation`/`preventDefault` para nao competir com a abertura do link. O divider gradient entre secoes nao existe mais — agora cada categoria e visualmente separada pela propria coluna. Arquivo: app/(app)/_components/useful-links-section.tsx.

21 de Maio de 2026

14 itens
518
MelhoriaTravel - Passagens aereas (/travel/air-tickets/new e /travel/air-tickets/{id}): `BoardingPassHeader` evoluiu de preview para o proprio formulario — as alteracoes sao feitas diretamente no cartao de embarque. O grid generico de campos foi suprimido para air-tickets (`config.resource !== 'air-tickets'`). Tudo cabe na tela sem scroll (container alterado para `h-[calc(100vh-5.5rem)]` e `w-[min(72vw,1100px)]`, gradient header compactado, section padding `py-3`). Inputs inline no boarding pass: (1) Companhia via `LabeledAutocomplete` com label/borda invisiveis; (2) Viagem via autocomplete; (3) Direcao e Status via `<details>` dropdown (status mantem carimbo rotacionado clicavel); (4) IATA codes editaveis em mono 48px com auto-uppercase + maxLength 3; (5) Cidades como inputs transparentes; (6) Datas/horas via `LabeledDateTimeInput` compactado (label oculta, h-7, transparente); (7) Strip middle: Voo/Classe/Assento/Bagagem/PNR como inputs mono uppercase; (8) Strip bottom: Compra (date), Tarifa (money), Moeda, Notas (textarea). Campos sensiveis a status (flight_number/seat_info/booking_code/purchased_at) ficam `disabled` com placeholder `—` quando status e PLANNING. Indicador de change: label fica cyan e texto cyan quando valor difere do inicial. Save continua usando `payloadFromValues` da config existente (todos os fields ainda no config para serializacao correta). Arquivos: app/(app)/_components/boarding-pass-header.tsx, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets/new e /travel/air-tickets/{id}): primeiro release do `BoardingPassHeader` visual estilo cartao de embarque. Layout: (1) strip superior com logo + nome da companhia + IATA/ICAO/nome da viagem + carimbo de status rotacionado -6deg (PLANNING=ring dashed amber, BOOKED=ring solid emerald, USED=cinza com linha diagonal, CANCELLED=red com strike); (2) hero central com IATA codes em font mono extra-bold tamanho 56px (`GRU ── ✈ ── JFK`), cidade + horario + data por extenso (pt-BR), linha pontilhada decorativa com aviao rotacionado e duracao do voo calculada (`HH M`); badge `+1D`/`+2D` quando chegada cruza dias; (3) strip inferior com Voo/Classe/Assento/Localizador em mono uppercase tracking-wide; bordas tracejadas separando as 3 secoes; ponto-furo branco nas laterais inferiores simulando perfuracao de ticket. Tudo lido em tempo real dos `formValues` — funciona como preview vivo enquanto o usuario edita. Adicionado JetBrains Mono via next/font (`--font-jetbrains`) e mapeado para `--font-mono` (era Inter). Novo componente `app/(app)/_components/boarding-pass-header.tsx` (props recebem airline/trip resolvidos + form values). Arquivos: app/layout.tsx, app/globals.css, app/(app)/_components/boarding-pass-header.tsx (novo), app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): campos `Status` e `Companhia aerea` trocaram de posicao no formulario. Nova ordem da primeira linha: Viagem - Status - Direcao; `Companhia aerea` desce para o inicio da segunda linha, ao lado de Localizador e Numero do voo. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): campo `is_active` removido em sincronia com o swagger (backend nao expoe mais o campo em `TravelAirTicket`, `CreateTravelAirTicketPayload`, `UpdateTravelAirTicketPayload`, nem como filtro `is_active` na listagem). Em `lib/api/travel.ts`: `is_active?: boolean` removido de `TravelAirTicket`, `CreateTravelAirTicketPayload` e `FetchTravelAirTicketsParams`. Em `travel-resource-screen.tsx`: removida a entrada `{ key: 'is_active', label: 'Ativo', kind: 'boolean' }` do `RESOURCE_CONFIGS['air-tickets']`; grid revertido de `md:grid-cols-4` para `md:grid-cols-3` (e textarea de notas volta a `md:col-span-3`) — a primeira linha agora exibe Viagem, Companhia aerea e Direcao. Outros resources (trips, airlines, hotel-reservations, vehicle-rentals) seguem com `is_active`. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - todos os campos `datetime` (`Saida`/`Chegada`/`Compra` em air-tickets, `Check-in`/`Check-out` em hotel-reservations, `Retirada`/`Devolucao` em vehicle-rentals) migraram de `FloatingDateTimeInput` (label flutuante dentro do input) para o novo `LabeledDateTimeInput` (label fora do input, em cima — padrao consolidado do projeto). Novo componente em `components/ui/labeled-datetime-input.tsx`: segue o mesmo layout de `LabeledInput`/`DatePickerInput` (Label `text-[12px] font-semibold text-slate-400` em cima + `Input` h-9 com `Calendar` icon a esquerda), mantendo todo o smart parsing (`+5 14:30`, `amanha 9h`, `25/03 16:00`, `+2h`, `-30m`). Helpers `parseSmartInput` e `formatDisplay` extraidos de `floating-datetime-input.tsx` como exports nomeados (`parseSmartDateTimeInput`, `formatDateTimeDisplay`). Arquivos: components/ui/labeled-datetime-input.tsx (novo), components/ui/floating-datetime-input.tsx, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets/new e /travel/air-tickets/{id}): autocomplete de `Companhia aerea` agora exibe a logo (favicon do `website` da airline via google s2) tanto nas linhas do dropdown (`rowIcon`) quanto no input apos selecionar (`selectedLeadingIcon`). Fallback para icone `Building2` em sky quando airline nao tem `website`. Novo componente local `AirlineLogo` (size `input`/`row` ajusta wrapper, img e icone de fallback). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Passagens aereas (/travel/air-tickets/new e /travel/air-tickets/{id}): grid do formulario agora e `md:grid-cols-4` (era 3), garantindo que a primeira linha contenha `Viagem`, `Companhia aerea`, `Direcao` e `Ativo`. Quando o `status` da passagem e `PLANNING` (Planejando), os campos `Localizador` (`booking_code`), `Numero do voo` (`flight_number`), `Assento` (`seat_info`) e `Compra` (`purchased_at`) sao ocultados do formulario — esses dados so existem apos a reserva ser efetivada. Filtragem aplicada no render do grid de campos em `TravelResourceSection`, sem alterar o config do resource. Tambem reordenado: campo `Ativo` (`is_active`) agora aparece logo apos `Direcao` (era penultimo, antes de `Notas`); textarea de notas usa `md:col-span-4` no resource air-tickets. Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
CorrecaoGerenciapp - Links Uteis: preview do icone agora detecta corretamente quando o nome resolve para um conjunto valido mas o icone nao existe (ex: `SiMicrosoft` — removido do conjunto Simple Icons por politica de marca). Antes ficava silenciosamente em branco; agora exibe estado `not-found` (icone `ImageOff` vermelho + borda vermelha + title explicativo). Implementacao: hook `useReactIcon(name)` substitui o `lazy()` direto, retornando `{status: 'empty'|'loading'|'ok'|'not-found', Icon}`. Cache em modulo (`reactIconResolvedCache: Map<string, ComponentType|null>`) lembra resultados (positivos e negativos) por nome completo, evitando re-fetch do mesmo modulo. Loading state mostra `Loader2` animado no tile. Avatar do header da edicao e componente novo `LinkCardIcon` (cards da listagem) tambem consomem o hook. Removidos `Suspense`/`lazy`/`ReactIconDynamic`/`resolveReactIconKey export` que ficaram obsoletos. Arquivo: app/(app)/_components/useful-links-section.tsx.
MelhoriaGerenciapp - Links Uteis: campo `Icone` migrado de Lucide (`lucide-react/dynamicIconImports`) para `react-icons` (~31 conjuntos: ai, bi, bs, cg, ci, di, fa, fa6, fc, fi, gi, go, gr, hi, hi2, im, io, io5, lia, lu, md, pi, ri, rx, si, sl, tb, tfi, ti, vsc, wi). Convencao de nome: `<PrefixUpper><IconName>` (ex: `FaShoppingCart`, `MdHome`, `HiGlobeAlt`, `LuGlobe`, `SiGoogle`). Helper `parseReactIconName` extrai o prefixo (2-3 letras com digito opcional como `hi2`), `resolveReactIconKey` valida no `reactIconLoaders` map (dynamic imports). Render via `lazy(() => import('react-icons/<set>').then(mod => ({ default: mod[full] })))` com `Suspense`. Cache em modulo (`reactIconComponentCache: Map<string, ComponentType>`) por nome completo. Placeholder atualizado; mensagem `not found` indica react-icons. Dependencia `react-icons@^5` instalada via npm. Arquivos: app/(app)/_components/useful-links-section.tsx, package.json.
NovidadeGerenciapp - Links Uteis: campo `Icone` agora suporta nomes de icones Lucide (PascalCase `Globe`, kebab-case `shopping-cart`, snake_case `shopping_cart`) alem de emojis e texto livre. Apos digitar o nome, exibe preview do icone ao lado do input (tile `size-9` com Lucide renderizado em emerald). Resolucao via `lucide-react/dynamicIconImports` com `React.lazy` + `Suspense`, cache de componentes em modulo (`lucideComponentCache: Map<LucideIconKey, LazyExoticComponent>`), normalizacao PascalCase/snake/space -> kebab-case. Mesmo renderizador aplicado ao avatar do header do formulario e aos cards da listagem `/useful-links`. Limite `maxLength={4}` removido do campo. Arquivo: app/(app)/_components/useful-links-section.tsx.
MelhoriaGerenciapp - Links Uteis (/useful-links): listagem migrada de Tabela para `cards agrupados por categoria`. Cada grupo tem header com badge da categoria (emerald), contagem e divisor degrade. Cards (grid responsivo md:2 lg:3 xl:4) exibem favicon/emoji (size-10 rounded-xl), titulo clicavel que abre a URL em nova aba, dominio truncado, notas em line-clamp-2, contador de acessos (icone Eye) ou label `novo`, e atalho `Abrir` em emerald no rodape. Botao de editar (Pencil) aparece no hover do card via group-hover. Cards inativos (`is_active === false`) ficam com `opacity-60`. Grupos sem categoria vao para `Sem categoria` (ultimo). Ordenacao interna do grupo: `sort_order` ASC, depois `title` ASC. Removidos sort por colunas (`useSortable`, `Table*` imports). Arquivo: app/(app)/_components/useful-links-section.tsx.
MelhoriaGerenciapp - Links Uteis (/useful-links/new, /useful-links/{id}): formulario migrado de `FloatingInput` (label flutuante) para `LabeledInput` + `Label` shadcn com label fora do input (padrao atual do projeto, alinhado a Travel Resource e CRM). Status migrado de `StatusToggleField` em `rounded-2xl` para o padrao `h-9` com Label `Status` no topo. Notas usam `Textarea` com Label shadcn no topo (substitui label inline com icone `StickyNote`). Padding visual e altura uniformizados (`h-9 rounded-md`). Arquivo: app/(app)/_components/useful-links-section.tsx.
NovidadeGerenciapp - novo modulo `Links Uteis` (/useful-links). CRUD completo (list/new/edit) consumindo `GET/POST /useful-links` e `GET/PUT/DELETE /useful-links/{id}` conforme swagger.json. Campos: `title` (obrigatorio), `url` (obrigatorio, com normalizacao automatica `https://`), `category`, `icon` (emoji, maxLength 4), `sort_order`, `notes`, `is_active`. Tela com header gradiente emerald (paleta gerenciapp), busca por titulo/url/categoria/notas, ordenacao por titulo/categoria/ordem/acessos. Lista exibe favicon automatico via `google.com/s2/favicons` quando ha URL e nao ha icone customizado, badge de categoria emerald, contador de acessos com icone Eye, botao `ArrowUpRight` para abrir em nova aba. Formulario mostra preview do favicon no header, botao `Abrir` no header (edit mode), painel de stats read-only com `access_count` e `last_accessed_at` formatado. Adicoes: novo arquivo `lib/api/useful-links.ts` (tipos `UsefulLink`, payloads, funcoes `fetch/create/update/deleteUsefulLink`); `useful-links-section.tsx` em `app/(app)/_components/`; `useful-links-screen.tsx` em `app/(app)/features/outros/useful-links/`; rotas `app/(app)/useful-links/page.tsx`, `/new/page.tsx`, `/[id]/page.tsx`. Registro em `nav.ts` (secao Atalhos do menu Gerenciapp), `nav-routes.ts`, `permissions.ts` (`useful-links`) e `nav-hub-grid.tsx` (icone `Link`, gradient emerald-teal). Arquivos novos: lib/api/useful-links.ts, app/(app)/_components/useful-links-section.tsx, app/(app)/features/outros/useful-links/useful-links-screen.tsx, app/(app)/useful-links/page.tsx, app/(app)/useful-links/new/page.tsx, app/(app)/useful-links/[id]/page.tsx. Arquivos alterados: app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx.
MelhoriaFin Extrato Bancario (/fin/extrato-bancario) - header principal redesenhado em estilo compacto para igualar tamanho e estilo dos campos de /crm/deals. Container reduzido (`px-4 py-3`), icone `h-9 w-9 rounded-xl` com FileText `size-4`, titulo `text-base font-bold` (subtitulo removido), todos os filtros agora em `h-8 rounded-xl border-white/20 bg-white/10 text-xs`. `FinAccountAutocomplete` (FloatingInput h-12) substituido por `CompactAccountSelect` local: trigger Popover h-8 com `Landmark` + nome da conta + `ChevronDown`, dropdown via shadcn Popover com busca por nome/numero e lista com favicon (`partner_domain`) ou icone Landmark. `FloatingDateInput` h-12 substituido por `CompactDateField` local: input texto h-8 (w-32) com mesmo smart parsing (`parseReferenceInput`: +5/-3/dd-mm/dd/mm/aaaa) e calendario nativo via `showPicker` no `Calendar` icon. Botoes Consultar e Novo reduzidos para `h-8 text-xs` com icone `size-3.5`. Arquivo: app/(app)/features/fin/extrato-bancario/extrato-bancario-screen.tsx.

20 de Maio de 2026

16 itens
817
NovidadeTravel - Viagens (/travel/trips): novo campo `Tipo` (`trip_type`) conforme swagger. Enum `TravelTripType` (`LAZER` | `NEGOCIOS`) adicionado em `lib/api/travel.ts` e propagado para `TravelTrip`, `FetchTravelTripsParams` (filtro) e `CreateTravelTripPayload`. Em `travel-resource-screen.tsx`: novo `TRIP_TYPE_OPTIONS` (Lazer/Negocios), entradas no `STATUS_LABELS` e campo `{ key: 'trip_type', kind: 'select' }` adicionado ao resource `trips` (logo apos `destination_summary`). Sem default obrigatorio — campo opcional. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - novo modulo `Locacoes de veiculo` (/travel/vehicle-rentals). CRUD completo (list/new/edit) consumindo `GET/POST /travel/vehicle-rentals` e `GET/PUT/DELETE /travel/vehicle-rentals/{id}` conforme swagger.json. Campos: `trip_id` (FK obrigatorio via LabeledAutocomplete), `rental_company` (obrigatorio), `status` (PLANNING/BOOKED/PICKED_UP/RETURNED/CANCELLED), `booking_code`, `vehicle_category`, `vehicle_model`, `plate_number`, `driver_name`, `pickup_location`, `pickup_at` (datetime via FloatingDateTimeInput), `dropoff_location`, `dropoff_at`, `total_amount`, `currency`, `is_active`, `notes`. Listagem mostra `Locadora` (coluna primaria) + `Localizador` (secundaria). Adicoes em `lib/api/travel.ts`: tipo `TravelVehicleRental`, payloads, enum `TravelVehicleRentalStatus`, funcoes `fetch/create/update/delete`. Novo `VEHICLE_RENTAL_STATUS_OPTIONS` em `travel-resource-screen.tsx`; resource `vehicle-rentals` registrado em `TravelResource`/`TravelEntity`/`RESOURCE_CONFIGS`. Entrada `Travel Vehicle Rentals` em `nav.ts` (secao Reservas, depois de Hoteis), `nav-routes.ts`, `permissions.ts` (`travel/vehicle-rentals`) e `nav-hub-grid.tsx` (icone `Car`, gradient amber-orange). Arquivos novos: app/(app)/travel/vehicle-rentals/page.tsx, app/(app)/travel/vehicle-rentals/new/page.tsx, app/(app)/travel/vehicle-rentals/[id]/page.tsx. Arquivos alterados: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx, app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx.
MelhoriaTravel - Passagens aereas (/travel/air-tickets): CRUD atualizado ao novo contrato do backend (swagger). Cada passagem agora representa um trecho (ida ou volta) ao inves de um round-trip unico. Mudancas em `lib/api/travel.ts`: tipo `TravelAirTicket` reescrito — campo `airline` (texto livre) substituido por `airline_id` (FK obrigatorio) + `airline_name` (read-only); novo enum `TravelAirTicketDirection` (`OUTBOUND`/`RETURN`); campos `outbound_*` e `return_*` substituidos por `flight_number`, `departure_airport`, `departure_city`, `departure_at`, `arrival_airport`, `arrival_city`, `arrival_at`. `FetchTravelAirTicketsParams.airline` virou `airline_id` + novo `direction`. `CreateTravelAirTicketPayload` ajustado equivalentemente (`airline_id` e `trip_id` requeridos). Em `travel-resource-screen.tsx`: novo `FieldKind: 'airline'` que renderiza `LabeledAutocomplete` com items de `fetchTravelAirlines()`; novo `AIR_TICKET_DIRECTION_OPTIONS` (Ida/Volta) e default `direction = 'OUTBOUND'` em `createEmptyValues`; config `air-tickets` reescrita (primaryKey `airline_name`, dateKey `departure_at`, searchKeys/fields atualizados). `STATUS_LABELS` recebe os rotulos de direcao. Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeTravel - Companhias aereas (/travel/airlines/new e /travel/airlines/{id}): novo banner sky `Preenchimento automatico via OpenFlights` acima do grid de campos. Botao `Buscar por IATA` consulta a base publica OpenFlights (~6.000 airlines em `https://raw.githubusercontent.com/jpatokal/openflights/master/data/airlines.dat`) e preenche `name`, `iata_code`, `icao_code` e `country`. Cache em memoria + localStorage (`openflights-airlines-v1`) evita re-fetch entre paginas/sessoes. Helper novo: `lib/api/openflights-airlines.ts` com `findAirlineByIata`/`findAirlineByIcao` (prefere airlines ativos). Banner so e renderizado quando `config.resource === 'airlines'`. Arquivos: lib/api/openflights-airlines.ts (novo), app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): header agrupa todos os contadores na esquerda. Antes era `flex items-center justify-between` com `XX parcelas` na esquerda e `pagas/pendentes/vencidas` na direita; agora e `flex items-center gap-4` com `XX parcelas` + `XX pagas` + `XX pendentes` + `XX vencidas` em sequencia na esquerda. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): nova coluna `Parceiro` (apos `Parcela`) com favicon do `domain` do parceiro (lookup em `allPartners` por `partner_id`) + `partner_name`, fallback para icone `Users`. Coluna `Status` movida para a extremidade direita da tabela (`text-right`), com a antiga coluna de acoes (botao de excluir) integrada na mesma cell — o botao aparece a esquerda do badge no hover da linha. Badge de status redesenhado: pill arredondada (`rounded-full`), uppercase tracking-wide, com `CheckCircle2` no Pago / `Clock3` no Pendente / ping animado no Vencido. Ordenacao padrao agora e `installment` ASC (era `due_date` ASC). Sort key `partner` adicionado ao `TxSortKey`. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): tabela de parcelas redesenhada e mais compacta. Padding vertical reduzido (`py-2.5` → `py-1` nas linhas, `py-1.5` no header). Fonte do corpo `text-sm` → `text-[12px]`. Coluna `Parcela` virou badge `bg-slate-100` com `font-mono`, separador `/` em cinza claro. Badges de status menores: largura `w-24 → w-[72px]`, `text-[11px] → text-[10px]`, padding `px-3 py-1 → px-1.5 py-0.5`, dot `size-2 → size-1.5`, raio `rounded-lg → rounded-md`. Estilo simplificado: removido gradiente/sombra dos badges Pago/Pendente; apenas `Vencido` mantem o ping animado para chamar atencao. Botao de excluir reduzido para `size-3.5`. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): header agora exibe, alinhados a direita (`ml-auto`), os totais `Valor pago` (emerald), `Valor pendente` (amber) e `Valor total` (slate). Calculados a partir das transacoes do grupo: para cada `tx`, `amount - discount_amount + charges_amount`. `Valor pago` soma transacoes com `paid_at` preenchido, `Valor pendente` soma com `paid_at` nulo, `Valor total` e a soma dos dois. Formatacao via `fmtMonetary` com prefixo `R$`, font tabular-nums. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
CorrecaoFin Grupos de Parcelas (/fin/installment-groups/{id}): apos salvar o grupo, o reload das transacoes nao dispara mais PUTs em massa. `loadGroupTransactions` agora aceita `{ skipNormalization?: boolean }` e em `handleSave` e chamado com `skipNormalization: true` — o backend ja ajustou os vencimentos durante o save do grupo, entao a normalizacao de dia-do-mes para contas CHECKING e pulada nesse caso. Abrir a aba `Transacoes` manualmente continua normalizando (chamada sem o flag). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): botoes padrao `Excluir` (do grupo) e `Salvar` (do formulario) ocultos no `FormFooter` quando `activeTab === 'transactions'` (via prop `hideDefaultActions`), mantendo o footer dedicado apenas a acoes da aba de transacoes. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): novo botao `Excluir em aberto` no `FormFooter` (slot `children`, lado esquerdo), visivel apenas quando `activeTab === 'transactions'` e com `permDelete`. Mostra badge com a contagem de transacoes em aberto. Ao clicar abre `ConfirmDeleteDialog` indicando a quantidade afetada. Confirmado, executa `Promise.allSettled` de `deleteFinTransaction` sobre todas as transacoes do grupo com `paid_at` nulo, remove as bem-sucedidas do state, exibe toast com contagens (sucessos/falhas) e chama `onReloadGroups` para atualizar os totais agregados (`paid_amount`, `pending_amount`, `installment_paid/pending`). Botao desabilitado quando nao ha transacoes em aberto ou enquanto a exclusao esta em andamento. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin Grupos de Parcelas (/fin/installment-groups/{id}) - apos salvar com sucesso o grupo (modo edit), as transacoes vinculadas sao recarregadas via `loadGroupTransactions()`. Isso garante que a aba `Transacoes` reflita imediatamente alteracoes que impactam parcelas (ex.: mudanca de `first_due_date` em conta CHECKING re-normaliza vencimentos, mudanca de `installment_total` regenera parcelas no backend). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeFin Grupos de Parcelas (/fin/installment-groups/{id}) - novos campos `Valor Pago` e `Valor Pendente` (ambos somente leitura) em uma nova sub-linha abaixo da Row 2 (Valor Total | Parcelas | Valor Parcela | datas). Row 2 mantida intacta para preservar o layout dos campos editaveis. Sub-linha `flex gap-3` com `Valor Pago` (icone R$ emerald, exibe `selectedGroup.paid_amount`) e `Valor Pendente` (icone R$ amber, exibe `selectedGroup.pending_amount`) lado a lado, cada um w-48. Renderizada apenas no modo edit (oculta na criacao). Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaCRM Dashboard (/crm/dashboard) - card `Atividades atrasadas` removido como card separado; a informacao foi mesclada no `sub` do card `Atividades abertas`, exibida ao lado de `X concluidas` com separador `·`, icone `AlertTriangle size-3` e cor rose (apenas quando `overdueActivitiesCount > 0`). Linha inferior passa a ter 2 cards (`Atividades abertas`, `Meta de vendas`) em `xl:grid-cols-2`. Prop `sub` do `StatCard` atualizada de `string` para `ReactNode` e o wrapper trocado de `<p>` para `<div>` para acomodar markup inline. Arquivo: app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.
MelhoriaCRM Dashboard (/crm/dashboard) - cards de resumo `Deals ganhos` e `Contatos` removidos. Linha superior agora tem 2 cards (Deals abertos, Empresas) e a inferior tem 3 (Atividades abertas, Atividades atrasadas, Meta de vendas), ambas em `xl:grid-cols-3`. Imports `Users` e variaveis `closedDealsCount`/`totalWonValue`/`contactsCount` tambem removidos. Arquivo: app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.
NovidadeCRM Dashboard (/crm/dashboard) - card `Pipeline de Vendas`: novos filtros `YEAR`, `Q1`, `Q2`, `Q3`, `Q4` no header do card (entre o titulo e o badge de total). Padrao inicial e o trimestre atual (derivado de `new Date().getMonth()`). `YEAR` mantem o comportamento original (usa `pipeline_stages` do dashboard ja carregado, respeitando o filtro de ano global). Ao selecionar Q1-Q4, dispara um fetch adicional de `/crm/dashboard` com `start_date`/`end_date` restritos ao trimestre do ano selecionado (ou ano atual, se nenhum estiver) e usa apenas o `pipeline_stages` retornado — os demais graficos (Vendas Fechadas por Mes, Por Trimestre, Comissao) nao sao afetados. O backend filtra os deals por `close_date` dentro da janela do trimestre. Badge do total no card reflete a soma dos estagios filtrados (excluindo estagios `is_closed && !is_won`). Spinner inline no badge enquanto a busca esta em andamento. Novo state `pipelineQuarter`, `pipelineStagesOverride`, `pipelineLoading`. Arquivo: app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.

19 de Maio de 2026

7 itens
43
NovidadeTravel - novo modulo `Companhias aereas` (/travel/airlines). CRUD completo (list/new/edit) consumindo `GET/POST /travel/airlines` e `GET/PUT/DELETE /travel/airlines/{id}` conforme `swagger.json`. Campos: `name` (obrigatorio), `iata_code`, `icao_code`, `country`, `website`, `is_active`, `notes`. Reutiliza o `TravelResourceScreen` generico, seguindo padroes ja consolidados (header gradiente sky, tabela com hover, formulario com `LabeledInput`/`StatusToggleField`/`Textarea`, `FormFooter`). Listagem mostra `Nome` (coluna primaria) e `IATA` (coluna secundaria). Adicoes: tipos e funcoes `TravelAirline`, `Create/FetchTravelAirlinePayload`, `fetch/create/update/deleteTravelAirline(s)` em lib/api/travel.ts; entrada `Travel Airlines` em nav.ts (secao `Cadastros` do menu Viagem), nav-routes.ts, permissions.ts, nav-hub-grid.tsx (icone `Building2`, gradient blue-sky). Arquivos novos: app/(app)/travel/airlines/page.tsx, app/(app)/travel/airlines/new/page.tsx, app/(app)/travel/airlines/[id]/page.tsx. Arquivos alterados: app/(app)/features/travel/travel-resource-screen.tsx, lib/api/travel.ts, app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx.
NovidadeTravel (passagens, hoteis, despesas) - campo `Viagem` (trip_id) substituido por componente autocomplete no formulario (/travel/air-tickets/new, /travel/hotel-reservations/new, /travel/expenses/new). Usa `LabeledAutocomplete` (mesmo padrao do CRM Activities/Contatos), busca por nome e resumo do destino, com icone `Plane` em sky. Trips sao carregadas via `fetchTravelTrips` quando o formulario abre (apenas para resources que nao sao `trips`). Novo `FieldKind: "trip"`. Arquivos: app/(app)/features/travel/travel-resource-screen.tsx.
MelhoriaTravel - modulo Destinos removido. Endpoints `/travel/destinations*` foram descontinuados no backend (ver swagger.json). Remocoes: tipos/funcoes `TravelDestination`, `fetchTravelDestinations`, `fetchTravelDestination`, `createTravelDestination`, `updateTravelDestination`, `deleteTravelDestination`, `CreateTravelDestinationPayload`, `FetchTravelDestinationsParams` (lib/api/travel.ts); pasta de rotas `app/(app)/travel/destinations/`; entrada `Travel Destinations` em nav.ts/nav-routes.ts/permissions.ts/nav-hub-grid.tsx; resource `destinations` em travel-resource-screen.tsx. Campos `destination_id` removidos dos schemas/forms/searchKeys de `TravelAirTicket` e `TravelHotelReservation`. Icone Type fallback de campos texto removido (campos como Companhia, Localizador, Classe, Voo etc. nao exibem mais o icone `T` a esquerda). Arquivos: lib/api/travel.ts, app/(app)/features/travel/travel-resource-screen.tsx, app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, lib/auth/permissions.ts, app/(app)/_components/nav-hub-grid.tsx.
MelhoriaTravel (passagens, hoteis, viagens, despesas) - formularios em /travel/*/new e /travel/*/{id}: campos refatorados para o padrao `label fora do input` consolidado em CRM Deals (`LabeledInput` + `Label` com `labelOutsideClass`). `FloatingInput`/`FloatingSelect` substituidos pelo conjunto `LabeledInput`/`shadcn Select`/`<Input type="datetime-local">`/`Textarea` com `Label` por cima, mantendo o indicador de mudanca (borda cyan + ponto). `DatePickerInput` ja seguia o padrao e recebeu `id`. `StatusToggleField` para `boolean` agora tambem tem `Label` por cima e altura `h-9`. Campo monetario com prefixo `R$` interno (sky no tema travel). Arquivo: app/(app)/features/travel/travel-resource-screen.tsx.
NovidadeFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): quando a conta vinculada e do tipo `Conta Corrente` (`account_type === "CHECKING"`), os vencimentos das parcelas seguintes sao normalizados para o mesmo dia-do-mes do `first_due_date` do grupo. Apos `fetchFinTransactions`, cada transacao nao paga com `installment_number > 1` cujo `due_date` divirja do esperado e atualizada via `updateFinTransaction({ due_date })`. O dia e mantido entre meses curtos com clamp para o ultimo dia do mes (ex.: dia 31 em fevereiro vira 28/29). Parcelas ja pagas (`paid_at` preenchido) sao preservadas. Novo helper `expectedDueDateForInstallment(firstDueIso, n)`. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Fluxo de Caixa (/fin/fluxo-caixa) - header: card `Inicial` passa a considerar apenas contas do tipo `Conta Corrente` (`account_type === "CHECKING"`). Novo `useMemo` `saldoInicialCorrente` cruza `accounts` (FinAccount com `account_type`) com `accountsBalance` (id + balance) e soma somente os saldos das contas correntes. O `saldo_inicial` retornado pela API (total geral) continua sendo guardado em `saldoInicial` e usado como fallback do `saldoFinal` quando nao ha dados visiveis no range. Arquivo: app/(app)/features/fin/fluxo-caixa/fluxo-caixa-screen.tsx.
NovidadeCRM Calculadora (/crm/calculadora): nova ferramenta de calculo de preco de licenciamento na secao `Cadastros` do CRM. Inputs: `Custo SAP NET` (R$), `Imposto %` (default 12,15%, aplicado tanto no gross-up do custo SAP quanto na composicao do Valor Final), `Margem %` (default 30%), `Manutencao %` (default 22%), `Meses pro-rata` (default 7). Calculo gross-up: `Custo SAP c/Impostos = Custo NET / (1 - Imposto)`; `Valor Final = Custo c/Impostos / (1 - Imposto - Margem)`; `Manutencao Anual = Valor Final * %`; `Pro-rata = Manutencao Anual * (meses / 12)`. Resultados em tabela `Composicao do Preco` (Custo NET, Imposto sobre Custo SAP, Custo c/Impostos, Imposto sobre Venda, Margem, Valor Final em destaque) + card `Manutencao` com totais Anual e Pro-rata. Botao `Restaurar padroes` no header. Sem chamada de API. Permissao publica (`PUBLIC_PAGES`). Arquivos novos: app/(app)/crm/calculadora/page.tsx, app/(app)/features/crm/calculadora/calculadora-screen.tsx. Arquivos alterados: app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, app/(app)/_components/nav-hub-grid.tsx, lib/auth/permissions.ts.

15 de Maio de 2026

12 itens
435
MelhoriaBooks - tipo `Book.subtitle` e `CreateBookPayload.subtitle` removidos de `lib/api/books.ts` apos o backend remover o campo `subtitle` de `models.Book`/`CreateBookPayload`/`UpdateBookPayload` no swagger. Arquivo: lib/api/books.ts.
MelhoriaBooks form (/books/new, /books/{id}) - Subtitulo: campo `Subtitle` removido por completo da UI. Coluna direita agora tem 5 linhas (era 6): linha 1 `Titulo + Status + Ativo + Favorito` (consolidando os toggles que estavam na linha 2 com Subtitulo), linha 2 `Autor + Editora`, linha 3 `Idioma + Categoria + Avaliacao`, linha 4 `ISBN-10 + ISBN-13 + Pag. atual + Total pag.`, linha 5 `Iniciado em + Concluido em`. State `formSubtitle`/`setFormSubtitle`, chave `subtitle` em `initialFormValues`, comparacao em `hasFormChanges`, populate/reset, dependencias do useMemo, payloads de create/update, busca via `normalizeText(b.subtitle)` e display do subtitulo na celula da lista removidos. Import nao usado `PenLine` tambem removido. O tipo `Book.subtitle` em `lib/api/books.ts` foi mantido para compatibilidade caso o backend retorne o campo. Arquivo: app/(app)/_components/books-section.tsx.
MelhoriaBooks form (/books/new, /books/{id}): preview da capa reduzido de `h-72` (288px ≈ 5 linhas de campos) para `h-[228px]` (4 linhas: 4 × 48px input + 3 × 12px gap), alinhando melhor com a coluna direita — o input `URL da capa` abaixo fica como 5a linha, e a 6a linha da direita (`Iniciado em/Concluido em`) extende ao lado direito do final da coluna esquerda. Arquivo: app/(app)/_components/books-section.tsx.
CorrecaoBooks form (/books/new, /books/{id}): apos a reorganizacao em duas colunas, em viewports menores a altura `h-[calc(100vh-180px)]` ainda estava cortando a coluna direita (linha `Iniciado em/Concluido em` ficava sob o textarea de Notas) e o preview da capa estava sendo espremido pelo flex parent. Container aumentado para `h-[calc(100vh-110px)]` (+70px de altura) e o preview da capa marcado com `shrink-0` para travar a altura `h-72` mesmo quando o flex parent for menor. Arquivo: app/(app)/_components/books-section.tsx.
MelhoriaBooks form (/books/new, /books/{id}): layout reorganizado em duas colunas para caber sem barra de rolagem. Container aumentado de `w-[880px]` para `w-[960px]`, body trocado de `space-y-3` com `overflow-y-auto` para `flex h-full flex-col gap-3 overflow-hidden`. Topo: coluna `w-48` a esquerda com preview vertical da capa (`h-72` no formato 2:3, placeholder com icone `BookOpen` + texto `Sem capa` quando vazio) + `URL da capa` abaixo; coluna `flex-1` a direita com 6 linhas compactas — `Titulo + Status (w-40)` | `Subtitulo + Ativo + Favorito` | `Autor + Editora` | `Idioma (w-40) + Categoria + Avaliacao (w-28)` | `ISBN-10 + ISBN-13 + Pag. atual (w-28) + Total pag. (w-28)` | `Iniciado em + Concluido em` (datas flex-1). Rodape: `Notas` em textarea `min-h-16 rows=2 resize-none` ocupando toda a largura. Todos os campos preservados, change tracking e payloads intactos. Arquivo: app/(app)/_components/books-section.tsx.
CorrecaoDashboard Home (/gerenciapp): apos a remocao dos cards `Financeiro`/`CRM`/`Admin` e a inclusao do `Books` no grupo `Gerenciapp` do nav, a home ficou sem renderizar os atalhos do grupo. `DashboardHome` agora monta `<NavHubGrid groups={gerenciappGroups} variant="gerenciapp" />` no `flex-1` abaixo do header (filtrando `navGroups` por `label === 'Gerenciapp'`), seguindo o mesmo padrao das hubs `/fin`, `/crm` e `/admin`. Carrega `permissions`/`isAdmin` da sessao via `getSession()` para o filtro de `canRead`. Com isso, o card de `Livros` (e futuros itens exclusivos do grupo) aparece em `/gerenciapp`. Arquivo: app/(app)/features/dashboard/dashboard-home.tsx.
NovidadeFin Conciliacao Cartao (/fin/conciliacao-cartao) - header: filtro `Vencimento` substituido por intervalo `Vencimento Inicial | Vencimento Final`. State `dueDateFilter` desmembrado em `startDueDateFilter` + `endDueDateFilter` (ambos `string`), com refs `startDueDatePickerRef` e `endDueDatePickerRef`. `loadSystemTxs` agora consulta `searchFinTransactions` com `start_due_date = startDueDateFilter || endDueDateFilter` e `end_due_date = endDueDateFilter || startDueDateFilter` quando ao menos um dos dois esta preenchido (preserva comportamento anterior de busca em data unica); se ambos vazios, mantem o fallback existente de derivar do `statementData.summary.dueDate` ou das datas das transacoes da aba. Ao processar a planilha (`processFile`), o `summary.dueDate` agora popula tanto inicial quanto final com a mesma data. `handleReset` limpa os dois campos. UI renderiza dois botoes-pill identicos lado a lado (mesma paleta violet do icone Calendar). Helper `openDueDatePicker` generalizado para `openDatePicker(ref)`. Arquivo: app/(app)/features/fin/conciliacao-cartao/conciliacao-cartao-screen.tsx.
NovidadeBooks - CRUD completo (/books, /books/new, /books/{id}): nova feature de biblioteca pessoal alinhada ao swagger (`models.Book`, `CreateBookPayload`, `UpdateBookPayload`). API client em `lib/api/books.ts` (`fetchBooks` com filtros `search/status/category/author/language/is_favorite/is_active`, `fetchBook`, `createBook`, `updateBook`, `deleteBook`). Tipo `Book` cobre `title` (obrigatorio), `subtitle`, `author`, `publisher`, `isbn_10`, `isbn_13`, `language`, `category`, `status` (`WANT_TO_READ|READING|READ|PAUSED|ABANDONED`), `rating`, `current_page`, `total_pages`, `started_at`/`finished_at` (FlexibleDate), `cover_url`, `notes`, `is_favorite`, `is_active`. UI em `app/(app)/_components/books-section.tsx` (lista + formulario integrado, paleta emerald do `sectionThemes.gerenciapp`), screen em `app/(app)/features/books/books-screen.tsx` e rotas `app/(app)/books/{page,new/page,[id]/page}.tsx`. Lista exibe thumbnail da capa (`<Image unoptimized>`), titulo + subtitulo, autor, badge de status (`WANT_TO_READ` slate, `READING` amber, `READ` emerald, `PAUSED` orange, `ABANDONED` red), avaliacao com estrela e barra de progresso de paginas. Formulario reutiliza `FloatingInput`, `FloatingSelect`, `DatePickerInput`, `Textarea`, `StatusToggleField`, `FormFooter`, `ConfirmDeleteDialog` e segue o padrao consolidado de change tracking + partial save (no edit envia somente campos alterados). Nav adicionado ao grupo `Gerenciapp` (secao `Biblioteca`) em `app/(app)/data/nav.ts` e ao mapping em `app/(app)/data/nav-routes.ts` (rota base `/books`), com metadata no `nav-hub-grid.tsx` (icone `BookOpen`, gradiente emerald-teal). Permissao registrada em `lib/auth/permissions.ts` (`Books -> books`). Arquivos novos: lib/api/books.ts, app/(app)/_components/books-section.tsx, app/(app)/features/books/books-screen.tsx, app/(app)/books/page.tsx, app/(app)/books/new/page.tsx, app/(app)/books/[id]/page.tsx. Arquivos alterados: app/(app)/data/nav.ts, app/(app)/data/nav-routes.ts, app/(app)/_components/nav-hub-grid.tsx, lib/auth/permissions.ts.
NovidadeFin Parceiros (/fin/partners/{id} - aba Detalhes): campo `Documento (CPF/CNPJ)` agora aplica mascara ao terminar a digitacao (`onBlur`) — 11 digitos formatam como CPF `XXX.XXX.XXX-XX`, 14 digitos formatam como CNPJ `XX.XXX.XXX/XXXX-XX`, demais comprimentos mantem o valor digitado (ainda incompleto). Novo helper `formatDocument` em `lib/format-helpers.ts` reutiliza `formatCpf`/`formatCnpj` ja existentes. Aplicado tambem no `populateForm` (documento vindo da API e formatado na carga). Arquivos: lib/format-helpers.ts, app/(app)/_components/fin-partners-section.tsx.
CorrecaoFin Parceiros (/fin/partners/{id}) - botao PIX (QR Code/Copia e Cola): chave PIX exibida com mascara visual (ex: `319.930.239-28`, `(31) 99302-3928`) estava sendo enviada formatada para o `buildPixBrCode`, gerando um BR Code invalido (o padrao BCB exige chave em formato canonico). Adicionada `normalizePixKey` em `lib/pix-brcode.ts` que remove a mascara antes de montar o payload TLV: email -> lowercase trimmed; EVP/aleatoria -> UUID lowercase com dashes; telefone (prefixo `+`, ou 11 digitos com padrao celular BR DDD+9, ou 10 digitos com DDD+fixo) -> E.164 `+55DDDXXXXXXXXX`; CPF (11 digitos sem padrao celular) -> so digitos; CNPJ (14 digitos) -> so digitos. `buildPixBrCode` e `detectPixKeyType` agora normalizam a chave antes de usar — assim o QR Code e o `Copia e Cola` funcionam mesmo quando o campo do form esta exibindo a mascara. Arquivo: lib/pix-brcode.ts.
NovidadeFin Parceiros (/fin/partners/{id} - aba Detalhes): campo `Chave PIX` agora formata automaticamente conforme o tipo da chave detectada durante a digitacao. Novo helper `formatPixKey` em `lib/format-helpers.ts` aplica a mascara apropriada: email (contem `@`) e normalizado para lowercase trimmed; chave aleatoria EVP (contem letras `a-f`) e formatada como UUID `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (lowercase, ate 32 hex); telefone (prefixo `+`) usa `formatPhone` existente; numerico com mais de 11 digitos usa `formatCnpj`; numerico com 11 digitos no padrao de celular BR (DDD 11-99 + digito `9` na posicao 3 + 8 digitos) e formatado como telefone `(DD) 9XXXX-XXXX`; numerico com 10 digitos no padrao de fixo BR (DDD 11-99 + primeiro digito 2-5) e formatado como `(DD) XXXX-XXXX`; demais casos com ate 11 digitos usam o novo helper `formatCpf` (mascara `XXX.XXX.XXX-XX`, progressiva). Aplicado no `onChange` do `FloatingInput` de Chave PIX e no `populateForm` (chave_pix vinda da API tambem e reformatada na carga). Arquivos: lib/format-helpers.ts, app/(app)/_components/fin-partners-section.tsx.
MelhoriaDashboard Home (/gerenciapp): cards de modulos `Financeiro`, `CRM` e `Admin` removidos por completo da home (`DashboardHome`), incluindo o array `modules`, o bloco de render dos cards (com header colorido, accent bar, glow orb e lista de shortcuts) e os imports nao mais utilizados (`Link`, `ArrowRight`, `Handshake`, `Shield`, `Wallet`). O header de boas-vindas + relogio (com `theme.gradient` emerald, dia/SEX, saudacao por horario, hora atual e badge `GerenciApp`) foi preservado. Abaixo do header passa a existir apenas um placeholder `flex-1` que reserva o espaco vertical para os acessos exclusivos que serao adicionados em seguida. Arquivo: app/(app)/features/dashboard/dashboard-home.tsx.

13 de Maio de 2026

3 itens
12
CorrecaoFin Grupos de Parcelas (/fin/installment-groups/{id} - aba Transacoes): coluna `Valor` agora exibe o valor final considerando desconto e acrescimo (`amount - discount_amount + charges_amount`), alinhada ao comportamento de Fin Transacoes e Fin Recorrencias. Ordenacao por valor tambem passa a usar o valor final. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
MelhoriaFin Transacoes (form de criacao/edicao em /fin/transactions/new e /fin/transactions/{id}): ao clicar no avatar do parceiro dentro do `FinPartnerAutocomplete`, o painel de edicao do parceiro agora abre como um `Sheet` centralizado na tela (`!left-1/2 !-ml-[440px] !top-[70px] !h-[calc(100vh-140px)] !w-[880px]`) em vez do sheet ancorado a direita com `width=640px`. Conteudo segue sendo o `PartnerSheetContent` (que renderiza `FinPartnersSection` em modo edit), envolto em wrapper `rounded-2xl bg-white shadow-2xl`. Mesmo padrao ja aplicado em Fin Fluxo Caixa. Arquivo: app/(app)/_components/fin-partner-autocomplete.tsx.
MelhoriaFin Fluxo Caixa (/fin/fluxo-caixa): ao expandir as transacoes de um dia e clicar no avatar de um parceiro, o painel de edicao do parceiro agora abre como um `Sheet` centralizado na tela (mesmo padrao do sheet de edicao de transacao — `!left-1/2 !-ml-[440px] !top-[70px] !h-[calc(100vh-140px)] !w-[880px]`) em vez do `SimpleOverlayPanel` ancorado a direita com `width=640px`. Conteudo segue sendo o `PartnerSheetContent` (que renderiza `FinPartnersSection` em modo `edit` com o `initialSelectedId`), agora envolto em um wrapper `rounded-2xl bg-white shadow-2xl`. Comportamento de close/save preservado (reset de `editingPartnerId`, limpeza de `dayDetails` e `loadData()`). Arquivo: app/(app)/features/fin/fluxo-caixa/fluxo-caixa-screen.tsx.

12 de Maio de 2026

3 itens
12
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campos `Comprometimento` (Select w-44) e `Reforma Tributaria` (Select w-32) movidos da linha de `Notas` para a linha de `Pre-Venda | Status Pre-Venda`, ficando agora `Pre-Venda | Status Pre-Venda | Comprometimento | Reforma Tributaria` (flex row, com os dois `LabeledInput` em `flex-1` e os dois Selects em larguras fixas). A linha de `Notas` ficou solta logo abaixo ocupando toda a largura disponivel (`flex-1 flex-col`), recuperando a area vertical antes compartilhada com os Selects. Comportamento dos campos (change tracking, payloads, readonly de Reforma Tributaria fora do modo create) preservado. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campo `Reuniao Pre-Vendas` (`DatePickerInput` ligado a `formPreVendasReuniaoDate`/`pre_vendas_reuniao_date`) removido da UI da linha `Pre-Venda | Status Pre-Venda | Reuniao Pre-Vendas`. O grid passou de 3 colunas (`md:grid-cols-[minmax(0,1fr)_minmax(0,1fr)_9rem]`) para 2 colunas iguais (`md:grid-cols-2`), ficando apenas `Pre-Venda | Status Pre-Venda`. O state (`formPreVendasReuniaoDate`/`setFormPreVendasReuniaoDate`), `initialFormValues.preVendasReuniaoDate`, populate/reset, change tracking e os payloads de create/update foram preservados para manter o round-trip da data com o servidor — o valor continua sendo carregado do deal e enviado de volta apenas se mudar (no edit como `null` quando vazio), sem expor edicao na tela. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals): novo filtro `Status Pre-Venda` no header da listagem, ao lado de `Comprometimento`. Popover lista valores distintos extraidos de `status_pre_venda` apenas de deals que estao nos estagios atualmente exibidos — em modo tabela respeita `filterPipelineId` + `filterStageIds` (quando ha selecao); em modo kanban respeita `filterPipelineId` e exclui deals em stages recolhidos (`collapsedKanbanStageIds`). Valores sao normalizados com trim, vazios descartados e ordenados via `localeCompare('pt-BR')`. Inclui opcao especial `Vazio` para filtrar deals sem o campo preenchido. Estilo segue o padrao dos filtros existentes com paleta `violet` (icone `Target`). Estado `filterStatusPreVenda: string` adicionado, persistido em `useListStatePersistence` (storageKey `crm-deals-list`) e integrado a `filteredDeals` (`EMPTY` filtra `!status_pre_venda?.trim()`, qualquer outro valor faz match exato apos trim). Reset de paginacao tambem reage ao novo filtro. Arquivo: app/(app)/_components/crm-deals-section.tsx.

08 de Maio de 2026

6 itens
15
MelhoriaCRM Deals (/crm/deals/{id}): `GET /admin/users` (`fetchUsuarios`) agora e lazy. `useCrmReferenceData` ganhou opcao `includeUsers?: boolean` (mirror de `includeDeals`) e funcao `loadUsersOnce`. `users` foi removido de `CORE_KINDS` (`loadAll` agora carrega so pipelines/stages/companies). Em `crm-deals-section.tsx`, o hook e chamado com `{ includeUsers: activeTab === 'activities' }` — o GET de usuarios so dispara quando o usuario entra na aba Atividades (onde `users` e usado para autocomplete de owner em tasks/meetings). Resultado: a aba Detalhes (default) deixa de fazer `GET /admin/users` no load. Arquivos: lib/hooks/use-crm-reference-data.ts, app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id}): pagina de edicao agora carrega o deal individualmente via `GET /crm/deals/{id}` (`fetchCrmDeal`) em vez de baixar a lista completa via `GET /crm/deals` e procurar em memoria. `useEntityList` ganhou option `enabled?: boolean` (default `true`); `deals-screen.tsx` usa `enabled: mode === 'list'` para nao disparar o fetch da lista nos modos `edit`/`new`. Em `edit` a screen tem state proprio (`singleDeal`/`singleLoading`/`singleError`) populado por `fetchCrmDeal(selectedId)` e passa o resultado como prop `initialDeal` para `CrmDealsSection`. O effect de selecao inicial da section prioriza `initialDeal`, e o effect de refresh tambem reflete `initialDeal` quando presente. `onReloadDeals` em modo edit aponta para `reloadSingleDeal` (refaz so o GET por id). Adicionalmente, `useCrmReferenceData` ficou com `deals` lazy: `loadAll` agora carrega apenas `pipelines/stages/companies/users` (CORE_KINDS) e `deals` so e buscado via `loadDealsOnce` quando o consumer passa `{ includeDeals: true }` (usado em `crm-deal-items-section.tsx`). Resultado: tela de detalhe deixa de fazer 2x `GET /crm/deals` (useEntityList + cache) e passa a fazer 1x `GET /crm/deals/{id}`. Arquivos: app/(app)/features/crm/deals/deals-screen.tsx, app/(app)/_components/crm-deals-section.tsx, app/(app)/_components/crm-deal-items-section.tsx, lib/hooks/use-entity-list.ts, lib/hooks/use-crm-reference-data.ts.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): icone do campo `Contato` trocado de `Contact` para `UserRound` (lucide). Aplicado tanto no placeholder (quando nenhum contato esta selecionado) quanto nos items do dropdown de contatos da empresa via novo prop `fallbackIcon` do `ContactAvatar` (`'contact' | 'user-round'`, default `'contact'` mantido para nao afetar outras telas). Arquivos: app/(app)/_components/crm-deals-section.tsx, app/(app)/_components/contact-avatar.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campos `Owner` e `Co-Owner` movidos para a mesma linha do `Status Pre-Venda` (`flex items-end gap-3`), ficando na ordem `Owner | Co-Owner | Status Pre-Venda | Status comissao | Reforma Tributaria` (todos com `flex-1` exceto os dois Selects de tamanho fixo). Notas passa a ocupar a largura total abaixo (antes era um grid 2-col com Owner/Co-Owner stacked a esquerda e Notas a direita). Mantidos o icone `Star` (preenchido amber) quando `selectedDeal.owner_hubspot_id`/`co_owner_hubspot_id === sessionHubspotId` e o change indicator (borda cyan + dot) via `hasChanged`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals - CRUD: novo campo `status_pre_venda` (string livre) adicionado conforme atualizacao do swagger em `models.CRMDeal`, `CreateCRMDealPayload` e `UpdateCRMDealPayload`. Tipos TS atualizados (`CRMDeal.status_pre_venda?: string`, payloads de create/update aceitam `status_pre_venda?: string | null`), state local `formStatusPreVenda`/`setFormStatusPreVenda`, `initialFormValues` ganhou chave `statusPreVenda`, populate/clear inclui o novo campo, change tracking compara `formStatusPreVenda` vs init, payloads de create/update enviam o campo (com partial save no edit usando `null` quando vazio). Adicionado `LabeledInput` `Status Pre-Venda` (flex-1) ao lado de `Vertical de Negocio` na linha de campos da aba Detalhes, antes de `Status comissao` e `Reforma Tributaria`. Arquivos: lib/api/crm-deals.ts, lib/api/crm-deals-create.ts, lib/api/crm-deals-update.ts, app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Contacts - CRUD: campo `hubspot_object_id` renomeado para `hubspot_id` em alinhamento com `models.CRMContact`/`CreateCRMContactPayload`/`UpdateCRMContactPayload` do swagger atualizado. Tipos TS (`CRMContact.hubspot_id`, `CreateCRMContactPayload.hubspot_id`, `UpdateCRMContactPayload.hubspot_id`), `initialFormValues` (chave `hubspot_id`), populate/reset, change tracking, payloads de create/update e o form de criacao/edicao de contato dentro do modulo de companies tambem atualizados. Apenas o modulo de contacts (CRMContact) foi afetado — companies (`models.CRMCompany`), pipelines e pipeline-stages mantem `hubspot_object_id` no swagger e no codigo. Arquivos: lib/api/crm-contacts.ts, lib/api/crm-contacts-create.ts, lib/api/crm-contacts-update.ts, app/(app)/_components/crm-contacts-section.tsx, app/(app)/_components/crm-companies-section.tsx.

07 de Maio de 2026

34 itens
17314
NovidadeFin Installment Groups (/fin/installment-groups/{id} - aba Transacoes): adicionada uma nova coluna na tabela de parcelas com botao de exclusao por linha. O icone `Trash2` so e visivel ao passar o mouse sobre a linha (`opacity-0 group-hover:opacity-100`), evitando poluicao visual mas mantendo a acao acessivel. Ao clicar, dispara um `ConfirmDeleteDialog` com `entityLabel='o lancamento'` e `itemName` montado a partir do numero da parcela (ex.: `Parcela 3/12`). Confirmando, chama `deleteFinTransaction(tx.id)` e remove a linha do `groupTxs` localmente, com toast de sucesso/erro. `e.stopPropagation()` no click do botao evita que a row click abra o sheet de edicao. Header da tabela ganhou um novo `<TableHead>` vazio (`w-0`, `aria-label='Acoes'`) ao final para reservar espaco a coluna. Arquivo: app/(app)/_components/fin-installment-groups-section.tsx.
NovidadeCRM Deals (/crm/deals - modo Kanban): cards passam a exibir `co_owner_name` ao lado de `owner_name` no rodape do card, separados por ` | ` (pipe). Quando nao ha co-owner, somente o owner e mostrado (formato anterior preservado). Tooltip do span agregado mostra ambos quando presentes (ex.: `Raphael Carneiro | Maria Silva`). Texto continua truncado para nao estourar o card. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals/{id}): icone `Star` (preenchido amber) exibido a esquerda do input `Owner` ou `Co-Owner` quando o valor do campo (apos `trim`) corresponde exatamente ao `sessionUserName` (`getSession()?.userName`) — indica visualmente que o usuario logado e o owner ou co-owner da oportunidade. Implementado via prop `leftIcon` do `LabeledInput` (que ja suporta padding `pl-8` automatico quando ha icone). Tooltip informativo via `leftIconTitle` (`Voce e o owner`/`Voce e o co-owner`). O icone reage em tempo real conforme o usuario digita no campo. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals/{id}): adicionada uma nova linha de campos `Owner` e `Co-Owner` (`LabeledInput` com `flex-1` cada, gap-3) imediatamente abaixo da linha `Vertical de Negocio | Status comissao | Reforma Tributaria`. Os states `formOwnerName`/`setFormOwnerName` e `formCoOwnerName`/`setFormCoOwnerName` ja existiam (e ja eram enviados em create/update payloads), mas nao estavam expostos na UI de edicao — so apareciam concatenados no header do form (`{[formOwnerName, formCoOwnerName].filter(Boolean).join(' | ')}`). Agora podem ser editados livremente, com change indicator (borda cyan + dot) via `hasChanged` comparando com `initialFormValues.current.ownerName`/`coOwnerName`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals): novo botao toggle `Meus deals` no header principal (ao lado de `Reforma Tributaria`), valido em ambos os modos `tabela` e `kanban`. Quando marcado, filtra `filteredDeals` para exibir apenas oportunidades cujo `owner_name === session.userName` (nome do usuario autenticado, obtido via `getSession()?.userName`). Estilo segue o padrao do botao `Reforma Tributaria` mas com cor `sky` (azul) — `border-sky-300/50 bg-sky-500/20` quando ativo e `text-sky-300` no icone `User`. O botao so e renderizado quando ha `sessionUserName` valido. Estado `filterMyDeals: boolean` adicionado, persistido via `useListStatePersistence` (storageKey `crm-deals-list`). Tambem persiste `filterTaxReform` (que antes era resetado a cada visita). Reset de paginacao (`useEffect` que zera `page` ao mudar filtros) atualizado para incluir `filterMyDeals`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals - modo Kanban): controles de ordenacao (`Select` de campo + botao `ArrowUp`/`ArrowDown` de direcao) movidos do header gradiente para uma barra acima do board, alinhados a direita (`ml-auto`). A barra acima do kanban sempre e renderizada (mesmo sem chips minimizados); o lado esquerdo abriga os chips de stages recolhidos e o lado direito os controles de sort. Estilos do `SelectTrigger` e do botao de direcao adaptados de `border-white/20 bg-white/10 text-white` (apropriado para o gradiente do header) para `bg-white/70 hover:bg-white` com cores do `theme` (apropriado para o fundo claro acima do board). A funcionalidade e o conjunto de campos disponiveis (`name`/`amount`/`close_date`/`last_activity_date`/`next_step_date`/`owner_name`/`updated_at`) seguem identicos. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals): toggle de visualizacao `Tabela`/`Kanban` (`LayoutList`/`Columns3`) movido no header principal — antes ficava apos o popover `Estagios`, agora fica imediatamente a direita do campo `Buscar`. O resto da ordem (`Reforma Tributaria`, `Estagios`, controles do kanban como `Pipeline` e botao `Sincronizar`) permaneceu inalterado. Visualmente o usuario vai do filtro mais usado (busca) direto para a alternancia de modo, sem ter que pular sobre filtros opcionais. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals - modo Kanban): popover de filtro por `Estagios` removido do header principal quando `viewMode === 'kanban'` (envolto em `{viewMode !== 'kanban' && (...)}` no JSX). Como o usuario controla a visibilidade das colunas via minimize/maximize do proprio kanban, o filtro era redundante e nao tinha como ser acessado/limpo apos esconder. O `filteredDeals` tambem ignora `filterStageIds` quando em kanban (`if (viewMode !== 'kanban' && filterStageIds.size > 0)`), evitando que filtros aplicados em modo tabela vazassem para o board e mantendo o estado salvo intacto para quando o usuario voltar a tabela. `viewMode` adicionado as deps do `useMemo`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals - modo Kanban): cada coluna de stage agora exibe um botao `Minimize2` no canto superior direito do header. Ao clicar, a coluna e removida do scroll do kanban e seu nome migra para uma barra de chips minimizados acima do board (somente quando ha pelo menos uma coluna recolhida). O chip mostra o icone do stage, nome, contador de deals e total monetario (quando > 0), com um icone `Maximize2` na direita; clicar no chip restaura a coluna a sua posicao original no kanban (a ordem das colunas expandidas continua respeitando `stage_order`). Estado `collapsedKanbanStageIds: Set<string>` adicionado e persistido via `useListStatePersistence` (storageKey `crm-deals-list`, salvo como array, restaurado como Set), portanto o usuario reabre a pagina com as mesmas colunas recolhidas. Toggle helper `toggleCollapsedKanbanStage` adicionado. Estrutura do kanban refatorada para uma IIFE que pre-calcula `orderedKanbanStages`, `collapsedStages` e `expandedStages`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
CorrecaoCRM Deals (/crm/deals/{id} - aba Atividades): meetings com `meeting_status = cancelled` (e tasks com `task_status/status = cancelled` ou `completed`) que ainda nao tinham `completed_at` apareciam na secao `Atrasadas` quando a data da reuniao/tarefa era no passado, em vez de cair em `Concluidas / Canceladas`. O `groupedActivities` so empurrava para `done` quando `a.completed_at` estava setado, ignorando o status real do task/meeting subjacente. Fix: replicado o helper `isActivityDone` do `crm-activities-section.tsx` — agora a classificacao tambem consulta `activityTaskMap`/`activityMeetingMap` e considera `done` quando `task.task_status`/`task.status`/`meeting.meeting_status`/`meeting.status` (lowercase) e `completed` ou `cancelled`. Deps do `useMemo` ampliadas para incluir os mapas. Arquivo: app/(app)/_components/crm-deals-section.tsx.
CorrecaoCRM Activities (/crm/activities): a coluna do icone de vinculo com deal (`Handshake`) na lista de atividades agora e renderizada para todas as linhas, nao apenas para `meeting`. Antes a TableCell era envolta em `{isMeeting && (...)}` em todas as tres variantes de linha (overdue, upcoming, done), o que causava deslocamento visual da ultima coluna (excluir) entre tasks e meetings — tasks ficavam com 6 celulas e meetings com 7, gerando o efeito de coluna ausente nas linhas de task. Fix: TableCell sempre renderizada (mantendo `w-0 px-1`), com o icone `Handshake` exibido somente quando ha deal vinculado. Para atividades sem deal vinculado, a celula fica vazia mas ocupa o espaco, alinhando corretamente as colunas em todas as linhas. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities): atividades do tipo `task` (tarefa) tambem passam a exibir o icone `Handshake` de vinculo com deal na ultima coluna, antes restrito apenas a `meeting`. Adicionado `taskData = isTask ? activityTaskMap.get(aid) : null` em `renderActivityRow`, e nova variavel `linkedDealId = meetingData?.deal_id ?? taskData?.deal_id ?? null` que resolve o deal vinculado de qualquer um dos dois tipos. As tres variantes de linha (overdue, upcoming, done) agora renderizam o icone `Handshake` quando `linkedDealId` esta presente, com a mesma cor amber (`text-amber-500` em overdue/upcoming, `text-amber-400/70` em done). Tipo `CRMTask` ja contem `deal_id?: string` no swagger (`lib/api/crm-tasks.ts`). Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Deals (/crm/deals/{id} - aba Emails): o popover do botao `Enviar Email` agora filtra os modelos pela `vertical_negocio` da oportunidade. Comparacao usa `normalizeText` (lowercase + NFD sem diacriticos) com colapso de espacos em branco para evitar mismatches por acentos, caixa ou espacos extras. Modelos sem `vertical_negocio` (gerais) continuam sendo exibidos para qualquer oportunidade. Quando a oportunidade nao tem vertical preenchida, todos os modelos ativos de DEAL sao listados. A lista de modelos passou a ser recarregada toda vez que o popover e aberto (antes era em cache de uma unica chamada por sessao). Mensagem de empty state especifica quando nenhum modelo corresponde a vertical do deal. Arquivos: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals - CRUD: campo `hubspot_object_id` renomeado para `hubspot_id` em alinhamento com `models.CRMDeal`/`CreateCRMDealPayload`/`UpdateCRMDealPayload` do swagger atualizado. Tipos TS (`CRMDeal.hubspot_id`, payloads de create e update), state local (`formHubspotId`/`setFormHubspotId`), `initialFormValues` (chave `hubspotId`), populate/clear, botoes `Sincronizar com HubSpot` e `Abrir no HubSpot` no header da edicao (`selectedDeal.hubspot_id`) e o `LabeledInput` readonly de `HubSpot ID` na Row 1 do form atualizados. Apenas o modulo de deals foi afetado — companies, contacts e pipeline-stages mantem `hubspot_object_id` no swagger e no codigo. Arquivos: lib/api/crm-deals.ts, lib/api/crm-deals-create.ts, lib/api/crm-deals-update.ts, app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Email Templates (/crm/email-templates/{id}): adicionada a variavel `{{deal_hubspot_id}}` (HubSpot ID) no grupo `Negociacao` da lista de variaveis disponiveis, conforme atualizacao do swagger nas descricoes de `subject_template`/`body_template`/`to_email_template`/`cc_email_template` (Create/Update CRMEmailTemplate) e do payload de render (`RenderCRMEmailTemplatePayload.variables`). Inserida apos `deal_id`. Tambem incluida automaticamente em `VALID_VARIABLE_KEYS` (validacao client-side de variaveis em assunto, corpo, To e CC). Arquivo: app/(app)/_components/crm-email-templates-section.tsx.
MelhoriaAdmin Users (/admin/users/{id}): containers `Permissoes atribuidas` e `Catalogo` deixados mais compactos para acomodar mais itens visiveis sem scroll. Reducoes aplicadas: padding externo do painel (`p-5` -> `p-4`, `gap-3` -> `gap-2.5`), grid das duas colunas (`gap-3` -> `gap-2.5`), headers dos cards (`px-4 py-3` -> `px-3 py-2`, titulo `text-sm` -> `text-xs`, icone `size-4` -> `size-3.5`, badge contador `px-2` -> `px-1.5`), padding interno das listas (`p-3` -> `p-2`), `CollapsibleGroup` (`rounded-xl` -> `rounded-lg`, `px-3 py-2.5` -> `px-2.5 py-1.5`, `px-3 pb-3` -> `px-2 pb-2`, label `text-xs` -> `text-[11px]`, chevron `size-3.5` -> `size-3`), spacing entre subgrupos (`space-y-2` -> `space-y-1.5`, `space-y-1.5` -> `space-y-1`), linhas de permissao (`gap-3 px-3 py-2 rounded-lg` -> `gap-2 px-2 py-1 rounded-md`, icon box `size-7` -> `size-6` com icone `size-3.5` -> `size-3`, nome `text-sm` -> `text-xs leading-tight`, codigo com `leading-tight`), `TypeToggle` (`h-7` -> `h-6`, `rounded-lg` -> `rounded-md`, `px-2 text-[11px]` -> `px-1.5 text-[10px]`, icone `size-3` -> `size-2.5`), botoes Read/Write/Admin do catalogo seguem o mesmo padrao reduzido, e empty state com `py-10` -> `py-6`. Arquivo: app/(app)/_components/auth-user-permissions-panel.tsx.
NovidadeAdmin Permissions (/admin/permissions): tabela agora e agrupada por servico. Permissoes sao agregadas pelo `service_id` (com `getServiceName` resolvendo o label) em grupos cujo cabecalho e uma `TableRow` com `colSpan=6`, fundo gradiente rose, avatar do servico, nome em destaque e badge com contador de permissoes. Cada cabecalho e clicavel e alterna `chevron right`/`chevron down` para colapsar/expandir o grupo (state local `collapsedGroups: Set<string>`). Permissoes sem servico vinculado sao agrupadas em `Sem servico` (italico/slate) e sempre listadas por ultimo. A ordenacao dos grupos respeita `sortDir` quando `sortKey === 'service'` (alfabetica asc por padrao em pt-BR). Dentro de cada grupo, as linhas mantem o sort original e ganham `pl-8` na coluna Nome para indentacao visual. O selectAll/seleccao em massa passa a considerar apenas permissoes de grupos expandidos (`selectableIds` filtra por `collapsedGroups`), evitando selecionar itens nao visiveis. Filtro por busca e demais comportamentos (multi-delete, click na linha, hover, paginacao) preservados. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
NovidadeAdmin Permissions (/admin/permissions): avatar do servico no cabecalho de grupo agora exibe o `icon` cadastrado no servico (emoji em `AdminService.icon`) ocupando todo o espaco do avatar. O servico do grupo e resolvido via `servicesById.get(group.serviceId)` e, quando ha icone, e renderizado como `<span class='text-2xl leading-none'>{groupIcon}</span>` em um container `size-8` sem fundo/sombra (deixa o proprio emoji ser o avatar). Quando o servico nao tem icone, mantem o fallback com fundo gradiente teal/cyan e icone `Layers`. Para o grupo `Sem servico`, mantem o avatar slate com `Layers`. As linhas de permission dentro de cada grupo tambem passam a usar o `groupIcon` (mesmo emoji) no avatar `size-8` da coluna Nome, com fallback para o icone `Shield` em gradiente rose quando o servico nao tem icone. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
MelhoriaAdmin Permissions (/admin/permissions): coluna `Servico` removida da tabela (a informacao ja e redundante com o agrupamento por servico nos cabecalhos) e substituida por uma nova coluna `Atualizado em` (alinhada na ultima posicao com `pr-4`, exibindo `formatRelativeTime(perm.updated_at)`). Tipo `SortKey` atualizado de `'name' | 'code' | 'service' | 'notes' | 'created_at'` para `'name' | 'code' | 'notes' | 'created_at' | 'updated_at'`, com nova case no switch de ordenacao. A ordenacao do grupo agora e sempre alfabetica em pt-BR (sortKey/sortDir nao influenciam mais a ordem dos grupos, ja que nao ha mais coluna de servico para clicar). Arquivo: app/(app)/_components/auth-permissions-section.tsx.
MelhoriaAdmin Permissions (/admin/permissions): celulas `Criado em` e `Atualizado em` agora exibem icone `Clock` (`size-3 text-slate-400`) a esquerda e usam `formatRelativeTimeLong` em vez de `formatRelativeTime`, mostrando o tempo relativo por extenso (ex.: `ha 1 semana`, `ha 2 horas`, `ha 3 dias`) em vez das abreviacoes (`1sem`, `2h`, `3d`). Layout em `<span class='inline-flex items-center gap-1.5'>` para alinhar icone e texto. Quando o timestamp e nulo, mantem o tracinho `—`. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
NovidadeAuth Permissions: CRUD atualizado conforme swagger para incluir o novo campo `group_id` (vinculo com grupo de permissoes) e `service_icon` (emoji do servico, retornado pela API). Tipo `AuthPermission` ganhou `group_id?` e `service_icon?`; `CreateAuthPermissionPayload` e `UpdateAuthPermissionPayload` ganharam `group_id?`; `FetchAuthPermissionsParams` ganhou `group_id?`. No componente `auth-permissions-section`, adicionado state local `formGroupId`/`setFormGroupId`, populate/clear inclui `group_id`, `initialFormValues` ganhou chave `group_id`, change tracking compara `formGroupId` vs init, payloads de create/update enviam `group_id` (com partial save no edit). Adicionado `FloatingSelect` `Grupo` (icone `FolderTree` violet) ao lado do `Servico` em um grid de 2 colunas; opcoes carregadas de `/admin/permission-groups` e filtradas pelo `service_id` selecionado (usando o servico do form como filtro client-side). Quando o servico muda, se o grupo selecionado nao pertence ao novo servico, e auto-resetado. O avatar de grupo no header da tabela (modo lista) agora prefere `permission.service_icon` retornado pela API, com fallback para `service.icon` resolvido via `servicesById`. Arquivos: lib/api/auth-permissions.ts, lib/api/admin-permission-groups.ts (novo), app/(app)/_components/auth-permissions-section.tsx.
NovidadeAdmin Permissions (/admin/permissions/{id}): apos um salvar bem-sucedido (criacao ou atualizacao), a tela de edicao agora fecha automaticamente e redireciona para a lista (`/admin/permissions`). Antes, em modo edit a tela permanecia aberta apos salvar e em modo new redirecionava para `/admin/permissions/{id-criado}`; agora ambos os modos retornam para a lista. Implementado em `handleUpdate` da screen wrapper, que e chamado pelo `auth-permissions-section` apenas quando a chamada da API e bem-sucedida (dentro do try). Toast de confirmacao continua sendo exibido por ser global. Arquivo: app/(app)/features/auth/permissions/auth-permissions-screen.tsx.
MelhoriaAdmin Permissions (/admin/permissions): coluna `Notas` substituida pela coluna `Grupo` (group_name). Tipo `AuthPermission` ganhou `group_name?` (campo retornado pela API conforme swagger). A celula renderiza um pill violet com icone `FolderTree` quando ha grupo associado e `—` quando vazio. `SortKey` atualizado de `'notes'` para `'group'` no tipo, com a case correspondente comparando `a.group_name` vs `b.group_name`. Filtro de busca passou a considerar tambem `group_name`. Arquivos: lib/api/auth-permissions.ts, app/(app)/_components/auth-permissions-section.tsx.
MelhoriaTop bar: removido o breadcrumb de navegacao (`Admin > Permissoes`, etc) que era exibido ao lado dos pills de modulo. Removidos: constante `ROUTE_LABELS` (~40 entradas), funcao `buildBreadcrumb`, `useMemo` `breadcrumb`, bloco JSX que renderizava os crumbs com `ChevronRight`, e import nao usado de `ChevronRight` do lucide-react. O `pathname` continua sendo usado para destacar quick links ativos. Arquivo: app/(app)/_components/top-bar.tsx.
NovidadeAdmin Permissions (/admin/permissions): agrupamento da tabela passou a ter dois niveis hierarquicos — primeiro por `service` (cabecalho rose com avatar do servico/emoji) e dentro de cada servico por `group` (cabecalho violet com icone `FolderTree`). Estrutura `groupedPermissions` reescrita como `ServiceGroup[]` contendo `subgroups: SubGroup[]`, cada subgroup com `key` composta `${serviceKey}:${groupKey}` para permitir collapse independente. Cabecalho de servico mostra `totalCount` (soma das permissoes de todos os subgroups). Cabecalho de grupo (`pl-10`, fundo violet sutil, chevron e icone menores) mostra contador local. Permissoes ganham indentacao adicional (`pl-14` na coluna Nome). Servicos sem icon caem para `Layers` em gradiente teal/cyan; grupo sem `group_id` aparece como `Sem grupo` (italico/slate) sempre por ultimo dentro do servico; servico `Sem servico` segue por ultimo. Collapse funciona em ambos os niveis: clicar em um servico colapsa todo o conteudo; clicar em um grupo colapsa apenas aquele subgroup. `selectableIds` agora considera apenas permissoes de servicos e grupos expandidos. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
MelhoriaAdmin Permissions (/admin/permissions): coluna `Grupo` substituida de volta por `Notas` na tabela ja que o group_name agora aparece no cabecalho de subgroup hierarquico (a coluna era redundante). `SortKey` voltou a usar `'notes'` em vez de `'group'`, com a case correspondente comparando `a.notes` vs `b.notes`. A celula renderiza o trecho de notas com truncate em 50 chars (mesmo formato anterior). Arquivo: app/(app)/_components/auth-permissions-section.tsx.
MelhoriaAdmin Permissions (/admin/permissions): linhas de permission compactadas para reduzir altura vertical e mostrar mais itens sem scroll. Reducoes aplicadas: padding vertical das celulas `py-2.5` -> `py-1`, checkbox `size-[18px] rounded-[5px]` -> `size-[16px] rounded-[4px]` com check svg `size-2.5` -> `size-2`, avatar `size-8` -> `size-6` (emoji `text-2xl` -> `text-lg`, fallback `Shield size-3.5` -> `size-3`), gap entre avatar e nome `gap-2.5` -> `gap-2`, nome `text-sm font-semibold` -> `text-xs font-semibold`, code pill `px-2 text-xs` -> `px-1.5 text-[11px]`, notas `text-sm` -> `text-xs`, datas (`Criado em`/`Atualizado em`) `text-xs gap-1.5` -> `text-[11px] gap-1` e icone `Clock size-3` -> `size-2.5`. Cabecalhos de servico/grupo e demais comportamentos preservados. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
NovidadeAdmin Permissions (/admin/permissions/new): campos `Nome`, `Codigo`, `Servico` e `Grupo` agora sao obrigatorios na criacao de uma permission. Labels exibem o sufixo `*` para indicar a obrigatoriedade. `hasFormChanges` em modo create retorna `true` somente quando os 4 campos estao preenchidos (`!!formName.trim() && !!formCode.trim() && !!formServiceId && !!formGroupId`), portanto o botao Salvar so habilita quando o form esta valido. `handleSave` ainda valida defensivamente: se `isCreating` e servico/grupo estao vazios, exibe toast de erro `Campos obrigatorios — Preencha Nome, Codigo, Servico e Grupo` e aborta o submit. Em modo edit a obrigatoriedade nao e aplicada (campos podem ser limpos via `Sem servico`/`Sem grupo`), conforme swagger que so marca `code` e `name` como required no payload de update. Arquivo: app/(app)/_components/auth-permissions-section.tsx.
NovidadeAdmin Users (/admin/users/{id} - aba Permissoes): permissoes do painel agora sao agrupadas em 2 niveis hierarquicos — primeiro por servico (cabecalho rose) e dentro de cada servico por grupo (cabecalho violet com icone `FolderTree`). Ajustes em `auth-users-section.tsx`: `createPermissionViewItem` passou a setar `subgroupLabel: permission.group_name?.trim() || null` em vez de sempre `null`, alimentando a infraestrutura de subgroups ja existente em `groupPermissionItems`/`PermissionGroupSection`. `buildPermissionSearchText` agora inclui `permission.group_name` no texto de busca. Sort dos servicos agora empurra `Sem servico` para o final; sort dos subgroups dentro de cada servico empurra subgroup sem label (permissoes sem `group_id`) para o final. No `auth-user-permissions-panel.tsx`, o cabecalho de subgroup foi enriquecido visualmente: agora exibe icone `FolderTree size-3` em violet ao lado do label uppercase (antes era apenas texto). Aplica-se tanto ao container `Permissoes atribuidas` quanto ao `Catalogo`. Arquivos: app/(app)/_components/auth-users-section.tsx, app/(app)/_components/auth-user-permissions-panel.tsx.
NovidadeAdmin Users (/admin/users/{id} - aba Permissoes): subgroups (groups dentro de service) agora podem ser recolhidos/expandidos individualmente, assim como ja era possivel para o nivel servico. Adicionado novo componente `CollapsibleSubgroup` no `auth-user-permissions-panel.tsx` (state local `useState(defaultOpen)`, chevron `ChevronDown`/`ChevronRight size-2.5` em violet, icone `FolderTree size-3`, label `text-[10px] font-semibold uppercase` em violet) com hover sutil violet. Renderizacao do subgroup foi ajustada em ambos os containers: subgroups com label (`group_name` presente) sao envoltos em `CollapsibleSubgroup`; subgroups sem label (permissoes sem `group_id`) sao renderizados diretamente sem header. Em `Permissoes atribuidas`, subgroups iniciam abertos (`defaultOpen=true`); no `Catalogo` iniciam fechados (`defaultOpen=false`) para alinhar com o comportamento ja existente do nivel servico. Arquivo: app/(app)/_components/auth-user-permissions-panel.tsx.
MelhoriaAdmin Users (/admin/users/{id}): abas (`Detalhes`, `Roles`, `Permissions`, `Tenants`) movidas do header gradiente horizontal para uma sidebar vertical a esquerda do form. Header gradiente teve o `pb-0` substituido por `pb-4` ja que nao acomoda mais as abas. Form body alterou de `flex flex-col` para `flex flex-row`: a esquerda, `<nav className='w-44 ... border-r border-rose-100 bg-rose-50/40'>` lista os tabs como botoes verticais (icone esquerda + label + badge contador a direita); a direita, `<div className='flex flex-1 min-h-0 flex-col'>` abriga os panels de cada tab. Aba ativa exibe fundo branco, texto rose e barra vertical gradiente rose/pink na borda esquerda interna; tabs desabilitadas (Roles/Permissions quando `formIsAdmin`) ficam com `cursor-not-allowed` e `text-slate-300` e mantem o titulo explicativo. Sidebar nao e renderizada em modo `isCreating`. Arquivo: app/(app)/_components/auth-users-section.tsx.
MelhoriaAdmin Users (/admin/users/{id} - aba Detalhes): largura dos campos do form aumentada. Grid alterado de `grid-cols-[280px_1fr_200px]` para `grid-cols-[260px_1fr]` (removida a coluna direita de 200px que continha apenas um `<div />` vazio, e a coluna do avatar reduzida levemente de 280px para 260px). Os FloatingInputs (Nome Completo, Email, Senha, Timezone, Ultimo Login) agora ocupam todo o espaco restante apos o avatar, ficando significativamente mais largos para acomodar valores como emails e timezones longos sem truncar. Arquivo: app/(app)/_components/auth-users-section.tsx.
MelhoriaAdmin Users (/admin/users/{id} - aba Permissions): tipo de permissao em `Permissoes atribuidas` substituido de `TypeToggle` (3 botoes lado-a-lado) para `TypeSelect` (Select dropdown shadcn) por linha. O trigger do select usa cor por tipo (sky/amber/emerald), exibe icone (`Eye`/`Pencil`/`Crown`) + label (`Read`/`Write`/`Admin`) e altura `h-7 w-[110px]`. Cada item do menu mostra icone na cor correspondente. Comportamento de troca preservado: `onChange` chama `onUpdatePermission(permission.id, type)`. Funcao `TypeToggle` removida do arquivo e suas constantes `typeButtonActive`/`typeButtonHover` (nao usadas em outros lugares) tambem foram removidas. Arquivo: app/(app)/_components/auth-user-permissions-panel.tsx.
CorrecaoCRM Deals (/crm/deals/{id}): corrigido bug em que clicar `Voltar` exibia o dialogo `Descartar alteracoes` mesmo sem alteracoes no form, e clicar `Salvar` retornava erro `Nenhum campo para atualizar`. Causa: `hasFormChanges` checava `formStatusComission !== iv.statusComission` incondicionalmente, mas o `changedPayload` em `handleSave` so inclui esse campo quando `showStatusComissionField` (estagio com `is_won`) e true. Quando o estagio nao era `is_won` mas o `formStatusComission` divergia do inicial por algum motivo (ex.: pipeline/stage troca, deal recarregado, hidrataao apos fetch), `hasFormChanges` ficava `true` e abria o dialogo, mas o payload saia vazio e a API rejeitava. Fix: aplicar o mesmo gating `showStatusComissionField &&` na comparacao de `formStatusComission` em `hasFormChanges`, e adicionar `showStatusComissionField` ao deps do `useMemo`. Arquivo: app/(app)/_components/crm-deals-section.tsx.

06 de Maio de 2026

6 itens
411
NovidadeFin Partners (/fin/partners/{id}): novo botao `Pagar PIX` ao lado do campo `Chave PIX` (ativo apenas quando ha valor preenchido). Abre dialog com QR Code BR Code estatico (PIX Copia e Cola) gerado client-side a partir de `partner.chave_pix` + `partner.name` (sanitizado, max 25 chars) + cidade `BRASIL`. Padrao EMVCo TLV completo (PIX `BR.GOV.BCB.PIX`, MCC `0000`, BRL `986`, txid `***`) com CRC16-CCITT. Dialog mostra nome do beneficiario, tipo da chave detectado (CPF/CNPJ/Email/Telefone/Aleatoria), QR Code (224px, level M) e textarea com codigo `Copia e Cola` + botao copiar. Sem valor pre-preenchido — o usuario informa o valor no app do banco. Adicionado: `lib/pix-brcode.ts` (`buildPixBrCode`, `detectPixKeyType`), `app/(app)/_components/pix-qr-dialog.tsx`, dependencia `qrcode.react@4.2.0`. Arquivos: lib/pix-brcode.ts (novo), app/(app)/_components/pix-qr-dialog.tsx (novo), app/(app)/_components/fin-partners-section.tsx, package.json.
NovidadeTop Bar - sino de notificacoes: refeito para consumir o novo endpoint `GET /fin/notifications` (`models.FinNotificationsResponse`) em vez de `GET /fin/transactions?is_paid=false&date_type=due_date&start_date=<hoje-90d>&end_date=<hoje>` (request pesado executado em todas as paginas autenticadas). Apenas items com `severity == "high"` sao exibidos no sino — items `medium` e `low` retornados pela API sao filtrados client-side. Os items `high` sao agrupados em tres secoes (`Vencidas` em vermelho, `Vencem hoje` em ambar, `Proximos vencimentos` em cinza) com base em `target_date` vs hoje. Cada linha exibe `title`/`partner_name`, data formatada `DD/MM/YYYY`, `account_name` e `amount` colorido (verde para entradas, vermelho para saidas). Click em um item navega para o `route` retornado (ex: `/fin/transactions/<entity_id>`). Painel ampliado de `w-72` para `w-96` com scroll interno (`max-h-[420px]`). Adicionado `lib/api/fin-notifications.ts` com types `FinNotificationItem`/`FinNotificationSummary`/`FinNotificationsResponse` e funcao `fetchFinNotifications({ days_ahead?, limit? })`. Arquivos: lib/api/fin-notifications.ts (novo), app/(app)/_components/top-bar.tsx.
MelhoriaFluxo de Caixa (/fin/fluxo-caixa): removido workaround `displayedAccountsBalance` que adicionava manualmente as contas `INVESTMENT` no painel `Saldos por Conta`. O endpoint `/fin/fluxo-caixa` agora retorna os saldos das contas de investimento direto em `accounts_balance`, entao a UI passa a usar esse array sem combinacao adicional com a lista de `accounts`. Arquivo: app/(app)/features/fin/fluxo-caixa/fluxo-caixa-screen.tsx.
NovidadeCRM Email Templates (/crm/email-templates/{id}): adicionada a variavel `{{company_short_name}}` (Nome curto) no grupo `Empresa` da lista de variaveis disponiveis. Utiliza o campo `short_name` da empresa quando resolvido pelo backend. Incluida tambem em `VALID_VARIABLE_KEYS` (validacao client-side de variaveis usadas em assunto, corpo, To e CC). Arquivo: app/(app)/_components/crm-email-templates-section.tsx.
NovidadeCRM Email Templates: novo campo `vertical_negocio` (string livre) adicionado ao CRUD conforme `models.CRMEmailTemplate`/`CreateCRMEmailTemplatePayload`/`UpdateCRMEmailTemplatePayload` do swagger. Adicionados: types em `lib/api/crm-email-templates.ts` (no objeto principal e no payload de criacao); state `formVerticalNegocio` com populate em `populateForm`/`clearForm`/`initialFormValues`; comparacao em `hasFormChanges`; envio em create (`vertical_negocio: trim() || undefined`) e update partial (envia string vazia quando o usuario limpa o valor para a API remover); FloatingInput `Vertical de Negocio` com icone `Briefcase` (teal-500) na coluna esquerda do form, posicionado entre `Contexto+Ordem` e `Destinatario`; busca textual da lista incluindo `vertical_negocio`; badge teal com icone `Briefcase` (size-2.5) ao lado do nome do template na tabela quando o campo esta preenchido. Arquivos: lib/api/crm-email-templates.ts, app/(app)/_components/crm-email-templates-section.tsx.
CorrecaoCRM Dashboard (/crm/dashboard - grafico Pipeline de Vendas): stage de `Perdido` (qualquer stage com `is_closed=true` e `is_won=false`) deixou de ser exibido no funnel. A barra horizontal e a tabela `pipelineRows` agora ignoram stages de fechamento perdido — apenas stages abertos e o(s) stage(s) ganhos sao exibidos. A ordenacao por `stage_order` e o restante dos calculos (count, amount) permanecem inalterados. Arquivo: app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.

05 de Maio de 2026

17 itens
647
CorrecaoCRM Dashboard (/crm/dashboard): modal `Recebiveis - {mes/ano}` (drill-down do grafico Comissao Mes a Mes) tinha colgroup com 8 `<col>` para uma tabela de 7 colunas, com larguras desbalanceadas (`Valor Bruto` e `Comissao (R$)` em apenas 7%, causando quebra de linha em valores como `R$ 66.582,94`). Corrigido removendo a coluna fantasma e redistribuindo: Deal 30% | Valor Bruto 14% | % 7% | Comissao (R$) 14% | Pagamento 14% | Comissao 14% | Icon 7%. Arquivo: app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.
NovidadeCRM Comissoes (/crm/commissions): tabela de Recebiveis exibe `PEP: {valor}` como tooltip nativo (atributo `title`) ao passar o mouse sobre uma linha. Quando `receivable.pep` esta vazio, o `title` e `undefined` (nenhum tooltip). Arquivo: app/(app)/_components/crm-commissions-section.tsx.
MelhoriaCRM Deal Item Receivables (/crm/deal-item-receivables/{id}): campo PEP movido da Row 1 (Documentos: Doc. Faturamento, Referencia, Doc. Venda, Item Doc. Venda) para a Row 6 (Status), posicionado a esquerda do Select `Status`. Row 1 voltou ao grid de 4 colunas. Row 6 agora e PEP (w-64) | Status (w-44) | Status Comissao (w-48) | Atualizado na Origem (w-56) — larguras dos selects reduzidas (antes ambos w-64) ja que as opcoes (`Pendente`/`Parcial`/`Pago`/`Isento`) sao curtas; PEP aumentado para w-64 e `Atualizado na Origem` reduzido de `flex-1` para w-56. Icone `Tag` teal no PEP mantido. Arquivo: app/(app)/_components/crm-deal-item-receivables-section.tsx.
NovidadeCRM Deal Items (/crm/deal-items/{id} - aba Receitas): novo botao `+ Novo` no header (glass style, icone `Plus`) navega para `/crm/deal-item-receivables/new?deal_item_id={id}&return_to={pathname}?tab=receivables`. O `deal_item_id` ja vinha sendo lido pelo screen do new (via searchParams) e usado tanto em `initialDealItemId` (que popula `deal_item_id` no payload de criacao) quanto no autocomplete de Item, entao apos clicar em Salvar o usuario e devolvido a aba Receitas com o novo recebivel ja vinculado. Visivel apenas quando `selectedItem?.id` esta presente e a aba ativa e `receivables`. Posicionado a esquerda do botao `Sincronizar Receitas`. Arquivo: app/(app)/_components/crm-deal-items-section.tsx.
MelhoriaCRM Comissoes (/crm/commissions): filtro de mes/ano no header migrou de `<input type="month">` (formato nativo `YYYY-MM` com seletor do navegador) para o mesmo padrao de digitacao livre `MM/AAAA` usado em /fin/balancete. Helpers locais `monthValueToDisplay`, `maskMonthInput` e `parseMonthInput` (essa retornando `YYYY-MM` para preservar a comparacao via `startsWith` ja existente). Mascara progressiva insere `/` apos os 2 digitos do mes; commit em onBlur ou Enter; Escape descarta e reverte. State adicional `commissionMonthDraft` sincronizado via `useEffect` com `commissionMonthFilter` para refletir filtros restaurados do sessionStorage. Mantido o icone `CalendarRange` e botao de limpar (XCircle). Arquivo: app/(app)/_components/crm-commissions-section.tsx.
MelhoriaCRM Comissoes (/crm/commissions): tabela de Recebiveis agora limita o render a 50 registros (`sortedReceivables.slice(0, 50)`) para evitar listas longas que prejudicam o desempenho do scroll. A ordenacao continua aplicada antes do corte, entao os 50 primeiros sao sempre os mais relevantes conforme o `recSortKey`/`recSortDir` ativos. Arquivo: app/(app)/_components/crm-commissions-section.tsx.
NovidadeCRM Deal Item Receivables: campo `pep` adicionado ao CRUD (presente em `models.CRMDealItemReceivable`, `models.CreateCRMDealItemReceivablePayload` e `models.UpdateCRMDealItemReceivablePayload`). Adicionados: `pep?: string` nos types, novo `FloatingInput` com label `PEP` e icone `Tag` (teal-500 em /crm/deal-item-receivables/{id}, violet-500 ao lado de `Referência` em /crm/deals/{id}#receivables), populate em populateForm/openEditReceivable, comparacao em hasChanges e dependencias do useMemo, payload em create e partial update, busca textual incluindo `pep`, e nova coluna `PEP` na exportacao Excel da listagem. Arquivos: lib/api/crm-deal-item-receivables.ts, lib/api/crm-deal-item-receivables-create.ts, lib/api/crm-deal-item-receivables-update.ts, app/(app)/_components/crm-deal-item-receivables-section.tsx, app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deal Item Receivables: campo `installment_number` removido do CRUD por nao existir mais nos modelos do swagger (`models.CRMDealItemReceivable`, `models.CreateCRMDealItemReceivablePayload`, `models.UpdateCRMDealItemReceivablePayload`). Removidos: types (`installment_number` em `CRMDealItemReceivable`/`CreateCRMDealItemReceivablePayload`/`UpdateCRMDealItemReceivablePayload`), state `installmentNumber`/`recFormInstallmentNumber`, populate em openEdit/openEditReceivable, comparacao em hasReceivableFormChanges/hasItemFormChanges, payload em create e partial update, FloatingInput `Parcela`/`Nº Parcela`, colunas `Parcela`/`#` em listas (CRM dashboard, comissoes, deal items receivables, deal receivables), opcao `installment_number` em ReceivableSortKey/RecSortKey/SortKey (sort default ajustado para `due_date`), e referencia em `itemName` do ConfirmDelete. Arquivos: lib/api/crm-deal-item-receivables.ts, lib/api/crm-deal-item-receivables-create.ts, lib/api/crm-deal-item-receivables-update.ts, app/(app)/_components/crm-deal-item-receivables-section.tsx, app/(app)/_components/crm-commissions-section.tsx, app/(app)/_components/crm-deals-section.tsx, app/(app)/_components/crm-deal-items-section.tsx, app/(app)/features/crm/dashboard/crm-dashboard-screen.tsx.
MelhoriaCRM Deal Items: campo `number_of_payments` removido do CRUD por nao existir mais nos modelos do swagger (`models.CRMDealItem`, `models.CreateCRMDealItemPayload`, `models.UpdateCRMDealItemPayload`). Removidos: state e setter `formNumberOfPayments`/`itemFormNumberOfPayments`, populate em openEdit/openEditItem e initialFormValues, comparacao em hasFormChanges/hasItemFormChanges, payload em create e partial update, input `Parcelas`/`Nº Parcelas` no JSON, helper `parseInt2` (so usado por esse campo), e a propriedade `number_of_payments` dos types `CRMDealItem`, `CreateCRMDealItemPayload`, `UpdateCRMDealItemPayload`. Arquivos: lib/api/crm-deal-items.ts, lib/api/crm-deal-items-create.ts, lib/api/crm-deal-items-update.ts, app/(app)/_components/crm-deal-items-section.tsx, app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals - kanban): `next_step_date` agora e exibido como data relativa (`em 5 minutos`, `ha 2 dias`) com icone `Clock` (size-3) a esquerda do texto. Usa o novo helper `formatRelativeTimeLongBidirectional` em `lib/date-helpers.ts` que retorna texto completo em pt-BR com prefixo `em` (futuro) ou `ha` (passado), alem de `agora` quando a diferenca e < 60s. Usa singular/plural correto (`minuto`/`minutos`, `hora`/`horas`, `dia`/`dias`, `semana`/`semanas`, `mes`/`meses`, `ano`/`anos`). A data absoluta passou a ficar como `title` (tooltip) na span. Cor vermelha (overdue) e mantida quando a data e anterior a hoje. Arquivos: lib/date-helpers.ts, app/(app)/_components/crm-deals-section.tsx.
NovidadeCRM Deals (/crm/deals - kanban): cards reorganizados em 3 linhas. Linha 1 (sem mudanca): logo do dominio + nome. Linha 2: `amount` (esquerda, emerald) + `close_date` (direita, slate-400 — antes ficava na linha do owner). Linha 3: `owner_name` (esquerda) + `last_activity` (icone) + `last_activity_date` (direita, novos — antes nao eram exibidos). Linha 4 (conditional): `next_step` + `next_step_date` (sem mudanca). Para suportar a nova data, o tipo `CRMDeal` em `lib/api/crm-deals.ts` ganhou os campos `last_activity?: string` (enum email/task/meeting) e `last_activity_date?: FlexibleTime` (refletindo `models.CRMDeal` do swagger). Icone do `last_activity` mapeado para `Mail` (email), `ClipboardList` (task) ou `Calendar` (meeting), com `aria-label` traduzido (Email/Tarefa/Reuniao). Formatacao usa `extractFlexibleTime` + `toLocaleDateString("pt-BR")`. Arquivos: lib/api/crm-deals.ts, app/(app)/_components/crm-deals-section.tsx.
MelhoriaFin Balancete (/fin/balancete): filtro de mes/ano no header deixou de ser um Select com lista fixa (12 meses anteriores) e passou a ser um campo de digitacao livre `MM/AAAA`. Mascara progressiva (so digitos, insercao automatica de `/` apos os 2 digitos do mes, max 7 chars) aplicada via novo helper `maskMonthInput`. Validacao via `parseMonthInput` (`mm` entre 1-12 e `yyyy` >= 2000) — commit acontece em onBlur ou Enter; Escape descarta e reverte. Helper `monthValueToDisplay` converte `MM-YYYY` interno para `MM/YYYY` exibido. Estilo glass mantido (h-8, w-130px, border-white/20, bg-white/10) com icone `Calendar` a esquerda. Removidos `getMonthOptions` e `monthOptions` memo. Arquivo: app/(app)/features/fin/balancete/balancete-screen.tsx.
NovidadeFin Partners (/fin/partners/{id}): adicionada opcao de remover o logo do parceiro. Quando `logo_url` esta preenchido, um botao circular vermelho com icone `X` (size-5, bg-red-500, border-2 white) aparece no canto superior-direito do avatar, complementando o botao `Pencil` (alterar) que continua no canto inferior-direito. Click abre `ConfirmDeleteDialog` (`Deseja excluir o logo de NOME?`); confirmacao chama `DELETE /fin/partners/{id}/logo` (novo helper `deleteFinPartnerLogo` em `lib/api/fin-partners.ts`), atualiza o partner local com `logo_url: ''`, propaga via `onUpdate` e dispara toast `Logo removido`. Durante a remocao o icone vira `Loader2` e ambos os botoes sao desabilitados. Arquivos: lib/api/fin-partners.ts, app/(app)/_components/fin-partners-section.tsx.
MelhoriaFin Partners (/fin/partners - lista): campo de busca passou a pesquisar apenas em `name` do parceiro e nos `aliases` cadastrados (cada parceiro pode ter varios). Removidos do haystack: `document` (CPF/CNPJ), `email` e `phone`. Para suportar a busca por alias, todos os aliases sao carregados na montagem da lista via `fetchFinPartnerAliases()` (sem filtro) e indexados em um Map `partner_id -> aliases[]` (memoized). O filtro casa o termo normalizado contra o nome do parceiro OU contra qualquer um de seus aliases. Filtro categoria/conta/status preservados. Arquivo: app/(app)/_components/fin-partners-section.tsx.
CorrecaoFin Partners (/fin/partners/{id}): ao limpar o campo `Conta` e salvar, o PUT agora envia `account_id: null` para que a API remova o vinculo. Antes, quando o usuario apagava o valor, o payload caia em `formAccountId || undefined` — e como `undefined` faz o JSON.stringify omitir a chave, o backend nunca recebia o sinal de limpar. Mantida a logica de partial save (so envia se o valor mudou em relacao ao `initialFormValues`). Arquivo: app/(app)/_components/fin-partners-section.tsx.
CorrecaoFin Transactions (campo `Parceiro` em /fin/transactions/new e /fin/transactions/{id}): quando o parceiro selecionado nao tinha nem `domain` nem `logo_url`, o avatar fallback (botao circular size-7 com icone `Users`) era renderizado sobre o label e o valor do input — o padding `pl-11` e o offset `[&_label]:!left-11` so eram aplicados quando havia logo. Agora os offsets sao aplicados sempre que ha um parceiro selecionado, ja que o botao do avatar tem o mesmo tamanho independentemente do conteudo. Arquivo: app/(app)/_components/fin-partner-autocomplete.tsx.
CorrecaoFin Transactions (/fin/transactions/new e /fin/transactions/{id}): removidas as regras de `tabIndex={-1}` que faziam o foco pular determinados campos durante a navegacao por Tab. Antes, os campos `Categoria` e `Conta` eram pulados quando preenchidos automaticamente (autoFilled) em modo de criacao; os campos `Venc. Original`, `Vencimento` e `Pago em` eram pulados quando a conta selecionada era do tipo cartao de credito; e o `Valor Final` (readonly) tinha tabIndex fixo em -1. Agora a navegacao segue a ordem natural de tabIndex em todos os campos. Arquivo: app/(app)/_components/fin-transaction-form.tsx.

30 de Abril de 2026

78 itens
24549
NovidadeFin Fluxo de Caixa (/fin/fluxo-caixa): bloco `Saldos por conta` agora exibe tambem contas do tipo `INVESTMENT`. Antes, mostrava apenas o que o endpoint `/fin/fluxo-caixa` retornava em `accounts_balance` (que filtra para CHECKING). Adicionado merge no frontend: contas INVESTMENT vindas de `fetchFinAccounts` (que ja era carregada para outros usos) sao acrescentadas a lista, com `balance` proveniente do proprio FinAccount. Dedupe por `id` para nao duplicar caso a API um dia inclua. Arquivo: app/(app)/features/fin/fluxo-caixa/fluxo-caixa-screen.tsx.
CorrecaoFin Balancete (/fin/balancete): ao expandir os lancamentos de uma conta/categoria em um mes, a ordenacao mudou de `amount ASC` para `transaction_date ASC` (mais natural cronologicamente). Usa `extractFlexibleTime` + `localeCompare` para ordenar as datas em formato ISO. Arquivo: app/(app)/features/fin/balancete/balancete-screen.tsx.
NovidadeFin Fluxo de Caixa (/fin/fluxo-caixa): avatar do parceiro nas linhas de transacao agora exibe `logo_url` como fallback quando o partner nao tem `domain`. Adicionado `partnersMap` (lookup por `tx.partner_id`) — o `partners` ja era fetched no componente. Prioridade: `tx.partner_domain` (favicon Google, com onError fallback ja existente) → `partner.logo_url` → `Building2`. Arquivo: app/(app)/features/fin/fluxo-caixa/fluxo-caixa-screen.tsx.
NovidadeFin Recurrences (/fin/recurrences): coluna `Parceiro` agora exibe `logo_url` como fallback quando o partner nao tem `domain`. O componente ja tinha acesso ao FinPartner completo via `partnersMap.get(rec.partner_id)`. Mesma prioridade unificada (domain → logo_url → icone). Arquivo: app/(app)/_components/fin-recurrences-section.tsx.
NovidadeFin Partners: fallback `logo_url` aplicado em todos os locais que renderizam o avatar diretamente a partir de objetos `FinPartner` (com acesso a `partner.logo_url`). Prioridade unificada: `partner.domain` (favicon Google) → `partner.logo_url` (imagem propria) → icone padrao. Locais atualizados: lista (tabela e cards) e header do form em `fin-partners-section.tsx`, header do form de transacao em `fin-transaction-form.tsx`, tabela de transacoes em `fin-transactions-table.tsx`, filtros ativos em `fin-transactions-active-filters.tsx`, extrato bancario (coluna Parceiro) em `extrato-bancario-screen.tsx`, e autocomplete `fin-partner-autocomplete.tsx` (icone do selecionado + cada item do dropdown + classes condicionais `[&_label]:!left-11` e `pl-11`). Nao aplicado em locais que so tem `partner_domain` denormalizado (accounts/transactions/groups/recurrences) — esses dependeriam de `partner_logo_url` no swagger atual, que ainda nao existe. Arquivos: app/(app)/_components/fin-partners-section.tsx, app/(app)/_components/fin-partner-autocomplete.tsx, app/(app)/_components/fin-transaction-form.tsx, app/(app)/_components/fin-transactions-table.tsx, app/(app)/_components/fin-transactions-active-filters.tsx, app/(app)/features/fin/extrato-bancario/extrato-bancario-screen.tsx.
NovidadeFin Partners (/fin/partners): listagem (tabela e cards) agora exibe `logo_url` como fallback quando o partner nao tem `domain` cadastrado. Prioridade de exibicao do avatar: domain favicon → logo_url → icone `User` padrao. Aplicado tanto na visualizacao em tabela quanto na de cards. Arquivo: app/(app)/_components/fin-partners-section.tsx.
NovidadeFin Partners (/fin/partners/{id}): adicionado suporte a `logo_url` e upload de imagem. (1) Tipo `FinPartner` em `lib/api/fin-partners.ts` ganhou `logo_url?: string`. (2) Novo helper `uploadFinPartnerLogo(id, file)` que faz `POST /fin/partners/{id}/logo/upload` (multipart, campo `logo`, jpg/png/webp). (3) State `formLogoUrl` populado a partir de `partner.logo_url` em `populateForm`. (4) Avatar do header agora exibe `logo_url` quando presente; fallback para o favicon do domain (comportamento antigo) e para o icone `Users` quando ambos ausentes. (5) Em edit mode, botao circular `Pencil` (size-5, bg-emerald-500, border-2 white) sobreposto no canto inferior-direito do avatar abre file picker (`accept="image/jpeg,image/png,image/webp"`); durante upload mostra `Loader2` animado. Resposta atualiza partner no form, na lista (via `onUpdate`) e dispara toast de sucesso. Arquivos: lib/api/fin-partners.ts, app/(app)/_components/fin-partners-section.tsx.
NovidadeCRM Activities (/crm/activities - lista): clicar em um item da secao lateral `Sem tarefas` (deals sem atividades) agora navega para `/crm/deals/{deal_id}?return_to=/crm/activities`. Antes, o handler `onOpenEntity` so era passado em modo edit/new — em modo lista o click nao tinha efeito. Adicionado handler equivalente no modo lista do `activities-screen.tsx` que tambem trata `company` e `activity`. Arquivo: app/(app)/features/crm/activities/activities-screen.tsx.
CorrecaoCRM Activities (/crm/activities/{id}): campo `Responsavel` (autocomplete custom de usuarios) tambem teve as sugestoes nativas do browser desabilitadas — adicionado `autoComplete="off"`, `spellCheck={false}` e `name` unico no LabeledInput nas duas variantes (Tarefa e Reuniao). Arquivo: app/(app)/_components/crm-activities-section.tsx.
CorrecaoCRM Activities/Contatos/Empresas (todos os usos de `LabeledAutocomplete`): inputs do autocomplete deixam de exibir as sugestoes nativas do navegador. Adicionado `autoComplete="off"`, `spellCheck={false}` e `name="labeled-autocomplete-{id}"` (unico por instancia para o Chrome respeitar) no LabeledInput interno. Aplicavel a Empresa, Contato e Oportunidade em `/crm/activities/{id}` e demais telas que usam o componente. Arquivo: app/(app)/_components/labeled-autocomplete.tsx.
CorrecaoCRM Contacts (/crm/contacts/{id}): botao Voltar agora respeita o parametro `return_to` da URL — antes ignorava e sempre redirecionava para `/crm/contacts`. Com essa correcao, ao clicar no avatar do contato em `/crm/activities/{id}` (que abre `/crm/contacts/{id}?return_to=/crm/activities/{id}`) e depois Voltar, retorna corretamente para a atividade. As paginas de Companies e Deals ja tinham esse handling. Arquivo: app/(app)/features/crm/contacts/contacts-screen.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): tamanho do avatar do header do formulario aumentado de `size-16` (64px) para `size-18` (72px), alinhando com a aba Contatos do CRM Companies. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): campo `LinkedIn` movido para a Row 4, posicionado a direita de `Notas`. Row 4 vira: Notas Textarea (flex-1) | LinkedIn (w-72 shrink-0). LinkedIn alinhado ao topo via `items-start`. Mesmo layout adotado na aba Contatos do CRM Companies. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): largura do campo `HubSpot ID` aumentada de `w-28` (112px) para `w-29` (116px), alinhando com o mesmo ajuste feito na aba Contatos do CRM Companies. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): largura do campo `HubSpot ID` aumentada de `w-28` (112px) para `w-29` (116px). Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Activities (/crm/activities/{id}): campo `Contato` agora exibe a foto do contato (`profile_picture_url`) tanto no leading icon do input (quando selecionado) quanto no rowIcon de cada linha do dropdown — `<img>` `size-5` arredondada (`rounded-full object-cover`). Quando o contato nao tem foto, mantem o icone `User` sky-500 padrao (alwaysLeadingIcon). Para isso a prioridade do leftIcon em `LabeledAutocomplete` foi invertida: `selectedItem.selectedLeadingIcon ?? alwaysLeadingIcon` (antes era o oposto), permitindo que o icone padrao sirva de fallback enquanto a foto do item selecionado ganha precedencia. Mudanca compativel com Empresa/Oportunidade (que so usam selectedLeadingIcon e fallbackRowIcon, nao alwaysLeadingIcon). Arquivos: app/(app)/_components/labeled-autocomplete.tsx, app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id}): clicar no leading icon dos campos `Contato` (icone User sky-500) e `Oportunidade` (logo da empresa do deal) tambem abre o registro correspondente em nova pagina, com `?return_to=/crm/activities/{activity_id}`. Adicionados `navigateToContactEdit` (router.push para `/crm/contacts/{id}`) e `navigateToDealEdit` (router.push para `/crm/deals/{id}`); aplicados nos dois forms (Tarefa e Reuniao). Mesma mecanica do botao de Empresa adicionado anteriormente. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id}): clicar na logo da empresa (selectedLeadingIcon) no campo `Empresa` agora navega para `/crm/companies/{company_id}` com `?return_to=/crm/activities/{activity_id}`, permitindo que o botao Voltar (e Salvar) na pagina da empresa retorne para o form de edicao da atividade. Funcionalidade implementada via novas props no `LabeledInput` (`onLeftIconClick`, `leftIconTitle` — quando set, o leftIcon vira um `<button>` clicavel com hover scale e focus ring) e `LabeledAutocomplete` (`onLeadingIconClick`, `leadingIconTitle` — repassa o handler para o LabeledInput somente quando ha um item selecionado). Aplicado nos dois forms de atividade (Tarefa e Reuniao) usando `navigateToCompanyEdit(companyId)` que monta a URL e chama `router.push`. Demais usos do LabeledInput/LabeledAutocomplete nao sao afetados pois as novas props sao opcionais. Arquivos: app/(app)/_components/labeled-input.tsx, app/(app)/_components/labeled-autocomplete.tsx, app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): aumentado o espacamento horizontal entre `Sobrenome` e `Cargo` na Row 2 — Cargo recebeu `ml-6` (24px adicionais a esquerda, alem dos 12px do gap-3 do flex), totalizando ~36px de respiro entre os dois campos. Os demais gaps da linha continuam em 12px (gap-3). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): espacamento vertical entre as linhas do formulario aumentado de `space-y-4` (16px) para `space-y-6` (24px). Removido o `mt-6` explicito da Row 1 (agora redundante, ja que o space-y-6 ja entrega 24px entre toolbar e Row 1). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): campo `LinkedIn` movido para a Row 3, posicionado a direita de `Notas`. Row 3 vira: Notas Textarea (flex-1) | LinkedIn (w-72 shrink-0). LinkedIn alinhado ao topo via `items-start` no flex container — fica na altura da primeira linha do Textarea de Notas. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Contacts: campo `LinkedIn` agora aceita tanto URL completa (`https://www.linkedin.com/in/...`) quanto apenas o slug do perfil (ex: `leonardo-carvalhopereira`). Ao clicar no botao do LinkedIn no header, o helper `buildLinkedinUrl` (novo em `lib/format-helpers.ts`) detecta o formato e prefixa `https://www.linkedin.com/in/` quando necessario, ou usa a URL como esta quando ja vem com `http://`/`https://`/`www.linkedin.com`. Aplicado em ambos os formularios: `/crm/contacts/{id}` e Companies → aba Contatos. Arquivos: lib/format-helpers.ts, app/(app)/_components/crm-contacts-section.tsx, app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contatos - Novo Contato): ao informar um email no formulario de criacao, o sistema verifica em todos os contatos do CRM (lista carregada eagermente ao abrir o form) se ja existe contato com aquele email e exibe um banner amber AlertTriangle entre o toolbar e a Row 1 com a mensagem `Email ja cadastrado` + nome do contato existente. Se o contato duplicado ja estiver vinculado a esta mesma empresa, a frase muda para `(ja vinculado a esta empresa)`; caso contrario, sugere usar `Associar Existente`. Implementado via novo state `duplicateEmailContact` + useEffect que escuta mudancas em `ctEmail` e `allContacts`. `openNewContact` agora carrega `allContacts` quando ainda nao foi populado. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): campo `HubSpot ID` agora e exibido tambem no modo de criacao de contato (antes era visivel apenas em edicao). Continua sempre readonly — em create mode e populado automaticamente quando a busca por email do HubSpot retorna um match. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): adicionado `mt-6` (24px) na Row 1 para aumentar o espaco vertical entre o toolbar (Voltar + acoes) e a primeira linha de campos. Sobrescreve o `mt-4` padrao do `space-y-4`. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): largura de `Nome` e `Sobrenome` aumentada de `w-36` (144px) para `w-44` (176px). Cargo continua absorvendo o restante da Row 2 com flex-1. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): `LinkedIn` voltou para a Row 3 (full-width, sozinho), retornando ao layout anterior. Row 2: Nome w-36 / Sobrenome w-36 / Cargo flex-1. Notas volta a ser Row 4. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): `Telefone` movido para a Row 1, posicionado a direita de `Email` (entre Email e HubSpot ID). Row 1 agora: Avatar / Email flex-1 / Telefone w-44 / HubSpot ID w-28 / Status. Row 2 ficou: Nome w-36 / Sobrenome w-36 / Cargo flex-1. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): `HubSpot ID` movido para a Row 1, posicionado a direita de `Email` (antes do bloco de Status). Row 1: Avatar / Email flex-1 / HubSpot ID w-28 (readonly em edit mode quando preenchido) / Status. Row 2 ficou: Nome w-36 / Sobrenome w-36 / Cargo flex-1 / Telefone w-44. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): `Nome` e `Sobrenome` movidos da Row 1 para a Row 2 (a esquerda de `Cargo`). Row 1 agora: Avatar / Email flex-1 / Status. Row 2: Nome w-36 / Sobrenome w-36 / Cargo flex-1 / Telefone w-44 / HubSpot ID w-28. Email passa a ocupar todo o espaco horizontal disponivel ao lado do avatar e Status. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): campo `Cargo` movido para a Row 2, posicionado a esquerda de `Telefone`. Row 2 agora: Cargo flex-1 / Telefone w-44 / HubSpot ID w-28 (readonly em edit mode quando preenchido). Row 3 ficou apenas com LinkedIn full-width. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): avatar do contato ganhou `-mt-6` (24px) para subir e ficar visualmente alinhado proximo ao topo dos labels. Tamanho do avatar aumentado para `size-18` (72px). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): largura de `Nome` e `Sobrenome` na Row 1 reduzida de `w-48` (192px) para `w-36` (144px). Como `Email` esta com `flex-1`, absorve automaticamente o espaco liberado e fica visivelmente mais largo. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): campo `Email` movido da Row 2 para a Row 1, posicionado a esquerda de `Nome` (Avatar / Email flex-1 / Nome w-48 / Sobrenome w-48 / Status). Row 2 ficou com Telefone flex-1 + HubSpot ID w-28 (readonly em edit mode). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos): formulario inline de edicao do contato migrado para o mesmo padrao consolidado em `/crm/contacts/{id}`. Substituido o conjunto antigo (FloatingInput com label flutuante e icones, StatusToggleBadge no toolbar, link de WhatsApp inline, textarea custom para Notas) por: (1) toolbar enxuto Voltar+titulo; (2) avatares circulares na direita (Email mailto, WhatsApp wa.me/55+digitos, LinkedIn, HubSpot, Copiar ID), todos size-8 bg-white com brand color do icone, visiveis apenas em edit mode com seus respectivos campos preenchidos; (3) Row 1 com Avatar shadcn (size-16, ring amber) + botao circular `Pencil` para upload de foto (POST /crm/contacts/{id}/profile-picture/upload — endpoint compartilhado com a pagina de Contacts) + Nome (w-48) + Sobrenome (w-48) + Status com Switch shadcn (ml-auto); (4) Row 2 com Email flex-1 + Telefone w-44 + HubSpot ID w-28 readonly (so em edit mode quando preenchido); (5) Row 3 Cargo full-width; (6) Row 4 LinkedIn full-width (campo novo, antes inexistente neste form); (7) Row 5 Notas Textarea shadcn com mesmo dirty-dot cyan dos demais. Adicionados estados `ctLinkedinUrl`, `ctProfilePictureUrl`, `ctIsUploadingPicture`, `ctHeaderIdCopied`, ref `ctFileInputRef`. Inclusos no `hasContactFormChanges`, `openNewContact`, `openEditContact` e no payload de save (linkedin_url) e no createCrmContact. Novo handler `handleContactUploadPicture` reutiliza `uploadCrmContactProfilePicture`. Removido `StatusToggleBadge` (imports + uso). Mantida a busca de contato HubSpot por email no modo de criacao (auto-fill de firstname/lastname/jobtitle/phone/hubspot_id). Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contatos): coluna `Nome` agora exibe `Avatar` shadcn (size-7) usando `profile_picture_url` do contato quando disponivel; fallback para o gradiente amber-500→yellow-600 com iniciais (mantendo o visual antigo). Substituiu o `<span>` estatico que so mostrava iniciais. Adicionado import de `Avatar/AvatarImage/AvatarFallback`. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Contacts (/crm/contacts): coluna `Nome` da lista agora exibe `Avatar` shadcn (size-7 com ring amber) usando `profile_picture_url` do contato quando disponivel; fallback para iniciais (primeira letra do nome + sobrenome, max 2 chars) ou icone `User` quando ausentes. Substituiu a div estatica `bg-amber-100` com icone `User` que era usada antes. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
NovidadeCRM Contacts (/crm/contacts/{id}): avatar do contato passou a aceitar upload de foto. (1) Tipo `CRMContact` em `lib/api/crm-contacts.ts` ganhou o campo `profile_picture_url?: string` (refletindo `models.CRMContact.profile_picture_url` do swagger). (2) Novo helper `lib/api/crm-contacts-profile-picture.ts` com `uploadCrmContactProfilePicture(id, file)` que faz `POST /crm/contacts/{id}/profile-picture/upload` (multipart/form-data, campo `profile_picture`) e devolve o contato atualizado. (3) Avatar do header do form agora renderiza `AvatarImage` quando `profile_picture_url` esta preenchido (fallback para iniciais/User como antes). (4) Adicionado botao circular com icone `Pencil` no canto inferior-direito do avatar (size-6, bg-amber-500, border-2 white) — visivel apenas em edit mode quando `permWrite` true. Click abre file picker (`accept="image/jpeg,image/png,image/webp"`) e dispara o upload; durante envio o icone vira `Loader2` animado e o botao fica desabilitado. Resposta atualiza o contato no form, na lista (via `onUpdate`) e dispara toast de sucesso. Arquivos: lib/api/crm-contacts.ts, lib/api/crm-contacts-profile-picture.ts (novo), app/(app)/_components/crm-contacts-section.tsx.
NovidadeCRM Contacts (/crm/contacts/{id}): adicionado botao circular de Email a direita do header (primeiro da fila, antes do WhatsApp), visivel apenas quando `email` esta preenchido. Mesmo estilo dos demais avatares (size-8, bg-white/95). Icone `Mail` da lucide em `text-amber-600` para combinar com o tema do CRM. Click abre `mailto:{email}`. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
NovidadeCRM Contacts (/crm/contacts/{id}): adicionado botao circular de WhatsApp a direita do header (antes do LinkedIn), visivel apenas quando `phone` esta preenchido. Mesmo estilo dos demais avatares (size-8, bg-white/95). Logo do WhatsApp via SVG inline (`size-6`, 24px) preenchido com a cor brand `#25D366`. Click abre `https://wa.me/{numero}` em nova aba; se o numero nao comecar com `55`, o codigo do pais e adicionado automaticamente. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): largura do campo `Telefone` reduzida de `flex-1` para `w-44` (176px) — suficiente para o maior formato `(XX) XXXXX-XXXX`. Email continua com `flex-1` e absorve o espaco extra na linha. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
NovidadeCRM Contacts (/crm/contacts/{id}): adicionado botao circular de LinkedIn a direita do header (antes do botao do HubSpot e do Copiar ID), visivel apenas quando `linkedin_url` esta preenchido. Mesmo estilo dos demais avatares do header (size-8, bg-white/95, border-white/20). Icone `Linkedin` da lucide preenchido com a cor brand `#0A66C2`. Click abre a URL do LinkedIn em nova aba. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): campo `HubSpot ID` movido novamente — agora aparece a direita de `Telefone` na Row 2 (Email flex-1 / Telefone flex-1 / HubSpot ID w-28 readonly). Row 1 voltou ao layout enxuto (Avatar / Nome / Sobrenome / Status). Arquivo: app/(app)/_components/crm-contacts-section.tsx.
NovidadeCRM Contacts: campo `Telefone` agora e formatado progressivamente no padrao brasileiro `(XX) XXXXX-XXXX` (mobile, 11 digitos) ou `(XX) XXXX-XXXX` (fixo, 10 digitos), reaproveitando o helper `formatPhone` de `lib/format-helpers.ts` ja usado em outros modulos. A formatacao acontece em cada tecla (state armazena a string formatada) e tambem ao popular o form a partir da API. A tabela de contatos tambem exibe o telefone formatado. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): botoes a direita do header padronizados com o padrao do CRM Companies. Substituido `CopyIdButton` (lozengo branco/transparente, icone size-3.5) por dois botoes circulares brancos com `size-8`, ring `border-white/20 bg-white/95` e icones `size-[18px]`: (1) abrir contato no HubSpot (logo /hubspot-logo.png, abre `https://app.hubspot.com/contacts/6740520/record/0-1/{hubspot_object_id}`, visivel apenas quando `formHubspotId` preenchido), (2) Copiar ID (icone `Copy` slate-600 → `Check` emerald-600 por 2s apos clique, controlado por novo state `headerIdCopied`). Removido import `CopyIdButton`. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): subtitulo do header do formulario passou a exibir `short_name` da empresa em vez de `name` (com fallback para `name` quando `short_name` ausente). Adicionado `companyShortNameMap` ao lado do existente `companyMap` (que continua sendo usado pela tabela e busca). Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): botao `Voltar` movido do canto direito para o canto esquerdo do header do formulario, posicionado antes do icone/titulo. Apenas o botao `Copiar ID` (CopyIdButton) permanece a direita. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): largura do campo `HubSpot ID` reduzida de `w-44` (176px) para `w-28` (112px). Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): campo `HubSpot ID` movido da Row 4 (ao lado de LinkedIn) para a Row 1, posicionado entre `Sobrenome` e `Status`. Row 4 agora contem apenas `LinkedIn` ocupando largura total. HubSpot ID continua readonly e visivel apenas em edit mode quando preenchido. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): ajuste fino do header do formulario — Nome ganhou `ml-4` (espaco extra entre avatar e o primeiro campo) e o avatar ganhou `-mt-6` para subir 24px e ficar visualmente proximo do topo dos labels. Avatar tambem aumentou de `size-14` (56px) para `size-16` (64px), com texto das iniciais `text-base` → `text-lg` e icone fallback `size-6` → `size-7`. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): largura dos campos `Nome` e `Sobrenome` reduzida de `flex-1` para `w-48` (192px) fixos. Status passou a usar `ml-auto` para permanecer alinhado a direita da linha. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): avatar a esquerda do campo Nome aumentado de `size-9` (36px) para `size-14` (56px). Texto das iniciais passou de `text-[11px]` para `text-base`, icone de fallback `User` de `size-4` para `size-6`, ring de `ring-1` para `ring-2` e shadow de `shadow-sm` para `shadow-md` para manter proporcao visual. Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Contacts (/crm/contacts/{id}): formulario de edicao migrado para o padrao shadcn consolidado nos demais modulos. Campos `Nome`, `Sobrenome`, `Email`, `Telefone`, `Cargo`, `LinkedIn` e `HubSpot ID` (readonly) trocaram `FloatingInput` (label flutuante + icone interno) por `LabeledInput` (label-on-top, sem icone, dirty-dot cyan). Campo `Empresa` migrado para `LabeledAutocomplete` — eliminados ~50 linhas de state/refs/handlers (companyInput, companyFocused, companyHighlight, companyInputRef, companyPopulatingRef, companyOptions memo, handleSelectCompany, useEffect de sync, dropdown via createPortal inline e overlay click-outside). Status (Ativo/Inativo) trocou `StatusToggleBadge` por `Switch` shadcn dentro de container com label externo, identico ao padrao adotado em CRM Companies. Notas trocou input single-line por `Textarea` shadcn com mesmo tratamento de borda/dot do dirty state. Adicionado `Avatar` shadcn (size-9, gradient amber-500→amber-600, ring amber-200/60) a esquerda do Nome com fallback para iniciais (primeira letra do nome + primeira letra do sobrenome, max 2 chars maiusculas) e icone `User` (size-4) quando ambos vazios. Spacer invisivel acima do avatar mantem alinhamento vertical com os LabeledInputs da mesma linha. Layout: Row 1 (Avatar size-9 / Nome flex-1 / Sobrenome flex-1 / Status w-fit), Row 2 grid 2-cols (Email / Telefone), Row 3 grid 2-cols (Cargo / Empresa), Row 4 (LinkedIn flex-1 / HubSpot ID w-44 readonly em edit), Row 5 (Notas Textarea full). Arquivo: app/(app)/_components/crm-contacts-section.tsx.
MelhoriaCRM Activities (/crm/activities/{id}): campos 'Empresa', 'Contato' e 'Oportunidade' (Task + Meeting form) extraidos como componente reutilizavel `LabeledAutocomplete` (`app/(app)/_components/labeled-autocomplete.tsx`). API: `value`, `onChange(id, item)`, `items: LabeledAutocompleteItem[]` (id, label, sublabel, searchableTexts, rowIcon, selectedLeadingIcon), `hasChanged`, `alwaysLeadingIcon`, `fallbackRowIcon`. Encapsula state interno (text, focused, highlight), filtragem, navegacao por teclado (Up/Down/Enter/Escape), dropdown via createPortal, blur snap-back, sync de texto com o item selecionado quando `value` muda externamente. Em `crm-activities-section.tsx` a duplicacao foi eliminada: ~480 linhas de JSX/state/handlers/memos repetidos (3 fields x 2 forms) viraram 6 invocacoes simples mais 3 useMemo (`companyItems`, `contactItems`, `dealItems`) que mapeiam allCompanies/allContacts/allDeals para items. Removidos: 9 useState (acXInput, acXHighlight, acXFocused) + 3 useRef (acXRef) + 3 filter memos (filteredAcX) + 4 selected/show memos + 9 handlers (handleSelectAcX, handleAcXInput, handleAcXKeyDown). Cross-coupling (deal/contact que muda quando company muda) preservado nos useEffects da parent. Comportamento visual mantido: logo da empresa (favicon Google) com fallback Building2 (Empresa) / Handshake (Oportunidade), icone User permanente (Contato), short_name fallback para name, sublabels (email para Contato, nome da empresa para Oportunidade). Arquivos: app/(app)/_components/labeled-autocomplete.tsx (novo), app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/{id} - Tarefa): larguras dos campos 'Data' e 'Horario' reduzidas — Data de `w-40` (160px) para `w-32` (128px); Horario de `w-36` (144px) para `w-28` (112px). Tarefa Row 1 (Titulo / Data / Horario) fica mais compacta, com Titulo absorvendo o espaco extra. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id} - campo 'Contato'): adicionado icone `User` (lucide, size-4 sky-500) a esquerda DENTRO do input via prop `leftIcon` do LabeledInput. Aplicado em ambos os formularios (Tarefa e Reuniao). Sempre visivel, alinhado ao tratamento ja usado em Empresa (que mostra a logo do dominio). Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id}): adicionado dot colorido a esquerda dos selects de Prioridade e Status (4 ocorrencias: Task + Meeting). Cores: Prioridade — LOW slate-400, MEDIUM blue-500, HIGH amber-500, URGENT red-500. Status — pending amber-500, in_progress blue-500, scheduled sky-500, confirmed teal-500, completed emerald-500, cancelled slate-400. O dot aparece apenas quando ha valor selecionado (size-2 rounded-full, posicao absolute left-2.5 top-1/2 -translate-y-1/2); nesses casos o trigger ganha `pl-7` para deixar espaco. Adicionados 2 helpers no topo do arquivo: `priorityDotClass` e `statusDotClass`. O dirty indicator cyan ja existente (right-8) foi mantido. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/{id}): proporcoes da linha Empresa/Contato/Oportunidade ajustadas. Grid trocado de `md:grid-cols-3` (3 colunas iguais) para `md:grid-cols-[0.7fr_0.55fr_1fr]` — Empresa e Contato mais estreitos, Oportunidade absorve o espaco restante. Aplicado em ambos os formularios (Tarefa e Reuniao). Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/{id} - campo 'Empresa'): texto exibido no input e nos itens do dropdown passou a usar `c.short_name` (com fallback para `c.name` quando ausente). Pontos atualizados: filtro do autocomplete (`filteredAcCompanies` agora casa contra `short_name` OU `name`), `handleSelectAcCompany`, blur revert (Task + Meeting), prefills (`initialDealId`, `initialCompanyId`, edit-mode load), comparacao de visibilidade do dropdown (`showAcCompanyDropdown`), e texto do `<p>` no item do dropdown. O `formCompanyId` (UUID enviado a API) nao mudou — apenas a label visual. Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id} - campo 'Oportunidade'): dropdown agora exibe a logo da empresa associada a cada deal (`https://www.google.com/s2/favicons?domain={dealCompany.domain}&sz=64`, size-4 rounded-sm object-contain) ao inves do icone Handshake amber. Fallback para Handshake quando o deal nao tem empresa ou a empresa nao tem dominio. Apos selecionado, a logo da empresa do deal tambem e exibida a esquerda DENTRO do input via `leftIcon`. Adicionada memo `selectedAcDealCompany` que faz o lookup de `allCompanies` por `selectedAcDealObj.company_id`. Refatorado o `.map` de `filteredAcDeals` para extrair `dealCompany` em const local (antes fazia 2 finds duplicados por iteracao). Aplicado em ambos os formularios (Tarefa e Reuniao). Arquivo: app/(app)/_components/crm-activities-section.tsx.
NovidadeCRM Activities (/crm/activities/{id}): apos selecionar uma empresa no autocomplete, a logo (favicon do dominio) tambem passa a ser exibida a esquerda DENTRO do input de 'Empresa' (size-4, rounded-sm, object-contain). Implementado via nova prop opcional `leftIcon` no `LabeledInput` (`app/(app)/_components/labeled-input.tsx`): quando informado, renderiza o elemento absolutamente posicionado em `left-2.5 top-1/2 -translate-y-1/2` e aplica `pl-8` no Input para evitar sobreposicao do texto. Aplicado em ambos os formularios (Tarefa e Reuniao). Quando a empresa selecionada nao tem `domain`, nenhum icone e exibido (input fica sem padding extra). Arquivos: app/(app)/_components/labeled-input.tsx, app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Activities (/crm/activities/{id}): dropdown do autocomplete 'Empresa' agora exibe a logo da empresa (favicon via `https://www.google.com/s2/favicons?domain={domain}&sz=64`, size-4 rounded-sm object-contain) quando `c.domain` esta preenchido. Mantido o fallback para o icone `Building2` (size-4 emerald-400) quando a empresa nao tem dominio. Aplicado em ambos os formularios (Tarefa e Reuniao). Padrao alinhado ao ja usado nos cards de atividades (linhas 1222, 1305, 1376) e em outros autocompletes do sistema. Arquivo: app/(app)/_components/crm-activities-section.tsx.
MelhoriaCRM Deals (/crm/deals - lista): campo de busca passou a pesquisar apenas em `name` do deal. Removidos do filtro: `owner_name`, nome do pipeline e nome do stage. Pipeline e stage continuam disponiveis como filtros dedicados (select de pipeline + chips de stages); para responsavel use o toggle 'Meus deals' / 'Todos'. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Companies (/crm/companies - lista): campo de busca passou a pesquisar apenas em `name` e `domain` da empresa. Removidos do haystack: `tax_id`, `owner_name`, `industry`, `city` e `state`. Filtro fica mais focado e previsivel — para filtrar por responsavel use o toggle 'Minhas empresas' / 'Todas empresas'; para status use o select dedicado. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Deals (/crm/deals/{id} - aba Detalhes): novo campo 'Vertical de Negócio' (`vertical_negocio`, string) adicionado conforme swagger.json (CRMDeal, CreateCRMDealPayload, UpdateCRMDealPayload). Campo posicionado na linha do Status comissao / Reforma Tributaria com flex-1, usando o componente LabeledInput. CRUD atualizado: state `formVerticalNegocio`, dep no useMemo de hasFormChanges, populate/clearForm, payload de create (envia se preenchido) e update parcial (changedPayload). Tipos TS atualizados em lib/api/crm-deals.ts, crm-deals-create.ts e crm-deals-update.ts (esta tambem ganhou `is_tax_reform` que estava ausente). Arquivos: lib/api/crm-deals.ts, lib/api/crm-deals-create.ts, lib/api/crm-deals-update.ts, app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - header global): header de acoes unificado em todas as abas (espelhando o padrao adotado em CRM Companies). Avatares Sincronizar (HubSpot deal), HubSpot e Copiar ID continuam visiveis em todas as abas. Removidos os elementos tab-especificos do header gradiente: select 'Status Comissao' (item form), select 'Status' (receivable form), selects 'Status' + 'Prioridade' (task form e meeting form). Esses controles ja existem dentro dos respectivos formularios inline, entao a duplicacao foi eliminada. Header fica visualmente fixo e identico independente da aba ativa. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - sidebar de abas): badges de count removidos de TODAS as abas (Itens, Receitas, Atividades, Emails, Anexos). Lista de abas fica visualmente mais homogenea, alinhada com o padrao adotado em CRM Companies. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Emails): botoes 'Enviar Email' (Popover com modelos) e '+ Email' migrados do header gradiente (glass) para acima da lista de emails via prop `listActions` do `EmailsSection`, espelhando o padrao usado em CRM Companies. Estilo trocado para pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 text-amber-700`). Mantida a logica do Popover (loading templates, lista vazia, sendingEmailId) e o ref `emailsSectionRef.current?.openNewEmail()`. Botoes gated em permWrite. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Atividades): botao '+ Nova Atividade' (Popover com Tarefa/Reuniao) migrado do header (gradiente glass) para a area da lista, espelhando o padrao usado em CRM Companies. Estilo trocado para pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 px-3 py-1.5`). Posicionado absolutamente no canto superior direito do container da lista (`absolute right-0 top-0 z-10`) para ficar na mesma linha do titulo da primeira secao ('ATRASADAS' / 'PROXIMAS' / etc), em vez de ocupar uma linha propria acima. Mantida a funcionalidade do Popover com 2 opcoes (Tarefa amber + Reuniao cyan). Botao gated em permWrite e visivel quando nenhum form inline esta aberto. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Receitas): botao 'Nova Receita' migrado do header (gradiente glass) para acima da tabela com estilo pill amber soft (mesmo padrao da aba Itens). Visivel apenas quando o usuario tem permWrite e o formulario inline nao esta aberto. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Itens): botao 'Sincronizar Itens' removido do header (gradiente). Botao '+ Novo Item' migrado do header para acima da tabela com estilo pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 px-3 py-1.5 text-xs font-medium text-amber-700`), espelhando o padrao usado em outras abas (External IDs em Companies, etc.). Funcao `handleSyncItems` e state `isSyncingItems` removidos pois nao tem mais uso. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campo 'Data Fechamento' movido para a Row 1 (entre 'Nome' e o badge do stage), com w-44 shrink-0. A Row 2/3 do formulario passou a ter apenas o campo 'Valor' (w-48). Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campo 'Valor' agora segue o mesmo padrao de input usado em Fin Transactions (`/fin/transactions/new`): prefixo 'R$' a esquerda em emerald-600 (text-xs font-bold), input shadcn com pl-9, text-right, font-semibold, tabular-nums, maxLength=15. Mantida a estrutura shadcn label-on-top (Label + Input) com h-9 alinhado aos demais campos. Estado interno (`formAmount`) passou a guardar a string formatada em pt-BR ('1.234,56'); a populacao usa `fmtMonetary` e o save usa o helper `currencyToNumber` (parse de '1.234,56' para 1234.56). Adicionados helpers locais `parseCurrencyInput`, `currencyToNumber` e `formatCurrencyBlur` (espelhando o padrao de fin-transaction-form.tsx). Removida a funcao local `amountDisplay`. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - header): botoes 'Sincronizar', 'HubSpot' e 'CopyId' convertidos para avatares circulares (size-8, rounded-full, bg-white/95) iguais aos usados em CRM Companies. Sincronizar: RefreshCw amber-600 com hover rotate-45 + scale-110. HubSpot: logo /hubspot-logo.png em size-7. Copiar ID: Copy slate-600 (ou Check emerald-600 por 2s apos clique). Estes 3 avatares passam a ser visiveis em TODAS as abas (antes so apareciam na aba Detalhes), unificando o header. CopyIdButton inline removido. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campo 'Reforma Tributaria' convertido para Select shadcn (w-32) com Label acima e duas opcoes 'Sim'/'Nao'. Border cyan + shadow para indicar mudanca pendente. Arquivo: app/(app)/_components/crm-deals-section.tsx.
CorrecaoCRM Deals (/crm/deals/{id} - aba Detalhes): badge de stage agora prioriza o icone definido na API (`CRMPipelineStage.icon`, geralmente um emoji como '🛠️' para Pre-venda) ao inves de inferir o icone lucide a partir do nome. Caso o stage nao tenha `icon` setado, mantem o fallback heuristico anterior por nome (Crosshair, Search, Lightbulb, Rocket, FileText, Flame, FileSignature, Trophy, XCircle, Ban, Circle). A paleta de cores (bg/border/text/dot) continua sendo derivada do nome do stage. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): badge de stage a direita do campo Nome estilizado como pill colorido (rounded-full, h-9, bg/border/text na cor do stage). `stageBadgeConfig` estendido para retornar tambem `bg` (ex: bg-sky-50) e `border` (ex: border-sky-200), alem de `dot` (mantido para outros usos), `icon` e `text`. Variantes dark mode incluidas. Arquivo: app/(app)/_components/crm-deals-section.tsx.
MelhoriaCRM Deals (/crm/deals/{id} - aba Detalhes): campos do formulario migrados de FloatingInput para o padrao shadcn label-on-top usado em CRM Companies, via componente compartilhado `LabeledInput` (`app/(app)/_components/labeled-input.tsx`). Convertidos: Nome, HubSpot ID (readonly), Empresa (autocomplete), Contato (autocomplete), Valor. O campo 'Data Fechamento' passou a usar o novo `DatePickerInput` (`components/ui/date-picker-input.tsx`) — Label acima + Input com mascara dd/mm/aaaa + Popover com Calendar. O Status comissao (Select) ganhou Label acima e altura h-9 alinhada aos demais. A Reforma Tributaria virou um wrapper com Label + Checkbox em h-9 rounded-md (sem gradiente). O campo Notas (textarea) foi simplificado para shadcn `<Textarea>` com Label acima, h-full no container flex (mantendo a altura preenchida na coluna direita). Mantidos: dropdowns de autocomplete (createPortal), change indicator (borda cyan + dot). Arquivo: app/(app)/_components/crm-deals-section.tsx.

29 de Abril de 2026

48 itens
15231
MelhoriaCRM Companies (/crm/companies/{id} - aba Detalhes): labels dos campos movidos para FORA do input (acima, padrao label-on-top) usando shadcn `<Label>` + `<Input>` + `<Textarea>`. Foi criado um helper local `LabeledInput` no arquivo (composto puramente de shadcn Input + Label + dot indicator de mudanca em cyan) e aplicado nos 8 campos de texto: Nome, Nome Curto, CNPJ/Tax ID, Dominio, Responsavel, SAP/Seidor ID, Setor, Cidade, Estado, Pais. Os botoes Tier e Status (Row 1) tambem ganharam Label acima para alinhamento visual. O campo Observacoes virou shadcn `<Textarea>` com Label acima. Os FloatingInputs antigos da aba Detalhes foram removidos — o componente continua em uso nas demais abas (Contratos, Contatos, Solucoes, Atividades, Emails). Mantidos: change indicator (borda cyan + dot pulsante), icones coloridos a esquerda, h-12 nos inputs. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header): subtitulo (dominio da empresa) removido logo abaixo do nome da empresa no header principal. Header fica mais limpo e focado apenas no nome — o dominio continua disponivel/editavel no campo correspondente da aba Detalhes. Arquivo: app/(app)/_components/crm-companies-section.tsx.
CorrecaoCRM Companies — campos `annual_revenue` (Receita Anual) e `number_employees` (Nº Funcionarios) removidos do CRUD para alinhar com a API atual: ambos foram retirados do swagger.json (models.CRMCompany, CreateCRMCompanyPayload e UpdateCRMCompanyPayload). Removidos: states formAnnualRevenue/formNumberEmployees, deps do useMemo de hasFormChanges, populate/clearForm, payloads de create e update parcial (changedPayload), os dois FloatingInputs da Row 3 e os imports nao mais usados (formatBrInteger, formatBrNumber, DollarSign). Tipos TS atualizados em app/(app)/data/crm-companies.ts e nas assinaturas de createCrmCompany e updateCrmCompany. Layout: a Row 3 (que tinha Setor + 2 numericos) foi unificada com a antiga Row 4 (Cidade | Estado | Pais), formando agora um grid-cols-4 (Setor | Cidade | Estado | Pais). Arquivos: app/(app)/_components/crm-companies-section.tsx, app/(app)/data/crm-companies.ts, lib/api/crm-companies-create.ts, lib/api/crm-companies-update.ts.
NovidadeCRM Companies (/crm/companies/{id} - aba Detalhes): adicionado toggle de status simples na primeira linha do formulario, a direita do campo 'Nome Curto'. Implementacao inline (h-12, rounded-xl, sem gradientes/shimmer/breathing) com paleta sutil: emerald-50/700 quando ativo, rose-50/700 quando inativo, icone Check/X (size-4, strokeWidth=3) e label 'Ativo'/'Inativo'. Mantido o dirty indicator (dot cyan pulsante) quando o status foi alterado e ainda nao foi salvo. O avatar de status no header continua disponivel para troca rapida do mesmo estado. Versao simples especifica desta tela; o StatusToggleBadge compartilhado (com animacoes mais elaboradas) continua em uso em outras telas. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - header): novo avatar de account_tier no FINAL da barra de acoes (depois de CopyId), separado dos demais por um divisor vertical (h-6 w-px bg-white/25, mx-1). Avatar circular (size-8, rounded-full) com estilo destacado por tier: A com gradiente emerald->green->emerald, B com orange->amber->orange, C com slate->slate->slate, todos com texto branco em font-extrabold (apenas a letra do tier, sem icones complementares). Overlay sutil from-black/10 to-white/30 reforca a sensacao de avatar 3D. Estado vazio mantem fundo branco translucido com '—' em slate-300. Click cicla os valores '' -> A -> B -> C -> ''. Hover aplica scale-110 + shadow tematico forte (emerald/orange/slate). Mantido o dirty indicator (ponto cyan pulsante) quando o tier foi alterado e nao salvo. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header): botao 'Sincronizar' tambem virou avatar circular (size-8, rounded-full) somente com icone, alinhado aos demais avatares (HubSpot, Status, Copiar ID). Fundo branco translucido (bg-white/95), icone RefreshCw em text-amber-600 (size-5, strokeWidth=2.5) com rotate-45 + scale-110 no hover. Estado loading mantido com Loader2 girando, sem texto. Tooltip dinamica ('Sincronizando...' / 'Sincronizar empresa com o HubSpot'). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header): botao 'Copiar ID' tambem virou avatar circular (size-8, rounded-full) com mesmas medidas dos avatares HubSpot e Tier. Fundo branco translucido (bg-white/95) consistente com HubSpot e Sincronizar. Estado idle: icone Copy em text-slate-600 (escurecendo no hover); apos clique, troca para Check verde (text-emerald-600) por 2s e volta ao Copy. Hover aplica scale-110 no icone. Implementado inline para nao mexer no CopyIdButton compartilhado (usado em 24+ telas) — o componente original continua disponivel e segue em uso na aba Contratos. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header global): header de acoes unificado em todas as abas usando o conjunto de Detalhes como referencia. Avatares Sincronizar (HubSpot company), HubSpot, Copiar ID e Tier passam a ser sempre visiveis (independente da aba ativa). Removidos os elementos tab-especificos do header: botao 'Sincronizar' (texto) da aba Oportunidades, badge de status do contrato + CopyId orbit_object_id da aba Contratos, selects de Status/Prioridade de tarefa e reuniao da aba Atividades. Tambem removido o import de CopyIdButton (nao mais utilizado neste arquivo). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Oportunidades): removidos os dois botoes '+ Oportunidade' da aba — o botao pill ao lado dos chips de filtro por estagio e tambem o botao no empty state. Criacao de oportunidades passa a ser feita exclusivamente pela tela /crm/deals/new (acessivel via Oportunidades no menu) ou pela acao de criar no funil/pipeline. Empty state simplificado para apenas o icone Handshake + mensagem. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - sidebar de abas): badge de count removido da aba 'Emails' (era a unica aba que ainda exibia contagem ao lado do label). Lista de abas fica visualmente mais homogenea, alinhada com as demais (Detalhes, IDs Externos, Oportunidades, Contratos, Contatos, Solucoes, Atividades) que ja nao mostravam count. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header): avatar de status (Check/X) removido do header agora que o toggle de status simples existe na primeira linha do formulario. Evita duplicacao de controles e mantem o header focado nas acoes contextuais (Sincronizar, HubSpot, CopyId, Tier). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - header): botao 'HubSpot' com texto + ExternalLink substituido por avatar circular (size-8, rounded-full, bg-white/95) exibindo a logo /hubspot-logo.png em size-7 (28px) com object-contain, mantendo um respiro fino dentro do circulo. Mantida a acao de abrir a empresa no HubSpot em nova aba. Hover aplica scale-110 na logo e shadow amber sutil. Visual mais compacto e alinhado ao tratamento de avatares de provedor da aba IDs Externos. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba IDs Externos): lista de cards substituida por tabela alinhada ao padrao da aba Oportunidades. Estrutura: container `overflow-hidden rounded-lg border` com Table compacta (`[&_td]:!text-xs [&_th]:!text-[11px]`), header com tableHeader/tableHeaderDark do theme e colunas Provedor / ID Externo / Primario. Linhas com zebra (idx%2===0 -> bg-white/40, senao theme.rowAlt), hover via theme.rowHover/rowHoverDark e onClick mantendo a abertura do modal de edicao. Coluna Provedor mostra avatar 24x24 (logo Hubspot/Orbit ou fallback ExternalLink amber) ao lado do nome. Coluna ID Externo usa tabular-nums. Coluna Primario exibe estrela amber preenchida quando is_primary, senao traco. Empty state preservado. Removido tambem o divisor (h-px bg-slate-200/60) que ficava entre o botao '+ ID Externo' e a lista, ja que a borda da tabela cumpre essa funcao. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos, tabela): colunas de data ('Inicio' e 'Fim') passaram a exibir formato curto dd/MM/yy e ficaram alinhadas no centro (header e celula com `text-center`). Implementado via isoToDisplay (que retorna dd/MM/yyyy) seguido de slice(0,6) + slice(8) para truncar a centena do ano. Mantido o parse manual via isoToDisplay (em vez de new Date + toLocaleDateString) para evitar shift de fuso horario que ocorreria com date-only strings (`yyyy-MM-dd` parseado como UTC midnight). Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contratos, tabela): adicionada coluna 'Fim' no final exibindo `actual_final_validity` (data real de termino) com fallback para `estimated_final_validity` quando a primeira esta vazia. Sortavel via nova chave `final_validity` que aplica o mesmo fallback no compare. ContractSortKey atualizado para 'description' | 'code' | 'sales_value' | 'initial_validity' | 'final_validity'. colSpan do empty state ajustado de 4 para 5. A coluna anterior 'Vigencia' foi renomeada para 'Inicio' para melhor refletir o conteudo (apenas `initial_validity`). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos, tabela): coluna 'Vigencia' simplificada para exibir apenas a data de inicio (`initial_validity`) em vez do range 'inicio -> fim'. Sort key trocado de `estimated_final_validity` para `initial_validity` (string compare via extractFlexibleTime); ContractSortKey atualizado. Removido o markup do range (span -> span -> span). Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Emails): botoes 'Enviar Email' (Popover com modelos) e '+ Email' migrados do header gradiente (glass) para acima da lista de emails, espelhando o padrao das demais abas. Estilo trocado para pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 text-amber-700`). Como a aba usa o componente externo `EmailsSection`, foi adicionada nova prop opcional `listActions?: ReactNode` que e renderizada acima da toolbar (no estado com emails) e acima do empty state (sem emails), via `<div className='flex items-center justify-end gap-2'>`. O parent `crm-companies-section.tsx` passa o Popover de templates + botao '+ Email' (gated em permWrite). Mantida a logica do Popover (loading templates, lista vazia, sendingEmailId) e o ref `emailsSectionRef.current?.openNewEmail()`. Arquivos: app/(app)/_components/emails-section.tsx, app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Atividades): botao '+ Nova Atividade' (Popover com Tarefa/Reuniao) migrado do header (glass) para a area da lista de atividades, espelhando o padrao de Contatos/Solucoes/Contratos. Estilo trocado de retangular glass branco para pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 px-3 py-1.5`). Posicionado absolutamente no canto superior direito do container da lista (`absolute right-0 top-0 z-10`) para ficar na mesma linha do titulo da primeira secao ('ATRASADAS' / 'PROXIMAS' / etc), em vez de ocupar uma linha propria acima. Mantida a funcionalidade do Popover com 2 opcoes (Tarefa amber + Reuniao cyan). Botao visivel quando activeTab === 'activities' && !taskFormOpen && !meetingFormOpen && !activityFormOpen e gated em permWrite. Lista renderizada abaixo (loading / sections de Atrasadas/Proximas/Concluidas / empty state) preservada. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Solucoes): grid de cards (grid-cols-2 com cards visuais com gradient stripe e blur orb) substituido por tabela seguindo o mesmo padrao das demais abas (Contatos, Contratos, Oportunidades, IDs Externos). Colunas sortaveis: checkbox (gated em permDelete), Fornecedor (com favicon 4x4 do vendor_domain via google s2/favicons ou fallback Lightbulb), Solucao (sol.name), Categoria (com icone FolderOpen amber), Notas (line-clamp-1 com tooltip). Sort keys novos: 'vendor' | 'name' | 'category', via novo memo `sortedCompanySolutions` que cruza CRMCompanySolution com allSolutions/solutionCategories para extrair os textos comparaveis. Botao '+ Solucao' migrado do header (glass) para acima da tabela com estilo pill amber. Adicionada selecao via checkbox e bulk delete (header com 'selecionar todas visiveis', linha individual com stopPropagation, FormFooter com contador + 'Limpar selecao' + botao Excluir vermelho). Bulk delete via Promise.allSettled chamando deleteCrmCompanySolution com toasts e refetch. Selecao resetada ao trocar empresa e ao recarregar. ConfirmDeleteDialog adicionado. Empty state preservado (Lightbulb + texto). Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contatos, formulario): campo Telefone agora aplica mascara progressiva via `formatPhone` no onChange (ex: digito 1 -> '1', '11' -> '11', '119' -> '(11) 9', ate '11987654321' -> '(11) 98765-4321'). Helper `formatPhone` em `lib/format-helpers.ts` reescrito para ser progressivo (clamp em 11 digitos BR + suporte a country code 55) em vez de retornar fallback bruto. Valor enviado ao backend e o ctPhone (ja formatado), garantindo persistencia consistente. Change tracking (hasContactFormChanges e payload do save) tambem comparam contra `formatPhone(editingContact.phone ?? '')` para evitar 'change' falso ao abrir contatos legacy salvos sem formatacao. populateForm e auto-preenchimento via search (mobilephone) tambem sao formatados via formatPhone para manter o estado consistente. Arquivos: lib/format-helpers.ts, app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos, formulario): icone do botao WhatsApp trocado de `MessageCircle` (lucide) para o SVG oficial do logo do WhatsApp (path do simple-icons, fill currentColor herdando a cor emerald-700 do botao). Mantido o tamanho size-3.5 e a animacao group-hover:scale-110. Import `MessageCircle` removido pois deixou de ser usado. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos, formulario): botoes WhatsApp e StatusToggleBadge (Ativo/Inativo) movidos do header (gradiente glass) para a linha do titulo do formulario inline ('Voltar | Editar Contato | ... | WhatsApp | Status'), via `ml-auto` para empurrar para a direita. WhatsApp re-estilizado de glass amber-on-emerald para pill emerald-50 (`border-emerald-200 bg-emerald-50 text-emerald-700`) com hover sutil; StatusToggleBadge mantem componente original. Logica de detectar celular (digits.length >= 10 && nao comeca com 55 -> prefix 55; mobile = length >= 12 && char[4] === '9') preservada. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contatos, tabela): coluna Telefone agora exibe o numero formatado via novo helper `formatPhone` em `lib/format-helpers.ts`. Mascaras suportadas: 11 digitos -> (XX) XXXXX-XXXX (celular), 10 digitos -> (XX) XXXX-XXXX (fixo), 13 com leading 55 -> +55 (XX) XXXXX-XXXX, 12 com leading 55 -> +55 (XX) XXXX-XXXX, 9/8 digitos sem DDD -> XXXXX-XXXX / XXXX-XXXX. Numeros que nao caem em nenhuma forma conhecida sao retornados como vieram (fallback). Helper exportado e disponivel para reuso em outras telas. Arquivos: lib/format-helpers.ts, app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contatos, tabela): celulas Email e Telefone ganharam icone identificador a esquerda do valor (Mail sky-400 para email, Phone emerald-400 para telefone, ambos `size-3.5 shrink-0`). Quando a celula esta vazia, mantem apenas o em-dash em slate-400. Recupera o vocabulario visual do antigo card de contato dentro do novo formato tabular. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contatos): grid de cards (grid-cols-2) substituido por tabela alinhada ao padrao das demais abas (Oportunidades, Contratos, IDs Externos). Colunas: checkbox (gated em permDelete), Nome (com avatar 7x7 e iniciais), Cargo, Email, Telefone (sortaveis pelas chaves ja existentes 'name' | 'job_title' | 'email' | 'phone'). Botoes 'Associar Existente' e '+ Contato' migrados do header (glass) para acima da tabela com estilo pill amber (`rounded-full border border-amber-200/80 bg-amber-50`). Adicionada selecao via checkbox e bulk delete (header com 'selecionar todos visiveis', linha individual com stopPropagation, FormFooter com contador + 'Limpar selecao' + botao Excluir vermelho), bulk delete via Promise.allSettled chamando deleteCrmContact com toasts e refetch. Selecao resetada ao trocar empresa, criar nova empresa e ao recarregar contatos. ConfirmDeleteDialog adicionado. Empty state preservado. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contratos, tabela): adicionada selecao via checkbox e bulk delete espelhando o padrao de Oportunidades e IDs Externos. Coluna nova de 16px no inicio da tabela (gated em permDelete) com checkbox de header 'selecionar todos os visiveis' (respeita filtros) e checkbox individual por linha (stopPropagation para nao acionar o onClick que abre o form). Linha selecionada ganha bg amber-50/70. Quando selectedContractIds.size > 0 e activeTab === 'contracts' && !contractFormOpen, o FormFooter exibe contador ('N contrato(s) selecionado(s)'), botao 'Limpar selecao' e botao 'Excluir' (vermelho com Trash2/Loader2). Bulk delete usa Promise.allSettled chamando deleteCrmContract por id, mostra toasts de sucesso/falha (com resolveErrorMessage no primeiro erro) e recarrega a lista. Selecao e resetada ao trocar de empresa, ao criar nova empresa e ao recarregar contracts. colSpan do empty state ajustado dinamicamente para permDelete ? 6 : 5. Adicionado ConfirmDeleteDialog. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contratos): filtros (Unidade de Negocio, Portfolio, Tipo, Status) trocados de Select shadcn para autocomplete por digitacao. Novo componente reutilizavel `FilterStringAutocomplete` (`app/(app)/_components/filter-string-autocomplete.tsx`) renderiza um trigger compacto (h-7, rounded-lg, slate borders) que troca para input de busca ao clicar/focar; dropdown via createPortal posicionado pelo getBoundingClientRect, navegavel por ArrowUp/Down/Enter/Escape e filtragem por normalizeText. Item selecionado fica em bold amber. Botao X aparece quando ha valor selecionado para limpar rapidamente. Click-outside fecha o dropdown (com checagem para nao fechar quando o clique e dentro do portal). Comportamento de filtragem e set/clear de valor permanece identico (mantidos os states contractFilterBU/Portfolio/Type/Status), mudou apenas o widget de selecao. Arquivo: app/(app)/_components/crm-companies-section.tsx + novo arquivo.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos): botao 'Sincronizar' migrado do header (glass com bg-white/10) para a area acima da tabela, espelhando o padrao adotado em '+ Oportunidade'. Estilo trocado de retangular glass para pill amber soft (`rounded-full border border-amber-200/80 bg-amber-50 px-3 py-1.5 text-xs text-amber-700`). Posicionado a direita do contador 'X de Y' na linha de filtros (`<div className='ml-auto flex items-center gap-2'>`). Adicionado tambem no empty state (quando nao ha contratos vinculados), com `mt-1` apos o texto 'Use Sincronizar para importar contratos.', tornando a acao primaria clicavel sem precisar voltar ao header. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos, tabela): coluna de valor renomeada de 'Venda' para 'Valor (R$)' e o simbolo R$ removido das celulas (passou a usar `fmtMonetary` em vez de `formatCurrency`, que ja inclui 'R$ '). Celula tambem ganhou `font-semibold` para reforcar a hierarquia visual do numero, alinhada com a coluna 'Valor (R$)' da tabela de Oportunidades. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos, tabela): coluna 'Status' removida e substituida por nova coluna 'Code'. O status passa a ser comunicado apenas pelo dot colorido (`size-2`) que ja aparecia a esquerda da descricao na coluna 'Contrato', agora com `title` (tooltip nativo) mostrando o texto do status no hover. A coluna 'Contrato' tambem ficou enxuta: era 2 linhas (descricao + code), virou 1 linha so com a descricao, ja que o code agora tem coluna propria. Sort por 'status' substituido por sort por 'code' (string compare); ContractSortKey atualizado para 'description' | 'code' | 'sales_value' | 'estimated_final_validity'. Removida a const `statusBadge` ja que nao havia mais consumidor. Filtro de status no header de filtros (Select 'Status') foi mantido — afeta apenas a lista, nao a tabela. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Contratos, tabela): paleta de status ajustada. 'Finalizado' (COMPLETED/FINALIZ/CONCLU) trocado de azul (sky) para vermelho (red) — sinaliza fim do ciclo do contrato, semelhante ao tratamento de stages perdidos. 'Cancelado' (CANCEL) trocado de vermelho (red) para cinza (slate) — perde a enfase visual ja que o contrato deixou de existir e nao precisa competir com 'Finalizado'. Cores aplicadas tanto no statusDot da coluna 'Contrato' quanto no statusBadge da coluna 'Status'. Demais cores preservadas: ATIVO/EXEC verde, PARALIS/SUSPENS amber, PENDEN/AGUARD violeta. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Contratos, tabela): indicador visual de status (apenas dot colorido `size-2`, sem texto) agora aparece na coluna 'Contrato', a esquerda da descricao. Logica de classificacao do status (ACTIVE/EXEC verde, COMPLETED/FINALIZ azul, STOPPED/PARALIS amber, CANCEL vermelho, PENDEN/AGUARD violeta, fallback slate) extraida para uma const `statusInfo` por linha; sao gerados `statusDot` (so o circulo) usado na coluna 'Contrato' e `statusBadge` (pill com texto) usado na coluna 'Status'. Estrutura da celula 'Contrato' virou flex (dot + bloco descricao/codigo) com gap-2 e `shrink-0` no dot. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba IDs Externos): botao '+ ID Externo' alinhado visualmente ao botao '+ Oportunidade'. Antes: `h-8 rounded-lg` (retangulo). Agora: `rounded-full py-1.5 shrink-0` (pill, mesmo formato do botao da aba Oportunidades). Demais classes (border amber-200/80, bg amber-50, hover, active:scale, dark) ja eram identicas. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id}): padding superior reduzido em todas as abas. O container de cada aba (Detalhes, IDs Externos, Oportunidades, Contratos, Contatos, Solucoes, Atividades x3) trocou `p-5` (20px todos os lados) por `px-5 pt-3 pb-5` (12px no topo, 20px nos demais), eliminando o espaco vazio que aparecia entre o header das abas e o conteudo (especialmente notavel em IDs Externos e Oportunidades, onde o botao '+' ficava muito distante do topo). Margem do row do botao em IDs Externos tambem reduzida de mb-3 para mb-2. Aba Emails nao foi tocada pois usa o componente externo EmailsSection. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba IDs Externos, tabela): adicionada selecao via checkbox e bulk delete espelhando o padrao da aba Oportunidades. Coluna nova de 16px no inicio da tabela (gated em permDelete) com checkbox de header 'selecionar todos os visiveis' e checkbox individual por linha (stopPropagation para nao acionar o onClick que abre o modal de edicao). Linha selecionada ganha bg amber-50/70. Quando selectedExtIdIds.size > 0 e activeTab === 'external_ids', o FormFooter exibe contador ('N ID(s) externo(s) selecionado(s)'), botao 'Limpar selecao' e botao 'Excluir' (vermelho com Trash2/Loader2). Bulk delete usa Promise.allSettled chamando deleteCrmCompanyExternalId por id, mostra toasts de sucesso/falha (com resolveErrorMessage no primeiro erro) e recarrega a lista. Selecao e resetada ao trocar de empresa e ao recarregar externalIds. Adicionado ConfirmDeleteDialog para a operacao em massa. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Oportunidades, tabela): adicionada possibilidade de selecionar oportunidades via checkbox (coluna nova de 16px no inicio da tabela, gated em permDelete). Header tem checkbox 'selecionar todas as visiveis' (respeita filtro de stage), linhas tem checkbox individual com stopPropagation para nao acionar o row click. Linha selecionada ganha bg amber-50/70. Quando selectedDealIds.size > 0 e activeTab === 'deals', o FormFooter exibe um contador ('N oportunidade(s) selecionada(s)'), botao 'Limpar selecao' e botao 'Excluir' (vermelho, com Trash2/Loader2). Bulk delete usa Promise.allSettled chamando deleteCrmDeal por id, mostra toasts de sucesso/falha, recarrega a lista. Selecao e resetada ao trocar de empresa e ao recarregar deals. Arquivos: app/(app)/_components/crm-companies-section.tsx, lib/api/crm-deals-delete.ts (importado).
MelhoriaCRM Companies (/crm/companies/{id} - aba Oportunidades): botao '+ Nova Oportunidade' renomeado para '+ Oportunidade' e estilo ajustado para casar com os chips de stage da mesma linha (rounded-full, py-1.5 px-3, text-xs, icone Plus size-3.5). Mantida a cor amber solida para diferenciar como acao primaria. Alteracao aplicada nos dois pontos do componente: botao ao lado dos chips de stage (estado com deals) e botao no empty state (sem deals). Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba Oportunidades, tabela): icone na coluna 'Nome' agora reflete o icone do stage da oportunidade. Quando o stage tem `icon` (emoji), renderiza-o como text-base; caso contrario, mantem o fallback baseado em flags (Trophy verde para is_won, XCircle vermelho para is_closed, CircleDot ambar para os demais). Aproxima a coluna 'Nome' do mesmo vocabulario visual dos chips de filtro. Em contrapartida, a coluna 'Estagio' deixou de exibir o emoji (apenas o nome do stage) para evitar duplicacao com o icone da coluna 'Nome'. Arquivo: app/(app)/_components/crm-companies-section.tsx.
CorrecaoCRM Companies (/crm/companies/{id}): footer da tela passou a respeitar a aba ativa. O FormFooter da empresa (Salvar/Excluir/timestamps de updated_at) agora aparece somente quando activeTab === 'details'. Em abas como 'deals', 'contracts' (sem form aberto), 'contacts' (sem form aberto) e 'solutions' (sem form aberto) o footer some, evitando confusao de que 'Salvar' afetaria itens da aba. As demais abas continuam mostrando seus proprios footers contextuais (contract/contact/solution/task/meeting) quando o respectivo form esta aberto, e activities/emails seguem sem footer. Arquivo: app/(app)/_components/crm-companies-section.tsx (ramo final da cadeia de ternarios passou de fallback para `activeTab === 'details' ? <FormFooter .../> : null`).
MelhoriaCRM Companies (/crm/companies/{id} - aba IDs Externos): botao '+ Novo ID Externo' migrado do header (glass + bg-white/10) para um footer dedicado da aba. O footer usa FormFooter com hideDefaultActions e renderiza o botao via slot `actions`, com gradiente amber/orange e icone Plus que rotaciona no hover. Estilo alinhado ao botao Save da FormFooter (h-10, rounded-xl, shimmer no hover). Visivel apenas quando permWrite e !isCreating. Arquivo: app/(app)/_components/crm-companies-section.tsx (remocao do bloco do header e adicao de novo ramo `activeTab === 'external_ids' && !isCreating` na cadeia de ternarios do footer).
MelhoriaCRM Companies (/crm/companies/{id} - aba IDs Externos): badge 'Primário' (estrela amber) movido do lado direito do nome do provider para o canto direito do card. Antes ficava colado ao texto do provider via inner flex; agora e renderizado como ultimo filho do button-card (flex w-full items-center gap-4), pos o bloco com flex-1, com `shrink-0` para nao espremer. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Companies (/crm/companies/{id} - aba IDs Externos): avatar do card agora exibe o logo do provider quando reconhecido. Para provider 'hubspot' (case-insensitive) usa /public/hubspot-logo.png; para 'orbit' usa /public/orbit-logo.png; outros providers continuam com o icone ExternalLink amber. O fundo do avatar muda para branco com ring slate quando ha logo (para nao misturar com a cor do logo) e mantem o gradiente amber/yellow no fallback. Renderizacao via next/image com width/height 24 e object-contain. Arquivo: app/(app)/_components/crm-companies-section.tsx (computa providerKey/providerLogo dentro do .map dos externalIds).
MelhoriaCRM Companies (/crm/companies/{id} - aba IDs Externos): provider e external_id agora ficam na mesma linha, separados por traco (ex: 'hubspot — 454102154'). Antes o external_id era renderizado em uma segunda linha abaixo do provider. Layout: container vira `flex min-w-0 flex-1 items-center gap-2`, provider mantem `font-semibold` slate-800 com `shrink-0`, traco em slate-300/600, external_id em `tabular-nums text-xs` slate-500 com `truncate` para nao estourar. Arquivo: app/(app)/_components/crm-companies-section.tsx.
MelhoriaCRM Companies (/crm/companies/{id} - aba Oportunidades): botao '+ Nova Oportunidade' migrado do header (glass + bg-white/10) para um footer dedicado da aba, espelhando o padrao adotado em IDs Externos. O botao 'Sincronizar' permanece no header. Footer usa FormFooter com hideDefaultActions e renderiza o botao via slot `actions`. Visivel apenas quando permWrite e !isCreating. Arquivo: app/(app)/_components/crm-companies-section.tsx (remocao do bloco do header e adicao de novo ramo `activeTab === 'deals' && !isCreating` na cadeia de ternarios do footer).
MelhoriaCRM Companies (/crm/companies/{id} - botoes '+ Novo ID Externo' e '+ Nova Oportunidade' nos footers): estilo suavizado. Antes: gradiente saturado amber-500/orange-500/amber-500 com shadow-lg, animate-bgShift e shimmer no hover (mesmo visual do botao Save). Agora: pill amber clarinha com `border border-amber-200/80 bg-amber-50 text-amber-700` (h-9, px-4), hover sobe para amber-100/300, active scale-98, sem shadow nem animacao de fundo. Mantida apenas a rotacao 90deg do icone Plus no hover. Suporte dark com `border-amber-700/40 bg-amber-900/20 text-amber-300`.
MelhoriaCRM Companies (/crm/companies/{id} - botoes '+ Novo ID Externo' e '+ Nova Oportunidade'): movidos do footer dedicado para acima da lista de cada aba (header row com `mb-3 flex items-center justify-end`). Padrao CRUD mais convencional: o botao fica visivel sem rolar a lista e proximo do conteudo que ele cria. Removidos os ramos `activeTab === 'external_ids'` e `activeTab === 'deals'` da cadeia de ternarios do footer; o footer agora aparece apenas em 'details' (ou nos forms internos contract/contact/solution/task/meeting). O botao mantem o mesmo estilo soft amber adotado anteriormente.
MelhoriaCRM Companies (/crm/companies/{id} - aba Oportunidades): botao '+ Nova Oportunidade' agora compartilha a mesma linha das chips de filtro de stage. Layout: container vira `flex items-start justify-between gap-3`, chips ficam num inner div `flex flex-wrap items-center gap-1.5` a esquerda, botao com `shrink-0` ancorado a direita ao topo (mesmo quando as chips quebram em multiplas linhas). Quando nao ha deals, o botao continua aparecendo em uma linha propria acima do empty-state. Arquivo: app/(app)/_components/crm-companies-section.tsx.
NovidadeCRM Pipeline Stages: campo `icon` (emoji, ex: 🏆) adicionado conforme nova spec do swagger.json (models.CRMPipelineStage, models.CreateCRMPipelineStagePayload, models.UpdateCRMPipelineStagePayload). Tipos atualizados em lib/api/crm-pipeline-stages.ts e lib/api/crm-pipelines.ts (definicao duplicada do tipo). Form de edicao (/crm/pipeline-stages/{id}) ganhou novo FloatingInput 'Icone' (w-32, text-center, text-lg, maxLength=4, placeholder 🏆) com icone Smile amber, posicionado antes do HubSpot Object ID. Lista (/crm/pipeline-stages) prefixa o emoji ao nome do estagio na coluna Nome. Consumers atualizados para usar o icon quando presente: (1) /crm/companies/{id} aba Oportunidades - chips de filtro renderizam stage.icon como prefix em vez de Trophy/XCircle/CircleDot quando disponivel; coluna Estagio da tabela tambem prefixa o emoji; (2) /crm/deals - helper stageIcon retorna span com stage.icon antes da logica de Trophy/XCircle/icones por stage_order; (3) /crm/dashboard - PipelineBar ganhou prop opcional icon no PipelineRow e renderiza o emoji antes do nome do estagio; o lookup vem do meta de pipeline-stages via stagesByName.get().

28 de Abril de 2026

13 itens
427
NovidadeCRM Commissions (/crm/commissions - tabela Deals): icone verde de 'valores batem' agora aparece tambem para deals SEM PEP cadastrado, desde que o total dos itens (em status PENDING/PARTIALLY_PAID/PAID) seja igual ao total dos recebiveis (status pendente + pago). Antes o icone so era avaliado para deals com PEP/PEP2/PEP3 preenchido em algum item. Para deals sem PEP que nao batem, a coluna continua vazia (estado 'none'). Tooltip do icone e label do filtro 'match' atualizados para nao mencionar mais 'PEP valido'. Arquivo: app/(app)/_components/crm-commissions-section.tsx (memo dealPepStatus passou a iterar sobre allDealIds e nao mais apenas dealsWithPep).
MelhoriaCRM Deal Items (/crm/deal-items/{id} - botao Atualizar/Orbit): handleSyncOrbit agora le o campo `orbit_contract_id` do response de GET /crm/deal-items/{id}/search (novo campo conforme models.CRMDealItemSearchResponse no swagger.json), usando-o como id para preencher o campo Orbit Contract do formulario. O legado `orb_contrato` permanece como fallback caso o backend ainda nao tenha propagado o novo campo. Arquivo: app/(app)/_components/crm-deal-items-section.tsx (linha que define orbitContractId). Comportamento de PEP segue inalterado.
MelhoriaCRM Deal Items (/crm/deal-items/{id} - aba Receitas): icone da ultima coluna da tabela de receitas agora reflete `is_comission_paid` (booleano) em vez do status do recebivel (`status`). CheckCircle2 emerald-500 quando comissao paga, Clock3 amber-500 quando pendente. Tooltip e aria-label tambem atualizados ('Comissao paga' / 'Comissao pendente'). Limpeza: removidos do arquivo o helper `RECEIVABLE_STATUS_ICONS`, a chamada a `classifyStatus` (e seu import), e os imports orfaos de AlertCircle e CircleDashed.
MelhoriaCRM Deals - comission_status: enum atualizado para PENDING, PARTIALLY_PAID, PAID, EXEMPT conforme nova spec do swagger (models.CRMDeal.comission_status). O valor legado `PARTIAL_PENDING` foi substituido por `PARTIALLY_PAID` em toda a aplicacao e o novo valor `EXEMPT` (Isento) foi adicionado. Pontos tocados: (1) /crm/commissions tabela Deals - DEAL_STATUS_OPTIONS ganhou EXEMPT, getDealStatusRowClass passou a tratar EXEMPT (slate) e PARTIALLY_PAID (sky), pastilha do Select de status agora usa a mesma logica do Items (CheckCircle2/Receipt/XCircle/Clock3 com cores correspondentes), filtro padrao agora abrange PENDING+PARTIALLY_PAID, translateCommissionStatus enxuto removendo branch obsoleto. (2) /crm/deals/{id} formulario - Select de Status comissao agora oferece Pendente, Parcial, Pago e Isento; icones do trigger atualizados para tratar EXEMPT (Ban slate) alem dos antigos.
MelhoriaCRM Dashboard (/crm/dashboard): tela passou a consumir o novo endpoint agregado GET /crm/dashboard?start_date&end_date (models.CRMDashboard, swagger.json). Os tres GETs pesados que listavam deals/companies/activities inteiros para calcular indicadores client-side foram removidos - os contadores (open_deals, closed_deals, open_deals_amount, closed_deals_amount, open_activities, closed_activities, delayed_activities, my_companies, contacts, sales_amount, sales_goal, sales_goal_percent), o pipeline_stages, e os agregados closed_sales_by_month, closed_sales_by_quarter e comissions_by_month vem prontos do servidor. Continuamos buscando contracts (cards 'Contratos ativos/expirando' nao existem na nova API), receivables (necessario apenas para o drill-down do mes da comissao), pipeline-stages (precisamos de is_won/is_closed para colorir as barras do pipeline) e sales-goals (marcadores de meta no grafico trimestral). Filtro por ano agora envia start_date=YYYY-01-01&end_date=YYYY-12-31 e refaz a chamada. PipelineBar refatorado para receber linhas pre-agregadas com lookup de is_won/is_closed por nome do estagio. Novo arquivo: lib/api/crm-dashboard.ts (tipos CRMDashboard, CRMDashboardPeriodSales, CRMDashboardQuarterSales, CRMDashboardComission, CRMDashboardPipelineStage e fetchCrmDashboard). StatCard 'Empresas' agora mostra `my_companies` (empresas atribuidas ao usuario) em vez de derivar de companies.is_active; 'Contatos' mostra dashboard.contacts (contatos CRM) em vez de somar number_employees das empresas.
CorrecaoCRM Dashboard (/crm/dashboard - grafico Comissao Mes a Mes): grafico estava aparecendo vazio porque o backend retorna `month` no formato 'MM/YY' (ex: '01/26', '02/26') e o normalizeMonthKey local exigia ano de 4 digitos. Adicionada terceira regex `/^(\d{1,2})[\/-](\d{2})$/` que expande YY para 20YY (quando YY<50) ou 19YY. Mesmo tratamento aplicado ao normalizeQuarterKey (suporta 'Q1/26' alem de 'Q1/2026'/'2026-Q1'). Tambem trocado o range fixo (current month + 9 forward) por renderizacao direta do que vem em comissions_by_month, ordenado cronologicamente: agora o grafico mostra exatamente os meses retornados pela API.
MelhoriaCRM Dashboard (/crm/dashboard - cards resumo): removidos os cards 'Contratos ativos' (linha 1) e 'Contratos expirando' (fallback condicional na linha 2). Linha 1 reduzida para 3 colunas em xl (xl:grid-cols-3) com os cards remanescentes Deals abertos, Deals ganhos e Empresas. Linha 2 mantida com 4 colunas e o card 'Meta de vendas' agora sempre visivel (sem fallback). Limpeza: removido estado `contracts`, fetch fetchCrmContracts, derivacoes filteredContracts/activeContracts/totalContractValue/expiringContracts, e imports orfaos CalendarClock, ScrollText, fetchCrmContracts e tipo CRMContract.
NovidadeCRM Commissions (/crm/commissions): adicionado filtro de mes da comissao no header. Input <input type="month"> glass logo a direita da busca, com icone CalendarRange e botao X para limpar. Quando preenchido (formato YYYY-MM), filtra em cascata: (1) tabela de Recebiveis - mostra apenas registros cujo `comission_date` cai no mes; (2) tabela de Items - mostra apenas items que possuem ao menos um recebivel no mes; (3) tabela de Deals - mostra apenas deals que possuem ao menos um item com recebivel no mes. Filtro persistido no sessionStorage `crm_commissions_state_v1` (chave `commissionMonthFilter`). Implementacao via memo `monthFilterSets` que pre-computa Sets de receivable_id/item_id/deal_id matchando o mes (extractFlexibleTime do helper de datas + comparacao por prefixo YYYY-MM).
NovidadeCRM Commissions (/crm/commissions - tabela Deals): celula da coluna Deal agora exibe o `deal.name` completo via tooltip nativo (atributo `title` no TableCell) quando o usuario para o mouse sobre a linha. O texto continua truncado visualmente (max-w-[220px] + truncate), mas o nome integral fica acessivel no hover.
MelhoriaCRM Dashboard (/crm/dashboard): fetchCrmDealItemReceivables removida do load inicial. Agora os recebiveis sao carregados sob demanda, apenas quando o modal de drill-down do grafico de comissoes abre pela primeira vez (useEffect dispara fetch apenas se selectedCommissionMonth!=null e receivables===null). Cache: o fetch acontece uma vez e e reusado em aberturas subsequentes do modal. UX: loading state no modal (Loader2 amber + texto 'Carregando recebiveis...') enquanto a fetch roda. Tipo do estado mudou de CRMDealItemReceivable[] para CRMDealItemReceivable[]|null para distinguir 'nao carregado' de 'lista vazia'. Beneficio: load inicial do dashboard mais rapido (3 fetches em vez de 4); recebiveis nao sao buscados se o usuario nunca abrir o modal. fetchCrmPipelineStages e fetchCrmSalesGoals mantidos pois fornecem metadados (is_won/is_closed/stage_order) e metas mensais que nao vem em /crm/dashboard.
MelhoriaCRM Dashboard (/crm/dashboard - grafico Vendas Fechadas por Mes): quando o filtro de ano esta vazio (Todos), o grafico agora mostra os 12 meses do ano atual (Jan-Dez) em vez dos ultimos 12 meses rolantes que abrangiam dois anos. Com filtro de ano selecionado, mostra os 12 meses do ano escolhido (comportamento ja existente). A secao 'Por Trimestre' continua usando a logica original (ultimos 12 meses quando sem filtro / ano filtrado), via uma base de dados separada `quarterlyMonths` introduzida para desacoplar os dois views. As metricas 'Meta de vendas' (totalGoalAmount/totalWonAmount) seguem o monthlyClosed e portanto tambem passam a ser do ano atual por padrao.
NovidadeCRM Deal Item Receivables (/crm/deal-item-receivables): adicionado resumo de Comissao na linha de totais a direita acima da tabela, no formato 'Comissao R$ X / R$ Y' onde X (em emerald) e a soma de comission_amount dos recebiveis com is_comission_paid=true e Y (em slate-700) e a soma total de comission_amount de todos os recebiveis filtrados/sortados. Mantido ao lado do 'Total Bruto' existente, separado por dot, seguindo o mesmo padrao tipografico (mono tabular semibold, text-[11px]).
CorrecaoCRM Dashboard (/crm/dashboard - grafico Comissao Mes a Mes): rotulo de dados acima de cada barra agora aparece corretamente. O LabelList existente usava `valueAccessor` lendo `entry.paid + entry.pending` direto, mas no recharts o entry da Bar nao expoe os campos da row no nivel raiz (so via entry.payload), entao o total era sempre 0/null e nenhum rotulo era renderizado. Corrigido adicionando um campo `total` (paid+pending) ao data points de monthlyCommissions e trocando o LabelList para `dataKey="total"` com formatter que mostra `R$ XXk` quando >=1000 ou `R$ XXX,XX` caso contrario, ocultando barras vazias. Tipografia tambem ficou um pouco mais visivel (fontSize 10, fill slate-600, weight 700).

24 de Abril de 2026

60 itens
19734
NovidadeAdmin Services (/admin/services/[id]): adicionado campo 'Icone' no formulario, conforme nova spec do swagger (AdminService.icon). Campo armazena emoji (ex: 👥, 💰) seguindo o mesmo padrao de Fin Categories: FloatingInput simples com icone Tag indigo (w-44), posicionado na mesma linha que Codigo e Rota a direita de Rota (layout flex-1 / flex-1 / w-44). O avatar circular no header gradient do formulario (size-11 branco) renderiza o emoji diretamente em text-[1.5rem] quando preenchido; fallback para o icone Layers teal quando vazio. Na listagem /admin/services, o avatar circular size-8 (gradient teal-to-cyan) de cada linha tambem exibe o emoji (text-base leading-none) quando svc.icon esta preenchido, caindo para o icone Layers branco padrao quando vazio. Change tracking e partial save integrados: icon entra em initialFormValues, hasFormChanges e no payload parcial do PUT, e no payload full do POST. Tipos AdminService, CreateAdminServicePayload e UpdateAdminServicePayload em lib/api/admin-services.ts ganharam a propriedade icon?: string.
MelhoriaNavegacao (AUTH): item 'Auth Permissions' movido da secao 'Permissoes' para a secao 'Sistema', aparecendo logo abaixo de 'Admin Services'. Agora a secao 'Permissoes' concentra apenas os relacionamentos (Roles, Role Permissions, User Roles, User Permissions), enquanto 'Sistema' agrupa os cadastros base compartilhados (Services + Permissions). Arquivo tocado: app/(app)/data/nav.ts.
CorrecaoLogin: mensagem de erro agora mostra o texto especifico de error.details[].message da API (ex: 'Usuario ou senha invalidos.') em vez de 'Request failed with status code 401' ou 'Nao autorizado.' generico. lib/errors.ts (resolveErrorMessage) passou a preferir details[].message sobre error.message quando ambos existirem (details carrega a mensagem mais especifica). app/login/page.tsx: substituido extrator inline de apiMessage pela chamada resolveErrorMessage(err, fallback).
MelhoriaPermissoes (guardas de rota): checagem de acesso de TODAS as rotas agora compara service_name (que o backend envia dentro de LoginPermission carregando o code da permission, ex: 'fin/accounts') em vez de permission_id (UUID hardcoded). Em lib/auth/permissions.ts: (1) UserPermissionEntry ganhou service_name?: string|null e group?: string|null (formato exato de models.LoginPermission); (2) removidas as constantes PERM_FIN_ACCOUNTS, PERM_FIN_TRANSACTIONS, PERM_CRM_*, PERM_AUTH_* (UUIDs nao sao mais usados); (3) PERMISSION_MAP reescrito mapeando cada NavItemKey para o code correspondente (ex: 'Fin Accounts' -> 'fin/accounts', 'Fin Partners' -> 'fin/partners', 'Fin Categories' -> 'fin/categories', 'CRM Deals' -> 'crm/deals', 'Auth Users' -> 'admin/users' etc); (4) removidos legacy display keys nao utilizados (Partners, Accounts, Transactions, Empresas, Solucoes, etc - ja nao referenciados por data/nav.ts nem nav-hub-grid.tsx); (5) getPermissionLevel simplificado: busca direto por p.permission_code === code. Backend precisa retornar permission_code dentro de models.LoginPermission (alem de permission_id/permission_type) para usuarios nao-admin conseguirem acessar as rotas - admins continuam bypassando via isAdmin=true. Convencao de code segue o base path da rota sem leading slash: /fin/accounts -> fin/accounts, /admin/users -> admin/users etc.
NovidadeAdmin Users (/admin/users lista): coluna Nome agora exibe a foto de perfil do usuario no avatar circular size-8. Substituido o span com iniciais em rose gradient pelo padrao Avatar/AvatarImage/AvatarFallback usando getAuthUserImageUrl(user) (MinIO). Quando nao ha imagem disponivel (404 ou sem upload), o fallback mantem as iniciais em rose gradient (comportamento original). shadow-sm preservado para consistencia visual.
NovidadeAdmin Users (/admin/users/[id] header): avatar circular no header principal (ao lado do botao Voltar) agora exibe a foto de perfil do usuario selecionado. Substituido o placeholder fixo (icone User rose em fundo branco size-11) pelo padrao Avatar/AvatarImage/AvatarFallback ja usado no card 'Foto de perfil' da aba Detalhes, consumindo o userImageUrl existente (getAuthUserImageUrl -> minio). Quando nao ha imagem carregada, o fallback mostra as iniciais do nome/email em rose-600 sobre fundo branco; se nem formFullName nem formEmail estao disponiveis (modo criacao), mantem o icone User original. Borda branca (border-white/50 border-2) e shadow-lg preservados para combinar com o gradiente do header.
MelhoriaAdmin Users (/admin/users/[id] aba Detalhes): reorganizado em 3 colunas (grid-cols-[280px_1fr_200px]). Coluna 1 e um card rose vertical com Avatar size-32 (foto ou iniciais grandes em rose gradient), nome+email centralizados e botao 'Alterar foto' full-width abaixo (legenda 'FOTO DE PERFIL' removida). Coluna 2 empilha verticalmente Nome Completo, Email, Nova Senha, Timezone e Ultimo Login (antes estavam em subgrids 2-col). Coluna 3 reservada vazia (<div />) para uso futuro. Campo 'Criado em' removido - apenas Ultimo Login permanece como info readonly. No modo criacao (sem selectedUser) a coluna da foto e omitida e os campos voltam a ocupar largura total.
MelhoriaAuth User Permissions: modelo `effect: allow|deny` substituído por `permission_type: READ|WRITE|ADMIN` conforme nova spec do swagger (models.AuthUserPermission). Rotas corrigidas de PUT/DELETE `/auth/user-permissions/:user/:perm` para `/admin/user-permissions/:user/:perm`. Filtro de listagem, sort key e badge da coluna passaram de Allow/Deny (emerald/rose) para Read/Write/Admin com paleta escalonada (sky → amber → emerald) e ícones Eye/Pencil/Crown. Na tela de edit do usuário (/admin/users/[id] aba Permissions), o painel AuthUserPermissionsPanel agora tem 3 StatPills (Read, Write, Admin), 4 filtro pills (Todas, Read, Write, Admin), toggle de 3 botões por item atribuído e 3 botões de 'Adicionar' por item do catálogo. permissionTotals recalculado para contar read/write/admin; removido bloco morto legado wrapped em `{false && ...}` da seção. Arquivos tocados: lib/api/auth-user-permissions.ts, app/(app)/_components/auth-user-permissions-panel.tsx (reescrito), app/(app)/_components/auth-user-permissions-section.tsx, app/(app)/_components/auth-users-section.tsx.
MelhoriaAuth Permissions (/admin/permissions): campo Notas do formulário unificado com o padrão do Admin Services. Substituído o FloatingInput por um Textarea (3 linhas, min-h 96px, resize-none) envolvido em container rounded-xl com ícone StickyNote à esquerda e label 'NOTAS' flutuante em uppercase cyan. Indicador visual de alteração (borda cyan + shadow) segue o mesmo padrão dos outros campos com hasChanged, e o hover suaviza para cyan-50.
MelhoriaAuth Permissions: campo `description` renomeado para `notes` conforme nova spec do swagger (models.AuthPermission, CreateAuthPermissionPayload, UpdateAuthPermissionPayload). Atualizados o tipo em lib/api/auth-permissions.ts e todos os pontos de leitura/escrita: auth-permissions-section.tsx (form state formNotes/setFormNotes, initialFormValues.notes, coluna da tabela 'Notas' com sort key 'notes', label do FloatingInput, payloads de create/update, busca full-text), auth-permission-autocomplete.tsx (filtro de busca), auth-users-section.tsx (buildPermissionSearchText), auth-roles-section.tsx (busca em availablePermissions) e auth-user-permissions-section.tsx (busca composta user+permission).
NovidadeAuth Permissions (/admin/permissions): adicionada seleção múltipla na listagem com exclusão em lote. Primeira coluna da tabela passou a ter checkbox (estilo rose/red, 18x18 com check SVG), e o header tem checkbox mestre que seleciona/desseleciona todas as permissões filtradas na lista atual. Quando pelo menos uma está selecionada, aparece barra rose acima da tabela (gradient rose-50 → white → rose-50) com contador, texto 'permissão(ões) selecionada(s)', botão 'Limpar seleção' (rose) e botão 'Excluir selecionadas' (red-600). A exclusão usa Promise.allSettled contra DELETE /admin/permissions/{id} em paralelo, remove as permissões excluídas da lista local e mostra toast com contagem de sucessos/falhas. ConfirmDeleteDialog reutilizado com entityLabel dinâmico conforme quantidade selecionada.
NovidadeAdmin Services (/admin/services): criada pagina CRUD completa para gestao dos servicos do sistema, seguindo o mesmo padrao visual/comportamental do CRUD de permissions (theme admin/rose). Lista com colunas Nome (avatar circular teal-to-cyan com icone Layers + nome), Codigo (badge rose mono), Rota (mono), Status (badge emerald Ativo / red Inativo) e Criado em (relativo), com busca (name/code/route/id), ordenacao por todas as colunas e botao 'Novo Serviço'. Formulario: Nome + toggle local ATIVO/INATIVO na primeira linha, Codigo (mono, amber Code2) e Rota (mono, sky Link2) em grid 2 colunas. Change tracking por campo com partial save (PUT so envia campos alterados); is_active entra no toggle visual convertido via String() para comparacao no initial ref. Endpoints: GET /admin/services (lista com filtros code/name/route/is_active), POST /admin/services (create requer code+name), GET /admin/services/{id}, PUT /admin/services/{id} (update parcial), DELETE /admin/services/{id}. Novos arquivos: lib/api/admin-services.ts (ampliado com fetchAdminService/create/update/delete), app/(app)/_components/admin-services-section.tsx, app/(app)/features/admin/services/admin-services-screen.tsx, app/(app)/admin/services/{page,new/page,[id]/page}.tsx. Integracao de navegacao: 'Admin Services' adicionado em data/nav-routes.ts (basePath /admin/services), data/nav.ts (grupo AUTH com nova secao 'Sistema'), _components/nav-hub-grid.tsx (meta com icone Layers e gradient teal-to-cyan) e lib/auth/permissions.ts (PERMISSION_MAP aponta para PERM_AUTH_PERMISSIONS).
MelhoriaDeal Items (/crm/deal-items/[id] - aba Detalhes): campo 'Orbit Contract ID' convertido de FloatingInput livre para autocomplete CrmContractAutocomplete (icone ScrollText orange, dropdown via createPortal z-[9999], navegavel por ArrowUp/ArrowDown/Enter/Escape). Busca contratos via GET /crm/contracts filtrado pela company_id da oportunidade vinculada (derivada de deals.find(d.id === formDealId)?.company_id). Quando o deal nao tem company, cai para lista geral. Filtra client-side por codigo, descricao, orbit_object_id ou company_domain (normalizado, ate 8 resultados). Cada item mostra a descricao do contrato em destaque e abaixo em fonte mono o codigo e o orbit_object_id com icone Hash. Valor armazenado continua sendo o orbit_object_id (string) salvo em orbit_contract_id - ao carregar um item existente, o autocomplete resolve o contrato correspondente e exibe o codigo/descricao no input; quando nao encontra match (ex: Orbit trouxe valor ainda nao sincronizado ou contrato de outra company), mostra o raw id. Botao X limpa o campo. Novo arquivo app/(app)/_components/crm-contract-autocomplete.tsx, reutilizando o padrao de crm-deal-autocomplete.tsx.
MelhoriaAuth Permissions (/admin/permissions): CRUD atualizado conforme nova spec do swagger. Schema da AuthPermission passou a ter service_id (FK para /admin/services) no lugar dos campos group/subgroup que nao existem mais, e ganhou created_by/updated_at/updated_by. Endpoints de update e delete corrigidos de /auth/permissions/:id para /admin/permissions/:id (o bug atingia Salvar e Excluir na tela de edicao). Formulario recebeu FloatingSelect Servico (teal) com options carregadas de fetchAdminServices, lista ganhou coluna Servico ordenavel entre Codigo e Descricao, busca agora considera o nome do servico, payloads de create/update agora enviam service_id como campo opcional. Novo arquivo lib/api/admin-services.ts encapsula GET /admin/services (fetchAdminServices) reutilizado tambem em auth-users-section.tsx, onde o agrupamento de permissions na aba do usuario passou a usar o nome do servico (via service_id → servicesById) em vez de permission.group/subgroup. Removido o arquivo obsoleto lib/api/permissions.ts que apontava para o endpoint /permissions descontinuado.
NovidadeUser Permissions (/admin/user-permissions): criada pagina CRUD completa para gestao de permissoes por usuario. Lista com avatar+nome do usuario, nome+codigo da permissao, badge de efeito (Allow emerald / Deny rose) e timestamp relativo, com busca por usuario/permissao e filtro por efeito (Todas / Allow / Deny). Formulario Nova permite selecionar usuario e permissao via autocompletes (AuthUserAutocomplete reutilizado + AuthPermissionAutocomplete novo) e alternar o efeito via toggle Allow/Deny. Formulario Edit trava a permissao e o usuario (readonly) e permite apenas alterar o efeito, seguindo a API (PUT so aceita { effect }). Rota composta /admin/user-permissions/[user_id]/[permission_id] para edicao, consistente com a chave composta do backend. Integrado a theme admin (rose) e ao padrao FormFooter + ConfirmDeleteDialog do projeto.
MelhoriaFin Installment Groups (/fin/installment-groups lista): coluna Parceiro agora exibe a logo dentro de um avatar circular size-7 (padrao visual usado em fin-transactions-table) - favicon do partner_domain com fallback Users indigo quando nao ha dominio. Antes era apenas um mini favicon size-4 rounded-sm sem wrapper, que desaparecia quando o parceiro nao tinha dominio cadastrado.
MelhoriaFin Partners (/fin/partners lista): textos das celulas (nome do parceiro, categoria, conta) trocados de text-sm (14px) para text-[13px] para leitura mais compacta. Document/subtitulo permanece text-[11px].
NovidadeFin Partners (/fin/partners lista): adicionadas colunas Criado e Atualizado a direita de Conta (esquerda de Status). Criado mostra a data dd/MM/yy em tabular-nums com icone Calendar violet a esquerda. Atualizado mostra data relativa via formatRelativeTimeLong ('ha 5 horas', 'ha 2 dias' etc) com icone Clock3 sky a esquerda, e tooltip (title=) com a data/hora completa no pt-BR. Ambas colunas sao ordenaveis via SortKey 'created_at' e 'updated_at' (comparacao por string ISO). Fallback '-' quando o partner nao tem timestamp.
MelhoriaFin Accounts (/fin/accounts header): filtros Tipo e Status trocados dos <select> nativos pelo componente HeaderStatusFilter (mesma API generica de options, label, placeholder, minWidth). Tipo recebe 4 opcoes mapeadas a partir de ACCOUNT_TYPE_LABELS+ACCOUNT_TYPE_STYLES, cada uma com o Icon e a cor correspondente (Landmark violet, CreditCard pink, TrendingUp emerald, HandCoins amber). Status tem duas opcoes: Ativos (FilledCheckCircle emerald) e Inativos (XCircle slate). Botao X de 'Limpar filtros' do header removido (cada filtro ja tem seu proprio X). FilledCheckCircle extraido para app/(app)/_components/filled-check-circle.tsx para reuso entre fin-partners-section e fin-accounts-section.
NovidadeHeaderStatusFilter (app/(app)/_components/header-status-filter.tsx): novo componente glass no mesmo estilo dos demais Header*Filter, agora generico para status. API flexivel via prop options (StatusOption[]: { value, label, Icon?, iconColor? }), permite qualquer conjunto de status. Avatar circular size-6 exibe o Icon da opcao selecionada (CheckCircle2 default) com a cor informada; popover lista as opcoes (sem campo de busca - lista pequena). X para limpar quando ha valor. Aplicado em /fin/partners header com opcoes Ativo (CheckCircle2 emerald) e Inativo (XCircle slate), substituindo o <select> nativo de Status.
NovidadeHeaderCategoryFilter (app/(app)/_components/header-category-filter.tsx): novo componente glass no mesmo estilo de HeaderAccountFilter/HeaderOwnerFilter, especifico para FinCategory. Avatar circular size-6 mostra o icon/emoji da categoria com fallback Tag amber; popover com busca normalizada por nome, navegacao por teclado e X para limpar. Props: categories (FinCategory[]), value, onChange, label, placeholder, minWidth.
MelhoriaFin Partners (/fin/partners header): filtros de Categoria e Conta trocados dos <select> nativos para HeaderCategoryFilter e HeaderAccountFilter (mesmos componentes usados em /fin/conciliacao-cartao e /fin/installment-groups). usedCategoryIds/usedAccountIds (so ids) viraram usedCategories/usedAccounts (FinCategory[]/FinAccount[]), filtrando e ordenando a partir de allCategories/allAccounts para preservar icon/partner_domain para os componentes. minWidth passado como '180px' para nao estourar a linha do header.
MelhoriaFin Installment Groups (/fin/installment-groups header): filtro de status (Pendentes/Todos) mantido como pill unico que alterna ao clique, mas redesenhado para sinalizar claramente que e interativo (antes parecia um badge somente leitura). Agora o botao tem (1) icone de estado a esquerda (Clock3 para Pendentes, Layers para Todos), (2) valor atual ('Pendentes' ou 'Todos'), (3) icone ArrowDownUp a direita indicando toggle (rotaciona 180deg no hover), (4) animacao de scale-[1.03] no hover. role=switch + aria-checked + title dinamico ('Clique para mostrar todos'/'Clique para mostrar apenas os pendentes') garantem semantica e affordance claras.
MelhoriaFin Installment Groups (/fin/installment-groups lista): colunas Pagas, Pend. e Total (contadores de parcelas) agora tem padding horizontal reduzido de px-3 para px-1.5 tanto no header quanto nas celulas, deixando o trio visualmente agrupado. Header tambem recebeu justify-center nos botoes de sort para centralizar o label+icone quando o conteudo e curto.
MelhoriaFin Installment Groups (/fin/installment-groups lista): coluna Categoria agora exibe o icone/emoji da categoria dentro de um avatar circular size-7 com fundo branco, borda branca e sombra, seguindo o mesmo padrao da coluna Parceiro. Fallback usa icone Tag amber quando nao ha category_icon. Antes era apenas o emoji solto em text-sm leading-none.
MelhoriaFin Installment Groups (/fin/installment-groups lista): coluna Transacao agora centralizada (header + celulas). Header recebeu text-center e justify-center no botao de sort; celulas recebem text-center.
NovidadeFin Installment Groups (/fin/installment-groups header): filtros de Owner e Conta agora sao encadeados. Selecionar um owner restringe accountOptions para apenas contas cujo owner_id bate com o owner selecionado; selecionar uma conta restringe ownerOptions para apenas o owner dessa conta. Implementado via filtro extra nos useMemo de ownerOptions/accountOptions (leitura de accountOwnerMap + selectedOwnerId/selectedAccountId).
NovidadeHeaderOwnerFilter (app/(app)/_components/header-owner-filter.tsx): novo componente glass no mesmo estilo do HeaderAccountFilter, agora para AuthUser. Avatar usa image_url do usuario (com User icone fallback quando nao ha foto), label 'OWNER' + nome (full_name ?? email), popover portal com busca normalizada por full_name/email + navegacao por teclado + X para limpar. Itens da lista mostram duas linhas (nome em cima, email embaixo) quando ambos existem. Props: owners (AuthUser[]), value, onChange, label, placeholder, minWidth. /fin/installment-groups substituiu o <select> nativo 'Todos owners' do header pelo novo componente; ownerOptions passou a retornar AuthUser[] em vez de {id,label} para preservar image_url/full_name/email no componente.
MelhoriaHeaderAccountFilter (app/(app)/_components/header-account-filter.tsx): extraido o filtro compacto de conta do header de /fin/conciliacao-cartao (glass pill com favicon a esquerda, label 'CONTA' + nome da conta selecionada, popover portal com busca normalizada + navegacao por teclado + botao X para limpar) para um componente reutilizavel. Props: accounts (FinAccount[]), value (id), onChange, label, placeholder, minWidth. /fin/conciliacao-cartao passou a consumir o componente (removidos os states accountPopoverOpen/accountSearch/accountHighlight/accountFieldRef, o selectedAccount memo, o filteredAccountOptions memo e o effect de click-outside, alem dos imports Landmark que ficou orfao). /fin/installment-groups substituiu o <select> nativo 'Todas contas' do header pelo mesmo componente (accountOptions agora filtra allAccounts pelos ids que aparecem nos groups, preservando partner_domain e account_number para o componente).
MelhoriaFin Installment Groups (/fin/installment-groups/{id} aba Transacoes): Sheet de edicao de transacao alinhado com o padrao das demais telas (partners/recurrences/fluxo-caixa). Antes o Sheet usava um TxSheetContent interno que fazia fetchFinTransaction + FinTransactionsSection com initialMode='edit' (pattern antigo). Agora usa FinTransactionForm direto com partners/categories/accounts ja carregados no useEffect da section e classe do SheetContent centralizada (!left-1/2 !-ml-[440px] !top-[70px] !h-[calc(100vh-140px)] !w-[880px] !border-0 !bg-transparent). onUpdate atualiza a tx dentro de groupTxs, onDelete remove e fecha, onReload chama loadGroupTransactions. Removidos: TxSheetContent helper, fetchFinTransaction import.
NovidadeFin Recurrences (/fin/recurrences/{id} aba Transacoes): clicar em uma linha da tabela agora abre o Sheet centralizado (880px x calc(100vh-140px)) com o FinTransactionForm para edicao em contexto, ao inves de navegar para /fin/transactions/{id}?return_to=.... onUpdate atualiza o item dentro de recTxs, onDelete remove e fecha o sheet, onReload recarrega as transacoes da recorrencia via fetchFinTransactionsByRecurrence. Reutiliza os autocompletes ja carregados (allPartners/allCategories/allAccounts) da section. useRouter removido (nao havia mais uso).
NovidadeFluxo de Caixa (/fin/fluxo-caixa): clicar em uma transacao dentro da expansao do dia agora abre um Sheet centralizado com o FinTransactionForm carregado para edicao em contexto (mesmo padrao usado em /fin/partners/{id} aba Transacoes), ao inves de navegar para /fin/transactions/{id}. fetchFinTransaction carrega os dados completos da tx (os itens expandidos so tem um subset dos campos), e spinner violet fica no lugar do form enquanto o GET roda. onUpdate/onDelete/onReload invalidam dayDetails e recarregam o fluxo-caixa para refletir alteracoes (datas, valores, pagamento, exclusao). partners e categories agora sao carregados junto com accounts para alimentar os autocompletes do form.
NovidadeFin Transactions (/fin/transactions): ao ordenar pelas colunas Referencia, Vencimento ou Pagamento, a tabela agora destaca a transicao entre dias com uma borda superior violet 2px (border-t-violet-300/70 dark:border-t-violet-500/40) na primeira linha de cada novo dia. Implementado em fin-transactions-table.tsx via useMemo que calcula dayKeys (YYYY-MM-DD via extractFlexibleTime) somente quando sortKey e uma das colunas de data. Sem efeito ao ordenar por Parceiro, Categoria, Conta, Valor ou Parcelas.
MelhoriaFin Partners (/fin/partners/{id} aba Transacoes): colunas Recorrencia e Status agora autosize com padding reduzido (w-px whitespace-nowrap px-1) ao inves de w-10 com px-4 padrao - headers e cells encolhem ao tamanho minimo do conteudo (icones), liberando espaco para as colunas de dados. Colunas Categoria e Conta ganharam whitespace-nowrap nos TableCells para evitar quebra de linha no texto.
MelhoriaFin Transactions (/fin/transactions coluna Valor): regra de coloracao da fonte expandida em fin-transactions-table.tsx. Vermelho agora cobre EXPENSE + TRANSFER_OUT + INVESTMENT_OUT; verde cobre INCOME + TRANSFER_IN + INVESTMENT_IN (antes so EXPENSE/INCOME eram coloridos, demais caiam no cinza). Alinhado com totais do cabecalho e com o padrao ja em uso em extrato-bancario/conciliacao-bancaria/balancete.
CorrecaoFin Transactions (edicao): apagar o campo Pago em e salvar agora envia paid_at: null no payload do PUT (antes enviava undefined, que o axios omite do JSON, fazendo o backend manter o valor antigo). Ajuste em getChangedPayload (lib/hooks/use-fin-transaction-form.ts): state.paidAt || null em vez de || undefined - assim o usuario consegue de fato 'desmarcar' uma transacao paga.
MelhoriaFin Partners (/fin/partners/{id} aba Transacoes): coluna Status deixou de ser ordenavel - cabecalho agora e um TableHead vazio com aria-label 'Status' (sem botao, sem icone de sort). Sort key 'is_paid' removido de TxSortKey e do switch de ordenacao.
NovidadeFin Partners (/fin/partners/{id} aba Transacoes): clicar em uma transacao agora abre um Sheet centralizado na tela (720px de largura x calc(100vh-120px) de altura, centralizado via left:50% / -ml:-440px / top:70px com dimensoes 880px x calc(100vh-140px) (exatamente as mesmas do container interno do FinTransactionForm); SheetContent ganhou !border-0 !bg-transparent !shadow-none para nao desenhar um segundo card por cima do form sem conflito de transform com as animacoes do radix) com o FinTransactionForm carregado para edicao em contexto - sem navegar para outra pagina. onUpdate atualiza a transacao dentro da lista do parceiro, onDelete remove e fecha o sheet, Voltar fecha o sheet. FinPartnersSection ganhou prop initialTab ('details'|'aliases'|'transactions'); FinPartnersScreen le ?tab= e propaga, permitindo deep-link para a aba desejada; se initialTab='transactions', loadTransactions roda junto com loadAliases no useEffect de applying initialMode.
MelhoriaFin Partners (/fin/partners/{id} aba Transacoes): coluna de recorrencia voltou a ser dedicada (separada de Status), mas agora so aparece se pelo menos uma das transacoes do parceiro tiver recurrence_id. Flag hasRecurringTx (useMemo sobre transactions) controla header e celula condicionalmente.
NovidadeFin Partners (/fin/partners/{id} aba Transacoes): adicionada coluna de conferencia (is_checked) a direita de Status. Botao clicavel na propria tabela (stopPropagation para nao navegar) alterna CheckCircle2 emerald (conferido) / Circle slate (nao conferido), com Loader2 spinner enquanto o PUT /fin/transactions/{id} { is_checked } roda. Update otimista com rollback em caso de erro + toast. Estado local checkingTxIds (Set<string>) controla o spinner por linha.
MelhoriaFin Partners (/fin/partners/{id} aba Transacoes): titulo 'Status' do cabecalho removido (restou apenas o icone de ordenacao). Adicionada uma coluna de recorrencia entre Parcela e Status, exibindo a pastilha violet com icone Repeat2 (size-6 bg-violet-100) quando tx.recurrence_id esta preenchido, seguindo o mesmo padrao da tabela principal de transacoes.
MelhoriaFin Partners (/fin/partners/{id} aba Transacoes): coluna Valor passou a mostrar apenas o numero (sem prefixo 'R$' e sem sinal '- '/'+'), com cor red-600 para transacoes de categoria EXPENSE e emerald-600 para as demais (INCOME/TRANSFER/INVESTMENT). Coluna Status deixou de exibir badge com texto 'Pago'/'Pendente' e passou a mostrar apenas icone centralizado - CheckCircle2 emerald para pagos e Clock3 amber para pendentes, com aria-label para acessibilidade. Adicionada coluna Parcela a direita de Valor, exibindo pill violet 'N/Total' (mesmo estilo da tabela principal em /fin/transactions) quando installment_number existir, ou '-' quando nao for parcelada; coluna sortable por installment_number.
MelhoriaAutocompletes: busca passou a ignorar acentos. Todos os componentes em app/(app)/_components/*-autocomplete.tsx (FinAccount, FinCategory, FinPartner, CrmCompany, CrmContact, CrmDeal, AuthUser) agora usam normalizeText (NFD + strip diacritics + lowercase) no termo buscado e nos campos comparados (nome, documento, email, dominio, tax_id, cargo, owner_name, account_number). Mesma normalizacao aplicada aos autocompletes inline do modal de filtros de transacoes (FinTransactionsFilterModal: partner/category/account) e do /fin/conciliacao-cartao (popover Conta no header + InlineCategoryAutocomplete + InlinePartnerAutocomplete). Assim 'cafe' encontra 'Cafe' e 'Cafeteria' encontra 'Cafeteria', independente de acentuacao no input ou no dado.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): avatar da categoria no InlineCategoryAutocomplete agora tem fundo transparente. Removidas as classes bg-amber-50/bg-slate-100 e rounded-full do container; apenas o icone (emoji ou Tag fallback) aparece, ocupando o espaco size-5. Aplicado tanto na celula quanto na lista do popover.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): icone da categoria no InlineCategoryAutocomplete agora ocupa praticamente todo o espaco do avatar. Emoji passou de text-[11px] (herdado) para text-[14px] e fallback Tag de size-3 para size-4 - ambos dentro do circulo size-5. Adicionado overflow-hidden para garantir que conteudo nao vaze. Vale tanto para a celula quanto para a lista do popover.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): titulo da coluna Valor em ambas as tabelas passou a ser centralizado (justify-center text-center). Antes estava a direita; os valores das celulas continuam alinhados a direita por convencao monetaria.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): ordem do toolbar da tabela Fatura Excel ajustada - o grupo de filtros de status (Todos/Conciliados/Pendentes/Divergentes) agora aparece depois do campo Buscar. Com o ml-auto no input de busca, os filtros ficam encostados na borda direita do toolbar, alinhados verticalmente com a coluna de Status na tabela em vez de ficarem soltos no meio do cabecalho.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): titulo da coluna Parcela na tabela Fatura Excel removido. A coluna continua visivel e ordenavel (o button do cabecalho continua clicavel exibindo o icone de ordenacao quando ativo), apenas o label textual foi removido para dar mais espaco visual.
CorrecaoConciliacao de Cartao (/fin/conciliacao-cartao): valores da coluna Valor em ambas as tabelas ganharam display:block - antes o span era inline e text-right nao alinhava o conteudo a direita da celula, fazendo o numero ficar mais a esquerda que o titulo Valor. Agora o span ocupa a celula inteira do grid e o text-right funciona como esperado.
CorrecaoConciliacao de Cartao (/fin/conciliacao-cartao): titulo da coluna Pgto da tabela Sistema agora e centralizado. Span ganhou display:block para ocupar o grid-cell inteiro, permitindo que o text-center de fato centralize o texto.
CorrecaoConciliacao de Cartao (/fin/conciliacao-cartao): titulo da coluna Parcela da tabela Fatura Excel agora e alinhado ao centro. Mesma correcao da coluna Valor: trocado align de 'text-center' para 'justify-center text-center' para posicionar os filhos flex (label + icone de ordenacao) no centro do cabecalho.
CorrecaoConciliacao de Cartao (/fin/conciliacao-cartao): titulo da coluna Valor em ambas as tabelas agora e alinhado a direita. Antes o align usava apenas 'text-right', mas como o cabecalho e um button com display:flex (label + icone de ordenacao), a classe de texto nao posicionava os filhos flex. Ajustado para 'justify-end text-right'.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): coluna Data de ambas as tabelas passou a exibir o formato dd/MM/yy (2 digitos no ano) para deixar a tabela mais compacta e alinhada com a coluna Parcela. Helper local formatDateBrShort adicionado. PDF e demais usos de formatDateBr permanecem em dd/MM/yyyy.
NovidadeConciliacao de Cartao (/fin/conciliacao-cartao): coluna Descricao (parceiro) de ambas as tabelas agora usa autocomplete compacto com favicon como avatar (circulo branco size-5 com favicon do dominio do parceiro, ou icone Users indigo fallback). Clicar abre popover com busca por nome/documento, navegacao por teclado e botao X para limpar. Na tabela Fatura: o fallback text quando nao ha parceiro e a descricao original do Excel (stmtTx.description). Na tabela Sistema: o fallback e notes; mudanca dispara updateFinTransaction com rollback otimista e propagacao automatica da category_id do parceiro quando aplicavel. Componente InlinePartnerAutocomplete adicionado no mesmo arquivo.
NovidadeConciliacao de Cartao (/fin/conciliacao-cartao): coluna Categoria de ambas as tabelas (Fatura Excel e Sistema) agora usa autocomplete compacto com icone da categoria como avatar (circulo amber size-5 com emoji/icone da categoria, ou Tag fallback). Clicar na celula abre um popover (portal) com campo de busca autofocado, lista scrollavel com icone+nome e navegacao por teclado (setas/Enter/Esc). Na tabela Fatura a selecao grava em rowOverrides (comportamento atual). Na tabela Sistema a mudanca dispara updateFinTransaction com rollback otimista em caso de erro e toast de feedback. Componente InlineCategoryAutocomplete adicionado no proprio arquivo.
CorrecaoAuth Tokens (/admin/tokens/{id}): corrigida rota da API usada pelo client de tokens de verificacao. fetchAuthVerificationToken, updateAuthVerificationToken e deleteAuthVerificationToken passaram de GET/PUT/DELETE /auth/tokens/{id} para /admin/tokens/{id} - path correto conforme swagger.json (tag 'Auth Tokens'). Endpoint /auth/tokens/{id} nao existe na API, entao a tela de edicao/exclusao retornava 404.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): filtros de Conta e Vencimento do header principal redesenhados para glass pills compactos (h-9) com maior contraste sobre o gradiente violeta - border-white/40, bg-white/20, backdrop-blur, hover border-white/60 + bg-white/30. Cada pill mostra favicon/icone em circulo branco a esquerda, label curto 'CONTA'/'VENCIMENTO' em uppercase branco 70% e valor em texto branco semibold logo abaixo. Funcionalidades preservadas: busca de conta via popover com autofocus, navegacao por teclado (setas + Enter + Esc), botao X para limpar conta; data abre o date picker nativo via showPicker. Removidos os imports FinAccountAutocomplete e FloatingDateInput deste header.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): subtitulo do header (que exibia 'Venc. <data> - <periodo>' ou 'Importe a fatura...') removido. O header agora mostra apenas o titulo 'Conciliacao de Cartao', deixando o contexto de vencimento por conta do card 'VENCIMENTO' no proprio header.
MelhoriaConciliacao de Cartao (/fin/conciliacao-cartao): filtros de status da tabela Fatura Excel (Todos, Conciliados, Pendentes, Divergentes) passaram a ser icon-only (Layers violet, CheckCircle2 emerald, Clock amber, AlertCircle red). Cada botao e um quadrado size-7 com cor de fundo correspondente quando ativo. O label continua disponivel via title/aria-label para acessibilidade.
NovidadeConciliacao de Cartao (/fin/conciliacao-cartao): ao selecionar um registro em uma das tabelas (Fatura ou Sistema), o par correspondente na tabela oposta agora e rolado automaticamente para dentro da area visivel quando estiver fora do campo de visao. Usa scrollIntoView com block:nearest, entao linhas ja visiveis nao causam salto.

22 de Abril de 2026

59 itens
21434
MelhoriaCRM Deal Items (/crm/deal-items): coluna Oportunidade passou a ser a primeira da tabela, seguida de Nome. Header e celulas do corpo trocados; larguras do skeleton ajustadas (w-32 na coluna Oportunidade, w-40 na coluna Nome) para manter o ritmo visual. Ordenacao padrao (name asc) nao mudou.
NovidadeFloatingDateInput: clicar no icone de calendario agora abre o date picker nativo do navegador (showPicker). Antes o icone era so decorativo; agora ele vira um botao que dispara um input type="date" invisivel posicionado no icone, preservando todo o parser inteligente do input visivel (+5, -3, 25/03, 2026-03-25). Tambem adicionado onIconClick no FloatingInput para habilitar icones clicaveis em outros contextos. Afeta todas as telas que usam FloatingDateInput (CRM activities, deals, contracts, deal-item-receivables, companies, emails e telas fin).
MelhoriaCRM Deal Items (/crm/deal-items): pagina de listagem alinhada com o estilo das demais paginas do projeto. Header ganhou sheen de luz decorativo, botao 'X' para limpar a busca e badge contador de itens a direita (padrao sectionThemes.counterBg). Botao 'Novo Item' migrou de glass para shadcn Button branco com gradiente amber (igual 'Nova Empresa'). Card da tabela trocou 'rounded-2xl border bg-white/80' por 'bg-white/30 backdrop-blur-xl' com theme.border. TableHeader agora e sticky top-0 e celulas de cabecalho usam o padrao amber-100/yellow-100 (theme.tableHeader). Loading state passou de spinner centralizado para 5 skeleton rows com bg-zinc-200/70 animate-pulse. Empty state ficou dentro da tabela (TableRow colSpan=6), padrao das demais listas. Gap externo aumentou de gap-3 para gap-4.
NovidadeCRM Deal Items: adicionado campo can_sync no CRUD (tipo CRMDealItem, CreateCRMDealItemPayload, UpdateCRMDealItemPayload e formulario). Toggle StatusToggleBadge ('Sincroniza'/'Nao sincroniza', default ligado) aparece na linha de Oportunidade/Orbit Contract ID do form. Change tracking e partial save incluem o novo campo.
NovidadeCRM Companies: adicionado campo sap_seidor_id no CRUD (tipo CRMCompany, createCrmCompany, updateCrmCompany e formulario). Campo 'SAP/Seidor ID' (icone Fingerprint teal) passou a ocupar a quarta coluna da linha CNPJ/Dominio/Responsavel, que virou grid-cols-4. Change tracking e partial save incluem o novo campo.
NovidadeCRM Deal Items: adicionados campos PEP 2 e PEP 3 no CRUD (tipo, create/update payloads, formulario de edicao). Os tres campos ficam agrupados em uma linha propria entre Nome/Status e Oportunidade; busca da lista tambem passa a considerar PEP 2 e PEP 3.
MelhoriaCRM Deal Items: HubSpot Line Item ID e HubSpot Product ID movidos para a linha 1 do formulario, a esquerda do Status (Nome flex-1 | Line Item w-44 | Product w-44 | Status w-40). Orbit Contract ID passou para a direita de Oportunidade (flex-1 | w-64), eliminando a linha dedicada a IDs externos.
CorrecaoCRM Deal Items: botao 'Sincronizar' (Orbit) no header do formulario agora so aparece na aba Detalhes. Antes vazava para a aba Receitas junto com o 'Sincronizar Receitas'.
NovidadeCRM Deal Items: ao clicar em 'Sincronizar Receitas' com PEP, PEP 2 e PEP 3 todos vazios, o sistema agora bloqueia a chamada e exibe toast de erro 'E obrigatorio informar o PEP para sincronizar'.
MelhoriaCRM Commissions: coluna Status da tabela Deals agora mostra apenas o icone (pastilha h-6 w-6 com CheckCircle2/Receipt/Clock3), sem texto. Tooltip e aria-label preservam o label. Header ficou centralizado com w-10, exibindo apenas o icone de ordenacao (titulo 'Status' removido); ao clicar na pastilha abre dropdown shadcn para trocar o status.
NovidadeCRM Commissions: tabela Deals ganhou uma coluna a esquerda de Status com um BadgeCheck emerald quando ao menos um item do deal tem PEP, PEP 2 ou PEP 3 preenchido. Coluna vazia quando nenhum item possui PEP.
NovidadeCRM Deal Items (aba Receitas): tabela ganhou coluna de checkbox (com select-all tri-state no header). Quando ha selecao, botao 'Excluir Selecionados (N)' aparece no header do formulario em estilo vermelho e dispara ConfirmDeleteDialog; confirmacao faz DELETE em paralelo via Promise.allSettled, reporta parciais via toast e recarrega a lista. Selecao e limpa ao sair da aba ou trocar de item.
NovidadeCRM Deal Items (aba Receitas): somatorio compacto adicionado acima da tabela - uma linha discreta alinhada a direita com 'N parcelas · Total Bruto R$ X' em slate-500, valor em mono tabular. Sem cards coloridos.
MelhoriaCRM Deal Items (aba Receitas): coluna Status passou a exibir apenas icone (sem texto) - CheckCircle2 emerald (paid), Clock3 amber (pending), AlertCircle red (overdue), XCircle slate (cancelled), CircleDashed slate (unknown). Texto original fica como tooltip/aria-label.
MelhoriaCRM Deal Items (aba Receitas): tipografia das celulas da tabela reduzida de 13px para 12px para leitura mais compacta. Cabecalhos permanecem em 11px.
MelhoriaCRM Deal Items (aba Receitas): coluna 'Valor Liquido' removida; adicionada coluna 'Faturamento' (billing_date) entre Valor Bruto e Vencimento, mantendo as duas datas agrupadas na ordem cronologica natural (faturamento - vencimento).
NovidadeCRM Deal Items (aba Receitas): adicionada coluna 'Pagamento' (payment_date) apos Vencimento, completando o fluxo cronologico Faturamento - Vencimento - Pagamento.
MelhoriaCRM Deal Items (aba Receitas): datas das colunas Faturamento, Vencimento e Pagamento formatadas como dd/MM/yy (ano 2 digitos) para tabela mais compacta.
NovidadeCRM Deal Items (aba Receitas): adicionada coluna 'Atualizado' (updated_at_source, dd/MM/yy) entre Pagamento e Status, para mostrar quando a receita foi atualizada na origem.
MelhoriaCRM Deal Items (aba Receitas): titulo 'Status' removido do cabecalho da coluna (coluna agora so mostra o icone). aria-label preservado para acessibilidade.
MelhoriaCRM Deal Items (aba Receitas): colunas Parcela, Referencia, Faturamento, Vencimento, Pagamento, Atualizado e Status alinhadas ao centro (header + celulas). Valor Bruto permanece a direita e checkbox a esquerda.
NovidadeCRM Deal Items (aba Receitas): tabela ganhou ordenacao por coluna. Ordenacao padrao Vencimento ASC; colunas Parcela, Valor Bruto, Faturamento, Vencimento e Pagamento agora sao clicaveis (cabecalhos em cursor-pointer com icones ArrowUp/ArrowDown) e alternam ASC/DESC. Datas vazias sao enviadas para o fim da lista em ASC via Number.POSITIVE_INFINITY.
NovidadeCRM Deal Items (aba Receitas): linhas da tabela agora sao clicaveis. Clicar em uma receita navega para /crm/deal-item-receivables/{id} com return_to apontando para /crm/deal-items/{dealItemId}?tab=receivables - assim Voltar ou Salvar no form de edicao do recebivel retorna exatamente para a aba Receitas do item de origem. Adicionada prop 'initialTab' em CrmDealItemsSection e parsing de ?tab=receivables na CrmDealItemsScreen. Clique no checkbox usa stopPropagation para nao disparar a navegacao.
NovidadeCRM Deal Item Receivables: exportacao Excel agora inclui as colunas 'Doc. Faturamento' (billing_document), 'Doc. Venda' (sales_document) e 'Item Doc. Venda' (sales_document_item) no final da planilha. Esses campos continuam nao sendo exibidos na tabela da pagina para manter o layout compacto.
CorrecaoCRM Commissions: duplo-clique em deal / item / receivable agora abre o formulario de edicao na mesma guia (router.push) em vez de abrir em nova janela (window.open + _blank). O return_to segue apontando para /crm/commissions, entao Voltar/Salvar retorna para a pagina de comissoes.
NovidadeCRM Commissions (tabela Deals): coluna BadgeCheck passou a ter tres estados. Sem icone quando nenhum item do deal tem PEP/PEP2/PEP3. BadgeCheck emerald quando ha PEP e a soma de total_price dos itens com commission_status PENDING/PARTIALLY_PAID/PAID bate (epsilon 0.01) com a soma de gross_amount dos recebiveis com status pendente ou pago. BadgeCheck vermelho quando ha PEP mas os totais divergem, sinalizando inconsistencia.
NovidadeCRM Commissions (tabela Deals): adicionado filtro por PEP no headerMeta, ao lado dos filtros de status. Tres botoes toggle (BadgeCheck emerald = PEP valido, BadgeCheck vermelho = divergencia, BadgeCheck outline slate = sem PEP) alternam a visibilidade dos deals conforme o estado de validacao. Valores padrao: todos ligados.
NovidadeCRM Commissions (tabela Deals): coluna Deal agora exibe um avatar a esquerda do nome usando o favicon de deal.domain (https://www.google.com/s2/favicons?domain=...&sz=128), no mesmo estilo de /fin/accounts (size-7, rounded-full, border-2 border-white/50, shadow-lg). Fallback para icone Building2 amber quando o deal nao tem domain.
MelhoriaCRM Commissions (tabelas Items e Recebiveis): coluna Status trocou o select badge de texto por SelectTrigger circular (!h-6 !w-6 rounded-full, chevron oculto) com apenas icone, seguindo o padrao ja usado na tabela Deals. Items: CheckCircle2 emerald (PAID), Receipt sky (PARTIALLY_PAID), XCircle slate (EXEMPT), Clock3 amber (PENDING). Recebiveis: CheckCircle2 emerald (pago) ou Clock3 amber (pendente). Titulo 'Status' removido dos cabecalhos (restou apenas o icone de ordenacao, w-10 centralizado). Helpers getItemStatusBadgeClass e getReceivableStatusBadgeClass removidos.
MelhoriaCRM Commissions (tabela Deals): subtitle com somatorio de deals agora em emerald-600 (font-semibold), ficando visualmente alinhado com o somatorio de Items e Recebiveis que tambem ficam verdes quando batem.
MelhoriaCRM Commissions: header principal migrou do Card amber simples para o padrao visual usado em /crm/deals - container rounded-2xl com crm-header-gradient, blur decorativos, sheen de luz, icon badge (Coins dentro de bg-white/18 rounded-xl), h1 branco 'Comissoes', input de busca glass style e botoes glass (Relatorio popover, Atualizar, Sincronizar Receitas) no padrao inline-flex h-8 rounded-xl border-white/20 bg-white/10 com hover shadow amber. Badge de contagem de deals foi removida do header principal (a contagem ja aparece no card da tabela Deals).
MelhoriaCRM Commissions: colunas Status das tres tabelas (Deals, Items, Recebiveis) deixaram de ser ordenaveis. Headers viraram TableHead vazio com aria-label='Status' (sem botao, sem icone de sort). Sort keys 'comission_status', 'commission_status' e 'is_comission_paid' removidos dos tipos DealSortKey/ItemSortKey/RecSortKey e dos switches de ordenacao.
MelhoriaCRM Commissions (tabela Recebiveis): coluna Valor foi movida para a direita de Com. - nova ordem: # / Venc. / Pgto. / Com. / Valor / Status. Agrupando primeiro os campos de data (cronologicos) e deixando o valor monetario mais proximo do status.
MelhoriaCRM Commissions: celulas de valor monetario nas tres tabelas agora sao font-semibold para destaque visual. Deals.amount (com text-right ja existente), Items.total_price e Recebiveis.gross_amount.
NovidadeCRM Commissions: selecoes e filtros da pagina agora sao persistidos em sessionStorage (chave crm_commissions_state_v1). selectedDealId, selectedItemId, selectedReceivableId, dealSearchTerm, dealStatusFilter, dealPepFilter, itemStatusFilter e receivableStatusFilter sao restaurados automaticamente ao montar o componente. Ao dar duplo-clique em um deal/item/recebivel, editar e voltar via router.push(returnTo), o estado original e restaurado (selecao das linhas, filtros ativos, termo de busca). Sets sao serializados como arrays.
CorrecaoCRM Commissions: correcao da restauracao de sessionStorage - o flag de controle virou state (didRestoreState) em vez de ref, garantindo que o effect de save so execute depois que os setters de restore forem commitados (re-render com o novo state). Antes o save rodava junto com o restore e sobrescrevia o sessionStorage com os valores iniciais, perdendo a persistencia.
MelhoriaCRM Commissions (tabela Recebiveis): filtro padrao agora inclui Pendente E Pago (new Set(['false', 'true'])) em vez de apenas Pendente. Exibe todos os recebiveis da hierarquia ativa por padrao; usuario pode filtrar explicitamente se quiser so uma categoria.
MelhoriaCRM Commissions (tabela Items): filtro padrao agora inclui Pendente, Parcial E Pago (new Set(['PENDING', 'PARTIALLY_PAID', 'PAID'])) - Isento fica desmarcado por padrao. Antes so vinham Pendente e Parcial.
NovidadeCRM Commissions (tabela Items): subtitle/somatorio do card agora exibe apenas o total_price do item selecionado quando ha selecionado. Sem selecao, continua exibindo a soma de todos os itens filtrados. Tambem afeta a comparacao itemsReceivablesMatch (cor verde/vermelha) - quando um item e isolado, a cor reflete o match/mismatch vs os recebiveis daquele item.
MelhoriaCRM Commissions (BadgeCheck PEP da tabela Deals): tolerancia de comparacao ampliada de 0.01 (1 centavo) para 0.05 (5 centavos) para mais ou menos. Diferencas por arredondamento em comissao/faturamento ate 5 centavos passam a contar como match (icone verde).
MelhoriaCRM Commissions: colunas de data alinhadas ao centro (Close em Deals ja estava; adicionado em # / Venc. / Pgto. / Com. em Recebiveis) e colunas de valor/total alinhadas a direita (Valor em Deals ja estava; adicionado em Total em Items e Valor em Recebiveis). Cabecalhos usam mx-auto/ml-auto no botao interno para alinhar o icone de sort corretamente.
NovidadeCRM Deal Item Receivables: botao 'Filtros' adicionado no header principal (com badge de contagem de filtros ativos) abre modal com todos os filtros, incluindo novo autocomplete de Oportunidade (CrmDealAutocomplete) que filtra recebiveis por deal_name. Filtros inline antigos substituidos por resumo compacto de filtros ativos abaixo do header.
NovidadeCRM Deal Item Receivables: somatorio compacto 'N recebiveis · Total Bruto R$ X' adicionado acima da tabela (valor em mono tabular, slate). Considera apenas os recebiveis apos filtros.
MelhoriaCRM Deal Item Receivables: badge 'N recebiveis' removido do header principal; contagem agora fica apenas na linha de somatorio acima da tabela, evitando duplicacao.
MelhoriaCRM Deal Item Receivables: somatorio 'N recebiveis · Total Bruto R$ X' movido para a mesma linha dos chips de filtros ativos (chips a esquerda, somatorio a direita via ml-auto). Linha aparece quando ha filtros ativos OU quando a tabela tem dados.
MelhoriaCRM Deal Item Receivables: botao Filtros movido para a direita do campo 'Buscar' no header (antes ficava junto de Sincronizar/Novo), agrupando controles de entrada na mesma regiao do header.
NovidadeCRM Deal Item Receivables: botao 'Exportar' adicionado no header (ao lado de Sincronizar). Gera arquivo Excel (xlsx) com todos os recebiveis apos filtros, contendo #, Deal, Valor Bruto, Comissao %, Comissao R$, Faturamento, Vencimento, Pagamento, Comissao Paga, Data Comissao e Atualizado (Origem). Nome do arquivo: recebiveis-YYYY-MM-DD.xlsx. Desabilita quando a lista esta vazia.
MelhoriaCRM Deal Item Receivables: coluna Status removida da tabela (TableHead + TableCell). Sort key 'status' removido, helpers relacionados (classifyStatus, statusBadgeClasses, statusDotClasses, STATUS_LABELS) desimportados. Coluna tambem removida do Excel exportado. Busca por texto ainda considera status.
MelhoriaCRM Deal Item Receivables: Excel exportado ja nao inclui linhas de titulo nem somatorio no topo - arquivo contem apenas o cabecalho e os dados da tabela, facilitando copia/cola e analises.
MelhoriaCRM Deal Item Receivables: tipografia das celulas da tabela reduzida de 13px para 12px (via '[&_td]:text-[12px]' no componente Table) para leitura mais compacta, alinhando com a tabela de receitas da aba em deal-items.
MelhoriaCRM Deal Item Receivables: titulos das colunas expandidos para nomes completos - '#' -> 'Parcela', 'Deal' -> 'Oportunidade', 'Valor' -> 'Valor Bruto', 'Com(%)' -> 'Comissao %', 'Com(R$)' -> 'Comissao R$', 'Fatu.' -> 'Faturamento', 'Venc.' -> 'Vencimento', 'Pgto.' -> 'Pagamento', 'Com' -> 'Status' (icone apenas, sem texto), 'Com(Date)' -> 'Data Comissao', 'Upd(Origem)' -> 'Atualizado'. whitespace-nowrap em todos TableHead, padding reduzido para px-2/py-2 e font do header para text-[11px] para caber tudo sem scroll horizontal.
MelhoriaCRM Deal Item Receivables: colunas de data (Faturamento, Vencimento, Pagamento, Data Comissao, Atualizado) alinhadas ao centro (header + celula). Coluna Atualizado passou a mostrar dd/MM/yy (sem hora) para reduzir largura. Coluna Status (ex-Comissao Paga) agora so exibe CheckCircle2 emerald (pago) ou Clock3 amber (pendente) com tooltip/aria-label.
MelhoriaCRM Deal Item Receivables: avatar da coluna Oportunidade alinhado ao padrao do /fin/accounts - size-7 circular (rounded-full) com border-2 border-white/50, bg-white, shadow-lg e favicon Google em sz=128 (object-cover). Fallback usa BriefcaseBusiness amber.
CorrecaoCrmDealAutocomplete: nova prop 'usePortal' (default true). Quando false, o dropdown renderiza inline (absolute) em vez de createPortal(document.body) - necessario dentro de Radix Dialog, pois portais externos sao tratados como clique fora pelo focus trap, impedindo selecao com mouse. Usado no modal de filtros de Deal Item Receivables.
MelhoriaCRM Deal Item Receivables (modal filtros): layout reorganizado - linha 2 agora 'Comissao | Comissao (mes)' (antes Comissao sozinha full-width) e linha 3 mantem 'Vencimento (mes) | Pagamento (mes)'. Linha dedicada a 'Comissao (mes)' no final foi removida.
MelhoriaCRM Deal Item Receivables (modal filtros): campo Comissao passou a usar FloatingSelect (padrao do projeto) - label flutuante embutido, icone Percent orange a esquerda, border cyan quando valor != ALL. Substitui select nativo com label externo.
MelhoriaCRM Deal Item Receivables (modal filtros): label 'Comissao' renomeado para 'Status' (no FloatingSelect e no chip de filtros ativos) - matching mais intuitivo com a coluna Status da tabela.
MelhoriaCRM Deal Item Receivables (modal filtros): campos Comissao (mes), Vencimento (mes) e Pagamento (mes) passaram a usar FloatingInput com mascara MM/YYYY e label flutuante (componente local MonthYearInput). Icones CalendarRange em cores distintas (cyan/amber/emerald). Removidos selects nativos e memos de opcoes (dueMonthOptions, paymentMonthOptions, comissionMonthOptions, baseFiltered). Parser aceita MM/YYYY digitado; campo vazio limpa o filtro.
MelhoriaCRM Deal Item Receivables (modal filtros): modal estilizado com separacao clara entre header (gradient cyan com icone Filter em pastilha + badge de contagem), body (space-y-4 px-6 py-5) e footer (border-top, fundo slate-50, actions). DialogContent com !p-0 !gap-0 overflow-hidden para controlar padding por secao.

21 de Abril de 2026

61 itens
1645
MelhoriaFin Recorrencias: campo Dia do mes agora fica sempre visivel ao lado de Dif.mes; so fica habilitado quando Dia Transacao = Dia exato (label recebe asterisco nesse caso). Trocar para outro modo continua limpando o valor.
MelhoriaFloatingInput: estado disabled agora tem estilo explicito (fundo slate-100, texto slate-400, cursor not-allowed, icone a 40% de opacidade) para deixar claro quando o campo nao esta editavel.
MelhoriaFin Recorrencias: StatusToggleBadge removido do header do formulario; StatusToggleField passa a ficar na primeira linha do formulario ao lado dos autocompletes de Parceiro, Categoria e Conta. Row 1 trocado de grid-cols-3 para flex (autocompletes flex-1, status no final).
MelhoriaStatusToggleField: medidas alinhadas ao preview 'Glassmorphism Pro' (#4) da pagina /gerenciapp/testes - rounded-2xl, px-5 py-2.5, sem largura/altura fixas (eram h-12 w-32).
NovidadeFin Recorrencias: CopyIdButton adicionado no header do formulario (so aparece em modo edicao), alinhado a direita - mesmo padrao de Fin Contas, Fin Parceiros e demais telas.
MelhoriaFin Categorias: linhas de categoria recebem identacao visual (pl-8 em vez de pl-4) para criar hierarquia com a linha de cabecalho do grupo.
NovidadeFin Categorias: cabecalho do grupo agora exibe a direita mini-badges com o breakdown de tipos (ex: '3 Despesa · 1 Receita') e status (ex: '3 ativas · 1 inativa') APENAS quando o grupo esta recolhido - preenche o espaco vazio sem poluir o modo expandido.
MelhoriaFin Categorias: avatares das colunas Categoria e Grupo reduzidos para size-5 (com icones text-base / size-4 preenchendo o espaco).
MelhoriaFin Categorias: tipografia da tabela ajustada - Grupo, Tipo e Status em text-xs (12px); nome do grupo e badge de contagem no cabecalho da secao em text-sm (14px).
MelhoriaFin Categorias: form de edicao reorganizado - StatusToggleBadge removido do header; StatusToggleField adicionado no final da primeira linha (Nome | Tipo | Status); campo Icone movido para a direita de Grupo na segunda linha.
MelhoriaFin Grupos de Categorias: form de edicao reorganizado - StatusToggleBadge removido do header; StatusToggleField adicionado no final da primeira linha (Nome | Descricao | Status). Row 1 trocado de grid-cols-2 para flex (Nome e Descricao com flex-1, status no final).
NovidadeFin Grupos de Categorias: CopyIdButton adicionado no header do formulario (so aparece em modo edicao), alinhado a direita - mesmo padrao das demais telas.
MelhoriaFin Transacoes: linhas 2 e 3 do form invertidas - linha de datas (Data Transacao, Venc. Original, Vencimento, Pago em) agora vem antes da linha de valores (Valor, Desconto, Encargos, Valor Final).
MelhoriaFin Transacoes: avatar do header agora exibe a logo do parceiro selecionado (favicon via google s2) com fallback para icone ArrowDownUp; subtitulo trocado do valor 'R$ X' para o nome da categoria selecionada.
MelhoriaFin Transacoes: titulo do form atualizado - 'Nova Transacao' -> 'Criando Transação' e 'Transacao' -> 'Alterando Transação'.
MelhoriaFin Transacoes: campos 'Venc. Original', 'Vencimento' e 'Pago em' recebem tabIndex={-1} quando a conta selecionada e do tipo Cartao de Credito - pulando os campos na navegacao por Tab.
MelhoriaFin Transacoes: badge de status no header agora so aparece para 'Pago' e 'Atrasado' - o badge 'Pendente' (amber) foi removido do header para reduzir ruido visual.
MelhoriaFin Grupos de Parcelas: somatorios de 'Pendente (R$)' e 'Parcela (R$)' movidos do header para uma linha propria acima da tabela (tema claro), em formato compacto (px-2 py-0.5, texto [11px], label [9px]). Espacamento vertical reduzido de gap-4 para gap-2 via -my-2.
NovidadeFin Grupos de Parcelas: filtro por Owner adicionado no header principal (select estilizado). Lista apenas os owners que tem grupos associados via account.owner_id; filtra a tabela e os somatorios.
NovidadeFin Grupos de Parcelas: coluna Conta agora exibe avatar circular (size-5) com favicon via account_domain + fallback Landmark violet.
NovidadeFin Grupos de Parcelas: filtro por Conta adicionado no header (select) - ao lado do filtro por Owner. Lista apenas as contas com grupos associados; somatorios respondem ao filtro.
MelhoriaFin Transacoes: ao selecionar um parceiro no modo criacao, se categoria e conta forem preenchidos automaticamente (a partir do parceiro), o foco pula direto para o campo 'Data Transacao' em vez de tabular por categoria/conta.
MelhoriaFin Transacoes: campos Conta e Parceiro no modal de filtros agora exibem o favicon no avatar com o mesmo estilo de /fin/accounts (size-7 rounded-full border-2 border-white/50 bg-white shadow-lg, Building2/Users como fallback) + label shift e pl-11.
MelhoriaFin Transacoes: modal de filtros reorganizado - linha 1 agora tem Status + Tipo de Conta + Conta (grid-cols-3), linha 2 tem Parceiro + Categoria (grid-cols-2).
MelhoriaFin Transacoes (novo): ao selecionar um parceiro que auto-preenche Categoria e Conta, esses dois campos recebem tabIndex={-1} (pulados na navegacao por Tab). Editar manualmente qualquer um dos dois limpa a flag e restaura o tabIndex.
NovidadeFin Transacoes: novo badge no header com o somatorio (R$) dos itens verificados (is_checked=true) alem de receita/despesa - badge sky com icone CheckCircle2; tooltip mostra a contagem de verificadas.
NovidadeFin Transacoes: duplo clique no titulo da coluna de check (ultima coluna da tabela) marca ou desmarca todos os itens filtrados em massa (Promise.allSettled), com optimistic update e toast de sucesso/erro.
MelhoriaFin Transacoes: coluna Parcelas na tabela agora exibe o valor em badge arredondado (rounded-full, border violet-200, bg violet-50, text-[11px] semibold tabular-nums, cor violet-700) em vez de texto simples.
MelhoriaFin Transacoes: coluna Vencimento agora pinta a data em vermelho (text-red-600, font-semibold) quando atrasada, em vez de mostrar o icone XCircle a esquerda. Tooltip 'Atrasado' preservado.
MelhoriaFin Transacoes: colunas Referencia, Vencimento e Pagamento alinhadas ao centro (antes estavam alinhadas a direita) - tanto o header quanto as celulas.
MelhoriaFin Transacoes: largura maxima da coluna Categoria aumentada de 160px para 220px para acomodar nomes mais longos sem truncar em excesso.
MelhoriaFin Transacoes: avatar da coluna Parceiro padronizado no mesmo estilo de /fin/accounts (size-7 rounded-full border-2 border-white/50 bg-white shadow-lg overflow-hidden) - favicon agora preenche o circulo todo (object-cover, sz=128); fallback Users indigo preservado.
MelhoriaFin Transacoes: badges de Receita, Despesa e Verificados no header agora so aparecem quando o somatorio e maior que zero - evita poluicao visual quando a filtragem nao contem items correspondentes.
NovidadeFin Fluxo de Caixa: quadro 'Saldos por Conta' agora exibe o logo (favicon) de cada account via partner_domain - busca fetchFinAccounts em paralelo, monta mapa accountDomainById e faz fallback para Landmark violet. Avatar padronizado (size-7 rounded-full border-2 border-white/50 bg-white shadow-lg).
MelhoriaFin Fluxo de Caixa: titulos das colunas 'Entrada', 'Saida' e 'Saldo' na tabela diaria renomeados para 'Entrada (R$)', 'Saida (R$)' e 'Saldo (R$)' indicando a unidade de medida.
MelhoriaFin Fluxo de Caixa: cabecalhos das colunas Entrada/Saida/Saldo alinhados ao centro; celulas mantidas alinhadas a direita para melhor leitura dos valores.
MelhoriaFin Fluxo de Caixa: prefixo 'R$' removido das celulas das colunas Entrada, Saida e Saldo (ja indicado no cabecalho '(R$)') - mantem apenas o valor formatado.
MelhoriaFin Fluxo de Caixa: cabecalhos Entrada/Saida/Saldo realinhados a direita para alinhar visualmente com os valores monetarios (text-center -> text-right).
NovidadeFin Fluxo de Caixa: nas linhas expandidas de transacoes do dia, coluna Conta agora exibe o logo (favicon) via lookup accountDomainById (fallback para tx.account_domain quando presente). Avatar padronizado com /fin/accounts (size-7 rounded-full border-2 border-white/50 bg-white shadow-lg, size-full object-cover).
MelhoriaFin Fluxo de Caixa: avatar de parceiro nas linhas expandidas padronizado no mesmo estilo/formato da coluna Conta (rounded-full border-2 border-white/50 bg-white shadow-lg size-full object-cover sz=128); fallback Building2 indigo. Icones ArrowUpRight/ArrowDownRight removidos do avatar de parceiro.
NovidadeCRM Deals / Emails: novo badge violet a direita do botao 'Expandir todas' exibindo a data relativa do ultimo email (ex: 'ha 5 horas' via formatRelativeTimeLong) - usa icone Calendar, tooltip mostra a data/hora absoluta, so aparece quando ha pelo menos 1 email.
MelhoriaFin Categorias: interacao do cabecalho do grupo invertida - clicar na linha (area vazia) agora recolhe/expande o grupo; clicar no nome do grupo abre a edicao do grupo (hover ganha underline violet para indicar a acao).
MelhoriaFin Recorrencias: labels dos campos Data Inicio / Data Fim renomeados para Vencimento Inicio / Vencimento Fim (mensagem de validacao tambem atualizada).
MelhoriaFin Recorrencias: campo transaction_type removido no backend. Removidos state/formulario/validacao/payload/filter/sort; tipo do valor na tabela agora derivado via category.category_type (INCOME/TRANSFER_IN/INVESTMENT_IN -> verde, demais -> vermelho). Funcao typeBadge e constante TRANSACTION_TYPE_LABELS removidas por estarem sem uso.
MelhoriaFin Recorrencias: avatar do header do formulario padronizado com o mesmo wrapper da tela Fin Contas (size-11 rounded-full border-2 border-white/50 bg-white shadow-lg) - favicon do parceiro cai dentro do circulo ou RefreshCw violet como fallback.
NovidadeFin Recorrencias: novo campo transaction_day_of_month (Dia do mes, integer 1-31) integrado ao CRUD. Novo modo transaction_day_mode 'EXACT_DAY' (Dia exato) adicionado; o input Dia do mes so aparece e e obrigatorio quando o modo e Dia exato. Trocar para outro modo limpa o valor automaticamente e o payload envia null para remover no backend.
MelhoriaFin Contas: avatar do Owner padronizado com o mesmo wrapper da coluna Conta (size-8 rounded-full border-2 border-white/50 bg-white shadow-lg).
MelhoriaFin Contas: tipografia da tabela ajustada - Conta (nome + agencia/numero) e Saldo em text-[13px]; demais celulas em text-xs (12px). Layout table-fixed com larguras proporcionais: Conta 22%, Owner 16%, Tipo 14%, Saldo 14%, Moeda 10%; Criado, Atualizado e Status autosize com whitespace-nowrap.
MelhoriaFin Categorias e Fin Grupos de Categorias: campo color removido no backend. Types, API clients (create/update payloads), formularios (FloatingColorInput removido), renderizacoes de tabela/autocomplete/partners/transactions/recurrences atualizados. Icones agora usam cores fixas do tema (violet/amber/emerald) em vez de color dinamico por registro.
MelhoriaFin Categorias: todas as celulas da tabela padronizadas para text-[13px]; avatar da coluna Grupo agora usa o mesmo wrapper circular (size-8 rounded-full border-2 border-white/50 bg-white shadow-lg) de Categoria/Contas.
MelhoriaFin Categorias: avatar da categoria na tabela agora segue o mesmo estilo de Fin Contas (size-8 rounded-full border-2 border-white/50 bg-white shadow-lg).
MelhoriaFin Categorias: pagina Grupos de Categorias removida e consolidada em /fin/categories. Botao 'Novo' abre um dialog para escolher entre Categoria ou Grupo; clicar no cabecalho de um grupo na tabela abre a edicao do grupo (chevron continua recolhendo a secao). Rotas sob /fin/categories/groups/* para criar e editar grupos.
MelhoriaFin Parceiros: tabela simplificada para exibir apenas as colunas Parceiro, Categoria, Conta, Chave Pix e Status, com distribuicao fluida (table-fixed) e ordenacao nas novas colunas.
NovidadeGET /fin/accounts passou a retornar o campo balance (saldo calculado pelo backend). Listagem de contas exibe o saldo por conta e o KPI Saldo Total na home do FIN volta a somar diretamente do endpoint de contas.
MelhoriaRemovidos campos initial_balance e current_balance de fin/accounts (nao existem mais no backend). Formulario e listagem ajustados; extrato bancario calcula saldo de abertura somando transacoes anteriores ao periodo.
NovidadeExibir favicon do banco nas contas usando o novo campo partner_domain retornado por GET /fin/accounts.
MelhoriaRemove modulo Fin Institutions - backend removeu a tabela e os campos institution_* das contas. Ajustes em nav, permissoes, formularios de contas, transacoes e parceiros.
MelhoriaRemovido conceito de Carteiras (fin/wallets): tabela eliminada no backend, campos antes na carteira (closing_day, credit_limit, due_day) agora vivem diretamente em fin/accounts. Removidas todas as paginas, API clients, menus, filtros e referencias ao conceito de Carteira.
NovidadeCRM Atividades: campo Notas agora suporta Markdown com toggle Editar/Pre-visualizar (icones Pencil/Eye) no formulario e no modal de edicao. Renderizacao via react-markdown + remark-gfm + remark-breaks (Enter quebra linha como no WhatsApp/Notion)
NovidadeCRM Atividades: icone de notas no formulario agora e sempre clicavel (independente do tipo tarefa/reuniao) e abre o modal de edicao
MelhoriaCRM Atividades: campo Notas aumentado de 3 para 6 linhas inline, com area de pre-visualizacao proporcional

20 de Abril de 2026

8 itens
521
NovidadeCRM Atividades: em reunioes, o icone do campo Notas agora e clicavel e abre um modal para edicao das notas. O modal tambem passou a permitir edicao direta quando o conteudo e HTML (textarea com o source)
NovidadeCRM Dashboard: modal de Recebiveis (drill-down da comissao mes a mes) agora tem coluna 'Paga' no final com um badge verde para registros com is_comission_paid=true
NovidadeCRM Commissions: totais de Items e Recebiveis (valor bruto) ficam verdes quando batem e vermelhos quando divergem, para facilitar a identificacao de inconsistencias
NovidadeCRM Recebiveis: agora e possivel selecionar multiplos recebiveis via checkboxes na tabela. Com mais de um selecionado, aparece uma barra contextual com botao 'Excluir selecionados' para remocao em lote
MelhoriaPagina Sobre: redesign com header dividido (identidade + stats clicaveis), filtros por tipo (Novidade/Correcao/Melhoria/Inicio) com contagens, busca no changelog, badges agregados por grupo, timeline com acento colorido por tipo (barra lateral + hover), dot da data com pulse suave e empty state quando os filtros nao retornam resultados
CorrecaoFin Transacoes: apos o auto-fill de 'Pago em' em contas CHECKING, limpar o campo manualmente preenchia de novo a cada re-render do effect. Agora o campo marca 'tocado' apos a primeira edicao do usuario (via ref) e o auto-fill nao volta mais - respeitando a escolha do usuario de deixar vazio
NovidadeFin Grupos de Parcelas: header principal agora exibe dois badges com os somatorios de 'Pendente (R$)' e 'Parcela (R$)' calculados a partir dos grupos filtrados (respeita busca e toggle Pendentes/Todos)
CorrecaoFin Transacoes: filtro Status 'Pendente' estava filtrando localmente por '!paid && (!due || due >= today)', escondendo os atrasados (due < today). Agora 'Pendente' retorna todas as transacoes nao pagas - incluindo atrasadas - alinhando com a UI, que nao expoe 'Atrasado' como opcao separada

17 de Abril de 2026

44 itens
16622
CorrecaoCRM Deals: aba Recebiveis carregava receitas item-a-item (loop sequencial). Agora dispara todas as chamadas em paralelo via Promise.all - deals com 20+ items abrem em uma fracao do tempo anterior
NovidadeCRM Deals/Items/Recebiveis: campo de busca aplica debounce de 200ms (lista nao pisca a cada tecla). Paginacao de verdade adicionada nas 3 listagens (50/100/200/500 por pagina, navegacao primeira/anterior/proxima/ultima) - antes carregava arrays inteiros sem limite
MelhoriaCRM Reference Data: novo hook compartilhado lib/hooks/use-crm-reference-data.ts (cache em modulo + subscribers + maps construidos uma vez) substitui a cache antiga sem pub/sub. Pipelines, stages, companies, users e deals carregados uma unica vez e compartilhados; deal-items nao faz mais fetchCrmDeals proprio
MelhoriaCRM Deals: handleSyncDeal (sync de oportunidade individual) trocou loop while+setTimeout manual por useSyncPolling, alinhando com o resto do app e eliminando codigo duplicado de polling
MelhoriaCRM Recebiveis: removidos helpers locais shortDate/shortDateTime; agora usam formatFlexibleDateShort/formatFlexibleDateTimeShort de lib/format-helpers (novo helper adicionado para padronizar dd/MM/yy HH:mm)
MelhoriaNovo componente compartilhado app/(app)/_components/table-pagination.tsx encapsula barra de paginacao (page-size + nav buttons) reutilizada nas 3 listagens de CRM
NovidadeFin Transacoes: campo de busca agora aplica debounce de 200ms na filtragem (lista nao pisca a cada tecla quando o usuario digita rapido). Reset de pagina tambem usa o termo debounced
NovidadeFin Transacoes: checkbox 'selecionar todas' do header da tabela ganhou role/aria-checked + tooltip dinamico que diferencia 'X selecionadas no total (Y nesta pagina)' quando ha selecoes fora da pagina visivel
MelhoriaFin Transacoes: removida dependencia indireta de 'state' no useEffect de prefill do form (Partial<typeof state> trocado por Partial<FinTransactionFormState>), evitando re-runs desnecessarios do effect a cada digitacao
NovidadeFin Transacoes: barra contextual de selecao em massa aparece abaixo do header quando ha linhas marcadas, com botoes Editar/Excluir e link Limpar selecao. Header principal volta a ficar respiravel
NovidadeFin Transacoes: campos de data com auto-fill (Pago em / Venc. Original) ganham badge Auto discreto no canto, com tooltip explicando que a edicao manual sobrescreve
NovidadeFin Transacoes: toggle de conferido agora mostra spinner durante a chamada e bloqueia novo clique. Pills de filtros ativos repintadas com tons violet do tema. Botao Aplicar do modal de filtros mostra Buscando... + spinner
NovidadeFin Transacoes: a11y - cabecalhos ordenaveis ganharam aria-sort/aria-label, icones clicaveis na tabela ganharam title/aria-label, botao Salvar do form de transacao ganhou tooltip do atalho Ctrl+Enter
NovidadeFin Transacoes: tabela ganhou paginacao de verdade (50/100/200/500 por pagina, navegacao primeira/anterior/proxima/ultima). Removido o slice(100) hardcoded que truncava silenciosamente datasets maiores
MelhoriaFin Transacoes: editar em massa agora guarda objetos completos (FinPartner, FinCategory, FinAccount) no estado em vez de 11 pares xxxId/xxxName, eliminando risco de display dessincronizado
MelhoriaFin Reference Data: hook agora expoe accountsMap/categoriesMap/partnersMap construidos uma vez no cache (identidade compartilhada). Active-filters e extrato-bancario consomem direto, eliminando .find() em loop por filtro/render
MelhoriaNovo helper components/ui/reference-date-input.tsx encapsula FloatingInput + parseReferenceInput. Usado em fin-transaction-form (4 datas), bulk-edit-dialog (2 datas) e transfer-dialog (1 data), cortando ~80 linhas de boilerplate de onChange/onKeyDown duplicado
MelhoriaFin Transacoes: arquivo principal (2857 linhas) extraido em 6 sub-componentes: fin-transaction-form, fin-transactions-table, fin-transactions-filter-modal, fin-transactions-active-filters, fin-transaction-bulk-edit-dialog, fin-transaction-transfer-dialog. Section virou orquestrador fino
MelhoriaFin Transacoes: estado do formulario consolidado em useReducer (16 useState -> 1 hook useFinTransactionForm) com change-tracking via state, eliminando re-renders globais a cada digitacao em campo de input
MelhoriaFin Transacoes: 3 useEffects redundantes (resolver accountInput/categoryInput/partnerInput por id) removidos. Display agora derivado nas autocompletes a partir do id+lookup
MelhoriaFin Reference Data: novo hook compartilhado useFinReferenceData (lib/hooks/use-fin-reference-data.ts) com cache em modulo + subscribers para accounts/categories/partners. Elimina fetches duplicados entre extrato-bancario e fin-transactions-section
CorrecaoFin Transacoes: remover pill de filtro ativa agora re-aplica a busca com o filtro removido em vez de cair silenciosamente para o universo de dados do mes corrente. Bug de UX que mascarava transacoes fora do periodo padrao
MelhoriaFin Transacoes: hook useFinTransactionFilters consolida estado de filtros (draft + applied) em useReducer com helpers apply()/clearField()/reset() e payload de busca centralizado
MelhoriaFin Transacoes: botao 'Nova Transferencia' no header reduzido para icone apenas (ArrowLeftRight) com tooltip/aria-label, posicionado a esquerda do botao '+ Nova'
MelhoriaFin Transacoes: dropdowns do modal Nova Transferencia agora ocultam reciprocamente a conta ja escolhida (a conta selecionada em De nao aparece no dropdown de Para, e vice-versa)
MelhoriaFin Transacoes: dropdowns De Conta / Para Conta do modal Nova Transferencia agora exibem apenas contas do tipo Conta Corrente (CHECKING). Cartao de Credito, Investimento e Emprestimo sao filtrados
CorrecaoFin Transacoes: modal de Nova Transferencia agora exibe aviso inline (banner vermelho) e desabilita o botao Confirmar quando as contas De e Para selecionadas sao iguais
CorrecaoFin Transacoes: validacao do modal de Nova Transferencia agora identifica especificamente qual conta (De ou Para) esta sem Parceiro vinculado e bloqueia a operacao com mensagem clara antes de chamar a API
NovidadeFin Transacoes: novo botao 'Nova Transferencia' no header da listagem abre modal com campos De Conta / Para Conta / Data / Valor. Ao confirmar, cria duas transacoes em paralelo (credito na conta destino com categoria TRANSFER_IN, debito na conta origem com categoria TRANSFER_OUT), usando o partner_id de cada conta e gerando notas automaticas. Ambas marcadas como pagas na data informada
NovidadeFin Transacoes: botao copy_id adicionado ao header do formulario de edicao, a direita do badge de status (Pago/Atrasado/Pendente). Visivel apenas em modo edicao
MelhoriaFin Contas: campo Parceiro movido da segunda linha para o final da primeira linha do formulario, ao lado de Tipo e Nome
NovidadeFin Contas: novo campo Parceiro (partner_id) no formulario de cadastro/edicao de contas, com autocomplete reutilizando FinPartnerAutocomplete. Tipo FinAccount, payloads de criacao e atualizacao tambem foram atualizados para incluir o campo
NovidadeFin Extrato Bancario: cabecalho da coluna 'Data' agora e clicavel para alternar a ordenacao entre crescente (ASC, padrao) e decrescente (DESC), com icone indicador (ArrowUp/ArrowDown). Saldo anterior por dia e calculado por grupo, garantindo valores corretos em ambas as direcoes
NovidadeFin Extrato Bancario: clique em uma linha agora navega para /fin/transactions/{id} (em vez de abrir overlay), passando os filtros atuais via return_to. Apos salvar ou voltar, retorna ao extrato com os mesmos filtros e a consulta recarregada automaticamente
NovidadeFin Categorias: listagem em tabela agora agrupa por grupo de categoria. Linha de cabecalho do grupo (com icone, nome e contagem) e clicavel para expandir/recolher. Botao no cabecalho da coluna Categoria alterna recolher/expandir todos os grupos
MelhoriaFin Categorias: listagem convertida de cards agrupados para tabela com colunas Categoria, Grupo, Tipo e Status. Todas as colunas ordenaveis, linhas clicaveis para editar
MelhoriaFin Installment Groups: ordenacao padrao alterada para Transacao (transaction_date) DESC
MelhoriaFin Installment Groups: coluna 'Transacao' movida para a primeira posicao da tabela (antes de Parceiro)
MelhoriaFin Installment Groups: coluna '1o Venc.' da listagem renomeada para 'Transacao' e agora exibe transaction_date em vez de first_due_date (ordenacao tambem ajustada)
MelhoriaFin Transacoes: campo 'Valor Final' (readOnly) removido da ordem de tabulacao com tabIndex=-1, ja que exibe apenas o resultado calculado
CorrecaoFin Transacoes: auto-preenchimento de 'Pago em' (Conta Corrente com data <= hoje) agora ocorre apenas em modo de criacao. Em edicao, o campo nao e mais sobrescrito ao carregar a transacao
NovidadeFin Transacoes: ao preencher 'Transacao' em uma conta tipo Conta Corrente, se a data for menor ou igual a hoje, o campo 'Pago em' e automaticamente preenchido com a mesma data
NovidadeFin Extrato Bancario: botao 'Novo' agora navega para /fin/transactions/new (em vez de abrir overlay), passando os filtros atuais (conta, periodo) via return_to. Apos salvar ou voltar, retorna ao extrato com os mesmos filtros aplicados e a consulta automaticamente recarregada
CorrecaoFin Transacoes: callback onCreated agora honra o parametro return_to ao criar uma nova transacao, retornando para a tela de origem em vez de ir para a listagem padrao

16 de Abril de 2026

39 itens
8328
MelhoriaFin Transacoes: modal de filtros reorganizado em 2 colunas (Status|Carteira, pares de datas lado a lado, Parceiro|Categoria) e largura aumentada para 800px, reduzindo a altura total
MelhoriaFin Transacoes: campos de data agrupados em fieldsets com legend (Vencimento, Venc. Original, Transacao, Pagamento), simplificando os labels internos para 'De' e 'Ate'
NovidadeFin Transacoes: adicionado botao de limpar (icone X) no canto superior direito de cada grupo de datas do modal de filtros, visivel apenas quando ha datas preenchidas
MelhoriaFin Transacoes: linha 'Tipo de Conta | Conta' do modal de filtros movida para logo abaixo de Status e acima dos grupos de datas
MelhoriaFin Transacoes: campo Carteira movido para a segunda linha do modal de filtros, ficando a direita de Tipo de Conta (Tipo de Conta | Carteira | Conta)
MelhoriaFin Transacoes: campos Parceiro e Categoria movidos para a primeira linha do modal de filtros, a direita de Status (Status | Parceiro | Categoria)
MelhoriaFin Transacoes: botao Limpar do modal de filtros movido do footer para o header, alinhado a direita do titulo
CorrecaoFin Transacoes: filtros Status, Tipo de Conta e Carteira no modal de filtros agora alteram a tabela apenas ao clicar em 'Aplicar' (antes eram aplicados instantaneamente). Introduzido estado 'applied' separado do rascunho do modal
NovidadeFin Transacoes: filtros padrao na listagem definidos como Status=Pendente, Tipo de Conta=Todos, Carteira=Todas, Vencimento=inicio ate fim do mes atual. Auto-aplicados no primeiro carregamento da tela
CorrecaoCRM Comissoes: rotas dos relatorios PDF e Excel do mes atual corrigidas de /crm/commissions/current-month/{pdf,excel} para /crm/reports/commissions/current-month/{pdf,excel}
CorrecaoBusca insensivel a acentos em todas as telas (normalizeText agora remove diacriticos via NFD). Ex: buscar 'aguia' agora encontra deals com 'aguia' (ou 'Aguia'), 'agua' encontra 'agua', etc
NovidadeCRM Dashboard: clique nas barras do grafico 'Comissao Mes a Mes' abre modal com tabela detalhada dos recebiveis do mes (deal, parcela, valor bruto, comissao, datas e status)
MelhoriaCRM Dashboard: hover das barras do grafico 'Comissao Mes a Mes' aprimorado com activeBar (fill mais escuro, stroke sutil e drop-shadow colorido) e cursor do tooltip com fundo amber suave e raio arredondado
MelhoriaCRM Dashboard: removidos os containers 'Proximas Atividades' e 'Deals Recentes' junto com subcomponente ActivityRow, helpers timeAgo e companyMap nao mais utilizados
MelhoriaCRM Dashboard: corpo da tabela do modal de recebiveis ajustado para 13px (antes 14px)
MelhoriaCRM Dashboard: coluna 'Vencimento' da tabela do modal de recebiveis substituida por 'Pagamento' (usando payment_date em vez de due_date)
MelhoriaCRM Dashboard: cabecalho da coluna 'Data Comissao' renomeado para 'Comissao' no modal de recebiveis
MelhoriaCRM Dashboard: datas das colunas 'Comissao' e 'Pagamento' no modal agora exibidas no formato dd/MM/yy (antes dd/MM/yyyy)
MelhoriaCRM Dashboard: coluna 'Status' substituida por '%' (commission_percentage) no modal de recebiveis do grafico Comissao Mes a Mes
MelhoriaCRM Dashboard: cabecalho da coluna de valor da comissao renomeado de 'Comissao' para 'Comissao (R$)' no modal de recebiveis
MelhoriaCRM Dashboard: coluna '%' (commission_percentage) movida para a direita de 'Valor Bruto' no modal de recebiveis, formando sequencia Bruto > % > Comissao (R$)
MelhoriaCRM Dashboard: coluna 'Pagamento' movida para a esquerda de 'Comissao' (data) no modal de recebiveis
NovidadeCRM Dashboard: todas as colunas da tabela do modal de recebiveis agora sao ordenaveis por clique no cabecalho (Deal, Parcela, Valor Bruto, %, Comissao R$, Pagamento, Comissao data) com icone de direcao indicando asc/desc
MelhoriaCRM Dashboard: cabecalhos da tabela do modal de recebiveis com whitespace-nowrap para evitar quebra de linha
MelhoriaCRM Dashboard: modal de recebiveis sem scroll horizontal — conteudo agora cabe na largura (padding de celulas reduzido de px-3 para px-2, coluna Deal trunca nomes longos com tooltip no hover)
MelhoriaCRM Dashboard: barra de rolagem vertical do modal de recebiveis agora usa a classe scrollbar-premium (estilo padrao do projeto)
MelhoriaCRM Dashboard: colunas da tabela do modal de recebiveis com largura fill proporcional via table-fixed + colgroup (Deal 30%, Parcela 8%, Valor Bruto 14%, % 8%, Comissao R$ 16%, Pagamento 12%, Comissao 12%)
NovidadeCRM Dashboard: zebra strip na tabela do modal de recebiveis (linhas impares com fundo amber suave, hover mais escuro mantido)
NovidadeCRM Dashboard: clique em uma linha da tabela do modal de recebiveis abre o formulario de edicao em nova guia (/crm/deal-item-receivables/[id])
MelhoriaCRM Recebiveis: campo 'Valor Comissao' agora e estritamente somente leitura — nao e mais enviado nos payloads de create/update (o backend calcula o valor a partir de net_amount * commission_percentage)
NovidadeCRM Deals: aba Receitas (recebiveis) do formulario de deal agora com colunas ordenaveis (Item, Parcela, Valor Bruto, Valor Liquido, Vencimento, Status). Ordem padrao: Parcela ascendente
MelhoriaCRM Deals: coluna 'Vencimento' da aba Receitas agora exibe o formato dd/MM/yy (ex: 16/04/26)
MelhoriaCRM Deals: cabecalho da coluna 'Vencimento' abreviado para 'Venc.' na aba Receitas
MelhoriaCRM Deals: coluna 'Valor Liquido' substituida por 'Comissao (R$)' (comission_amount) na aba Receitas
NovidadeCRM Deals: nova coluna 'Pago' (is_comission_paid) no final da tabela da aba Receitas — exibe icone CheckCircle2 verde apenas para TRUE, ordenavel
MelhoriaCRM Deals: coluna 'Status' substituida por 'Comissao' (comission_date) na aba Receitas, formato dd/MM/yy. Removidos helpers receivableStatusLabel e receivableStatusBadge nao mais utilizados
MelhoriaCRM Deals: coluna 'Pago' (is_comission_paid) substituida por 'Pagamento' (payment_date) na aba Receitas, formato dd/MM/yy
MelhoriaCRM Dashboard: grafico 'Comissao Mes a Mes' agora colore barras como Pago/Pendente baseado em payment_date (antes usava is_comission_paid). Totais do modal tambem atualizados
MelhoriaCRM Dashboard: valores da coluna 'Comissao (R$)' do modal de recebiveis agora sao coloridos conforme pago (emerald) ou pendente (amber) baseado em payment_date

15 de Abril de 2026

10 itens
433
NovidadeFin Transacoes: ao clicar em 'Nova transacao' com filtro por Parceiro ativo, a categoria e conta padrao cadastradas no parceiro sao automaticamente preenchidas no formulario
CorrecaoFin Transacoes: autocomplete do campo Conta (FinAccountAutocomplete) passa a exibir apenas contas com is_active = true no dropdown
CorrecaoFin Transacoes: botao Limpar dentro do modal de filtros nao limpa mais os campos de data De e Ate
NovidadeFin Fluxo de Caixa: clicar em uma transacao passa a navegar para /fin/transactions/{id} com parametro return_to, para que o botao Voltar retorne ao fluxo de caixa
CorrecaoFin Transacoes: coluna Valor da listagem passa a exibir o valor final considerando desconto e acrescimo (amount - discount_amount + charges_amount)
MelhoriaFin Transacoes: badge de pago (CheckCircle verde) movido da coluna de icones para a coluna Pagamento, a esquerda da data
MelhoriaFin Transacoes: badge de atrasado (XCircle vermelho) movido da coluna de icones para a coluna Vencimento, a esquerda da data
NovidadeFin Fluxo de Caixa: dias com vencimentos em atraso retornados pela API agora sao exibidos na listagem com badge Atrasado (a API passou a retornar dias anteriores a hoje com titulos nao pagos)
NovidadeFin Transacoes: aba Anexos agora aceita upload de multiplos arquivos simultaneamente (drag & drop ou selecao pelo botao)
MelhoriaFin Transacoes: opcao Atrasado removida do select Status no modal de filtros; transacoes atrasadas agora estao incluidas no status Pendente

14 de Abril de 2026

11 itens
911
NovidadeCRM — Atividades: icone Handshake passa a ser exibido nas linhas de reunioes que possuem oportunidade vinculada, nos tres grupos da lista (Atrasadas, Proximas e Concluidas)
NovidadeCRM — Atividades: icone de lixeira aparece no hover da linha da lista permitindo excluir a tarefa ou reuniao diretamente, com dialogo de confirmacao
MelhoriaCRM — Atividades: removido o toggle de validacao (CheckCircle2/XCircle) das linhas da lista, mantendo apenas a coluna de exclusao no final da linha
NovidadeCRM — Atividades: filtros (busca e tipo Tarefa/Reuniao) agora sao persistidos em sessionStorage e restaurados ao voltar para a lista
NovidadeCRM — Contratos: novo botao Sincronizar no header da lista que dispara a sync assincrona via POST /crm/contracts/sync, com polling de progresso em /crm/contracts/sync/{job_id} e reload automatico ao concluir
NovidadeCRM — Contratos: botao 'Filtros' no header abre modal com os 4 filtros (Unidade, Portfolio, Tipo, Status) em grid 2x2, multi-select com checkbox, interdependentes, com 'Limpar todos' e 'Aplicar'; badge no botao indica total de filtros ativos
NovidadeCRM — Contratos: toggle 'Minhas empresas / Todas empresas' no header que filtra contratos por owner_name igual ao usuario da sessao
NovidadeCRM — Contratos: lista inicial exibe apenas 10 registros ate que algum filtro (busca, unidade, portfolio, tipo, status ou Minhas empresas) seja aplicado; contador indica '10 de N' enquanto estiver truncado
NovidadeCRM — Contratos: botao Exportar no header com opcoes PDF (paisagem A4) e Excel (.xlsx) que exportam a lista filtrada com codigo, descricao, tipo, unidade, portfolio, executivo, status, valores e vigencia
NovidadeCRM — Contratos: tabela redesenhada com avatar com icone FolderOpen, tipo do contrato como chip, coluna Portfolio/Executivo, valor com margem percentual e vigencia com duracao (anos/meses/dias)
CorrecaoCRM — Contratos: corrigido bug da coluna Vigencia que exibia sequencias \u2192 e \u2014 como texto literal ao inves de seta e traco

10 de Abril de 2026

2 itens
11
NovidadeCRM — Oportunidades: novo campo toggle Reforma Tributaria (is_tax_reform) no formulario de edicao/criacao de deals
CorrecaoCRM — Oportunidades: ao excluir uma oportunidade, o formulario agora fecha e navega de volta para a pagina de origem

09 de Abril de 2026

5 itens
23
NovidadeCRM — Empresas: novo botao HubSpot no header da edicao quando a empresa possui ID externo do provedor HubSpot, abrindo o registro da company diretamente no HubSpot em nova guia
NovidadeCRM — Empresas: novo botao Sincronizar no header da edicao (visivel quando a empresa possui ID externo HubSpot) que dispara a sync da company especifica via /crm/companies/sync passando company_id, com polling de progresso e reload automatico ao concluir
MelhoriaCRM — Atividades/Tarefas/Reunioes: campo de oportunidade migrado de multi-select (deal_ids) para single-select (deal_id) acompanhando a mudanca da API. UI substituida por autocomplete unico no padrao FloatingInput, removendo o painel lateral e o modal de oportunidades
MelhoriaCRM — Atividades: reordenacao de campos no formulario. Tarefa: linha 2 fica com Empresa + Contato + Prioridade + Status (Status no final), linha 3 com Oportunidade + Responsavel. Reuniao: linha 3 reordenada para Empresa - Contato - Oportunidade - Responsavel
MelhoriaCRM — Reunioes: campos de inicio/fim divididos em tres campos nativos: Data (dd/MM/yyyy) + Inicio (HH:mm) + Fim (HH:mm). A data e unica para a reuniao e aplicada tanto ao start_at quanto ao end_at; alteracao na data de inicio replica automaticamente para o fim. Removidos os smart inputs (resolveMeetingStartInput/EndInput)

08 de Abril de 2026

3 itens
12
NovidadeFinanceiro — Planejamento Mensal: seletor de tipo de data no header (Pagamento, Vencimento ou Transacao) para definir qual data e usada no calculo do realizado
CorrecaoFinanceiro — Transacoes: exclusao e edicao em lote agora preservam os filtros ativos, re-aplicando a busca filtrada ao inves de recarregar a lista completa
CorrecaoFinanceiro — Transacoes: corrigido erro de hydration causado por leitura de sessionStorage durante SSR na restauracao de filtros

07 de Abril de 2026

1 item
1
NovidadeCRM — Meta de Vendas: nova tela com CRUD completo para metas de vendas mensais, com filtro por pipeline, valor monetario e observacoes

31 de Marco de 2026

13 itens
2110
NovidadeFinanceiro — Parceiros: nova aba Transacoes na tela de edicao, listando todas as transacoes do parceiro via API com filtro partner_id
CorrecaoAdmin — Safe Vault: lista nao carrega automaticamente, exige filtro de busca conforme API (search, name, type, is_active)
MelhoriaHeader — Cores dos menus (CRM, Financeiro, Admin) alinhadas com os tons das paginas (amber, violet, rose)
NovidadeCRM — Oportunidades/Anexos: arrastar arquivos para dentro de pastas com drag-and-drop, movendo via API com feedback visual
MelhoriaCRM — Atividades: campo 'Ata da Reuniao' removido de reunioes; campo 'Notas' agora unificado para tarefas e reunioes
MelhoriaCRM — Atividades: reorganizacao do formulario — campo Responsavel adicionado (task e meeting), layout simplificado com rows claras, botao Notas avulso removido de meetings
MelhoriaFinanceiro — Contas: navegacao refatorada de overlay panel para roteamento direto (/fin/accounts/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Instituicoes: navegacao refatorada de overlay panel para roteamento direto (/fin/institutions/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Carteiras: navegacao refatorada de overlay panel para roteamento direto (/fin/wallets/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Categorias: navegacao refatorada de overlay panel para roteamento direto (/fin/categories/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Grupos de Categorias: navegacao refatorada de overlay panel para roteamento direto (/fin/category-groups/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Recorrencias: navegacao refatorada de overlay panel para roteamento direto (/fin/recurrences/[id]), abrindo pagina dedicada com formulario de edicao
MelhoriaFinanceiro — Grupos de Parcelas: navegacao refatorada de overlay panel para roteamento direto (/fin/installment-groups/[id]), abrindo pagina dedicada com formulario de edicao

30 de Marco de 2026

9 itens
63
MelhoriaCRM — Oportunidades: navegacao refatorada de overlay panels para roteamento direto (/crm/deals/[id]), abrindo pagina dedicada com formulario de edicao
NovidadeCRM — Oportunidades/Anexos: suporte a pastas com criacao, navegacao hierarquica, upload em pasta atual e listagem separada de pastas e arquivos
NovidadeCRM — Contatos: pagina completa com CRUD, listagem com busca/ordenacao, formulario com autocomplete de empresa, status ativo/inativo, LinkedIn, e integracao HubSpot
MelhoriaCRM — Modelos de Email: navegacao refatorada de overlay panels para roteamento direto (/crm/email-templates/[id]), abrindo pagina dedicada com formulario
NovidadeCRM — Empresas/Emails: botao Enviar Email na aba emails com selecao de modelos filtrados por context_type COMPANY
NovidadeCRM — Itens de Oportunidade: pagina completa com CRUD, listagem com busca/ordenacao, formulario com autocomplete de oportunidade, valores, parcelas, comissao e IDs externos
NovidadeFinanceiro — Parceiros: aba Aliases no formulario de edicao com CRUD completo (criar, editar, ativar/desativar, excluir) para nomes alternativos do parceiro
MelhoriaFinanceiro — Conciliacao Bancaria e Cartao: aliases de parceiros agora sao dinamicos via API (tabela partner_aliases) em vez de hardcoded no codigo, com suporte a category_id por alias
NovidadeFinanceiro — Balancete: botao Exportar no header com opcoes de PDF (jspdf-autotable, A4 paisagem) e Excel (xlsx), incluindo secao, grupo, categoria, 5 meses e total geral

25 de Marco de 2026

2 itens
2
NovidadeFinanceiro — Extrato Bancario: nova tela de conferencia com selecao de conta corrente e periodo, exibicao estilo extrato bancario com saldo acumulado, agrupamento por data, resumo de entradas/saidas/saldo, filtro por parceiro/categoria, e abertura de detalhes da transacao em painel lateral
NovidadeFinanceiro — Conciliacao Bancaria: nova tela para conciliar extratos bancarios (OFX/CSV) com lancamentos do sistema. Upload de arquivo, auto-conciliacao por valor e data, layout lado a lado (extrato banco vs sistema), inclusao em lote de pendentes, baixa em lote de conciliados

24 de Marco de 2026

18 itens
1611
NovidadeCRM — Dashboard com visao consolidada: stat cards (deals, empresas, contratos, atividades), pipeline de vendas por estagio, top vendedores, atividades pendentes/atrasadas, deals recentes
NovidadeHeader — Breadcrumb de navegacao mostrando o caminho da pagina atual (ex: Financeiro > Transacoes)
NovidadeHeader — Notificacoes com icone de sino e badge, exibindo transacoes vencidas e total pendente
NovidadeHeader — Indicador de status ativo no tenant (dot verde ao lado do icone da empresa)
NovidadeHeader — Link Admin visivel apenas para usuarios administradores
NovidadeHeader — Indicador de sessao ativa (dot verde) no avatar do usuario
NovidadeFinanceiro — Planejamento Mensal: nova tela com aba Planejamento (edicao inline de valores por categoria, agrupados por tipo receita/despesa, copiar de outro mes) e aba Comparativo (planejado vs realizado com variacao e % executado)
NovidadeCRM — Empresas > Contratos: filtros por Unidade de Negocio, Portfolio, Tipo e Status na listagem de contratos
NovidadeCRM — Modelos de Email: nova tela CRUD para criar/editar templates de email com variaveis dinamicas, preview renderizado, contexto (Geral/Empresa/Deal/Contato) e status ativo/inativo
MelhoriaAPI — Adaptacao de todos os clients para o novo formato de resposta (data.items para listas, data para item unico). Helpers centralizados extractList/extractOne em client.ts
CorrecaoMensagens de erro da API agora exibem detalhes (error.message + error.details[].message)
NovidadeFinanceiro — Conciliacao de Cartao: upload de fatura Excel (.xlsx) Santander, selecao de aba/cartao, selecao de conta do sistema, layout lado a lado (fatura Excel vs transacoes do sistema), conciliacao automatica por valor e data
NovidadeFinanceiro — Conciliacao de Cartao: botao Baixar Lancamentos para marcar como pagos todos os lancamentos conciliados
NovidadeFinanceiro — Planejamento Mensal: badges de resumo no header (receita, despesa, resultado), barra de progresso geral de execucao
NovidadeFinanceiro — Planejamento Mensal: botao expandir/colapsar todos os grupos, indicador visual de celulas editadas nao salvas (borda cyan + dot)
NovidadeFinanceiro — Planejamento Mensal: exportacao PDF do planejamento com totalizadores
NovidadeFinanceiro — Planejamento Mensal: historico clicavel — clicar no valor de um mes anterior preenche automaticamente o planejado
NovidadeFinanceiro — Planejamento Mensal: alerta visual em categorias de despesa com orcamento estourado (fundo vermelho + icone)

23 de Marco de 2026

4 itens
121
MelhoriaSubstituido sistema de Sheet por overlay panels empilhados no CRM (deals, companies, activities)
NovidadeNavegacao entre entidades CRM via paineis empilhados (deal -> empresa -> atividade)
CorrecaoModais e selects nao ficam mais escondidos atras do painel de edicao
CorrecaoCorrigido erro de hidratacao em telas CRM com createPortal

20 de Marco de 2026

7 itens
25
MelhoriaAUTH — Substituicao da paleta Amber por Rose em todas as telas da secao Auth (page.tsx, auth-permissions, auth-roles, auth-sessions, auth-verification-tokens, auth-users): gradientes de header, bordas, sombras, headers de tabela, badges de tema e elementos de UI da secao
MelhoriaFinanceiro — Balancete: API atualizada para /fin/balancete/grouped (sections > groups > categories). Drilldown de transacoes movido para modal Sheet. Valores zerados sem comparativo. Sections e groups colapsaveis (iniciam recolhidos). Somatorios por section e group
NovidadeFinanceiro — Balancete: clique em valor abre modal com transacoes via POST /fin/transactions/search. Lista premium com icone calendario (dia/semana), badges de valor, vencimento e pagamento
MelhoriaHub Financeiro (/fin): redesign com header padrao GerenciApp, KPIs (Saldo, Receitas, Despesas) na sidebar, NavHubGrid com sections
MelhoriaHub GerenciApp (/gerenciapp): redesign como hub central com cards de modulos (Financeiro, CRM, Autenticacao) com atalhos rapidos e animacoes de entrada
MelhoriaNavegacao: menus duplicados removidos de /gerenciapp. Cada modulo tem sua propria hub (/fin, /crm, /auth). Paginas legadas removidas (/financeiro/*, /cadastros/partners, /outros/assistente-ai, /outros/usuarios)
NovidadeComponentes reutilizaveis: FinPartnerAutocomplete, FinCategoryAutocomplete, FinAccountAutocomplete criados e aplicados em Recorrencias, Parcelas e Parceiros

19 de Marco de 2026

4 itens
4
MelhoriaFinanceiro — Balancete: redesign completo. Paleta corrigida de indigo para emerald (padrao FIN). Selects nativos substituidos por shadcn Select. Checkbox nativo substituido por shadcn Checkbox. Classes compartilhadas de ui-classes.ts aplicadas. Linha de totais sticky no rodape da tabela. Indicadores de tendencia entre meses (setas up/down). Badge 'Atual' no mes corrente. Empty state com icone e mensagem. Detalhes expandidos com icone carteira, parceiro e data formatada. Subtitulo no header. Badges de contagem separados (grupos + categorias)
MelhoriaFinanceiro — Transacoes: filtros Parceiro, Categoria e Conta movidos para modal (botao Filtros no header). Autocomplete com createPortal no estilo do formulario de edicao. Badges dos filtros ativos exibidos no header com botao para remover individualmente. Filtros de data inicio/fim e tipo de data (vencimento, transacao, pagamento). Totais de receitas e despesas no header. Coluna Conta estilizada por tipo (Corrente, Cartao, Investimento, Emprestimo). Colunas Parceiro, Categoria e Conta clicaveis para editar o respectivo cadastro
MelhoriaFinanceiro — Fluxo de Caixa: ajustado para nova estrutura da API (saldo_inicial e accounts_balance). Card de Saldo Inicial adicionado. Saldos por conta exibidos abaixo dos cards de resumo
MelhoriaFinanceiro — Fluxo de Caixa: redesign completo. Grafico horizontal (full width) substituindo o vertical lateral. Cards de saldo por conta com favicon da instituicao. Highlight do dia atual com badge 'Hoje' e marcador no grafico. Barras proporcionais entrada/saida em cada linha da tabela. Layout reorganizado: grafico em cima, cards de contas, tabela embaixo

18 de Marco de 2026

4 itens
13
MelhoriaFinanceiro — Carteiras: formulario de edicao/criacao atualizado para refletir campos reais da API (name, wallet_type com Select enum, color, icon, notes, is_active). Removidos campos inexistentes (institution, balance, balance_date, dia_vencimento, image_url, description)
MelhoriaFinanceiro — Contas: formulario atualizado conforme swagger. Substituidos bank_name/bank_code por institution_id com autocomplete de instituicoes (GET /fin/institutions). Campos: name, account_type (enum), wallet_id, institution_id, agency, account_number, currency_code, initial_balance, current_balance, credit_limit, closing_day, due_day, notes, is_active
NovidadeFinanceiro — Instituicoes: CRUD completo em /fin/institutions com listagem (busca, ordenacao por nome/codigo/tipo/status), formulario com campos name, short_name, code, type (autocomplete), compe, ispb, swift, domain, color, is_active, supports_pix, supports_open_finance. Toggles visuais para PIX e Open Finance. Botao Buscar no campo Codigo consulta BrasilAPI (brasilapi.com.br/api/banks) e preenche automaticamente nome, ISPB, COMPE e tipo
MelhoriaFinanceiro — Parceiros: formulario atualizado com autocomplete para Conta (fin/accounts) e Categoria (fin/categories) em vez de inputs de texto UUID. Status movido para o header. Layout: Nome + Documento | Email + Telefone | Conta + Categoria | Notas. Navegacao de volta apos salvar em new/edit

17 de Marco de 2026

1 item
1
NovidadeCRM — pagina Emails: adicionados campos company_id, deal_id, contact_id (autocomplete com createPortal) e provider (Select) ao formulario de edicao/criacao

16 de Marco de 2026

6 itens
6
NovidadeCRM — pagina Solucoes de Empresas com CRUD completo: listagem com busca/ordenacao por empresa/solucao/categoria/notas, formulario com change tracking e partial saves
NovidadeCRM — pagina Estagios do Pipeline com CRUD completo: listagem com busca/ordenacao, badges Fechado/Ganho, toggles animados no formulario, campo ordem numerico, HubSpot ID readonly
NovidadeCRM — pagina Atividades CRM em /crm/activities: listagem agrupada (Atrasadas, Proximas, Concluidas) com busca, badges de tipo/prioridade, nome da empresa, quick-complete e navegacao para empresa
NovidadeFinanceiro — pagina Parceiros com CRUD completo: listagem com busca/ordenacao por nome/documento/email, badges de status ativo/inativo, formulario com change tracking e partial saves
NovidadeFinanceiro — pagina Categorias com CRUD completo: listagem com busca/ordenacao, badges coloridos por tipo (Despesa, Receita, Transferencia, Investimento), select de grupo, formulario com change tracking e partial saves
NovidadeFinanceiro — pagina Grupos de Categorias com CRUD completo: listagem com busca/ordenacao, campo ordem numerico, formulario com change tracking e partial saves

13 de Marco de 2026

20 itens
146
MelhoriaCRM — extraidos formatBrNumber, formatBrInteger e formatCnpj para lib/format-helpers.ts, eliminando duplicacao entre companies, deals e empresas sections
MelhoriaCRM — criado hook useSyncPolling para logica de polling assincrono reutilizavel, substituindo 8+ implementacoes duplicadas no projeto
MelhoriaCRM — criado hook useListStatePersistence para persistencia de estado de lista (busca, ordenacao, scroll) em sessionStorage
MelhoriaCRM — extraidos componentes CrmTaskModal e CrmMeetingModal reutilizaveis, eliminando duplicacao de ~300 linhas entre companies e deals sections
NovidadeCRM — pagina Soluções com layout dual-panel: categorias a esquerda filtrando soluções a direita, CRUD completo via modal para ambas entidades
MelhoriaCRM Deals — aba Tasks com formulario inline no body ao inves de modal, com botao Voltar para retornar a lista
NovidadeCRM Deals — campo Empresa na task com autocomplete: busca por nome e utiliza o ID nas requisicoes
NovidadeCRM Deals — campos Contato e Responsavel na task com autocomplete (contato filtrado por empresa selecionada)
NovidadeCRM Deals — footer dinamico por aba ativa (detalhes/tasks), oculto na lista de tasks
NovidadeCRM Deals — change tracking na task: salvar habilitado apenas com alteracoes, payload parcial no PUT, indicadores visuais (borda cyan + dot) nos campos alterados
NovidadeCRM — confirmacao de exclusao em todos os modais CRM (tasks, meetings, solucoes, categorias)
NovidadeCRM Deals — nova task pre-preenchida com contato do deal, usuario logado, status Pendente e prioridade Media
NovidadeCRM Deals — sinalizacao visual de prioridade (borda amber para Alta, borda red pulsante para Urgente) e badge Atrasada no vencimento
NovidadeCRM Deals — lista de tasks agrupada por estado: Atrasadas (vermelho), Proximas (violet) e Concluidas/Canceladas (opaco com line-through)
NovidadeCRM Deals — status e prioridade como badges coloridos traduzidos (Pendente, Em Progresso, Baixa, Media, Alta, Urgente), ordenacao inteligente por grupo e destaque visual para tasks urgentes/alta na lista
NovidadeCRM Deals — badges de contagem nas abas Tasks e Meetings (vermelho quando ha tasks atrasadas)
NovidadeCRM Deals — coluna status removida das secoes Atrasadas e Proximas (redundante com o agrupamento), mantida em Concluidas/Canceladas
NovidadeCRM Deals — botao de concluir task com um clique na lista (circulo que vira check no hover), disponivel nas secoes Atrasadas e Proximas
NovidadeCRM Deals — aba Meetings com mesma estrategia de agrupamento: Atrasadas, Proximas e Realizadas/Canceladas, badges traduzidos, botao de marcar como realizada e badge de contagem na aba
MelhoriaCRM Deals — aba Meetings com formulario inline no body (mesmo padrao de Tasks), substituindo o modal por edicao direta com FormFooter, change tracking e confirmacao de exclusao

12 de Marco de 2026

12 itens
912
NovidadeCRM — novo menu CRM adicionado ao header principal, com 12 opcoes de navegacao (Commissions, Companies, Contacts, Contracts, Deals, Deal Items, Deal Item Receivables, Pipelines, Pipeline Stages, Solutions, Solution Categories, Company Solutions)
NovidadeCRM Companies — pagina completa com listagem, busca, filtros, ordenacao, formulario de criacao/edicao com todos os campos da API (name, tax_id, domain, owner, industry, company_size, account_tier, city, state, country, annual_revenue, notes), sincronizacao via HubSpot e CRUD completo
NovidadeCRM Companies — aba Deals com lista de deals, botao Sincronizar (async com polling e barra de progresso) e botao Novo Deal
NovidadeCRM Companies — aba IDs Externos com CRUD completo de identificadores externos (HubSpot/Orbit) via modal
NovidadeCRM Companies — sincronizacao assincrona com polling e barra de progresso
NovidadeCRM Oportunidades — pagina completa com listagem, busca, ordenacao, formulario de criacao/edicao (nome, pipeline, estagio, owner, co-owner, valor, probabilidade, data fechamento, company/contact ID), sincronizacao async com HubSpot e CRUD completo
NovidadeCRM Companies — aba Contatos com listagem de contatos vinculados a empresa (nome, email, cargo, telefone), colunas ordenáveis, modal de criacao/edicao/exclusao de contatos e navegacao via tab query param
MelhoriaCRM Companies — header do formulario de edicao com animacoes (orbs, sheen, status-breathe) e abas horizontais no estilo seidor/empresas, badges de contagem nas abas Deals e Contatos
NovidadeCRM Companies — abas Tasks e Meetings com listagem, modal de criacao/edicao/exclusao, colunas ordenaveis e CRUD completo via API
MelhoriaCRM Oportunidades — formulario de edicao com header animado (orbs, sheen, premium gradient), abas verticais (Detalhes, Tasks, Meetings) e largura 1080px
NovidadeCRM Oportunidades — abas Tasks e Meetings com listagem, colunas ordenaveis, modal de criacao/edicao/exclusao e CRUD completo via API (deal_id)
CorrecaoCRM Meetings — modal corrigido com campos corretos do swagger (notes em vez de description, sem meeting_url), adicionados campos Prioridade e Tipo Local, Status e Prioridade como Select pre-definido

10 de Marco de 2026

2 itens
2
NovidadeDeals — campos Next Step, Next Step Date e Next Step Status adicionados ao formulario de edicao
NovidadeDeals — botao Sincronizar Line Items no header da aba Line Items, chamando sync-by-deal com resumo no toast

09 de Marco de 2026

9 itens
234
NovidadeGerenciApp Home — header premium com gradiente animado emerald/teal, orbs flutuantes, sheen e relogio em tempo real
MelhoriaSeidor Home — Resumo agora exibe KPIs financeiros (Deals, Line Items, Receita Liquida, Comissoes) com cards, barra de etapas e anel radial de comissoes pagas
MelhoriaSeidor Home — lista de tarefas substituida por painel Resumo com contagens de Empresas, Deals, Contatos e Contratos
MelhoriaSeidor Home — container de navegacao e header simplificados
MelhoriaEmpresas — botoes Novo contato e Nova solucao navegam na mesma aba; middle-click ou Ctrl+click abrem em nova guia
CorrecaoEmpresas — aba Contratos agora filtra pelo id correto da company em vez do orbit_id
CorrecaoSeidor — requisicoes da area Seidor nao enviam mais o header tenant_id desnecessario
CorrecaoEmpresas — filtros, busca e ordenacao da lista agora sao preservados ao navegar para edicao e voltar, usando sessionStorage
NovidadeEmpresas — botoes Novo contato e Nova solucao nas abas de edicao agora abrem em nova guia do navegador

06 de Marco de 2026

19 itens
415
MelhoriaDeals — tabela atualizada com gradiente no header, bordas, hover shadow, avatar scale, close date com icone Calendar em gradient box; formulario reescrito com FloatingInput, FormFooter, change tracking (parcial saves), justSaved, autocomplete de empresa com createPortal
MelhoriaContratos — tabela atualizada com gradiente no header, bordas, hover shadow, avatar scale, vigencia/atualizado com icones em gradient box; formulario reescrito com FloatingInput, FormFooter, change tracking (parcial saves), justSaved, autocomplete de parceiro com createPortal
NovidadeSeidor Menu — lista de tarefas pendentes do HubSpot adicionada na pagina inicial, com prioridade, status, deal associado e due date
MelhoriaEmpresas — formulario de edicao reescrito com FloatingInput, FormFooter, change tracking (parcial saves), status local toggle, justSaved, e botao Atualizar no footer
MelhoriaContatos — removido do menu de navegacao Seidor; pagina de lista eliminada; formulario de edicao acessivel via aba Contatos em Empresas
MelhoriaContatos — formulario reescrito com FloatingInput, FormFooter, change tracking (parcial saves), autocomplete de empresa com portal, status local toggle e integracao HubSpot preservada
MelhoriaFloatingInput — componente reutilizavel criado para inputs com label flutuante, suporte a icon/prefix/suffix/currency/date/mono, eliminando ~500 linhas duplicadas em receitas e line-items
MelhoriaFormFooter — componente reutilizavel criado para footer de formularios com shimmer separator, timestamp, botoes Excluir/Salvar com animacao justSaved
MelhoriaSolucoes — removido do menu de navegacao Seidor; pagina de lista eliminada; formulario de edicao acessivel via aba Solucoes em Empresas
MelhoriaSolucoes — formulario reescrito com FloatingInput, FormFooter, change tracking (parcial saves) e animacao justSaved
MelhoriaGrupos Economicos removidos — pagina, rotas, navegacao, componentes, APIs e referencias em Empresas/Solucoes eliminados
MelhoriaLine Items — removido do menu de navegacao; pagina de edicao acessivel via aba Line Items no formulario de Deals, com retorno ao deal de origem
MelhoriaLine Items — header do formulario de edicao atualizado com gradiente cyan/teal e estilo glass-morphism, identico ao header de Deals
MelhoriaLine Items — formulario reorganizado com secoes logicas (Identificacao, Contrato, Financeiro), inputs consistentes com Deals, e melhor hierarquia visual
NovidadeLine Items — campo ORB Contract ID convertido para autocomplete com busca em contratos Seidor, exibindo code e usando id como valor
NovidadeLine Items — campo Deal ID convertido para autocomplete com busca em deals, exibindo name e usando id como valor
MelhoriaLine Items — layout do formulario reorganizado: Line Item ID + Nome, Deal, ORB Contract + PEP, Valor + Comissao + Status
MelhoriaLine Items — form com largura responsiva (60vw) e altura fixa (80vh), footer unificado entre abas com mt-auto
NovidadeLine Items — aba Receitas refatorada: filtros por status (Todas/Pendentes/Pagas/Vencidas), cards com staggered animation, deteccao automatica de vencidas, progress bar, totalizadores Pago vs Pendente no footer

05 de Marco de 2026

1 item
1
NovidadeDeals — aba Arquivos no formulario de edicao com file manager completo: arvore de pastas expandivel/colapsavel, upload via drag & drop com barra de progresso e presigned URL, exclusao de arquivos com confirmacao, validacao de tamanho maximo (50MB)

04 de Marco de 2026

7 itens
61
NovidadeSolucoes — formulario de edicao atualizado com campos solution_domain e is_active, layout reorganizado (Tipo/Solucao, Empresa/Dominio, Contatos), toggle de status no header
MelhoriaEmpresas — ajuste conforme backend: campo classification removido, campo hubspot_id adicionado no formulario, payloads de criacao/atualizacao e tipo SeidorCompany atualizados
NovidadeEmpresas — aba Contatos com botao 'Novo contato' que navega para criacao de contato ja vinculado a empresa
NovidadeEmpresas — aba Contratos filtra apenas contratos ativos por padrao, com checkbox 'Exibir inativos' no header para mostrar todos
NovidadeEmpresas — abas Contatos e Solucoes no formulario de edicao, exibindo registros vinculados a empresa via company_id com tabela navegavel
NovidadeSolucoes — pagina completa no menu Seidor com CRUD completo: listagem com colunas ordenaveis (solucao, tipo, contato empresa, contato seidor, atualizado), busca, split-view com formulario de edicao (ID, solucao, tipo, company ID, contato empresa, contato seidor, observacoes)
NovidadeContatos — pagina completa no menu Seidor com CRUD completo: listagem com colunas ordenaveis (nome, email, telefone, cargo, tipo, atualizado), busca, filtro por status, split-view com formulario de edicao contendo todos os campos (ID, nome, email, telefone, cargo, tipo, company ID, HubSpot ID, status ativo/inativo)

03 de Marco de 2026

6 itens
6
NovidadeEmpresas — botao Sincronizar Empresas no header da listagem, chamando POST /seidor/companies/sync para importar/atualizar empresas da API externa
NovidadeEmpresas — formulario de edicao com layout ajustado: ID + Name + Class na primeira linha, CNPJ + Domain + Owner na segunda, Orbit ID na terceira; altura autosize com max na altura disponivel
NovidadePagina Contratos no menu Seidor — CRUD completo com listagem, criacao, edicao e exclusao de contratos; tabela com colunas ordenaveis, busca, split-view com formulario lateral contendo todos os campos (descricao, codigo, status, tipo, valores, vigencia, parceiro, gestor, portfolio, unidade de negocio, filial, ERP, etc.)
NovidadeEmpresas — aba Contratos com CRUD completo: clique em um contrato abre formulario de edicao inline com todos os campos, botoes Salvar e Excluir com confirmacao
NovidadeEmpresas — tabela de contratos ajustada para 4 colunas (Contrato, Status, Valor Venda, Vigencia) eliminando scroll horizontal; subtitulo mostra nome do parceiro
NovidadeEmpresas — requisicao de contratos agora envia partner_id com o orbit_id da empresa

25 de Fevereiro de 2026

5 itens
41
NovidadeBalancete — percentual de diferenca em relacao ao ultimo mes exibido em cada coluna da tabela e nos cards de resultado
NovidadeBalancete — filtro 'Meses' no header permite escolher de 1 a 5 meses para exibir, controlando colunas da tabela e cards de resultado
NovidadeBalancete — colunas da tabela de detalhes (despesas expandidas) agora sao ordenaveis ao clicar nos headers, com indicadores visuais de direcao
NovidadeBalancete — clicar em um lancamento na tabela de detalhes expandida abre o formulario de edicao da transacao
CorrecaoTransacoes — filtro Tipo agora inicia com valor padrao 'Todos' em vez de 'Debito'

24 de Fevereiro de 2026

5 itens
23
NovidadeFormulario de Empresas — adicionados campos Classification e Orbit ID ao formulario de edicao/criacao, payloads de API e tipo SeidorCompany atualizados
MelhoriaEliminacao de codigo duplicado (Fase 2) — dialogs de confirmacao extraidos para ConfirmDeleteDialog e ConfirmStatusDialog (10 sections), funcoes de formatacao (formatCurrency, formatFlexibleDate, formatFlexibleDateTime) centralizadas em format-helpers.ts (8 sections), componente CopyIdButton criado para botoes de copiar ID (6 sections)
MelhoriaEliminacao de codigo duplicado (Fase 1) — funcoes utilitarias (resolveErrorMessage, extractFlexibleTime, formatRelativeTime, formatListDate, parseAmountValue, formatAmountDisplay, normalizeText) extraidas para modulos compartilhados; hooks reutilizaveis criados (useEntityList, usePermissions, useSortable, useStatusToggle, useDeleteConfirm); componentes de botao compartilhados (SaveButton, DeleteButton, UpdateButton) aplicados em 11 sections e 5 screens
NovidadePagina de Conciliacao de Cartao — importacao de extrato XLS/XLSX, selecao de carteira credito, matching automatico por valor e parcela com desempate por proximidade de data, indicadores visuais de conciliacao e salvamento em lote
MelhoriaPagina Empresas atualizada com padroes premium — header de edicao com gradiente cyan/teal e blur decorativo, avatar circular com ring, botao Voltar glassmorphism, copy ID icon-only, tabs shadcn com gradiente ativo, tabela glassmorphism com scrollbar estilizada e bordas suaves, inputs com backdrop-blur e hover transition, counter badge com gradiente, botao Novo com animacao rotate-90, modal de exclusao substituido por AlertDialog

23 de Fevereiro de 2026

6 itens
51
NovidadeCalendario do dia na pagina inicial Seidor — widget lateral exibe eventos do Outlook via Power Automate com indicador de reuniao atual, contagem de participantes, link para Teams e ordenacao por horario
NovidadeEdicao em massa de transacoes — botao Editar ao selecionar transacoes abre modal com tabela de campos (datas, recorrente, conciliado, carteira, conta, parceiro) com checkbox para habilitar e autocomplete nos campos de relacionamento
NovidadeAtalho Ctrl+L na tela de transacoes para liquidar em massa — abre modal de data de pagamento e aplica PUT payment_date em todas as transacoes selecionadas
NovidadeAo criar transacao com parcela 1/N, modal pergunta se deseja criar automaticamente as demais parcelas com vencimento nos meses seguintes
NovidadeColuna Conciliado na tabela de transacoes com icone clicavel para alternar status diretamente na listagem
MelhoriaExtrair componente DateInput e date-helpers compartilhados para eliminar duplicacao de funcoes de data e padrao JSX em transactions, wallets e receitas

20 de Fevereiro de 2026

21 itens
6213
NovidadeColuna Conta no balancete exibe formato Codigo - Emoji - Nome, separando codigo e nome com o icone da conta entre eles
MelhoriaFormulario de edicao de transacoes atualizado com padroes premium — header gradiente emerald com blur decorativo, botao Voltar glassmorphism, badges de valor e status com ping animado, tabs shadcn com gradiente, Labels shadcn, botoes gradiente (Excluir/Salvar), modais nativos substituidos por AlertDialog, animacao ao trocar de tab
MelhoriaPagina Transacoes atualizada com padroes premium — tabela glassmorphism com scrollbar estilizada, header com counter glassmorphism e botao Novo animado, icones de ordenacao (ArrowDownUp/ArrowUp/ArrowDown) nos headers da tabela, linhas zebradas com bordas suaves
MelhoriaPagina Wallets atualizada com padroes premium — tabela glassmorphism com scrollbar estilizada, header com counter glassmorphism e botao Novo animado, formulario com header gradiente emerald e blur decorativo, inputs glassmorphism, Labels shadcn, botoes gradiente, Badge premium com ping animado para status, modais nativos substituidos por AlertDialog
MelhoriaPagina Contas atualizada com padroes premium — tabela glassmorphism com scrollbar estilizada, header com counter glassmorphism e botao Novo animado, formulario com header gradiente emerald e blur decorativo, inputs glassmorphism, Labels shadcn, botoes gradiente, Badge para tipo e status, modais nativos substituidos por AlertDialog, tabs shadcn com gradiente, ordenacao em todas as colunas, animacao ao trocar de tab
MelhoriaPagina Safe Vault atualizada com padroes premium — tabela glassmorphism com scrollbar estilizada, colunas Criado/Atualizado com icones coloridos (Calendar/Clock), Badge premium com gradiente e ping animado para status, Badge para tipo, header com counter glassmorphism e botao Novo animado, formulario de edicao com header gradiente emerald e blur decorativo, inputs glassmorphism, botoes gradiente, Labels shadcn, modais nativos substituidos por AlertDialog
MelhoriaTabela principal de parceiros redesenhada — badges premium com gradiente e ping animado para status, colunas Criado/Atualizado com icones coloridos (Calendar/Clock), Chave Pix com icone em caixa gradiente, skeletons atualizados para novo layout
NovidadeFormatacao automatica da chave Pix no formulario de parceiros — CPF, CNPJ e telefone formatados visualmente com badge de tipo detectado e botao para copiar valor sem formatacao
MelhoriaHeader do formulario de edicao de parceiros redesenhado com gradiente emerald, blur decorativo, avatar com favicon/iniciais, botoes glassmorphism e status com ping animado
MelhoriaPagina de parceiros migrada para componentes shadcn/ui — AlertDialog nos 3 modais (exclusao, status, transferencia), Tabs com gradiente emerald, Badge de status na tabela, Label nos 7 campos do formulario
MelhoriaMelhorias visuais na pagina de Parceiros — badge glassmorphism com contagem, botao Novo com gradiente e animacao, tabela com backdrop-blur, inputs com hover verde, acento corrigido em datas relativas
NovidadeCampo Notas adicionado ao formulario de edicao de usuarios — textarea com estilo glassmorphism, incluso no CRUD (criar e atualizar)
MelhoriaRedesign premium do card de edicao de usuarios — header com gradiente emerald e blur decorativo, avatar com ring branco translucido, botoes glassmorphism no header, tabs com fundo sutil, corpo do form com gradiente suave, inputs com sombra e borda translucida, metadata com toque emerald
MelhoriaPagina de edicao de usuarios totalmente migrada para componentes shadcn/ui — AlertDialog, Tabs, Badge, Avatar, Label, DropdownMenu, Tooltip, Separator, Card, Button e Select substituem todos os elementos HTML nativos
NovidadeAbas Detalhes e Transacoes no formulario de edicao de contas — aba Transacoes exibe transacoes vinculadas a conta com navegacao para edicao da transacao
NovidadeExpand/collapse de grupos na tabela de contas — chevron animado em cada grupo permite recolher/expandir filhos, com badge de contagem quando recolhido
MelhoriaPadronizacao do botao Voltar em todos os formularios de edicao — estilo gradiente com texto, animacao hover no icone, paleta emerald (Gerenciapp) ou cyan (Seidor) conforme contexto
CorrecaoCorrecao do PUT/DELETE de permissoes de usuario — endpoints agora usam /users-permissions/:user_id/:permission_id conforme swagger
CorrecaoCorrecao da acao Nenhum em permissoes — agora faz PUT com permission_type NONE em vez de DELETE, com guard contra nivel duplicado e unwrap de resposta da API
NovidadeUpload de foto no avatar do formulario de edicao de usuarios — clique no avatar abre seletor de imagem, com hover de camera e loading, similar a pagina de perfil
MelhoriaTabelas de usuarios e contas redesenhadas — badges premium com gradiente, borda e sombra para Perfil, Status, Tipo, Codigo; colunas Criado/Atualizado com icone colorido e info de autor; formato de tempo relativo compacto

19 de Fevereiro de 2026

27 itens
11313
NovidadeFiltros server-side na pagina de receitas — filtro por mes de vencimento, compensacao e comissao (YYYY-MM), toggle compensacao preenchida, com barra de filtros colapsavel
CorrecaoCorrecao do tipo de wallet — campo type agora envia CREDITO/DEBITO em maiusculo conforme esperado pela API
MelhoriaLista de receitas — coluna Deal Name como primeira, Line Item Name ao lado, filtro Pendente e ordenacao Dt. Comissao ASC como padrao
NovidadeProgress bar rico em operacoes assincronas — circulo SVG animado, barra com shimmer, contagem de registros processados/total e percentual em tempo real
MelhoriaPadronizacao dos campos de data em transacoes — icone de calendario movido para a esquerda do input, consistente com receitas e deals
NovidadeControle de acesso por permissoes — paginas, cards do hub e botoes de CRUD (criar, editar, excluir) respeitam o nivel de permissao (NONE, READ, WRITE, ADMIN) retornado pela API de login
CorrecaoCorrecao do vinculo de tenant em usuarios — agora envia tenant_id no payload conforme swagger
NovidadeCampo Data Atualizacao adicionado ao formulario de edicao de receitas (somente leitura, ao lado de Item Doc Venda)
NovidadeSeletor de tenant (empresa) no header — permite trocar entre empresas vinculadas ao usuario com reload automatico
MelhoriaAgrupamento de permissoes na aba Permissoes de usuarios agora usa group_name da API em vez de mapeamento fixo
NovidadeAba Tenants na edicao de usuarios — exibe tenants vinculados com opcao de adicionar ou remover vinculos via /users-tenants
CorrecaoCorrecao do formato de resposta da API em todos os endpoints — unwrap automatico de { data: [...] } para arrays
NovidadeFiltro Recorrente (is_recurring) adicionado ao painel de filtros de transacoes
MelhoriaLayout de transacoes redesenhado com grid 5 colunas — filtros col-2 e lista col-3 quando expandido
MelhoriaMulti-select melhorado: busca mantida ao selecionar, itens selecionados removidos do dropdown, tags exibidas abaixo do input
MelhoriaReorganizacao das secoes de filtros: Filtros (grid-cols-4), Periodo (grid-cols-3), Entidade (grid-cols-3)
NovidadeTab order otimizado nos filtros: auto-focus no Status, skip em Tipo/Conciliado/Recorrente e botoes de calendario
NovidadeColunas Conta e Parcelas ocultadas automaticamente quando filtros estao expandidos
MelhoriaHeader do fluxo de caixa redesenhado com gradiente verde compacto seguindo padrao das demais paginas
MelhoriaCards negativos no balancete e fluxo de caixa com estilo clean — fundo branco com gradiente red sutil, borda e texto vermelho
MelhoriaCards somatorios do fluxo de caixa e balancete separados do header verde, com gradiente sutil, icone maior e efeito blur decorativo
NovidadeCampo Vencimento oculto no formulario de criacao de transacao, exibindo apenas Vencimento Original
MelhoriaPagina Usuarios redesenhada com layout split-pane (lista e edicao lado a lado), header compacto verde, colunas responsivas e Copy ID
NovidadeAbas Detalhes e Permissoes na edicao de usuarios com controle granular de permissao (Nenhum, Leitura, Escrita, Admin) por modulo via API /users-permissions
MelhoriaCRUD de permissoes ajustado para usar /permissions (registro mestre) e /users-permissions com permission_id conforme swagger — carregamento dinamico dos servicos disponiveis
MelhoriaTela de permissoes aprimorada — barra resumo com contagem, metadata de atualizacao por permissao, acoes em lote por grupo (Definir todos) e botao Limpar todas
MelhoriaInfo do usuario (criado/atualizado) compactado em linha unica minimalista com data relativa e campos criado por / atualizado por

18 de Fevereiro de 2026

18 itens
135
MelhoriaPagina Receitas redesenhada com layout split-pane, header compacto, filtros inline, header de edicao neutro e toggle Pendente/Paga no footer
MelhoriaPagina Line Items redesenhada com layout split-pane, header compacto, filtros inline, header de edicao neutro e abas com borda inferior
MelhoriaPagina Deals redesenhada com layout split-pane, header compacto, header de edicao neutro e abas com borda inferior
MelhoriaPagina Empresas redesenhada com layout split-pane, header compacto, header de edicao neutro e abas com borda inferior
NovidadeSeletor de emoji (icone) substituindo URL de imagem em Contas, com componente AccountIcon reutilizavel e EmojiPicker por categorias
NovidadeToggle de tema Dark/Light no header com persistencia de preferencia
NovidadeLayout split-pane na pagina de Contas — lista e edicao lado a lado sem navegacao entre paginas
NovidadeLayout split-pane na pagina de Wallets — lista e edicao lado a lado sem navegacao entre paginas
NovidadeLayout split-pane na pagina de Safe Vaults — lista e edicao lado a lado sem navegacao entre paginas
MelhoriaRedesign premium das paginas hub Gerenciapp e Seidor — greeting card com glassmorphism, cards horizontais com icone+texto, layout mais compacto
NovidadeIcones de Assistente AI, Usuarios e Sobre no header principal, antes do avatar do usuario
NovidadeAvatar com logo da empresa na lista de parceiros usando o domain (fallback para iniciais)
NovidadeLayout split-pane na pagina de parceiros — lista e edicao lado a lado sem navegacao entre paginas
NovidadeNova barra de navegacao superior (top bar) substituindo a sidebar lateral, com logos clicaveis e menu do usuario
NovidadePaginas hub com cards de navegacao por modulo nas telas iniciais do Gerenciapp e Seidor
NovidadePagina de perfil redesenhada com layout side-by-side, cards glass e icones coloridos por campo
NovidadeTroca de senha na pagina de perfil via PUT /users/me/password, com validacao e feedback visual
NovidadeUpload de foto do avatar na pagina de perfil via POST /users/me/image/upload

13 de Fevereiro de 2026

13 itens
634
NovidadeAbas Detalhes e Deals na edicao de empresas: aba Detalhes mostra formulario existente, aba Deals lista deals vinculados por company_id com navegacao para edicao
NovidadeBotao Atualizar na edicao de empresas para buscar dados atualizados via API externa (GET /companies/:id/search)
NovidadeBalancete ajustado para exibir 4 meses (mes adicional retornado pela API) com layout flexivel
NovidadeValidacao de dia util nos campos de data de transacoes: modal pergunta se deseja mover para o proximo dia util quando a data informada cai em fim de semana ou feriado nacional
CorrecaoCampos de data agora usam o fuso horario local do usuario em vez de UTC fixo
NovidadeNavegacao da aba Receitas na edicao de line items para edicao da receita com retorno automatico (backTo) ao line item de origem
MelhoriaToggle premium de comissao paga no header da receita com sliding glass pill, animacao spring bounce e efeitos glassmorphism
CorrecaoDropdown de company na edicao de deal nao era cortado pelo container (posicionamento fixed)
NovidadeBotao Sincronizar no header de Line Items para sincronizar dados via POST /seidor/line-items/sync
MelhoriaModal de comissoes previstas por mes no dashboard com colunas Deal Name, Line Item, Parcela, Vlr. Liquido, Com. R$ e Com. %, links clicaveis, ordenacao e totais
CorrecaoCampo status na edicao de line item agora carrega corretamente o valor da API com normalizacao automatica
MelhoriaPadronizacao dos status de comissao de line items para maiusculo (PENDENTE, PARCIAL, PAGA, ISENTA)
MelhoriaFormulario de edicao de receitas reorganizado com grid responsivo (grid-cols-12) em 3 secoes (Identificacao, Valores, Datas), removendo larguras fixas e separador vertical

12 de Fevereiro de 2026

16 itens
79
NovidadeGrupos do sidebar colapsaveis: clique no label do grupo para recolher/expandir os itens com animacao suave
MelhoriaRedesign premium do sidebar: accent bar no item ativo, orbs decorativos, scrollbar customizado, seta ChevronRight, dropdown animado, group labels com dot colorido, separador gradient e sombras refinadas
MelhoriaPadronizacao visual dos labels e icones nos formularios GerenciApp (inline-flex, text-[11px], icones emerald com opacity, remocao de dividers e section headers)
MelhoriaLabels dos formularios Seidor com icones contextuais (Hash, Tag, User, Banknote, CalendarDays, etc.) e estilo inline-flex uppercase tracking-wide
MelhoriaRemocao de subdivisoes (icon boxes e dividers) nos formularios de edicao Seidor para layout mais limpo e continuo
MelhoriaPadronizacao visual das paginas Seidor (Dashboard, Empresas, Line Items, Receitas) seguindo o design de Deals: headers compactos, back button nativo com animacao, sidebar de resumo, inputs h-9 e botoes nativos com gradientes
MelhoriaRedesign do formulario de edicao de Deals com sidebar de resumo, secoes agrupadas (Identificacao, Responsaveis, Negociacao) e campo Amount com prefixo R$
MelhoriaPolish visual da edicao de Deals: sidebar unificado com divisores, ID como badge monospace, badges de contexto (Company, Close Date) no header e abas com gradiente cyan
NovidadeCampo Company no formulario de Deals com busca e selecao de empresas cadastradas (combobox)
NovidadeCRUD completo de Empresas no menu Seidor (criar, listar, editar, excluir) com endpoint /seidor/companies
NovidadeBusca e ordenacao por colunas na tabela de Empresas (Name, CNPJ, Domain, Owner)
MelhoriaRenomeacao de 'Vendas' para 'Line Items' no menu Seidor: tipos, componentes, rotas e labels atualizados
NovidadeCRUD completo de Deals no menu Seidor (criar, listar, editar, excluir) com endpoint /seidor/deals
NovidadeMenu Deals no sidebar Seidor com icone Handshake e navegacao entre listagem, criacao e edicao
NovidadeBusca e ordenacao por colunas na tabela de Deals (Name, Owner, Company, Amount, Close Date)
MelhoriaReordenacao do sidebar Seidor: Deals agora aparece acima de Line Items

10 de Fevereiro de 2026

20 itens
164
NovidadeGuias Detalhes e Transacoes no formulario de edicao de parceiro com listagem de transacoes vinculadas
NovidadeBotao Transferencia no formulario de edicao de parceiro para transferir transacoes entre parceiros
NovidadeID copiavel no card de exibicao do parceiro (formulario de edicao)
NovidadeOrdenacao por colunas na tabela de Safe Vault (clique no header)
NovidadeStatus de transacao com 3 estados: Pago, Pendente e Atrasado baseado em data de pagamento e vencimento
NovidadeGuias Detalhes e Receitas no formulario de edicao de vendas com navegacao por abas
MelhoriaRemocao da coluna Acoes na lista de vendas; clique na linha para abrir edicao
NovidadeBotao Carregar Atualizacoes na edicao de venda para sincronizar dados do HubSpot
NovidadeOrdenacao por colunas na lista de vendas (clique no header)
NovidadeOrdenacao por colunas na lista de receitas (clique no header)
NovidadeColunas Compensacao e Dt. Comissao na lista de receitas em substituicao a Faturamento
MelhoriaRedesign do formulario de edicao de receitas com secoes Documentos/Valores/Datas, section headers com icones, summary cards e fundo destacado na secao de valores
NovidadeLabel Sincronizado em no rodape do formulario de receitas com data de ultima atualizacao
NovidadeDashboard Seidor com visao geral de KPIs (vendas, receitas, comissoes), tabelas de vendas recentes, receitas pendentes e relatorio de comissoes
NovidadeGrafico de barras no Dashboard Seidor mostrando comissao prevista mes a mes
NovidadePerfil do usuario no rodape do sidebar com avatar, nome e menu popup (Ver perfil / Sair)
NovidadePagina Meu Perfil com informacoes da conta (nome, email, ID, admin)
NovidadeFoto do perfil Google no sidebar e pagina de perfil quando logado via Gmail
MelhoriaPagina inicial Gerenciapp com mensagem aleatoria gerada por IA em vez de cards de atalho
MelhoriaPagina inicial Seidor com mensagem aleatoria gerada por IA, paleta cyan e mesmo design da home Gerenciapp

09 de Fevereiro de 2026

6 itens
411
NovidadeRelatorio de Comissoes em PDF na pagina de Vendas
NovidadeBotao Atualizar Receitas com acompanhamento de progresso via polling
NovidadeColuna de acoes na lista de vendas com botoes de edicao e visualizacao de receitas
NovidadeColunas valor liquido, data atualizacao e updated_at na lista de receitas
CorrecaoCorrecao de fuso horario na exibicao de datas (UTC)
MelhoriaReorganizacao do formulario de vendas: PEP e ORB na secao Identificacao, unificacao de Responsaveis e Valores

04 de Fevereiro de 2026

1 item
1
NovidadeExportacao Excel para Balancete, Fluxo de Caixa e Transacoes

31 de Janeiro de 2026

3 itens
111
CorrecaoMensagens de transacoes atualizadas para portugues
NovidadeCRUD de receitas e vendas no modulo Seidor
MelhoriaRefatoracao de codigo para melhor legibilidade

30 de Janeiro de 2026

1 item
1
NovidadeMelhorias nas tabelas de vendas e carteiras

29 de Janeiro de 2026

3 itens
111
NovidadeExtracao de email do Google e rastreamento de ultimo login
CorrecaoCorrecao de URL de redirecionamento mobile
MelhoriaRefatoracao de codigo para melhor legibilidade

28 de Janeiro de 2026

2 itens
11
NovidadeTratamento de status e totais de comissao em vendas
MelhoriaRefatoracao de codigo para melhor legibilidade

26 de Janeiro de 2026

1 item
1
NovidadeSecao de Vendas com busca e exibicao de dados

23 de Janeiro de 2026

1 item
1
NovidadeFiltragem por tipo e alternancia de status em carteiras

11 de Janeiro de 2026

1 item
1
NovidadeExibicao de imagem de conta na tabela de contas

05 de Janeiro de 2026

2 itens
2
NovidadeCalculo de totais mensais no Balancete
NovidadeSecoes de Balancete e Fluxo de Caixa com busca de dados

24 de Dezembro de 2025

5 itens
32
CorrecaoPrevencao de redirecionamento em localhost
CorrecaoMelhoria na deteccao de dispositivo mobile
NovidadeRedirecionamento mobile e normalizacao de tipo de carteira
NovidadeAtualizacao de endpoint de login Google para /login/google
NovidadeLogin Google atualizado para usar credential

22 de Dezembro de 2025

1 item
1
NovidadeCarregamento de transacoes com filtros e sidebar colapsavel

19 de Dezembro de 2025

6 itens
3111
NovidadeGestao de carteiras e transacoes
NovidadeSecao de contas com operacoes CRUD
CorrecaoMelhoria de tipagem e consistencia em Partners
NovidadeAutenticacao Google e gestao de cofre seguro
MelhoriaRefatoracao de codigo para melhor legibilidade
InicioCriacao inicial do projeto GerenciApp