9 Commits

Author SHA1 Message Date
Felipe Coutinho
1df2ba787d chore: bump versão para 2.5.2 e atualizar changelog
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:51 +00:00
Felipe Coutinho
e5d9b66cca feat(dashboard): complementar texto de recorrências com "mensais"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:48 +00:00
Felipe Coutinho
37edb1b76d feat(notes): substituir ícone de tarefa pendente por RiSubtractLine em contextos read-only
No card e no modal de detalhes de anotações, onde não há interação
de marcação, tarefas não concluídas exibem RiSubtractLine em vez
do quadrado com borda. Locais interativos mantêm o comportamento atual.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:44 +00:00
Felipe Coutinho
6288f5f8d4 feat(budgets, cards): progress bar em cor destructive quando limite excedido
Adiciona prop indicatorClassName ao componente Progress. Orçamentos
estourados e cartões com 100% do limite utilizado exibem a barra
com indicador e fundo na cor destructive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:39 +00:00
Felipe Coutinho
57ac326c2a feat(transactions): filtro de contas por tipo dinheiro e sinal + em transferências recebidas
Ao selecionar "Dinheiro" como forma de pagamento, exibe apenas contas
do tipo "Dinheiro". Transferências recebidas (amount > 0) passam a
exibir sinal + mantendo a cor azul.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:35 +00:00
Felipe Coutinho
dccc18b1c1 fix(transfers): corrigir forma de pagamento de pix para transferência bancária
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:31 +00:00
Felipe Coutinho
0cb01a1d4c feat(accounts): adicionar tipos de conta dinheiro e outros com ícones no seletor
Adiciona "Dinheiro" (issue #50) e "Outros" à lista de tipos de conta.
Implementa AccountTypeSelectContent com ícones distintos por tipo via
getAccountTypeIcon em shared/utils/icons.tsx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 15:42:27 +00:00
Felipe Coutinho
51652da4f8 fix(invoices): exibir ícone de anexo na fatura do cartão (2.5.1)
fetchCardTransactions não preenchia hasAttachments, então o ícone não
aparecia em /cards/[cardId]/invoice. Agora delega para
fetchTransactionsWithRelations, que já calcula o flag via EXISTS.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 01:44:08 +00:00
Felipe Coutinho
7a74f9405e fix(lint): corrigir formatação do snapshot de migration e imports
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 22:28:27 +00:00
24 changed files with 3238 additions and 3333 deletions

View File

@@ -5,6 +5,29 @@ Todas as mudanças notáveis deste projeto serão documentadas neste arquivo.
O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/), O formato é baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/),
e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/). e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR/).
## [2.5.2] - 2026-05-04
Esta versão traz melhorias visuais e de usabilidade em contas, lançamentos, orçamentos, cartões e anotações: novos tipos de conta, ícones no seletor, feedback visual de limite excedido nas progress bars e refinamentos nos ícones de tarefas em anotações.
### Adicionado
- Novos tipos de conta `"Dinheiro"` e `"Outros"` na lista padrão do diálogo de contas (issue #50).
- Ícones por tipo de conta no seletor (Conta Corrente, Poupança, Carteira Digital, Investimento, Pré-Pago, Dinheiro, Outros).
- Filtro automático: ao selecionar `"Dinheiro"` como forma de pagamento em lançamentos, o select de conta exibe apenas contas do tipo `"Dinheiro"`.
- Sinal `+` no valor de transferências recebidas na tabela de lançamentos (mantém cor azul).
### Alterado
- Forma de pagamento de novas transferências entre contas alterada de `"Pix"` para `"Transferência bancária"`.
- Progress bar de orçamentos excedidos agora exibe indicador e fundo na cor `destructive`.
- Progress bar de cartões com 100% do limite utilizado agora exibe indicador e fundo na cor `destructive`.
- Ícone de tarefa não concluída no card e no modal de detalhes de anotações substituído por `RiSubtractLine` (locais sem interação de marcação).
## [2.5.1] - 2026-05-04
Versão de correção pontual focada na exibição do indicador de anexo nas tabelas de lançamentos da fatura do cartão. Em `/cards/[cardId]/invoice`, lançamentos com anexos não mostravam o ícone porque o fetcher dedicado da fatura não calculava o flag `hasAttachments`. A primeira tentativa de adicionar o EXISTS via `extras` na query relacional gerou SQL inválido (Drizzle re-aliasava `transactionAttachments.transactionId` para o alias da tabela externa). A correção definitiva troca o fetcher pela função compartilhada `fetchTransactionsWithRelations` de `features/transactions`, que já implementa o EXISTS corretamente via `select`.
### Corrigido
- Ícone de anexo voltou a aparecer na tabela de lançamentos da fatura do cartão (`/cards/[cardId]/invoice`). `fetchCardTransactions` em `features/invoices/queries.ts` agora delega para `fetchTransactionsWithRelations`, garantindo que o flag `hasAttachments` seja preenchido com a mesma EXISTS subquery usada no restante do app.
## [2.5.0] - 2026-05-01 ## [2.5.0] - 2026-05-01
Esta versão melhora o fechamento de faturas, a correção de lançamentos já registrados e a conferência de saldos contra o extrato do banco. O novo **ajuste de fatura** fecha a conta entre o total calculado pelo sistema e o valor real cobrado pelo banco, sem exigir que o usuário reabra lançamentos individuais. A mesma ideia foi estendida para **contas correntes**: na página do extrato, ao lado de "Saldo ao final do período", o usuário informa o saldo real e o sistema cria (ou atualiza) um lançamento de ajuste no período visualizado. Também entra o fluxo de **reembolso** para despesas à vista: pelo menu de ações do lançamento, o usuário informa a data do reembolso e o sistema cria uma receita espelhada no extrato ou na fatura correta. O widget de boletos do dashboard ganhou paridade com o widget de faturas — confirmação de pagamento agora pede conta de origem e data antes de quitar o boleto. Por fim, o **limite do cartão** passou a ser obrigatório e o sistema bloqueia despesas em cartão que ultrapassem o limite disponível, retornando uma mensagem com o valor exato disponível. As operações mantêm rastro no lançamento gerado e respeitam a proteção de faturas já pagas. Esta versão melhora o fechamento de faturas, a correção de lançamentos já registrados e a conferência de saldos contra o extrato do banco. O novo **ajuste de fatura** fecha a conta entre o total calculado pelo sistema e o valor real cobrado pelo banco, sem exigir que o usuário reabra lançamentos individuais. A mesma ideia foi estendida para **contas correntes**: na página do extrato, ao lado de "Saldo ao final do período", o usuário informa o saldo real e o sistema cria (ou atualiza) um lançamento de ajuste no período visualizado. Também entra o fluxo de **reembolso** para despesas à vista: pelo menu de ações do lançamento, o usuário informa a data do reembolso e o sistema cria uma receita espelhada no extrato ou na fatura correta. O widget de boletos do dashboard ganhou paridade com o widget de faturas — confirmação de pagamento agora pede conta de origem e data antes de quitar o boleto. Por fim, o **limite do cartão** passou a ser obrigatório e o sistema bloqueia despesas em cartão que ultrapassem o limite disponível, retornando uma mensagem com o valor exato disponível. As operações mantêm rastro no lançamento gerado e respeitam a proteção de faturas já pagas.

View File

@@ -8,7 +8,7 @@
> **⚠️ Não há versão online hospedada.** Você precisa clonar o repositório e rodar localmente ou no seu próprio servidor. > **⚠️ Não há versão online hospedada.** Você precisa clonar o repositório e rodar localmente ou no seu próprio servidor.
[![Version](https://img.shields.io/badge/version-2.5.0-blue?style=flat-square)](CHANGELOG.md) [![Version](https://img.shields.io/badge/version-2.5.2-blue?style=flat-square)](CHANGELOG.md)
[![Next.js](https://img.shields.io/badge/Next.js-black?style=flat-square&logo=next.js)](https://nextjs.org/) [![Next.js](https://img.shields.io/badge/Next.js-black?style=flat-square&logo=next.js)](https://nextjs.org/)
[![TypeScript](https://img.shields.io/badge/TypeScript-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-blue?style=flat-square&logo=postgresql)](https://www.postgresql.org/) [![PostgreSQL](https://img.shields.io/badge/PostgreSQL-blue?style=flat-square&logo=postgresql)](https://www.postgresql.org/)

View File

@@ -109,12 +109,8 @@
"name": "account_userId_user_id_fk", "name": "account_userId_user_id_fk",
"tableFrom": "account", "tableFrom": "account",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -214,12 +210,8 @@
"name": "tokens_api_user_id_user_id_fk", "name": "tokens_api_user_id_user_id_fk",
"tableFrom": "tokens_api", "tableFrom": "tokens_api",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -301,12 +293,8 @@
"name": "anexos_user_id_user_id_fk", "name": "anexos_user_id_user_id_fk",
"tableFrom": "anexos", "tableFrom": "anexos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -316,9 +304,7 @@
"anexos_chave_arquivo_unique": { "anexos_chave_arquivo_unique": {
"name": "anexos_chave_arquivo_unique", "name": "anexos_chave_arquivo_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["chave_arquivo"]
"chave_arquivo"
]
} }
}, },
"policies": {}, "policies": {},
@@ -438,12 +424,8 @@
"name": "orcamentos_user_id_user_id_fk", "name": "orcamentos_user_id_user_id_fk",
"tableFrom": "orcamentos", "tableFrom": "orcamentos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -451,12 +433,8 @@
"name": "orcamentos_categoria_id_categorias_id_fk", "name": "orcamentos_categoria_id_categorias_id_fk",
"tableFrom": "orcamentos", "tableFrom": "orcamentos",
"tableTo": "categorias", "tableTo": "categorias",
"columnsFrom": [ "columnsFrom": ["categoria_id"],
"categoria_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
} }
@@ -569,12 +547,8 @@
"name": "cartoes_user_id_user_id_fk", "name": "cartoes_user_id_user_id_fk",
"tableFrom": "cartoes", "tableFrom": "cartoes",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -582,12 +556,8 @@
"name": "cartoes_conta_id_contas_id_fk", "name": "cartoes_conta_id_contas_id_fk",
"tableFrom": "cartoes", "tableFrom": "cartoes",
"tableTo": "contas", "tableTo": "contas",
"columnsFrom": [ "columnsFrom": ["conta_id"],
"conta_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
} }
@@ -669,12 +639,8 @@
"name": "categorias_user_id_user_id_fk", "name": "categorias_user_id_user_id_fk",
"tableFrom": "categorias", "tableFrom": "categorias",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -769,12 +735,8 @@
"name": "dashboard_notification_states_user_id_user_id_fk", "name": "dashboard_notification_states_user_id_user_id_fk",
"tableFrom": "dashboard_notification_states", "tableFrom": "dashboard_notification_states",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -821,12 +783,8 @@
"name": "establishment_logos_user_id_user_id_fk", "name": "establishment_logos_user_id_user_id_fk",
"tableFrom": "establishment_logos", "tableFrom": "establishment_logos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -834,10 +792,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"establishment_logos_user_id_name_key_pk": { "establishment_logos_user_id_name_key_pk": {
"name": "establishment_logos_user_id_name_key_pk", "name": "establishment_logos_user_id_name_key_pk",
"columns": [ "columns": ["user_id", "name_key"]
"user_id",
"name_key"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -927,12 +882,8 @@
"name": "contas_user_id_user_id_fk", "name": "contas_user_id_user_id_fk",
"tableFrom": "contas", "tableFrom": "contas",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -995,12 +946,8 @@
"name": "import_category_mappings_user_id_user_id_fk", "name": "import_category_mappings_user_id_user_id_fk",
"tableFrom": "import_category_mappings", "tableFrom": "import_category_mappings",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1008,12 +955,8 @@
"name": "import_category_mappings_category_id_categorias_id_fk", "name": "import_category_mappings_category_id_categorias_id_fk",
"tableFrom": "import_category_mappings", "tableFrom": "import_category_mappings",
"tableTo": "categorias", "tableTo": "categorias",
"columnsFrom": [ "columnsFrom": ["category_id"],
"category_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -1021,10 +964,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"import_category_mappings_user_id_description_key_pk": { "import_category_mappings_user_id_description_key_pk": {
"name": "import_category_mappings_user_id_description_key_pk", "name": "import_category_mappings_user_id_description_key_pk",
"columns": [ "columns": ["user_id", "description_key"]
"user_id",
"description_key"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -1195,12 +1135,8 @@
"name": "pre_lancamentos_user_id_user_id_fk", "name": "pre_lancamentos_user_id_user_id_fk",
"tableFrom": "pre_lancamentos", "tableFrom": "pre_lancamentos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1208,12 +1144,8 @@
"name": "pre_lancamentos_lancamento_id_lancamentos_id_fk", "name": "pre_lancamentos_lancamento_id_lancamentos_id_fk",
"tableFrom": "pre_lancamentos", "tableFrom": "pre_lancamentos",
"tableTo": "lancamentos", "tableTo": "lancamentos",
"columnsFrom": [ "columnsFrom": ["lancamento_id"],
"lancamento_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "set null", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -1383,12 +1315,8 @@
"name": "antecipacoes_parcelas_lancamento_id_lancamentos_id_fk", "name": "antecipacoes_parcelas_lancamento_id_lancamentos_id_fk",
"tableFrom": "antecipacoes_parcelas", "tableFrom": "antecipacoes_parcelas",
"tableTo": "lancamentos", "tableTo": "lancamentos",
"columnsFrom": [ "columnsFrom": ["lancamento_id"],
"lancamento_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1396,12 +1324,8 @@
"name": "antecipacoes_parcelas_pagador_id_pagadores_id_fk", "name": "antecipacoes_parcelas_pagador_id_pagadores_id_fk",
"tableFrom": "antecipacoes_parcelas", "tableFrom": "antecipacoes_parcelas",
"tableTo": "pagadores", "tableTo": "pagadores",
"columnsFrom": [ "columnsFrom": ["pagador_id"],
"pagador_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1409,12 +1333,8 @@
"name": "antecipacoes_parcelas_categoria_id_categorias_id_fk", "name": "antecipacoes_parcelas_categoria_id_categorias_id_fk",
"tableFrom": "antecipacoes_parcelas", "tableFrom": "antecipacoes_parcelas",
"tableTo": "categorias", "tableTo": "categorias",
"columnsFrom": [ "columnsFrom": ["categoria_id"],
"categoria_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1422,12 +1342,8 @@
"name": "antecipacoes_parcelas_user_id_user_id_fk", "name": "antecipacoes_parcelas_user_id_user_id_fk",
"tableFrom": "antecipacoes_parcelas", "tableFrom": "antecipacoes_parcelas",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -1557,12 +1473,8 @@
"name": "faturas_user_id_user_id_fk", "name": "faturas_user_id_user_id_fk",
"tableFrom": "faturas", "tableFrom": "faturas",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1570,12 +1482,8 @@
"name": "faturas_cartao_id_cartoes_id_fk", "name": "faturas_cartao_id_cartoes_id_fk",
"tableFrom": "faturas", "tableFrom": "faturas",
"tableTo": "cartoes", "tableTo": "cartoes",
"columnsFrom": [ "columnsFrom": ["cartao_id"],
"cartao_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
} }
@@ -1665,12 +1573,8 @@
"name": "anotacoes_user_id_user_id_fk", "name": "anotacoes_user_id_user_id_fk",
"tableFrom": "anotacoes", "tableFrom": "anotacoes",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -1774,12 +1678,8 @@
"name": "passkey_userId_user_id_fk", "name": "passkey_userId_user_id_fk",
"tableFrom": "passkey", "tableFrom": "passkey",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -1892,12 +1792,8 @@
"name": "compartilhamentos_pagador_pagador_id_pagadores_id_fk", "name": "compartilhamentos_pagador_pagador_id_pagadores_id_fk",
"tableFrom": "compartilhamentos_pagador", "tableFrom": "compartilhamentos_pagador",
"tableTo": "pagadores", "tableTo": "pagadores",
"columnsFrom": [ "columnsFrom": ["pagador_id"],
"pagador_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1905,12 +1801,8 @@
"name": "compartilhamentos_pagador_shared_with_user_id_user_id_fk", "name": "compartilhamentos_pagador_shared_with_user_id_user_id_fk",
"tableFrom": "compartilhamentos_pagador", "tableFrom": "compartilhamentos_pagador",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["shared_with_user_id"],
"shared_with_user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -1918,12 +1810,8 @@
"name": "compartilhamentos_pagador_created_by_user_id_user_id_fk", "name": "compartilhamentos_pagador_created_by_user_id_user_id_fk",
"tableFrom": "compartilhamentos_pagador", "tableFrom": "compartilhamentos_pagador",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["created_by_user_id"],
"created_by_user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -2036,12 +1924,8 @@
"name": "pagadores_user_id_user_id_fk", "name": "pagadores_user_id_user_id_fk",
"tableFrom": "pagadores", "tableFrom": "pagadores",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -2130,12 +2014,8 @@
"name": "insights_salvos_user_id_user_id_fk", "name": "insights_salvos_user_id_user_id_fk",
"tableFrom": "insights_salvos", "tableFrom": "insights_salvos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -2221,12 +2101,8 @@
"name": "session_userId_user_id_fk", "name": "session_userId_user_id_fk",
"tableFrom": "session", "tableFrom": "session",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["userId"],
"userId" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -2236,9 +2112,7 @@
"session_token_unique": { "session_token_unique": {
"name": "session_token_unique", "name": "session_token_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["token"]
"token"
]
} }
}, },
"policies": {}, "policies": {},
@@ -2284,12 +2158,8 @@
"name": "lancamento_anexos_lancamento_id_lancamentos_id_fk", "name": "lancamento_anexos_lancamento_id_lancamentos_id_fk",
"tableFrom": "lancamento_anexos", "tableFrom": "lancamento_anexos",
"tableTo": "lancamentos", "tableTo": "lancamentos",
"columnsFrom": [ "columnsFrom": ["lancamento_id"],
"lancamento_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -2297,12 +2167,8 @@
"name": "lancamento_anexos_anexo_id_anexos_id_fk", "name": "lancamento_anexos_anexo_id_anexos_id_fk",
"tableFrom": "lancamento_anexos", "tableFrom": "lancamento_anexos",
"tableTo": "anexos", "tableTo": "anexos",
"columnsFrom": [ "columnsFrom": ["anexo_id"],
"anexo_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -2310,10 +2176,7 @@
"compositePrimaryKeys": { "compositePrimaryKeys": {
"lancamento_anexos_lancamento_id_anexo_id_pk": { "lancamento_anexos_lancamento_id_anexo_id_pk": {
"name": "lancamento_anexos_lancamento_id_anexo_id_pk", "name": "lancamento_anexos_lancamento_id_anexo_id_pk",
"columns": [ "columns": ["lancamento_id", "anexo_id"]
"lancamento_id",
"anexo_id"
]
} }
}, },
"uniqueConstraints": {}, "uniqueConstraints": {},
@@ -2789,12 +2652,8 @@
"name": "lancamentos_antecipacao_id_antecipacoes_parcelas_id_fk", "name": "lancamentos_antecipacao_id_antecipacoes_parcelas_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "antecipacoes_parcelas", "tableTo": "antecipacoes_parcelas",
"columnsFrom": [ "columnsFrom": ["antecipacao_id"],
"antecipacao_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "set null", "onDelete": "set null",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -2802,12 +2661,8 @@
"name": "lancamentos_user_id_user_id_fk", "name": "lancamentos_user_id_user_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
}, },
@@ -2815,12 +2670,8 @@
"name": "lancamentos_cartao_id_cartoes_id_fk", "name": "lancamentos_cartao_id_cartoes_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "cartoes", "tableTo": "cartoes",
"columnsFrom": [ "columnsFrom": ["cartao_id"],
"cartao_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
}, },
@@ -2828,12 +2679,8 @@
"name": "lancamentos_conta_id_contas_id_fk", "name": "lancamentos_conta_id_contas_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "contas", "tableTo": "contas",
"columnsFrom": [ "columnsFrom": ["conta_id"],
"conta_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
}, },
@@ -2841,12 +2688,8 @@
"name": "lancamentos_categoria_id_categorias_id_fk", "name": "lancamentos_categoria_id_categorias_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "categorias", "tableTo": "categorias",
"columnsFrom": [ "columnsFrom": ["categoria_id"],
"categoria_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
}, },
@@ -2854,12 +2697,8 @@
"name": "lancamentos_pagador_id_pagadores_id_fk", "name": "lancamentos_pagador_id_pagadores_id_fk",
"tableFrom": "lancamentos", "tableFrom": "lancamentos",
"tableTo": "pagadores", "tableTo": "pagadores",
"columnsFrom": [ "columnsFrom": ["pagador_id"],
"pagador_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "cascade" "onUpdate": "cascade"
} }
@@ -2924,9 +2763,7 @@
"user_email_unique": { "user_email_unique": {
"name": "user_email_unique", "name": "user_email_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["email"]
"email"
]
} }
}, },
"policies": {}, "policies": {},
@@ -2997,12 +2834,8 @@
"name": "preferencias_usuario_user_id_user_id_fk", "name": "preferencias_usuario_user_id_user_id_fk",
"tableFrom": "preferencias_usuario", "tableFrom": "preferencias_usuario",
"tableTo": "user", "tableTo": "user",
"columnsFrom": [ "columnsFrom": ["user_id"],
"user_id" "columnsTo": ["id"],
],
"columnsTo": [
"id"
],
"onDelete": "cascade", "onDelete": "cascade",
"onUpdate": "no action" "onUpdate": "no action"
} }
@@ -3012,9 +2845,7 @@
"preferencias_usuario_user_id_unique": { "preferencias_usuario_user_id_unique": {
"name": "preferencias_usuario_user_id_unique", "name": "preferencias_usuario_user_id_unique",
"nullsNotDistinct": false, "nullsNotDistinct": false,
"columns": [ "columns": ["user_id"]
"user_id"
]
} }
}, },
"policies": {}, "policies": {},

