fix: corrige timezone e seleção de parcelas na análise de parcelas
- Ajusta timezone em datas de vencimento para evitar dia anterior - Corrige bug ao selecionar parcelas individuais (React state) - Melhora UI: exibe Total/Pendente sempre, Selecionado inline
This commit is contained in:
@@ -81,7 +81,8 @@ export function InstallmentAnalysisPage({
|
||||
installmentId: string
|
||||
) => {
|
||||
const newMap = new Map(selectedInstallments);
|
||||
const current = newMap.get(seriesId) || new Set<string>();
|
||||
// Criar uma NOVA instância do Set para React detectar a mudança
|
||||
const current = new Set(newMap.get(seriesId) || []);
|
||||
|
||||
if (current.has(installmentId)) {
|
||||
current.delete(installmentId);
|
||||
|
||||
@@ -41,18 +41,26 @@ export function InstallmentGroupCard({
|
||||
selectedInstallments.size === unpaidInstallments.length &&
|
||||
unpaidInstallments.length > 0;
|
||||
|
||||
const isPartiallySelected =
|
||||
selectedInstallments.size > 0 &&
|
||||
selectedInstallments.size < unpaidInstallments.length;
|
||||
|
||||
const progress =
|
||||
group.totalInstallments > 0
|
||||
? (group.paidInstallments / group.totalInstallments) * 100
|
||||
: 0;
|
||||
|
||||
const selectedAmount = group.pendingInstallments
|
||||
.filter((i) => selectedInstallments.has(i.id))
|
||||
.reduce((sum, i) => sum + i.amount, 0);
|
||||
.filter((i) => selectedInstallments.has(i.id) && !i.isSettled)
|
||||
.reduce((sum, i) => sum + Number(i.amount), 0);
|
||||
|
||||
// Calcular valor total de todas as parcelas (pagas + pendentes)
|
||||
const totalAmount = group.pendingInstallments.reduce(
|
||||
(sum, i) => sum + i.amount,
|
||||
0
|
||||
);
|
||||
|
||||
// Calcular valor pendente (apenas não pagas)
|
||||
const pendingAmount = unpaidInstallments.reduce(
|
||||
(sum, i) => sum + i.amount,
|
||||
0
|
||||
);
|
||||
|
||||
return (
|
||||
<Card className={cn(isFullySelected && "border-primary/50")}>
|
||||
@@ -84,22 +92,23 @@ export function InstallmentGroupCard({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 flex items-center gap-0.5">
|
||||
<MoneyValues
|
||||
amount={group.totalPendingAmount}
|
||||
className="text-base font-bold"
|
||||
/>
|
||||
|
||||
{selectedInstallments.size > 0 && (
|
||||
<span className="mx-1 text-muted-foreground">|</span>
|
||||
)}
|
||||
|
||||
{selectedInstallments.size > 0 && (
|
||||
<div className="shrink-0 flex items-center gap-3">
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-xs text-muted-foreground">Total:</span>
|
||||
<MoneyValues
|
||||
amount={selectedAmount}
|
||||
className="text-base text-primary"
|
||||
amount={totalAmount}
|
||||
className="text-base font-bold"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-xs text-muted-foreground">
|
||||
Pendente:
|
||||
</span>
|
||||
<MoneyValues
|
||||
amount={pendingAmount}
|
||||
className="text-sm font-medium text-primary"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -109,22 +118,20 @@ export function InstallmentGroupCard({
|
||||
<span>
|
||||
{group.paidInstallments} de {group.totalInstallments} pagas
|
||||
</span>
|
||||
<span>
|
||||
{unpaidCount} {unpaidCount === 1 ? "pendente" : "pendentes"}
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span>
|
||||
{unpaidCount} {unpaidCount === 1 ? "pendente" : "pendentes"}
|
||||
</span>
|
||||
{selectedInstallments.size > 0 && (
|
||||
<span className="text-primary font-medium">
|
||||
• Selecionado: <MoneyValues amount={selectedAmount} className="text-xs font-medium text-primary inline" />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Progress value={progress} className="h-2" />
|
||||
</div>
|
||||
|
||||
{/* Badges de status */}
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
{isPartiallySelected && (
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{selectedInstallments.size} de {unpaidCount} selecionadas
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Botão de expandir */}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -19,7 +19,8 @@ function calculateDueDate(period: string, dueDay: string | null): Date | null {
|
||||
const day = parseInt(dueDay, 10);
|
||||
if (isNaN(day)) return null;
|
||||
|
||||
return new Date(parseInt(year), parseInt(month) - 1, day);
|
||||
// Criar data ao meio-dia para evitar problemas de timezone
|
||||
return new Date(parseInt(year), parseInt(month) - 1, day, 12, 0, 0);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"@types/pg": "^8.15.6",
|
||||
"@types/react": "19.2.7",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"baseline-browser-mapping": "^2.8.32",
|
||||
"depcheck": "^1.4.7",
|
||||
"dotenv": "^17.2.3",
|
||||
"drizzle-kit": "0.31.7",
|
||||
|
||||
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@@ -174,6 +174,9 @@ importers:
|
||||
'@types/react-dom':
|
||||
specifier: 19.2.3
|
||||
version: 19.2.3(@types/react@19.2.7)
|
||||
baseline-browser-mapping:
|
||||
specifier: ^2.8.32
|
||||
version: 2.8.32
|
||||
depcheck:
|
||||
specifier: ^1.4.7
|
||||
version: 1.4.7
|
||||
@@ -2037,8 +2040,8 @@ packages:
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
baseline-browser-mapping@2.8.25:
|
||||
resolution: {integrity: sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==}
|
||||
baseline-browser-mapping@2.8.32:
|
||||
resolution: {integrity: sha512-OPz5aBThlyLFgxyhdwf/s2+8ab3OvT7AdTNvKHBwpXomIYeXqpUUuT8LrdtxZSsWJ4R4CU1un4XGh5Ez3nlTpw==}
|
||||
hasBin: true
|
||||
|
||||
better-auth@1.4.1:
|
||||
@@ -5666,7 +5669,7 @@ snapshots:
|
||||
base64-js@1.5.1:
|
||||
optional: true
|
||||
|
||||
baseline-browser-mapping@2.8.25: {}
|
||||
baseline-browser-mapping@2.8.32: {}
|
||||
|
||||
better-auth@1.4.1(next@16.0.4(@babel/core@7.28.5)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0):
|
||||
dependencies:
|
||||
@@ -5728,7 +5731,7 @@ snapshots:
|
||||
|
||||
browserslist@4.27.0:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.8.25
|
||||
baseline-browser-mapping: 2.8.32
|
||||
caniuse-lite: 1.0.30001754
|
||||
electron-to-chromium: 1.5.249
|
||||
node-releases: 2.0.27
|
||||
|
||||
Reference in New Issue
Block a user