v1.43.1 - Fix: Espaços em branco mobile eliminados + Textos compactos

This commit is contained in:
marcoitaloesp-ai 2025-12-16 11:32:44 +00:00 committed by GitHub
parent e753c65cf0
commit a244632e0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 76 additions and 39 deletions

View File

@ -5,6 +5,29 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/).
Este projeto adota [Versionamento Semântico](https://semver.org/pt-BR/).
## [1.43.1] - 2025-12-16
### Fixed
- **Espaços em branco desnecessários em Mobile** - Otimização completa de altura e padding
- Widget Fluxo de Caixa:
- Removido `h-100` em mobile (agora se ajusta ao conteúdo)
- Card-body padding reduzido: 1rem
- Estados loading/erro: altura 280px (antes 350px fixo)
- Gráfico: 280px (mobile) vs 350px (desktop)
- Resumo: margens reduzidas `mt-3 pt-2`
- Widget Projeção de Saldo:
- Card-body padding: 1rem em mobile
- Gráfico reduzido: 250px (mobile) vs 350px (desktop)
- Alertas compactos: padding `p-2`, margens `mb-2/mb-3`, fonte 0.75rem
- Textos abreviados em alertas para economizar espaço
### Improved
- **Abreviações em textos mobile** - Labels compactos sem quebra de linha
- Fluxo de Caixa: "RECEITAS", "DESPESAS", "MÉD. REC.", "MÉD. DESP."
- Sobrepagamentos: "TOTAL", "QTD", "MÉDIA"
- Alertas: "Saldo negativo em" ao invés de "Previsão de saldo negativo em"
- Todos com `whiteSpace: 'nowrap'` para prevenir quebras
## [1.43.0] - 2025-12-16
### Added

View File

@ -101,7 +101,7 @@ cd frontend && ./deploy.sh
### Backend
```bash
cd backend && ./deploy.sh
```
```github/.DIRETRIZES_DESENVOLVIMENTO_v5
## 📖 Documentação

View File

@ -1 +1 @@
1.43.0
1.43.1

View File

@ -259,19 +259,18 @@ const BalanceProjectionChart = () => {
</div>
)}
</div>
<div className="card-body" style={{ display: isMobile && !isExpanded ? 'none' : 'block' }}>
<div className="card-body" style={{ display: isMobile && !isExpanded ? 'none' : 'block', padding: isMobile ? '1rem' : undefined }}>
{/* Summary Stats */}
{summary && (
<>
{/* Alert if overdue transactions included */}
{summary.overdue_count > 0 && (
<div className="alert alert-warning d-flex align-items-center mb-3" role="alert">
<i className="bi bi-exclamation-circle-fill me-2"></i>
<div className={`alert alert-warning d-flex align-items-center ${isMobile ? 'mb-2 p-2' : 'mb-3'}`} role="alert" style={isMobile ? { fontSize: '0.75rem' } : undefined}>
<i className={`bi bi-exclamation-circle-fill ${isMobile ? 'me-1' : 'me-2'}`} style={isMobile ? { fontSize: '0.9rem' } : undefined}></i>
<div>
<strong>{t('reports.projectionChart.overdueIncluded') || 'Atenção'}:</strong>{' '}
{summary.overdue_count} {t('reports.projectionChart.overdueTransactions') || 'transação(ões) em atraso'}{' '}
{t('reports.projectionChart.includedInProjection') || 'já incluída(s) no saldo atual'}.
{' '}
{!isMobile && (t('reports.projectionChart.includedInProjection') || 'já incluída(s) no saldo atual.')}{' '}
<span className={summary.overdue_impact < 0 ? 'text-danger fw-bold' : 'text-success fw-bold'}>
({summary.overdue_impact >= 0 ? '+' : ''}{currency(summary.overdue_impact, data?.currency)})
</span>
@ -328,18 +327,18 @@ const BalanceProjectionChart = () => {
{/* Alert if negative balance predicted */}
{summary?.negative_month && (
<div className="alert alert-danger d-flex align-items-center mb-4" role="alert">
<i className="bi bi-exclamation-triangle-fill me-2 fs-5"></i>
<div className={`alert alert-danger d-flex align-items-center ${isMobile ? 'mb-3 p-2' : 'mb-4'}`} role="alert" style={isMobile ? { fontSize: '0.75rem' } : undefined}>
<i className={`bi bi-exclamation-triangle-fill ${isMobile ? 'me-1 fs-6' : 'me-2 fs-5'}`}></i>
<div>
<strong>{t('reports.projectionChart.warning') || 'Atenção!'}</strong>{' '}
{t('reports.projectionChart.negativeAlert') || 'Previsão de saldo negativo em'}{' '}
{isMobile ? 'Saldo negativo em' : (t('reports.projectionChart.negativeAlert') || 'Previsão de saldo negativo em')}{' '}
<strong>{summary.negative_month}</strong>
</div>
</div>
)}
{/* Chart */}
<div style={{ height: isMobile ? '300px' : '350px' }}>
<div style={{ height: isMobile ? '250px' : '350px' }}>
<Line data={chartData} options={options} />
</div>

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import {
Chart as ChartJS,
CategoryScale,
@ -36,10 +36,17 @@ const CashflowChart = ({ data, loading, scale = 'monthly', primaryCurrency = 'EU
const { t } = useTranslation();
const { currency } = useFormatters();
const chartRef = useRef(null);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth < 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
if (loading) {
return (
<div className="d-flex justify-content-center align-items-center" style={{ height: '350px' }}>
<div className="d-flex justify-content-center align-items-center" style={{ height: isMobile ? '280px' : '350px' }}>
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</span>
</div>
@ -49,7 +56,7 @@ const CashflowChart = ({ data, loading, scale = 'monthly', primaryCurrency = 'EU
if (!data || data.length === 0) {
return (
<div className="d-flex justify-content-center align-items-center text-slate-400" style={{ height: '350px' }}>
<div className="d-flex justify-content-center align-items-center text-slate-400" style={{ height: isMobile ? '280px' : '350px' }}>
<div className="text-center">
<i className="bi bi-bar-chart fs-1 mb-2"></i>
<p>{t('dashboard.noDataAvailable')}</p>
@ -211,7 +218,7 @@ const CashflowChart = ({ data, loading, scale = 'monthly', primaryCurrency = 'EU
};
return (
<div style={{ height: '350px' }}>
<div style={{ height: isMobile ? '280px' : '350px' }}>
<Chart ref={chartRef} type="bar" data={chartData} options={options} />
</div>
);

View File

@ -273,30 +273,30 @@ const OverpaymentsAnalysis = ({ data, loading, onTransactionClick }) => {
<div className={`row ${isMobile ? 'g-2' : 'g-3'} mb-3`}>
<div className="col-4">
<div className={`text-center ${isMobile ? 'p-1' : 'p-2'} rounded`} style={{ background: 'rgba(0,0,0,0.2)' }}>
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{t('dashboard.totalOverpaid')}
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.6rem' : '10px', whiteSpace: isMobile ? 'nowrap' : 'normal' }}>
{isMobile ? 'TOTAL' : t('dashboard.totalOverpaid')}
</small>
<span className={`text-warning fw-bold ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.85rem' : undefined }}>
<span className={`text-warning fw-bold d-block ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
+{currency(selectedMonthData.total, 'BRL')}
</span>
</div>
</div>
<div className="col-4">
<div className={`text-center ${isMobile ? 'p-1' : 'p-2'} rounded`} style={{ background: 'rgba(0,0,0,0.2)' }}>
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{t('dashboard.transactions')}
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.6rem' : '10px', whiteSpace: isMobile ? 'nowrap' : 'normal' }}>
{isMobile ? 'QTD' : t('dashboard.transactions')}
</small>
<span className={`text-white fw-bold ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.85rem' : undefined }}>
<span className={`text-white fw-bold d-block ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
{selectedMonthData.count}
</span>
</div>
</div>
<div className="col-4">
<div className={`text-center ${isMobile ? 'p-1' : 'p-2'} rounded`} style={{ background: 'rgba(0,0,0,0.2)' }}>
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{t('dashboard.avgPerTransaction')}
<small className="text-slate-400 d-block text-uppercase" style={{ fontSize: isMobile ? '0.6rem' : '10px', whiteSpace: isMobile ? 'nowrap' : 'normal' }}>
{isMobile ? 'MÉDIA' : t('dashboard.avgPerTransaction')}
</small>
<span className={`text-warning fw-bold ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.85rem' : undefined }}>
<span className={`text-warning fw-bold d-block ${isMobile ? 'fs-6' : 'fs-5'}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
+{currency(selectedMonthData.total / selectedMonthData.count, 'BRL')}
</span>
</div>

View File

@ -21,6 +21,7 @@ const Dashboard = () => {
const [loading, setLoading] = useState(true);
const [cashflowLoading, setCashflowLoading] = useState(true);
const [variancesLoading, setVariancesLoading] = useState(true);
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
// Dados do dashboard
const [summary, setSummary] = useState(null);
@ -32,6 +33,13 @@ const Dashboard = () => {
const [cashflowMonths, setCashflowMonths] = useState(12);
const [variancesMonths, setVariancesMonths] = useState(12);
// Detectar resize
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth < 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// Carregar resumo geral
const loadSummary = useCallback(async () => {
try {
@ -325,7 +333,7 @@ const Dashboard = () => {
<div className="row g-4">
{/* Coluna Principal - Fluxo de Caixa */}
<div className="col-lg-8">
<div className="card border-0 h-100" style={{ background: '#0f172a' }}>
<div className={`card border-0 ${!isMobile ? 'h-100' : ''}`} style={{ background: '#0f172a' }}>
<div className="card-header border-0 d-flex justify-content-between align-items-center py-3"
style={{ background: 'transparent', borderBottom: '1px solid rgba(59, 130, 246, 0.2)' }}>
<h6 className="text-white mb-0 d-flex align-items-center">
@ -346,7 +354,7 @@ const Dashboard = () => {
))}
</div>
</div>
<div className="card-body">
<div className="card-body" style={{ padding: isMobile ? '1rem' : undefined }}>
<CashflowChart
data={cashflow?.data || []}
loading={cashflowLoading}
@ -355,36 +363,36 @@ const Dashboard = () => {
{/* Resumo do período */}
{cashflow && !cashflowLoading && (
<div className="row mt-4 pt-3" style={{ borderTop: '1px solid rgba(255,255,255,0.1)' }}>
<div className={`row ${isMobile ? 'mt-3 pt-2' : 'mt-4 pt-3'}`} style={{ borderTop: '1px solid rgba(255,255,255,0.1)' }}>
<div className="col-6 col-md-3 text-center">
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: '10px' }}>
{t('dashboard.totalIncome')}
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{isMobile ? 'RECEITAS' : t('dashboard.totalIncome')}
</small>
<span className="text-success fw-bold">
<span className={`text-success fw-bold d-block ${isMobile ? '' : ''}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
{currency(cashflow.totals?.income || 0, summary?.primary_currency || 'EUR')}
</span>
</div>
<div className="col-6 col-md-3 text-center">
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: '10px' }}>
{t('dashboard.totalExpenses')}
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{isMobile ? 'DESPESAS' : t('dashboard.totalExpenses')}
</small>
<span className="text-danger fw-bold">
<span className={`text-danger fw-bold d-block ${isMobile ? '' : ''}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
{currency(cashflow.totals?.expense || 0, summary?.primary_currency || 'EUR')}
</span>
</div>
<div className="col-6 col-md-3 text-center mt-2 mt-md-0">
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: '10px' }}>
{t('dashboard.avgIncome')}
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{isMobile ? 'MÉD. REC.' : t('dashboard.avgIncome')}
</small>
<span className="text-success">
<span className={`text-success d-block ${isMobile ? '' : ''}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
{currency(cashflow.totals?.average_income || 0, summary?.primary_currency || 'EUR')}
</span>
</div>
<div className="col-6 col-md-3 text-center mt-2 mt-md-0">
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: '10px' }}>
{t('dashboard.avgExpense')}
<small className="text-slate-500 d-block text-uppercase" style={{ fontSize: isMobile ? '0.65rem' : '10px' }}>
{isMobile ? 'MÉD. DESP.' : t('dashboard.avgExpense')}
</small>
<span className="text-danger">
<span className={`text-danger d-block ${isMobile ? '' : ''}`} style={{ fontSize: isMobile ? '0.8rem' : undefined }}>
{currency(cashflow.totals?.average_expense || 0, summary?.primary_currency || 'EUR')}
</span>
</div>