v1.43.5 - Otimização mobile da página Liabilities

- Header responsivo: flex-column mobile, botão full-width
- Summary cards: Grid 2x2 mobile, fontes compactas (0.65-0.9rem)
- Filtros: Layout 50/50 sem label em mobile
- Cards contratos: col-12 mobile, padding reduzido, fontes ajustadas
- Progress bar: 6px mobile vs 8px desktop
- Botões e valores: fontes menores (0.75rem) para melhor legibilidade
This commit is contained in:
marcoitaloesp-ai 2025-12-16 12:56:50 +00:00 committed by GitHub
parent 5f3bf18b99
commit d84da4b6b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 76 additions and 32 deletions

View File

@ -5,6 +5,20 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/pt-BR/).
Este projeto adota [Versionamento Semântico](https://semver.org/pt-BR/).
## [1.43.5] - 2025-12-16
### Improved
- **Página Liabilities - Mobile Otimizado** - Contas Passivo adaptadas para mobile
- Header: Layout flex-column, botão full-width, fontes reduzidas (1.1rem/0.75rem)
- Summary Cards: Grid 2 colunas mobile, sem ícones laterais, texto truncado
- Valores compactos: 0.9rem mobile vs 1.25rem desktop
- Filtros: Grid 50/50 mobile sem label, fontes 0.8rem
- Cards de Contratos: col-12 mobile, padding 0.75rem, fontes 0.65-0.85rem
- Progress bar: 6px mobile vs 8px desktop
- Botões: fontes 0.75rem mobile, mantém ícones e funcionalidade
- Desktop: Layout original preservado
## [1.43.4] - 2025-12-16
### Improved

View File

@ -1 +1 @@
1.43.4
1.43.5

View File

@ -10,6 +10,15 @@ const LiabilityAccounts = () => {
const toast = useToast();
const { currency: formatCurrency } = useFormatters();
// Mobile detection
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth < 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// States
const [accounts, setAccounts] = useState([]);
const [summary, setSummary] = useState(null);
@ -347,20 +356,22 @@ const LiabilityAccounts = () => {
return (
<div className="container-fluid py-3">
{/* Header */}
<div className="d-flex justify-content-between align-items-center mb-4">
<div className={`d-flex ${isMobile ? 'flex-column gap-2' : 'justify-content-between align-items-center'} mb-4`}>
<div>
<h4 className="mb-1">
<h4 className="mb-1" style={{ fontSize: isMobile ? '1.1rem' : '1.5rem' }}>
<i className="bi bi-file-earmark-text me-2"></i>
{t('liabilities.title')}
</h4>
<small className="text-muted">{t('liabilities.subtitle')}</small>
<small className="text-muted" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}>
{t('liabilities.subtitle')}
</small>
</div>
<button
className="btn btn-primary"
className={`btn btn-primary ${isMobile ? 'w-100' : ''}`}
onClick={handleOpenImportModal}
>
<i className="bi bi-upload me-2"></i>
{t('liabilities.importContract')}
{isMobile ? t('common.import') : t('liabilities.importContract')}
</button>
</div>
@ -369,9 +380,9 @@ const LiabilityAccounts = () => {
<div className="row g-3 mb-4">
{Object.entries(totalsByCurrency).map(([currency, totals]) => (
<React.Fragment key={currency}>
<div className="col-md-3">
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-danger text-white h-100">
<div className="card-body py-3">
<div className="card-body" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<div className="d-flex justify-content-between align-items-center">
<div>
<div className="small opacity-75">{t('liabilities.totalDebt')} ({currency})</div>
@ -428,16 +439,19 @@ const LiabilityAccounts = () => {
{/* Filters */}
<div className="card mb-4">
<div className="card-body py-2">
<div className="row g-2 align-items-center">
<div className="col-auto">
<label className="col-form-label">{t('common.filter')}:</label>
</div>
<div className="col-auto">
<div className="card-body" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<div className={`row g-2 ${isMobile ? '' : 'align-items-center'}`}>
{!isMobile && (
<div className="col-auto">
<label className="col-form-label">{t('common.filter')}:</label>
</div>
)}
<div className={isMobile ? "col-6" : "col-auto"}>
<select
className="form-select form-select-sm"
value={filter.status}
onChange={(e) => setFilter(prev => ({ ...prev, status: e.target.value }))}
style={{ fontSize: isMobile ? '0.8rem' : '0.875rem' }}
>
<option value="">{t('liabilities.allStatuses')}</option>
{Object.entries(liabilityAccountService.statuses).map(([key, label]) => (
@ -445,11 +459,12 @@ const LiabilityAccounts = () => {
))}
</select>
</div>
<div className="col-auto">
<div className={isMobile ? "col-6" : "col-auto"}>
<select
className="form-select form-select-sm"
value={filter.is_active}
onChange={(e) => setFilter(prev => ({ ...prev, is_active: e.target.value }))}
style={{ fontSize: isMobile ? '0.8rem' : '0.875rem' }}
>
<option value="">{t('common.all')}</option>
<option value="1">{t('common.active')}</option>
@ -482,21 +497,25 @@ const LiabilityAccounts = () => {
) : (
<div className="row g-3">
{accounts.map(account => (
<div key={account.id} className="col-md-6 col-lg-4">
<div key={account.id} className={isMobile ? "col-12" : "col-md-6 col-lg-4"}>
<div className="card h-100">
<div className="card-header d-flex justify-content-between align-items-center">
<div className="d-flex align-items-center">
<div className="card-header d-flex justify-content-between align-items-center"
style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<div className="d-flex align-items-center" style={{ minWidth: 0, flex: 1, marginRight: '0.5rem' }}>
<i className={`${account.icon || 'bi-file-earmark-text'} me-2`}
style={{ color: account.color || '#DC2626' }}></i>
<strong>{account.name}</strong>
style={{ color: account.color || '#DC2626', fontSize: isMobile ? '0.9rem' : '1rem' }}></i>
<strong style={{ fontSize: isMobile ? '0.85rem' : '1rem' }} className="text-truncate">
{account.name}
</strong>
</div>
<span className={`badge ${getStatusBadge(account.status)}`}>
<span className={`badge ${getStatusBadge(account.status)}`}
style={{ fontSize: isMobile ? '0.65rem' : '0.75rem', flexShrink: 0 }}>
{getStatusLabel(account.status)}
</span>
</div>
<div className="card-body">
<div className="card-body" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
{account.creditor && (
<div className="small text-muted mb-2">
<div className="text-muted mb-2" style={{ fontSize: isMobile ? '0.7rem' : '0.875rem' }}>
<i className="bi bi-building me-1"></i>
{account.creditor}
</div>
@ -504,11 +523,12 @@ const LiabilityAccounts = () => {
{/* Progress Bar */}
<div className="mb-3">
<div className="d-flex justify-content-between small mb-1">
<div className="d-flex justify-content-between mb-1"
style={{ fontSize: isMobile ? '0.7rem' : '0.875rem' }}>
<span>{t('liabilities.progress')}</span>
<span>{account.progress_percentage || 0}%</span>
<span className="fw-bold">{account.progress_percentage || 0}%</span>
</div>
<div className="progress" style={{ height: '8px' }}>
<div className="progress" style={{ height: isMobile ? '6px' : '8px' }}>
<div
className="progress-bar bg-success"
style={{ width: `${account.progress_percentage || 0}%` }}
@ -517,30 +537,39 @@ const LiabilityAccounts = () => {
</div>
{/* Values */}
<div className="row g-2 small">
<div className="row g-2" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}>
<div className="col-6">
<div className="text-muted">{t('liabilities.principal')}</div>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.75rem' }}>
{t('liabilities.principal')}
</div>
<div className="fw-bold">{formatCurrency(account.principal_amount, account.currency)}</div>
</div>
<div className="col-6">
<div className="text-muted">{t('liabilities.remaining')}</div>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.75rem' }}>
{t('liabilities.remaining')}
</div>
<div className="fw-bold text-danger">{formatCurrency(account.remaining_balance, account.currency)}</div>
</div>
<div className="col-6">
<div className="text-muted">{t('liabilities.installments')}</div>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.75rem' }}>
{t('liabilities.installments')}
</div>
<div className="fw-bold">{account.paid_installments}/{account.total_installments}</div>
</div>
<div className="col-6">
<div className="text-muted">{t('liabilities.monthlyRate')}</div>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.75rem' }}>
{t('liabilities.monthlyRate')}
</div>
<div className="fw-bold">{formatPercent(account.monthly_interest_rate)}</div>
</div>
</div>
</div>
<div className="card-footer bg-transparent">
<div className="card-footer bg-transparent" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<div className="d-flex gap-2">
<button
className="btn btn-sm btn-outline-primary flex-grow-1"
onClick={() => handleOpenDetail(account)}
style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}
>
<i className="bi bi-eye me-1"></i>
{t('common.details')}
@ -551,6 +580,7 @@ const LiabilityAccounts = () => {
setSelectedAccount(account);
setShowDeleteModal(true);
}}
style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}
>
<i className="bi bi-trash"></i>
</button>