mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
style(notes): polimento visual nas tarefas e modal de detalhes
Ícone de tarefa concluída em card e detalhes simplificado para RiCheckLine verde sem caixa. Checkbox no modal de edição usa bg/border success com texto success-foreground (claro no light, escuro no dark). Footer do modal de detalhes reordenado: Cancelar à esquerda, Alterar primário à direita. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -227,12 +227,12 @@ export function AccountDialog({
|
||||
});
|
||||
};
|
||||
|
||||
const title = mode === "create" ? "Nova conta" : "Editar conta";
|
||||
const title = mode === "create" ? "Nova conta" : "Atualizar conta";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Cadastre uma nova conta para organizar seus lançamentos."
|
||||
: "Atualize as informações da conta selecionada.";
|
||||
const submitLabel = mode === "create" ? "Salvar conta" : "Atualizar conta";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
const handleMainDialogOpenChange = (open: boolean) => {
|
||||
if (!open && logoDialogOpen) {
|
||||
|
||||
@@ -212,7 +212,7 @@ export function AccountsPage({
|
||||
onOpenChange={handleRemoveOpenChange}
|
||||
title={removeTitle}
|
||||
description="Ao remover esta conta, todos os dados relacionados a ela serão perdidos."
|
||||
confirmLabel="Remover conta"
|
||||
confirmLabel="Remover"
|
||||
pendingLabel="Removendo..."
|
||||
confirmVariant="destructive"
|
||||
onConfirm={handleRemoveConfirm}
|
||||
|
||||
@@ -161,13 +161,12 @@ export function BudgetDialog({
|
||||
});
|
||||
};
|
||||
|
||||
const title = mode === "create" ? "Novo orçamento" : "Editar orçamento";
|
||||
const title = mode === "create" ? "Novo orçamento" : "Atualizar orçamento";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Defina um limite de gastos para acompanhar suas despesas."
|
||||
: "Atualize os detalhes do orçamento selecionado.";
|
||||
const submitLabel =
|
||||
mode === "create" ? "Salvar orçamento" : "Atualizar orçamento";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
const disabled = categories.length === 0;
|
||||
const parsedAmount = Number.parseFloat(formState.amount);
|
||||
const sliderValue = Number.isFinite(parsedAmount)
|
||||
|
||||
@@ -165,7 +165,7 @@ export function BudgetsPage({
|
||||
onOpenChange={handleRemoveOpenChange}
|
||||
title={removeTitle}
|
||||
description="Esta ação remove o limite configurado para a categoria selecionada."
|
||||
confirmLabel="Remover orçamento"
|
||||
confirmLabel="Remover"
|
||||
pendingLabel="Removendo..."
|
||||
confirmVariant="destructive"
|
||||
onConfirm={handleRemoveConfirm}
|
||||
@@ -176,7 +176,7 @@ export function BudgetsPage({
|
||||
onOpenChange={setDuplicateOpen}
|
||||
title="Copiar orçamentos do último mês?"
|
||||
description="Isso copiará os limites definidos no mês anterior para as categorias que ainda não possuem orçamento neste mês."
|
||||
confirmLabel="Copiar orçamentos"
|
||||
confirmLabel="Copiar"
|
||||
pendingLabel="Copiando..."
|
||||
onConfirm={handleDuplicateConfirm}
|
||||
/>
|
||||
|
||||
@@ -194,12 +194,12 @@ export function CardDialog({
|
||||
});
|
||||
};
|
||||
|
||||
const title = mode === "create" ? "Novo cartão" : "Editar cartão";
|
||||
const title = mode === "create" ? "Novo cartão" : "Atualizar cartão";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Inclua um novo cartão de crédito para acompanhar seus gastos."
|
||||
: "Atualize as informações do cartão selecionado.";
|
||||
const submitLabel = mode === "create" ? "Salvar cartão" : "Atualizar cartão";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
const handleMainDialogOpenChange = (open: boolean) => {
|
||||
if (!open && logoDialogOpen) {
|
||||
|
||||
@@ -201,7 +201,7 @@ export function CardsPage({
|
||||
onOpenChange={handleRemoveOpenChange}
|
||||
title={removeTitle}
|
||||
description="Ao remover este cartão, os registros relacionados a ele serão excluídos permanentemente."
|
||||
confirmLabel="Remover cartão"
|
||||
confirmLabel="Remover"
|
||||
pendingLabel="Removendo..."
|
||||
confirmVariant="destructive"
|
||||
onConfirm={handleRemoveConfirm}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { useMemo, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { deleteCategoryAction } from "@/features/categories/actions";
|
||||
import { ConfirmActionDialog } from "@/shared/components/confirm-action-dialog";
|
||||
import { CategoryIconBadge } from "@/shared/components/entity-avatar";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { Card, CardContent } from "@/shared/components/ui/card";
|
||||
import {
|
||||
@@ -32,7 +33,6 @@ import {
|
||||
CATEGORY_TYPES,
|
||||
type CategoryType,
|
||||
} from "@/shared/lib/categories/constants";
|
||||
import { CategoryIconBadge } from "@/shared/components/entity-avatar";
|
||||
import { CategoryDialog } from "./category-dialog";
|
||||
import type { Category } from "./types";
|
||||
|
||||
@@ -250,7 +250,7 @@ export function CategoriesPage({ categories }: CategoriesPageProps) {
|
||||
onOpenChange={handleRemoveOpenChange}
|
||||
title={removeTitle}
|
||||
description="Ao remover esta categoria, os lançamentos associados serão desrelacionados."
|
||||
confirmLabel="Remover categoria"
|
||||
confirmLabel="Remover"
|
||||
pendingLabel="Removendo..."
|
||||
confirmVariant="destructive"
|
||||
onConfirm={handleRemoveConfirm}
|
||||
|
||||
@@ -136,13 +136,12 @@ export function CategoryDialog({
|
||||
});
|
||||
};
|
||||
|
||||
const title = mode === "create" ? "Nova categoria" : "Editar categoria";
|
||||
const title = mode === "create" ? "Nova categoria" : "Atualizar categoria";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Crie uma categoria para organizar seus lançamentos."
|
||||
: "Atualize os detalhes da categoria selecionada.";
|
||||
const submitLabel =
|
||||
mode === "create" ? "Salvar categoria" : "Atualizar categoria";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
return (
|
||||
<Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
|
||||
|
||||
@@ -171,7 +171,7 @@ export function BillPaymentDialog({
|
||||
Processando...
|
||||
</>
|
||||
) : (
|
||||
"Confirmar pagamento"
|
||||
"Confirmar"
|
||||
)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -59,7 +59,7 @@ export function GoalProgressItem({
|
||||
size="icon-sm"
|
||||
className="transition-opacity text-primary hover:opacity-80"
|
||||
onClick={() => onEdit(item)}
|
||||
aria-label={`Editar orçamento de ${item.categoryName}`}
|
||||
aria-label={`Atualizar orçamento de ${item.categoryName}`}
|
||||
>
|
||||
<RiPencilLine className="size-3.5" />
|
||||
</Button>
|
||||
|
||||
@@ -193,7 +193,7 @@ export function InvoicePaymentDialog({
|
||||
Processando...
|
||||
</>
|
||||
) : (
|
||||
"Confirmar pagamento"
|
||||
"Confirmar"
|
||||
)}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -38,12 +38,12 @@ export function EditPaymentDateDialog({
|
||||
<DialogTrigger asChild>{trigger}</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Editar data de pagamento</DialogTitle>
|
||||
<DialogTitle>Atualizar data de pagamento</DialogTitle>
|
||||
<DialogDescription>
|
||||
Selecione a data em que o pagamento foi realizado.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="space-y-4 py-4">
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="payment-date">Data de pagamento</Label>
|
||||
<DatePicker
|
||||
|
||||
@@ -97,15 +97,11 @@ export function NoteCard({
|
||||
<div className="min-h-0 flex-1 space-y-2 overflow-hidden">
|
||||
{sortedTasks.slice(0, 5).map((task) => (
|
||||
<div key={task.id} className="flex items-start gap-2 text-sm">
|
||||
<div
|
||||
className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border ${
|
||||
task.completed
|
||||
? "bg-success border-success"
|
||||
: "border-input"
|
||||
}`}
|
||||
>
|
||||
{task.completed && (
|
||||
<RiCheckLine className="h-3 w-3 text-background" />
|
||||
<div className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
{task.completed ? (
|
||||
<RiCheckLine className="h-4 w-4 text-success" />
|
||||
) : (
|
||||
<div className="h-4 w-4 rounded-sm border border-input" />
|
||||
)}
|
||||
</div>
|
||||
<span
|
||||
|
||||
@@ -65,15 +65,11 @@ export function NoteDetailsDialog({
|
||||
key={task.id}
|
||||
className="flex items-center gap-3 rounded-md px-3 py-1.5"
|
||||
>
|
||||
<div
|
||||
className={`flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border ${
|
||||
task.completed
|
||||
? "bg-success border-success"
|
||||
: "border-input"
|
||||
}`}
|
||||
>
|
||||
{task.completed && (
|
||||
<RiCheckLine className="h-4 w-4 text-primary-foreground" />
|
||||
<div className="flex h-4 w-4 shrink-0 items-center justify-center">
|
||||
{task.completed ? (
|
||||
<RiCheckLine className="h-4 w-4 text-success" />
|
||||
) : (
|
||||
<div className="h-4 w-4 rounded-sm border border-input" />
|
||||
)}
|
||||
</div>
|
||||
<span
|
||||
@@ -95,23 +91,22 @@ export function NoteDetailsDialog({
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button type="button" variant="outline">
|
||||
Cancelar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
{onEdit && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
onOpenChange(false);
|
||||
onEdit(note);
|
||||
}}
|
||||
>
|
||||
Editar
|
||||
Alterar
|
||||
</Button>
|
||||
)}
|
||||
<DialogClose asChild>
|
||||
<Button type="button" variant="outline">
|
||||
Fechar
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@@ -94,13 +94,14 @@ export function NoteDialog({
|
||||
}
|
||||
}, [dialogOpen, note, resetForm]);
|
||||
|
||||
const dialogTitle = mode === "create" ? "Nova anotação" : "Editar anotação";
|
||||
const dialogTitle =
|
||||
mode === "create" ? "Nova anotação" : "Atualizar anotação";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Crie uma nota simples ou uma lista de tarefas."
|
||||
: note?.type === "tarefa"
|
||||
? "Editando lista de tarefas."
|
||||
: "Editando nota.";
|
||||
? "Atualize sua lista de tarefas"
|
||||
: "Atualize sua nota";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
const titleCount = formState.title.length;
|
||||
@@ -361,7 +362,6 @@ export function NoteDialog({
|
||||
className="shrink-0 gap-1.5"
|
||||
>
|
||||
<RiAddCircleFill className="h-4 w-4" />
|
||||
Adicionar
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -374,7 +374,7 @@ export function NoteDialog({
|
||||
className="flex items-center gap-3 rounded-md px-3 py-1.5 hover:bg-muted/50"
|
||||
>
|
||||
<Checkbox
|
||||
className="data-[state=checked]:bg-success data-[state=checked]:border-success"
|
||||
className="data-[state=checked]:bg-success! data-[state=checked]:border-success! data-[state=checked]:text-success-foreground!"
|
||||
checked={task.completed}
|
||||
onCheckedChange={() => handleToggleTask(task.id)}
|
||||
disabled={isPending}
|
||||
|
||||
@@ -216,12 +216,12 @@ export function PayerDialog({
|
||||
});
|
||||
};
|
||||
|
||||
const title = mode === "create" ? "Nova pessoa" : "Editar pessoa";
|
||||
const title = mode === "create" ? "Nova pessoa" : "Atualizar pessoa";
|
||||
const description =
|
||||
mode === "create"
|
||||
? "Selecione um avatar e informe os detalhes para criar uma nova pessoa."
|
||||
: "Atualize os detalhes da pessoa selecionada.";
|
||||
const submitLabel = mode === "create" ? "Salvar pessoa" : "Atualizar pessoa";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
const isUploadSelected =
|
||||
uploadedAvatar !== null && formState.avatarUrl === uploadedAvatar;
|
||||
|
||||
@@ -151,8 +151,8 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
|
||||
{orderedPayers.length === 0 ? (
|
||||
<div className="flex min-h-[320px] items-center justify-center rounded-lg border border-dashed bg-muted/30">
|
||||
<div className="max-w-sm text-center text-sm text-muted-foreground">
|
||||
Cadastre seu primeira pessoa para organizar cobranças e
|
||||
pagamentos recorrentes.
|
||||
Cadastre seu primeira pessoa para organizar cobranças e pagamentos
|
||||
recorrentes.
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@@ -186,7 +186,7 @@ export function PayersPage({ payers, avatarOptions }: PayersPageProps) {
|
||||
onOpenChange={handleRemoveOpenChange}
|
||||
title={removeTitle}
|
||||
description="Ao remover esta pessoa, os registros relacionados a ele deixarão de ser associados automaticamente."
|
||||
confirmLabel="Remover pessoa"
|
||||
confirmLabel="Remover"
|
||||
pendingLabel="Removendo..."
|
||||
confirmVariant="destructive"
|
||||
onConfirm={handleRemoveConfirm}
|
||||
|
||||
@@ -642,7 +642,7 @@ export function MassAddDialog({
|
||||
</Button>
|
||||
<Button onClick={handleSubmit} disabled={loading}>
|
||||
{loading && <Spinner className="size-4" />}
|
||||
Criar {transactions.length}{" "}
|
||||
Salvar {transactions.length}{" "}
|
||||
{transactions.length === 1 ? "lançamento" : "lançamentos"}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -242,7 +242,7 @@ export function TransactionDetailsDialog({
|
||||
</Button>
|
||||
</DialogClose>
|
||||
{onEdit && !transaction.readonly && (
|
||||
<Button onClick={handleEdit}>Editar</Button>
|
||||
<Button onClick={handleEdit}>Alterar</Button>
|
||||
)}
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
|
||||
@@ -229,8 +229,7 @@ export function TransactionDialog({
|
||||
}
|
||||
|
||||
if (formState.isSplit && !formState.payerId) {
|
||||
const message =
|
||||
"Selecione a pessoa principal para dividir o lançamento.";
|
||||
const message = "Selecione a pessoa principal para dividir o lançamento.";
|
||||
setErrorMessage(message);
|
||||
toast.error(message);
|
||||
return;
|
||||
@@ -460,7 +459,7 @@ export function TransactionDialog({
|
||||
? "Nova Despesa"
|
||||
: "Nova Receita"
|
||||
: "Novo lançamento"
|
||||
: "Editar lançamento";
|
||||
: "Atualizar lançamento";
|
||||
const description =
|
||||
mode === "create"
|
||||
? isImportMode
|
||||
@@ -471,7 +470,7 @@ export function TransactionDialog({
|
||||
? `Informe os dados abaixo para registrar ${defaultTransactionType === "Despesa" ? "uma nova despesa" : "uma nova receita"}.`
|
||||
: "Informe os dados abaixo para registrar um novo lançamento."
|
||||
: "Atualize as informações do lançamento selecionado.";
|
||||
const submitLabel = mode === "create" ? "Salvar lançamento" : "Atualizar";
|
||||
const submitLabel = mode === "create" ? "Salvar" : "Atualizar";
|
||||
|
||||
const showInstallments = formState.condition === "Parcelado";
|
||||
const showRecurrence = formState.condition === "Recorrente";
|
||||
|
||||
Reference in New Issue
Block a user