View File

@@ -1,6 +1,6 @@
{ {
"name": "openmonetis", "name": "openmonetis",
"version": "2.5.0", "version": "2.5.2",
"private": true, "private": true,
"packageManager": "pnpm@10.33.0", "packageManager": "pnpm@10.33.0",
"scripts": { "scripts": {

BIN
public/logos/dinheiro.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -37,7 +37,9 @@ const DEFAULT_ACCOUNT_TYPES = [
"Conta Poupança", "Conta Poupança",
"Carteira Digital", "Carteira Digital",
"Conta Investimento", "Conta Investimento",
"Dinheiro",
"Pré-Pago | VR/VA", "Pré-Pago | VR/VA",
"Outros",
] as const; ] as const;
const DEFAULT_ACCOUNT_STATUS = ["Ativa", "Inativa"] as const; const DEFAULT_ACCOUNT_STATUS = ["Ativa", "Inativa"] as const;

View File

@@ -12,7 +12,10 @@ import {
SelectValue, SelectValue,
} from "@/shared/components/ui/select"; } from "@/shared/components/ui/select";
import { Textarea } from "@/shared/components/ui/textarea"; import { Textarea } from "@/shared/components/ui/textarea";
import { StatusSelectContent } from "./account-select-items"; import {
AccountTypeSelectContent,
StatusSelectContent,
} from "./account-select-items";
import type { AccountFormValues } from "./types"; import type { AccountFormValues } from "./types";
@@ -54,12 +57,16 @@ export function AccountFormFields({
onValueChange={(value) => onChange("accountType", value)} onValueChange={(value) => onChange("accountType", value)}
> >
<SelectTrigger id="account-type" className="w-full"> <SelectTrigger id="account-type" className="w-full">
<SelectValue placeholder="Selecione o tipo" /> <SelectValue placeholder="Selecione o tipo">
{values.accountType && (
<AccountTypeSelectContent label={values.accountType} />
)}
</SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{accountTypes.map((type) => ( {accountTypes.map((type) => (
<SelectItem key={type} value={type}> <SelectItem key={type} value={type}>
{type} <AccountTypeSelectContent label={type} />
</SelectItem> </SelectItem>
))} ))}
</SelectContent> </SelectContent>

View File

@@ -1,6 +1,18 @@
"use client"; "use client";
import StatusDot from "@/shared/components/status-dot"; import StatusDot from "@/shared/components/status-dot";
import { getAccountTypeIcon } from "@/shared/utils/icons";
export function AccountTypeSelectContent({ label }: { label: string }) {
const icon = getAccountTypeIcon(label);
return (
<span className="flex items-center gap-2">
{icon}
<span>{label}</span>
</span>
);
}
export function StatusSelectContent({ label }: { label: string }) { export function StatusSelectContent({ label }: { label: string }) {
const isActive = label === "Ativa"; const isActive = label === "Ativa";

View File

@@ -90,6 +90,7 @@ export function BudgetCard({ budget, onEdit, onRemove }: BudgetCardProps) {
<Progress <Progress
value={usagePercent} value={usagePercent}
className={cn("h-2.5", exceeded && "bg-destructive/20!")} className={cn("h-2.5", exceeded && "bg-destructive/20!")}
indicatorClassName={cn(exceeded && "bg-destructive")}
aria-label={`${usagePercent.toFixed(1)}% do orçamento utilizado`} aria-label={`${usagePercent.toFixed(1)}% do orçamento utilizado`}
/> />
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">

View File

@@ -69,6 +69,7 @@ export function CardItem({
const usagePercent = const usagePercent =
limit > 0 ? Math.min(Math.max((used / limit) * 100, 0), 100) : 0; limit > 0 ? Math.min(Math.max((used / limit) * 100, 0), 100) : 0;
const exceeded = usagePercent >= 100;
const logoPath = resolveLogoSrc(logo); const logoPath = resolveLogoSrc(logo);
const brandAsset = resolveCardBrandAsset(brand); const brandAsset = resolveCardBrandAsset(brand);
@@ -194,7 +195,8 @@ export function CardItem({
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<Progress <Progress
value={usagePercent} value={usagePercent}
className="h-2.5" className={cn("h-2.5", exceeded && "bg-destructive/20!")}
indicatorClassName={cn(exceeded && "bg-destructive")}
aria-label={`${usagePercent.toFixed(0)}% do limite utilizado`} aria-label={`${usagePercent.toFixed(0)}% do limite utilizado`}
/> />
<span className="text-xs text-muted-foreground"> <span className="text-xs text-muted-foreground">

View File

@@ -14,7 +14,7 @@ import {
TooltipContent, TooltipContent,
TooltipTrigger, TooltipTrigger,
} from "@/shared/components/ui/tooltip"; } from "@/shared/components/ui/tooltip";
import { getCurrentPeriod, formatPeriodForUrl } from "@/shared/utils/period"; import { formatPeriodForUrl, getCurrentPeriod } from "@/shared/utils/period";
import { cn } from "@/shared/utils/ui"; import { cn } from "@/shared/utils/ui";
type BillListItemProps = { type BillListItemProps = {

View File

@@ -13,7 +13,7 @@ const formatOccurrences = (value: number | null) => {
return "Recorrência contínua"; return "Recorrência contínua";
} }
return `${value} recorrências`; return `${value} recorrências mensais`;
}; };
export function RecurringExpensesWidget({ export function RecurringExpensesWidget({

View File

@@ -114,10 +114,12 @@ export async function fetchDashboardPeriodOverview(
.select({ .select({
period: transactions.period, period: transactions.period,
transactionType: transactions.transactionType, transactionType: transactions.transactionType,
totalAmount: sql<number>`coalesce(sum(case when ${transactions.note} ilike ${refundPattern} then 0 else ${transactions.amount} end), 0)`.as( totalAmount:
sql<number>`coalesce(sum(case when ${transactions.note} ilike ${refundPattern} then 0 else ${transactions.amount} end), 0)`.as(
"total", "total",
), ),
refundAmount: sql<number>`coalesce(sum(case when ${transactions.note} ilike ${refundPattern} then ${transactions.amount} else 0 end), 0)`.as( refundAmount:
sql<number>`coalesce(sum(case when ${transactions.note} ilike ${refundPattern} then ${transactions.amount} else 0 end), 0)`.as(
"refund", "refund",
), ),
accountExcludeFromBalance: financialAccounts.excludeFromBalance, accountExcludeFromBalance: financialAccounts.excludeFromBalance,

View File

@@ -1,5 +1,6 @@
import { and, desc, eq, type SQL, sum } from "drizzle-orm"; import { and, eq, type SQL, sum } from "drizzle-orm";
import { cards, invoices, transactions } from "@/db/schema"; import { cards, invoices, transactions } from "@/db/schema";
import { fetchTransactionsWithRelations } from "@/features/transactions/queries";
import { buildInvoicePaymentNote } from "@/shared/lib/accounts/constants"; import { buildInvoicePaymentNote } from "@/shared/lib/accounts/constants";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { import {
@@ -104,14 +105,5 @@ export async function fetchInvoiceData(
} }
export async function fetchCardTransactions(filters: SQL[]) { export async function fetchCardTransactions(filters: SQL[]) {
return db.query.transactions.findMany({ return fetchTransactionsWithRelations({ filters });
where: and(...filters),
with: {
payer: true,
financialAccount: true,
card: true,
category: true,
},
orderBy: desc(transactions.purchaseDate),
});
} }

View File

@@ -7,6 +7,7 @@ import {
RiFileList2Line, RiFileList2Line,
RiInboxUnarchiveLine, RiInboxUnarchiveLine,
RiPencilLine, RiPencilLine,
RiSubtractLine,
} from "@remixicon/react"; } from "@remixicon/react";
import { import {
buildNoteDisplayTitle, buildNoteDisplayTitle,
@@ -101,7 +102,7 @@ export function NoteCard({
{task.completed ? ( {task.completed ? (
<RiCheckLine className="h-4 w-4 text-success" /> <RiCheckLine className="h-4 w-4 text-success" />
) : ( ) : (
<div className="h-4 w-4 rounded-sm border border-input" /> <RiSubtractLine className="h-4 w-4 text-muted-foreground" />
)} )}
</div> </div>
<span <span

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { RiCheckLine } from "@remixicon/react"; import { RiCheckLine, RiSubtractLine } from "@remixicon/react";
import { import {
buildNoteDisplayTitle, buildNoteDisplayTitle,
formatNoteCreatedAtLong, formatNoteCreatedAtLong,
@@ -69,7 +69,7 @@ export function NoteDetailsDialog({
{task.completed ? ( {task.completed ? (
<RiCheckLine className="h-4 w-4 text-success" /> <RiCheckLine className="h-4 w-4 text-success" />
) : ( ) : (
<div className="h-4 w-4 rounded-sm border border-input" /> <RiSubtractLine className="h-4 w-4 text-muted-foreground" />
)} )}
</div> </div>
<span <span

View File

@@ -3,10 +3,7 @@
import { and, eq } from "drizzle-orm"; import { and, eq } from "drizzle-orm";
import { z } from "zod"; import { z } from "zod";
import { cards, categories, transactions } from "@/db/schema"; import { cards, categories, transactions } from "@/db/schema";
import { import { buildRefundNote, isRefundNote } from "@/shared/lib/accounts/constants";
buildRefundNote,
isRefundNote,
} from "@/shared/lib/accounts/constants";
import { getUser } from "@/shared/lib/auth/server"; import { getUser } from "@/shared/lib/auth/server";
import { db } from "@/shared/lib/db"; import { db } from "@/shared/lib/db";
import { PERIOD_FORMAT_REGEX } from "@/shared/lib/invoices"; import { PERIOD_FORMAT_REGEX } from "@/shared/lib/invoices";

View File

@@ -93,6 +93,8 @@ export function PaymentMethodSection({
? accountOptions.filter( ? accountOptions.filter(
(option) => option.accountType === "Pré-Pago | VR/VA", (option) => option.accountType === "Pré-Pago | VR/VA",
) )
: formState.paymentMethod === "Dinheiro"
? accountOptions.filter((option) => option.accountType === "Dinheiro")
: accountOptions; : accountOptions;
const hasSecondaryColumn = isCartaoSelected || showContaSelect; const hasSecondaryColumn = isCartaoSelected || showContaSelect;

View File

@@ -348,10 +348,12 @@ function buildColumns({
cell: ({ row }) => { cell: ({ row }) => {
const isReceita = row.original.transactionType === "Receita"; const isReceita = row.original.transactionType === "Receita";
const isTransfer = row.original.transactionType === "Transferência"; const isTransfer = row.original.transactionType === "Transferência";
const isIncomingTransfer =
isTransfer && Number(row.original.amount) > 0;
return ( return (
<MoneyValues <MoneyValues
amount={row.original.amount} amount={row.original.amount}
showPositiveSign={isReceita} showPositiveSign={isReceita || isIncomingTransfer}
className={cn( className={cn(
"whitespace-nowrap", "whitespace-nowrap",
isReceita ? "text-success" : "text-foreground", isReceita ? "text-success" : "text-foreground",

View File

@@ -7,9 +7,12 @@ import { cn } from "@/shared/utils/ui";
function Progress({ function Progress({
className, className,
indicatorClassName,
value, value,
...props ...props
}: React.ComponentProps<typeof ProgressPrimitive.Root>) { }: React.ComponentProps<typeof ProgressPrimitive.Root> & {
indicatorClassName?: string;
}) {
return ( return (
<ProgressPrimitive.Root <ProgressPrimitive.Root
data-slot="progress" data-slot="progress"
@@ -21,7 +24,10 @@ function Progress({
> >
<ProgressPrimitive.Indicator <ProgressPrimitive.Indicator
data-slot="progress-indicator" data-slot="progress-indicator"
className="bg-primary h-full w-full flex-1 transition-all" className={cn(
"bg-primary h-full w-full flex-1 transition-all",
indicatorClassName,
)}
style={{ transform: `translateX(-${100 - (value || 0)}%)` }} style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/> />
</ProgressPrimitive.Root> </ProgressPrimitive.Root>

View File

@@ -45,7 +45,8 @@ export const requiredDecimalSchema = (fieldName: string = "valor") =>
.transform((value) => value.replace(",", ".")), .transform((value) => value.replace(",", ".")),
]) ])
.transform((value, ctx) => { .transform((value, ctx) => {
const parsed = typeof value === "number" ? value : Number.parseFloat(value); const parsed =
typeof value === "number" ? value : Number.parseFloat(value);
if (Number.isNaN(parsed)) { if (Number.isNaN(parsed)) {
ctx.addIssue({ ctx.addIssue({
code: z.ZodIssueCode.custom, code: z.ZodIssueCode.custom,

View File

@@ -1,5 +1,5 @@
export const TRANSFER_CATEGORY_NAME = "Transferência interna"; export const TRANSFER_CATEGORY_NAME = "Transferência interna";
export const TRANSFER_ESTABLISHMENT_SAIDA = "Saída - Transf. entre contas"; export const TRANSFER_ESTABLISHMENT_SAIDA = "Saída - Transf. entre contas";
export const TRANSFER_ESTABLISHMENT_ENTRADA = "Entrada - Transf. entre contas"; export const TRANSFER_ESTABLISHMENT_ENTRADA = "Entrada - Transf. entre contas";
export const TRANSFER_PAYMENT_METHOD = "Pix"; export const TRANSFER_PAYMENT_METHOD = "Transferência bancária";
export const TRANSFER_CONDITION = "À vista"; export const TRANSFER_CONDITION = "À vista";

View File

@@ -36,13 +36,37 @@ export const getConditionIcon = (condition: string): ReactNode => {
return registry[key] ?? null; return registry[key] ?? null;
}; };
export const getAccountTypeIcon = (accountType: string): ReactNode => {
const key = normalizeKey(accountType);
const registry: Record<string, ReactNode> = {
contacorrente: <RemixIcons.RiBankLine className={ICON_CLASS} aria-hidden />,
contapoupanca: (
<RemixIcons.RiSafe2Line className={ICON_CLASS} aria-hidden />
),
carteiradigital: (
<RemixIcons.RiWalletLine className={ICON_CLASS} aria-hidden />
),
containvestimento: (
<RemixIcons.RiFundsLine className={ICON_CLASS} aria-hidden />
),
prepagovrva: <RemixIcons.RiCouponLine className={ICON_CLASS} aria-hidden />,
dinheiro: <RemixIcons.RiCashLine className={ICON_CLASS} aria-hidden />,
outros: <RemixIcons.RiMoreFill className={ICON_CLASS} aria-hidden />,
};
return (
registry[key] ?? (
<RemixIcons.RiBankLine className={ICON_CLASS} aria-hidden />
)
);
};
export const getPaymentMethodIcon = (paymentMethod: string): ReactNode => { export const getPaymentMethodIcon = (paymentMethod: string): ReactNode => {
const key = normalizeKey(paymentMethod); const key = normalizeKey(paymentMethod);
const registry: Record<string, ReactNode> = { const registry: Record<string, ReactNode> = {
dinheiro: ( dinheiro: <RemixIcons.RiCashLine className={ICON_CLASS} aria-hidden />,
<RemixIcons.RiMoneyDollarCircleLine className={ICON_CLASS} aria-hidden />
),
pix: <RemixIcons.RiPixLine className={ICON_CLASS} aria-hidden />, pix: <RemixIcons.RiPixLine className={ICON_CLASS} aria-hidden />,
boleto: <RemixIcons.RiBarcodeLine className={ICON_CLASS} aria-hidden />, boleto: <RemixIcons.RiBarcodeLine className={ICON_CLASS} aria-hidden />,
credito: ( credito: (