refactor: melhorar visualização e contagem de parcelas pagas

Ajustes finais na análise de parcelas:

- Corrigir contagem de parcelas pagas (agora conta isSettled corretamente)
- Estilização aprimorada para parcelas pagas:
  * Cores verdes do sistema (green-50, green-700, dark mode suportado)
  * Fundo verde claro com bordas verdes
  * Texto e valores em verde
  * Badge "Paga" com variant outline e cores verdes
  * Line-through com decoração verde semi-transparente
- Remover card "Resumo" lateral (informação já está no card principal)
- Remover título "Lançamentos Parcelados" da página
- Layout full-width sem grid lateral
- Remover imports não utilizados (Separator, AnalysisSummaryPanel)
This commit is contained in:
Claude
2025-11-16 16:27:43 +00:00
parent 4411d992fa
commit f6bbb0d5e0
3 changed files with 61 additions and 80 deletions

View File

@@ -2,12 +2,10 @@
import MoneyValues from "@/components/money-values";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { Card, CardContent } from "@/components/ui/card";
import { useMemo, useState } from "react";
import type { InstallmentAnalysisData } from "./types";
import { InstallmentGroupCard } from "./installment-group-card";
import { AnalysisSummaryPanel } from "./analysis-summary-panel";
import {
RiCalculatorLine,
RiCheckboxBlankLine,
@@ -98,7 +96,7 @@ export function InstallmentAnalysisPage({
};
// Calcular totais
const { totalInstallments, grandTotal, selectedCount } = useMemo(() => {
const { grandTotal, selectedCount } = useMemo(() => {
let installmentsSum = 0;
let installmentsCount = 0;
@@ -120,7 +118,6 @@ export function InstallmentAnalysisPage({
});
return {
totalInstallments: installmentsSum,
grandTotal: installmentsSum,
selectedCount: installmentsCount,
};
@@ -178,70 +175,46 @@ export function InstallmentAnalysisPage({
</div>
)}
<div className="grid gap-4 lg:grid-cols-[1fr_280px]">
{/* Conteúdo principal */}
<div className="flex flex-col gap-6">
{/* Seção de Lançamentos Parcelados */}
{data.installmentGroups.length > 0 && (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-2">
<Separator className="flex-1" />
<h2 className="text-lg font-semibold">Lançamentos Parcelados</h2>
<Separator className="flex-1" />
</div>
<div className="flex flex-col gap-3">
{data.installmentGroups.map((group) => (
<InstallmentGroupCard
key={group.seriesId}
group={group}
selectedInstallments={
selectedInstallments.get(group.seriesId) || new Set()
}
onToggleGroup={() =>
toggleGroupSelection(
group.seriesId,
group.pendingInstallments
.filter((i) => !i.isSettled)
.map((i) => i.id)
)
}
onToggleInstallment={(installmentId) =>
toggleInstallmentSelection(group.seriesId, installmentId)
}
/>
))}
</div>
</div>
)}
{/* Estado vazio */}
{hasNoData && (
<Card>
<CardContent className="flex flex-col items-center justify-center gap-3 py-12">
<RiCalculatorLine className="size-12 text-muted-foreground/50" />
<div className="text-center">
<p className="font-medium">Nenhuma parcela pendente</p>
<p className="text-sm text-muted-foreground">
Você está em dia com seus pagamentos!
</p>
</div>
</CardContent>
</Card>
)}
</div>
{/* Painel lateral de resumo (sticky) */}
{!hasNoData && (
<div className="lg:sticky lg:top-4 lg:self-start">
<AnalysisSummaryPanel
totalInstallments={totalInstallments}
grandTotal={grandTotal}
selectedCount={selectedCount}
{/* Seção de Lançamentos Parcelados */}
{data.installmentGroups.length > 0 && (
<div className="flex flex-col gap-3">
{data.installmentGroups.map((group) => (
<InstallmentGroupCard
key={group.seriesId}
group={group}
selectedInstallments={
selectedInstallments.get(group.seriesId) || new Set()
}
onToggleGroup={() =>
toggleGroupSelection(
group.seriesId,
group.pendingInstallments
.filter((i) => !i.isSettled)
.map((i) => i.id)
)
}
onToggleInstallment={(installmentId) =>
toggleInstallmentSelection(group.seriesId, installmentId)
}
/>
</div>
)}
</div>
))}
</div>
)}
{/* Estado vazio */}
{hasNoData && (
<Card>
<CardContent className="flex flex-col items-center justify-center gap-3 py-12">
<RiCalculatorLine className="size-12 text-muted-foreground/50" />
<div className="text-center">
<p className="font-medium">Nenhuma parcela pendente</p>
<p className="text-sm text-muted-foreground">
Você está em dia com seus pagamentos!
</p>
</div>
</CardContent>
</Card>
)}
</div>
);
}

View File

@@ -41,9 +41,7 @@ export function InstallmentGroupCard({
const progress =
group.totalInstallments > 0
? ((group.paidInstallments + selectedInstallments.size) /
group.totalInstallments) *
100
? (group.paidInstallments / group.totalInstallments) * 100
: 0;
const selectedAmount = group.pendingInstallments
@@ -156,7 +154,7 @@ export function InstallmentGroupCard({
className={cn(
"flex items-center gap-3 rounded-md border p-2 transition-colors",
isSelected && !isPaid && "border-primary/50 bg-primary/5",
isPaid && "bg-muted/50 opacity-60"
isPaid && "border-green-200 bg-green-50 dark:border-green-900 dark:bg-green-950/30"
)}
>
<Checkbox
@@ -168,23 +166,32 @@ export function InstallmentGroupCard({
<div className="flex min-w-0 flex-1 items-center justify-between gap-3">
<div className="min-w-0">
<p className={cn("text-sm font-medium", isPaid && "line-through")}>
<p className={cn(
"text-sm font-medium",
isPaid && "text-green-700 dark:text-green-400 line-through decoration-green-600/50"
)}>
Parcela {installment.currentInstallment}/
{group.totalInstallments}
{isPaid && (
<Badge variant="secondary" className="ml-2 text-xs">
<Badge variant="outline" className="ml-2 text-xs border-green-500 text-green-700 dark:text-green-400">
Paga
</Badge>
)}
</p>
<p className="text-xs text-muted-foreground">
<p className={cn(
"text-xs",
isPaid ? "text-green-600 dark:text-green-500" : "text-muted-foreground"
)}>
Vencimento: {dueDate}
</p>
</div>
<MoneyValues
amount={installment.amount}
className={cn("shrink-0 text-sm", isPaid && "opacity-60")}
className={cn(
"shrink-0 text-sm",
isPaid && "text-green-700 dark:text-green-400"
)}
/>
</div>
</div>