webmoney/frontend/src/pages/LiabilityAccounts.jsx
marcoitaloesp-ai 1637e5da0c
v1.43.6 - Modal de detalhes Liabilities otimizado para mobile
- Modal fullscreen mobile, xl desktop
- Summary cards: Grid 2x2 mobile, fontes compactas
- Taxas: Grid 3 colunas com labels curtos (Mensal/Anual/Total)
- Progress bar: 12px mobile, fontes reduzidas
- Parcelas: Cards layout mobile substituindo tabela
- Cards incluem: status, valores, juros, taxas, reconciliação, botões
- Footer: Botão full-width mobile
- i18n: Adicionadas traduções 'monthly', 'annual', 'total'
2025-12-16 13:02:58 +00:00

1473 lines
69 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { liabilityAccountService } from '../services/api';
import { useToast } from '../components/Toast';
import { ConfirmModal } from '../components/Modal';
import { useFormatters } from '../hooks';
const LiabilityAccounts = () => {
const { t } = useTranslation();
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);
const [loading, setLoading] = useState(true);
const [showImportModal, setShowImportModal] = useState(false);
const [showDetailModal, setShowDetailModal] = useState(false);
const [showDeleteModal, setShowDeleteModal] = useState(false);
const [showReconcileModal, setShowReconcileModal] = useState(false);
const [selectedAccount, setSelectedAccount] = useState(null);
const [selectedInstallment, setSelectedInstallment] = useState(null);
const [eligibleTransactions, setEligibleTransactions] = useState([]);
const [loadingTransactions, setLoadingTransactions] = useState(false);
const [reconcileSearch, setReconcileSearch] = useState('');
const [markAsPaidOnReconcile, setMarkAsPaidOnReconcile] = useState(true);
const [saving, setSaving] = useState(false);
const [filter, setFilter] = useState({ status: '', is_active: '' });
const [showPriceAnalysisModal, setShowPriceAnalysisModal] = useState(false);
// Import form state
const [importForm, setImportForm] = useState({
file: null,
name: '',
creditor: '',
contract_number: '',
currency: 'EUR',
description: '',
});
useEffect(() => {
loadAccounts();
}, [filter]);
const loadAccounts = async () => {
try {
setLoading(true);
const params = {};
if (filter.status) params.status = filter.status;
if (filter.is_active !== '') params.is_active = filter.is_active;
const response = await liabilityAccountService.getAll(params);
if (response.success) {
setAccounts(response.data);
setSummary(response.summary);
}
} catch (error) {
toast.error(t('liabilities.loadError'));
} finally {
setLoading(false);
}
};
const handleOpenImportModal = () => {
setImportForm({
file: null,
name: '',
creditor: '',
contract_number: '',
currency: 'EUR',
description: '',
});
setShowImportModal(true);
};
const handleCloseImportModal = () => {
setShowImportModal(false);
};
const handleImportChange = (e) => {
const { name, value, files } = e.target;
if (name === 'file') {
setImportForm(prev => ({ ...prev, file: files[0] }));
} else {
setImportForm(prev => ({ ...prev, [name]: value }));
}
};
const handleImportSubmit = async (e) => {
e.preventDefault();
if (!importForm.file) {
toast.error(t('liabilities.selectFile'));
return;
}
if (!importForm.name.trim()) {
toast.error(t('validation.required'));
return;
}
setSaving(true);
try {
const formData = new FormData();
formData.append('file', importForm.file);
formData.append('name', importForm.name);
formData.append('creditor', importForm.creditor);
formData.append('contract_number', importForm.contract_number);
formData.append('currency', importForm.currency);
formData.append('description', importForm.description);
const response = await liabilityAccountService.import(formData);
if (response.success) {
toast.success(t('liabilities.importSuccess', { count: response.imported_installments }));
handleCloseImportModal();
loadAccounts();
// Abrir detalhes do contrato importado
setSelectedAccount(response.data);
setShowDetailModal(true);
}
} catch (error) {
toast.error(error.response?.data?.message || t('liabilities.importError'));
} finally {
setSaving(false);
}
};
const handleOpenDetail = async (account) => {
try {
const response = await liabilityAccountService.getById(account.id);
if (response.success) {
setSelectedAccount(response.data);
setShowDetailModal(true);
}
} catch (error) {
toast.error(t('liabilities.loadError'));
}
};
const handleCloseDetail = () => {
setShowDetailModal(false);
setSelectedAccount(null);
};
const handleDelete = async () => {
if (!selectedAccount) return;
setSaving(true);
try {
const response = await liabilityAccountService.delete(selectedAccount.id);
if (response.success) {
toast.success(t('liabilities.deleteSuccess'));
setShowDeleteModal(false);
setSelectedAccount(null);
loadAccounts();
}
} catch (error) {
toast.error(t('liabilities.deleteError'));
} finally {
setSaving(false);
}
};
const handleMarkInstallmentPaid = async (installment) => {
try {
const response = await liabilityAccountService.updateInstallment(
selectedAccount.id,
installment.id,
{ status: 'paid' }
);
if (response.success) {
toast.success(t('liabilities.installmentPaid'));
// Recarregar conta atualizada
const accountResponse = await liabilityAccountService.getById(selectedAccount.id);
if (accountResponse.success) {
setSelectedAccount(accountResponse.data);
}
loadAccounts();
}
} catch (error) {
toast.error(t('liabilities.updateError'));
}
};
// ============================================
// Conciliação de Parcelas
// ============================================
const handleOpenReconcileModal = async (installment) => {
setSelectedInstallment(installment);
setReconcileSearch('');
setMarkAsPaidOnReconcile(true);
setShowReconcileModal(true);
await loadEligibleTransactions(installment);
};
const handleCloseReconcileModal = () => {
setShowReconcileModal(false);
setSelectedInstallment(null);
setEligibleTransactions([]);
};
const loadEligibleTransactions = async (installment, search = '') => {
setLoadingTransactions(true);
try {
const params = {};
if (search) params.search = search;
const response = await liabilityAccountService.getEligibleTransactions(
selectedAccount.id,
installment.id,
params
);
if (response.success) {
setEligibleTransactions(response.data);
}
} catch (error) {
toast.error(t('liabilities.loadError'));
} finally {
setLoadingTransactions(false);
}
};
const handleReconcileSearch = async (e) => {
const value = e.target.value;
setReconcileSearch(value);
// Debounce search
if (value.length >= 2 || value.length === 0) {
await loadEligibleTransactions(selectedInstallment, value);
}
};
const handleReconcile = async (transaction) => {
setSaving(true);
try {
const response = await liabilityAccountService.reconcile(
selectedAccount.id,
selectedInstallment.id,
transaction.id,
markAsPaidOnReconcile
);
if (response.success) {
toast.success(t('liabilities.reconcileSuccess'));
handleCloseReconcileModal();
// Recarregar conta atualizada
const accountResponse = await liabilityAccountService.getById(selectedAccount.id);
if (accountResponse.success) {
setSelectedAccount(accountResponse.data);
}
loadAccounts();
}
} catch (error) {
toast.error(error.response?.data?.message || t('liabilities.reconcileError'));
} finally {
setSaving(false);
}
};
const handleUnreconcile = async (installment) => {
if (!confirm(t('liabilities.unreconcile') + '?')) return;
setSaving(true);
try {
const response = await liabilityAccountService.unreconcile(
selectedAccount.id,
installment.id
);
if (response.success) {
toast.success(t('liabilities.unreconcileSuccess'));
// Recarregar conta atualizada
const accountResponse = await liabilityAccountService.getById(selectedAccount.id);
if (accountResponse.success) {
setSelectedAccount(accountResponse.data);
}
loadAccounts();
}
} catch (error) {
toast.error(t('liabilities.unreconcileError'));
} finally {
setSaving(false);
}
};
const formatPercent = (value) => {
if (value === null || value === undefined) return '-';
return `${parseFloat(value).toFixed(2)}%`;
};
const formatDate = (dateString) => {
if (!dateString) return '-';
return new Date(dateString).toLocaleDateString();
};
const getStatusBadge = (status) => {
const badges = {
active: 'bg-primary',
paid_off: 'bg-success',
defaulted: 'bg-danger',
renegotiated: 'bg-warning text-dark',
pending: 'bg-secondary',
paid: 'bg-success',
partial: 'bg-info',
overdue: 'bg-danger',
cancelled: 'bg-dark',
};
return badges[status] || 'bg-secondary';
};
const getStatusLabel = (status, isInstallment = false) => {
const labels = isInstallment
? liabilityAccountService.installmentStatuses
: liabilityAccountService.statuses;
return labels[status] || status;
};
// Calcular totais por moeda
const getTotalsByCurrency = () => {
const totals = {};
accounts.forEach(account => {
const currency = account.currency || 'EUR';
if (!totals[currency]) {
totals[currency] = {
principal: 0,
paid: 0,
pending: 0,
interest: 0,
};
}
totals[currency].principal += parseFloat(account.principal_amount) || 0;
totals[currency].paid += parseFloat(account.total_paid) || 0;
totals[currency].pending += parseFloat(account.total_pending) || 0;
totals[currency].interest += parseFloat(account.total_interest) || 0;
});
return totals;
};
const totalsByCurrency = getTotalsByCurrency();
return (
<div className="container-fluid py-3">
{/* Header */}
<div className={`d-flex ${isMobile ? 'flex-column gap-2' : 'justify-content-between align-items-center'} mb-4`}>
<div>
<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" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}>
{t('liabilities.subtitle')}
</small>
</div>
<button
className={`btn btn-primary ${isMobile ? 'w-100' : ''}`}
onClick={handleOpenImportModal}
>
<i className="bi bi-upload me-2"></i>
{isMobile ? t('common.import') : t('liabilities.importContract')}
</button>
</div>
{/* Summary Cards */}
{Object.keys(totalsByCurrency).length > 0 && (
<div className="row g-3 mb-4">
{Object.entries(totalsByCurrency).map(([currency, totals]) => (
<React.Fragment key={currency}>
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-danger text-white h-100">
<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>
<div className="h5 mb-0">{formatCurrency(totals.principal, currency)}</div>
</div>
<i className="bi bi-cash-stack fs-2 opacity-50"></i>
</div>
</div>
</div>
</div>
<div className="col-md-3">
<div className="card bg-success text-white h-100">
<div className="card-body py-3">
<div className="d-flex justify-content-between align-items-center">
<div>
<div className="small opacity-75">{t('liabilities.totalPaid')} ({currency})</div>
<div className="h5 mb-0">{formatCurrency(totals.paid, currency)}</div>
</div>
<i className="bi bi-check-circle fs-2 opacity-50"></i>
</div>
</div>
</div>
</div>
<div className="col-md-3">
<div className="card bg-warning text-dark h-100">
<div className="card-body py-3">
<div className="d-flex justify-content-between align-items-center">
<div>
<div className="small opacity-75">{t('liabilities.totalPending')} ({currency})</div>
<div className="h5 mb-0">{formatCurrency(totals.pending, currency)}</div>
</div>
<i className="bi bi-hourglass-split fs-2 opacity-50"></i>
</div>
</div>
</div>
</div>
<div className="col-md-3">
<div className="card bg-info text-white h-100">
<div className="card-body py-3">
<div className="d-flex justify-content-between align-items-center">
<div>
<div className="small opacity-75">{t('liabilities.totalInterest')} ({currency})</div>
<div className="h5 mb-0">{formatCurrency(totals.interest, currency)}</div>
</div>
<i className="bi bi-percent fs-2 opacity-50"></i>
</div>
</div>
</div>
</div>
</React.Fragment>
))}
</div>
)}
{/* Filters */}
<div className="card mb-4">
<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]) => (
<option key={key} value={key}>{label}</option>
))}
</select>
</div>
<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>
<option value="0">{t('common.inactive')}</option>
</select>
</div>
</div>
</div>
</div>
{/* Contracts List */}
{loading ? (
<div className="text-center py-5">
<div className="spinner-border" role="status">
<span className="visually-hidden">{t('common.loading')}</span>
</div>
</div>
) : accounts.length === 0 ? (
<div className="card">
<div className="card-body text-center py-5">
<i className="bi bi-inbox fs-1 text-muted mb-3 d-block"></i>
<h5 className="text-muted">{t('liabilities.noContracts')}</h5>
<p className="text-muted mb-3">{t('liabilities.importHint')}</p>
<button className="btn btn-primary" onClick={handleOpenImportModal}>
<i className="bi bi-upload me-2"></i>
{t('liabilities.importContract')}
</button>
</div>
</div>
) : (
<div className="row g-3">
{accounts.map(account => (
<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"
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', 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)}`}
style={{ fontSize: isMobile ? '0.65rem' : '0.75rem', flexShrink: 0 }}>
{getStatusLabel(account.status)}
</span>
</div>
<div className="card-body" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
{account.creditor && (
<div className="text-muted mb-2" style={{ fontSize: isMobile ? '0.7rem' : '0.875rem' }}>
<i className="bi bi-building me-1"></i>
{account.creditor}
</div>
)}
{/* Progress Bar */}
<div className="mb-3">
<div className="d-flex justify-content-between mb-1"
style={{ fontSize: isMobile ? '0.7rem' : '0.875rem' }}>
<span>{t('liabilities.progress')}</span>
<span className="fw-bold">{account.progress_percentage || 0}%</span>
</div>
<div className="progress" style={{ height: isMobile ? '6px' : '8px' }}>
<div
className="progress-bar bg-success"
style={{ width: `${account.progress_percentage || 0}%` }}
></div>
</div>
</div>
{/* Values */}
<div className="row g-2" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}>
<div className="col-6">
<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" 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" 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" 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" 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')}
</button>
<button
className="btn btn-sm btn-outline-danger"
onClick={() => {
setSelectedAccount(account);
setShowDeleteModal(true);
}}
style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}
>
<i className="bi bi-trash"></i>
</button>
</div>
</div>
</div>
</div>
))}
</div>
)}
{/* Import Modal */}
{showImportModal && (
<div className="modal show d-block" tabIndex="-1" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
<div className="modal-dialog modal-lg">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">
<i className="bi bi-upload me-2"></i>
{t('liabilities.importContract')}
</h5>
<button
type="button"
className="btn-close"
onClick={handleCloseImportModal}
disabled={saving}
></button>
</div>
<form onSubmit={handleImportSubmit}>
<div className="modal-body">
<div className="alert alert-info">
<i className="bi bi-info-circle me-2"></i>
{t('liabilities.importInfo')}
</div>
<div className="row g-3">
<div className="col-12">
<label className="form-label">{t('liabilities.excelFile')} *</label>
<input
type="file"
className="form-control"
name="file"
accept=".xlsx,.xls"
onChange={handleImportChange}
required
/>
<div className="form-text">{t('liabilities.fileFormatHint')}</div>
</div>
<div className="col-md-8">
<label className="form-label">{t('liabilities.contractName')} *</label>
<input
type="text"
className="form-control"
name="name"
value={importForm.name}
onChange={handleImportChange}
placeholder={t('liabilities.contractNamePlaceholder')}
required
/>
</div>
<div className="col-md-4">
<label className="form-label">{t('common.currency')}</label>
<select
className="form-select"
name="currency"
value={importForm.currency}
onChange={handleImportChange}
>
<option value="EUR">EUR - Euro</option>
<option value="BRL">BRL - Real</option>
<option value="USD">USD - Dólar</option>
</select>
</div>
<div className="col-md-6">
<label className="form-label">{t('liabilities.creditor')}</label>
<input
type="text"
className="form-control"
name="creditor"
value={importForm.creditor}
onChange={handleImportChange}
placeholder={t('liabilities.creditorPlaceholder')}
/>
</div>
<div className="col-md-6">
<label className="form-label">{t('liabilities.contractNumber')}</label>
<input
type="text"
className="form-control"
name="contract_number"
value={importForm.contract_number}
onChange={handleImportChange}
placeholder={t('liabilities.contractNumberPlaceholder')}
/>
</div>
<div className="col-12">
<label className="form-label">{t('common.description')}</label>
<textarea
className="form-control"
name="description"
value={importForm.description}
onChange={handleImportChange}
rows="2"
></textarea>
</div>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={handleCloseImportModal}
disabled={saving}
>
{t('common.cancel')}
</button>
<button
type="submit"
className="btn btn-primary"
disabled={saving}
>
{saving ? (
<>
<span className="spinner-border spinner-border-sm me-2"></span>
{t('common.importing')}
</>
) : (
<>
<i className="bi bi-upload me-2"></i>
{t('liabilities.import')}
</>
)}
</button>
</div>
</form>
</div>
</div>
</div>
)}
{/* Detail Modal */}
{showDetailModal && selectedAccount && (
<div className="modal show d-block" tabIndex="-1" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
<div className={`modal-dialog ${isMobile ? 'modal-fullscreen' : 'modal-xl'} modal-dialog-scrollable`}>
<div className="modal-content">
<div className="modal-header" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<h5 className="modal-title d-flex align-items-center" style={{ fontSize: isMobile ? '0.95rem' : '1.25rem' }}>
<i className={`${selectedAccount.icon || 'bi-file-earmark-text'} me-2`}
style={{ color: selectedAccount.color, fontSize: isMobile ? '0.9rem' : '1rem' }}></i>
<span className="text-truncate">{selectedAccount.name}</span>
<button
type="button"
className="btn btn-link text-info p-0 ms-2"
onClick={() => setShowPriceAnalysisModal(true)}
title={t('liabilities.priceAnalysis')}
>
<i className="bi bi-info-circle fs-5"></i>
</button>
</h5>
<button
type="button"
className="btn-close"
onClick={handleCloseDetail}
></button>
</div>
<div className="modal-body" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
{/* Contract Type / Description */}
{selectedAccount.description && (
<div className="alert alert-info mb-3" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem', padding: isMobile ? '0.5rem' : '0.75rem' }}>
<i className="bi bi-info-circle me-2"></i>
<strong>{t('liabilities.contractType')}:</strong> {selectedAccount.description}
</div>
)}
{/* Summary Cards */}
<div className="row g-2 mb-3">
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-light">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.875rem' }}>{t('liabilities.principal')}</div>
<div className="mb-0 fw-bold" style={{ fontSize: isMobile ? '0.85rem' : '1.25rem' }}>{formatCurrency(selectedAccount.principal_amount, selectedAccount.currency)}</div>
</div>
</div>
</div>
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-light">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.875rem' }}>{t('liabilities.totalInterest')}</div>
<div className="mb-0 fw-bold" style={{ fontSize: isMobile ? '0.85rem' : '1.25rem' }}>{formatCurrency(selectedAccount.total_interest, selectedAccount.currency)}</div>
</div>
</div>
</div>
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-light">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.875rem' }}>{t('liabilities.totalFees')}</div>
<div className="mb-0 text-warning fw-bold" style={{ fontSize: isMobile ? '0.85rem' : '1.25rem' }}>{formatCurrency(selectedAccount.total_fees, selectedAccount.currency)}</div>
{!isMobile && <div className="small text-muted">{t('liabilities.extraCharges')}</div>}
</div>
</div>
</div>
<div className={isMobile ? "col-6" : "col-md-3"}>
<div className="card bg-light">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.65rem' : '0.875rem' }}>{t('liabilities.totalContract')}</div>
<div className="mb-0 fw-bold" style={{ fontSize: isMobile ? '0.85rem' : '1.25rem' }}>{formatCurrency(selectedAccount.total_contract_value, selectedAccount.currency)}</div>
</div>
</div>
</div>
</div>
{/* Interest Rates */}
<div className="row g-2 mb-3">
<div className={isMobile ? "col-4" : "col-md-4"}>
<div className="card border-info">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.6rem' : '0.875rem' }}>{isMobile ? t('liabilities.monthly') : t('liabilities.monthlyRate')}</div>
<div className="mb-0 text-info fw-bold" style={{ fontSize: isMobile ? '0.9rem' : '1.5rem' }}>{formatPercent(selectedAccount.monthly_interest_rate)}</div>
</div>
</div>
</div>
<div className={isMobile ? "col-4" : "col-md-4"}>
<div className="card border-info">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.6rem' : '0.875rem' }}>{isMobile ? t('liabilities.annual') : t('liabilities.annualRate')}</div>
<div className="mb-0 text-info fw-bold" style={{ fontSize: isMobile ? '0.9rem' : '1.5rem' }}>{formatPercent(selectedAccount.annual_interest_rate)}</div>
</div>
</div>
</div>
<div className={isMobile ? "col-4" : "col-md-4"}>
<div className="card border-info">
<div className="card-body text-center" style={{ padding: isMobile ? '0.5rem' : '0.75rem' }}>
<div className="text-muted" style={{ fontSize: isMobile ? '0.6rem' : '0.875rem' }}>{isMobile ? t('liabilities.total') : t('liabilities.totalRate')}</div>
<div className="mb-0 text-info fw-bold" style={{ fontSize: isMobile ? '0.9rem' : '1.5rem' }}>{formatPercent(selectedAccount.total_interest_rate)}</div>
</div>
</div>
</div>
</div>
{/* Progress */}
<div className="mb-3">
<div className="d-flex justify-content-between mb-2" style={{ fontSize: isMobile ? '0.75rem' : '0.875rem' }}>
<span>{t('liabilities.paymentProgress')}</span>
<span className="fw-bold">{selectedAccount.paid_installments}/{selectedAccount.total_installments} {isMobile ? '' : t('liabilities.installments').toLowerCase()}</span>
</div>
<div className="progress" style={{ height: isMobile ? '12px' : '20px' }}>
<div
className="progress-bar bg-success"
style={{ width: `${selectedAccount.progress_percentage || 0}%`, fontSize: isMobile ? '0.65rem' : '0.75rem' }}
>
{selectedAccount.progress_percentage}%
</div>
</div>
<div className="d-flex justify-content-between text-muted mt-1" style={{ fontSize: isMobile ? '0.65rem' : '0.875rem' }}>
<span>{t('liabilities.paid')}: {formatCurrency(selectedAccount.principal_paid, selectedAccount.currency)}</span>
<span>{t('liabilities.remaining')}: {formatCurrency(selectedAccount.remaining_balance, selectedAccount.currency)}</span>
</div>
</div>
{/* Installments Table */}
<h6 className="mb-3" style={{ fontSize: isMobile ? '0.85rem' : '1rem' }}>
<i className="bi bi-list-ol me-2"></i>
{t('liabilities.installmentsList')}
</h6>
{isMobile ? (
/* Mobile: Cards layout */
<div className="d-flex flex-column gap-2">
{selectedAccount.installments?.map(inst => (
<div
key={inst.id}
className={`card border ${inst.status === 'paid' ? 'border-success bg-success bg-opacity-10' : inst.is_overdue ? 'border-danger bg-danger bg-opacity-10' : 'border-secondary'}`}
>
<div className="card-body p-2">
{/* Header */}
<div className="d-flex justify-content-between align-items-center mb-2">
<div className="fw-bold" style={{ fontSize: '0.85rem' }}>
<i className="bi bi-hash"></i>{inst.installment_number} - {formatDate(inst.due_date)}
</div>
<span className={`badge ${getStatusBadge(inst.status)}`} style={{ fontSize: '0.65rem' }}>
{getStatusLabel(inst.status, true)}
</span>
</div>
{/* Values */}
<div className="row g-1 mb-2" style={{ fontSize: '0.7rem' }}>
<div className="col-6">
<div className="text-muted" style={{ fontSize: '0.6rem' }}>{t('liabilities.installmentAmount')}</div>
<div className="fw-bold">{formatCurrency(inst.installment_amount, selectedAccount.currency)}</div>
</div>
{inst.paid_amount > 0 && (
<div className="col-6">
<div className="text-muted" style={{ fontSize: '0.6rem' }}>{t('liabilities.paidAmount')}</div>
<div className={`fw-bold ${inst.paid_amount > inst.installment_amount ? 'text-warning' : 'text-success'}`}>
{formatCurrency(inst.paid_amount, selectedAccount.currency)}
{inst.paid_amount > inst.installment_amount && <i className="bi bi-arrow-up-circle-fill ms-1"></i>}
</div>
</div>
)}
<div className="col-4">
<div className="text-muted" style={{ fontSize: '0.6rem' }}>{t('liabilities.capital')}</div>
<div>{formatCurrency(inst.principal_amount, selectedAccount.currency)}</div>
</div>
<div className="col-4">
<div className="text-muted" style={{ fontSize: '0.6rem' }}>{t('liabilities.interest')}</div>
<div>{formatCurrency(inst.interest_amount, selectedAccount.currency)}</div>
</div>
{inst.fee_amount > 0 && (
<div className="col-4">
<div className="text-muted" style={{ fontSize: '0.6rem' }}>{t('liabilities.fees')}</div>
<div className="text-warning">{formatCurrency(inst.fee_amount, selectedAccount.currency)}</div>
</div>
)}
</div>
{/* Reconciliation */}
{inst.reconciled_transaction_id ? (
<div className="d-flex justify-content-between align-items-center">
<span className="badge bg-info" style={{ fontSize: '0.65rem' }}>
<i className="bi bi-link-45deg me-1"></i>{t('liabilities.reconciled')}
</span>
<button
className="btn btn-sm btn-outline-warning"
onClick={() => handleUnreconcile(inst)}
disabled={saving}
style={{ fontSize: '0.7rem', padding: '0.25rem 0.5rem' }}
>
<i className="bi bi-link-45deg"></i>
</button>
</div>
) : (
<div className="d-flex gap-1">
{inst.status !== 'paid' && (
<button
className="btn btn-sm btn-outline-success flex-fill"
onClick={() => handleMarkInstallmentPaid(inst)}
style={{ fontSize: '0.7rem', padding: '0.25rem' }}
>
<i className="bi bi-check me-1"></i>{t('liabilities.markPaid')}
</button>
)}
<button
className="btn btn-sm btn-outline-primary flex-fill"
onClick={() => handleOpenReconcileModal(inst)}
style={{ fontSize: '0.7rem', padding: '0.25rem' }}
>
<i className="bi bi-link me-1"></i>{t('liabilities.reconcile')}
</button>
</div>
)}
</div>
</div>
))}
</div>
) : (
/* Desktop: Table layout */
<div className="table-responsive">
<table className="table table-sm table-hover">
<thead className="table-light">
<tr>
<th style={{ width: '50px' }}>#</th>
<th>{t('liabilities.dueDate')}</th>
<th className="text-end">{t('liabilities.installmentAmount')}</th>
<th className="text-end">{t('liabilities.paidAmount')}</th>
<th className="text-end">{t('liabilities.capital')}</th>
<th className="text-end">{t('liabilities.interest')}</th>
<th className="text-end">{t('liabilities.fees')}</th>
<th className="text-center">{t('common.status')}</th>
<th className="text-center">{t('liabilities.reconciliation')}</th>
<th style={{ width: '120px' }}></th>
</tr>
</thead>
<tbody>
{selectedAccount.installments?.map(inst => (
<tr key={inst.id} className={inst.status === 'paid' ? 'table-success' : inst.is_overdue ? 'table-danger' : ''}>
<td>{inst.installment_number}</td>
<td>{formatDate(inst.due_date)}</td>
<td className="text-end fw-bold">{formatCurrency(inst.installment_amount, selectedAccount.currency)}</td>
<td className="text-end">
{inst.paid_amount > 0 ? (
<span className={inst.paid_amount > inst.installment_amount ? 'text-warning' : ''}>
{formatCurrency(inst.paid_amount, selectedAccount.currency)}
{inst.paid_amount > inst.installment_amount && (
<i className="bi bi-arrow-up-circle-fill ms-1" title={t('transactions.overpayment')}></i>
)}
</span>
) : '-'}
</td>
<td className="text-end">{formatCurrency(inst.principal_amount, selectedAccount.currency)}</td>
<td className="text-end">{formatCurrency(inst.interest_amount, selectedAccount.currency)}</td>
<td className="text-end">{inst.fee_amount > 0 ? formatCurrency(inst.fee_amount, selectedAccount.currency) : '-'}</td>
<td className="text-center">
<span className={`badge ${getStatusBadge(inst.status)}`}>
{getStatusLabel(inst.status, true)}
</span>
</td>
<td className="text-center">
{inst.reconciled_transaction_id ? (
<span className="badge bg-info" title={t('liabilities.linkedTransaction') + `: #${inst.reconciled_transaction_id}`}>
<i className="bi bi-link-45deg me-1"></i>
{t('liabilities.reconciled')}
</span>
) : (
<span className="badge bg-secondary">
{t('liabilities.notReconciled')}
</span>
)}
</td>
<td>
<div className="btn-group btn-group-sm">
{inst.status !== 'paid' && !inst.reconciled_transaction_id && (
<button
className="btn btn-outline-success"
onClick={() => handleMarkInstallmentPaid(inst)}
title={t('liabilities.markPaid')}
>
<i className="bi bi-check"></i>
</button>
)}
{!inst.reconciled_transaction_id ? (
<button
className="btn btn-outline-primary"
onClick={() => handleOpenReconcileModal(inst)}
title={t('liabilities.reconcile')}
>
<i className="bi bi-link"></i>
</button>
) : (
<button
className="btn btn-outline-warning"
onClick={() => handleUnreconcile(inst)}
title={t('liabilities.unreconcile')}
disabled={saving}
>
<i className="bi bi-link-45deg"></i>
</button>
)}
</div>
</td>
</tr>
))}
</tbody>
<tfoot className="table-light fw-bold">
<tr>
<td colSpan="2">{t('common.total')}</td>
<td className="text-end">{formatCurrency(selectedAccount.total_contract_value, selectedAccount.currency)}</td>
<td className="text-end">{formatCurrency(selectedAccount.principal_amount, selectedAccount.currency)}</td>
<td className="text-end">{formatCurrency(selectedAccount.total_interest, selectedAccount.currency)}</td>
<td className="text-end">{formatCurrency(selectedAccount.total_fees, selectedAccount.currency)}</td>
<td colSpan="2"></td>
</tr>
</tfoot>
</table>
</div>
)}
</div>
<div className="modal-footer" style={{ padding: isMobile ? '0.75rem' : '1rem' }}>
<button
type="button"
className={`btn btn-secondary ${isMobile ? 'w-100' : ''}`}
onClick={handleCloseDetail}
style={{ fontSize: isMobile ? '0.85rem' : '1rem' }}
>
{t('common.close')}
</button>
</div>
</div>
</div>
</div>
)}
{/* Reconcile Modal */}
{showReconcileModal && selectedInstallment && (
<div className="modal show d-block" tabIndex="-1" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
<div className="modal-dialog modal-lg">
<div className="modal-content">
<div className="modal-header">
<h5 className="modal-title">
<i className="bi bi-link me-2"></i>
{t('liabilities.reconcileInstallment')}
</h5>
<button
type="button"
className="btn-close"
onClick={handleCloseReconcileModal}
disabled={saving}
></button>
</div>
<div className="modal-body">
{/* Installment Info */}
<div className="alert alert-info mb-3">
<div className="row">
<div className="col-md-4">
<strong>{t('liabilities.installments')}:</strong> #{selectedInstallment.installment_number}
</div>
<div className="col-md-4">
<strong>{t('liabilities.dueDate')}:</strong> {formatDate(selectedInstallment.due_date)}
</div>
<div className="col-md-4">
<strong>{t('liabilities.installmentAmount')}:</strong> {formatCurrency(selectedInstallment.installment_amount, selectedAccount?.currency)}
</div>
</div>
</div>
{/* Options */}
<div className="mb-3">
<div className="form-check">
<input
type="checkbox"
className="form-check-input"
id="markAsPaid"
checked={markAsPaidOnReconcile}
onChange={(e) => setMarkAsPaidOnReconcile(e.target.checked)}
/>
<label className="form-check-label" htmlFor="markAsPaid">
{t('liabilities.markAsPaid')}
</label>
</div>
</div>
{/* Search */}
<div className="mb-3">
<label className="form-label">{t('liabilities.searchTransactions')}</label>
<input
type="text"
className="form-control"
value={reconcileSearch}
onChange={handleReconcileSearch}
placeholder={t('common.search') + '...'}
/>
</div>
{/* Transactions List */}
<h6 className="mb-2">{t('liabilities.eligibleTransactions')}</h6>
{loadingTransactions ? (
<div className="text-center py-4">
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">{t('common.loading')}</span>
</div>
</div>
) : eligibleTransactions.length === 0 ? (
<div className="alert alert-warning">
{t('liabilities.noEligibleTransactions')}
</div>
) : (
<div className="table-responsive" style={{ maxHeight: '300px' }}>
<table className="table table-sm table-hover">
<thead className="table-light sticky-top">
<tr>
<th>{t('transactions.date')}</th>
<th>{t('transactions.description')}</th>
<th>{t('transactions.account')}</th>
<th className="text-end">{t('transactions.amount')}</th>
<th style={{ width: '80px' }}></th>
</tr>
</thead>
<tbody>
{eligibleTransactions.map(tx => (
<tr key={tx.id}>
<td>{formatDate(tx.effective_date || tx.planned_date)}</td>
<td>
<div className="text-truncate" style={{ maxWidth: '200px' }} title={tx.description}>
{tx.description || tx.original_description}
</div>
</td>
<td>{tx.account?.name || '-'}</td>
<td className="text-end fw-bold text-danger">
{formatCurrency(Math.abs(tx.amount), tx.account?.currency)}
</td>
<td>
<button
className="btn btn-sm btn-primary"
onClick={() => handleReconcile(tx)}
disabled={saving}
>
<i className="bi bi-link"></i>
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={handleCloseReconcileModal}
disabled={saving}
>
{t('common.cancel')}
</button>
</div>
</div>
</div>
</div>
)}
{/* Delete Confirmation Modal */}
<ConfirmModal
show={showDeleteModal}
onHide={() => setShowDeleteModal(false)}
onConfirm={handleDelete}
title={t('liabilities.deleteTitle')}
message={t('liabilities.deleteConfirm', { name: selectedAccount?.name })}
confirmText={t('common.delete')}
cancelText={t('common.cancel')}
variant="danger"
loading={saving}
/>
{/* PRICE System Analysis Modal */}
{showPriceAnalysisModal && selectedAccount && (
<div className="modal show d-block" tabIndex="-1" style={{ backgroundColor: 'rgba(0,0,0,0.5)', zIndex: 1060 }}>
<div className="modal-dialog modal-xl modal-dialog-scrollable">
<div className="modal-content">
<div className="modal-header bg-info text-white">
<h5 className="modal-title">
<i className="bi bi-mortarboard me-2"></i>
{t('liabilities.priceAnalysisTitle')} - {selectedAccount.name}
</h5>
<button
type="button"
className="btn-close btn-close-white"
onClick={() => setShowPriceAnalysisModal(false)}
></button>
</div>
<div className="modal-body">
{/* Contract Summary */}
<div className="alert alert-primary mb-4">
<div className="row text-center">
<div className="col-md-3">
<div className="small opacity-75">{t('liabilities.principal')}</div>
<div className="h5 mb-0">{formatCurrency(selectedAccount.principal_amount, selectedAccount.currency)}</div>
</div>
<div className="col-md-3">
<div className="small opacity-75">{t('liabilities.totalInterest')}</div>
<div className="h5 mb-0">{formatCurrency(selectedAccount.total_interest, selectedAccount.currency)}</div>
</div>
<div className="col-md-3">
<div className="small opacity-75">{t('liabilities.installments')}</div>
<div className="h5 mb-0">{selectedAccount.total_installments}</div>
</div>
<div className="col-md-3">
<div className="small opacity-75">{t('liabilities.totalContract')}</div>
<div className="h5 mb-0">{formatCurrency(selectedAccount.total_contract_value, selectedAccount.currency)}</div>
</div>
</div>
</div>
{/* Overview */}
<div className="alert alert-info">
<h6 className="alert-heading">
<i className="bi bi-info-circle me-2"></i>
{t('liabilities.priceOverview')}
</h6>
<p className="mb-0">{t('liabilities.priceOverviewText')}</p>
</div>
{/* What is PRICE */}
<div className="card mb-3">
<div className="card-header bg-primary text-white">
<i className="bi bi-question-circle me-2"></i>
{t('liabilities.whatIsPrice')}
</div>
<div className="card-body">
<p>{t('liabilities.whatIsPriceText')}</p>
<ul className="mb-0">
<li><strong>{t('liabilities.priceFeature1')}</strong></li>
<li><strong>{t('liabilities.priceFeature2')}</strong></li>
<li><strong>{t('liabilities.priceFeature3')}</strong></li>
</ul>
</div>
</div>
{/* Mathematical Formula */}
<div className="card mb-3">
<div className="card-header bg-dark text-white">
<i className="bi bi-calculator me-2"></i>
{t('liabilities.priceMathFormula')}
</div>
<div className="card-body">
<div className="bg-light p-3 rounded text-center mb-3" style={{ fontFamily: 'monospace', fontSize: '1.1em' }}>
PMT = PV × [i × (1 + i)] / [(1 + i) - 1]
</div>
<div className="row">
<div className="col-md-6">
<p className="mb-2"><strong>{t('liabilities.priceWhere')}:</strong></p>
<ul className="small">
<li><code>PMT</code> = {t('liabilities.pricePMT')}</li>
<li><code>PV</code> = {t('liabilities.pricePV')}</li>
<li><code>i</code> = {t('liabilities.priceI')}</li>
<li><code>n</code> = {t('liabilities.priceN')}</li>
</ul>
</div>
<div className="col-md-6">
<div className="alert alert-secondary small mb-0">
<strong>{t('liabilities.thisContract')}:</strong><br/>
PV = {formatCurrency(selectedAccount.principal_amount, selectedAccount.currency)}<br/>
i = {formatPercent(selectedAccount.monthly_interest_rate)} {t('liabilities.perMonth')}<br/>
n = {selectedAccount.total_installments} {t('liabilities.installments').toLowerCase()}<br/>
<hr className="my-2"/>
PMT {formatCurrency(selectedAccount.installments?.[0]?.installment_amount || 0, selectedAccount.currency)}/{t('liabilities.perMonth')}
</div>
</div>
</div>
</div>
</div>
{/* Amortization Behavior */}
<div className="card mb-3">
<div className="card-header bg-warning">
<i className="bi bi-graph-up me-2"></i>
{t('liabilities.amortizationBehavior')}
</div>
<div className="card-body">
<div className="row g-3">
<div className="col-md-6">
<h6><i className="bi bi-1-circle me-2"></i>{t('liabilities.earlyInstallments')}</h6>
<ul className="small text-muted">
<li>{t('liabilities.earlyInstallmentsText1')}</li>
<li>{t('liabilities.earlyInstallmentsText2')}</li>
</ul>
</div>
<div className="col-md-6">
<h6><i className="bi bi-arrow-right-circle me-2"></i>{t('liabilities.lateInstallments')}</h6>
<ul className="small text-muted">
<li>{t('liabilities.lateInstallmentsText1')}</li>
<li>{t('liabilities.lateInstallmentsText2')}</li>
</ul>
</div>
</div>
{selectedAccount.installments?.length >= 3 && (
<div className="mt-3">
<h6>{t('liabilities.visualExample')}:</h6>
<div className="table-responsive">
<table className="table table-sm table-bordered small">
<thead className="table-light">
<tr>
<th>#</th>
<th>{t('liabilities.installmentValue')}</th>
<th>{t('liabilities.interest')}</th>
<th>{t('liabilities.amortization')}</th>
</tr>
</thead>
<tbody>
{/* First installment */}
<tr>
<td>{selectedAccount.installments[0].installment_number}</td>
<td>{formatCurrency(selectedAccount.installments[0].installment_amount, selectedAccount.currency)}</td>
<td className="text-danger">{formatCurrency(selectedAccount.installments[0].interest_amount, selectedAccount.currency)}</td>
<td className="text-success">{formatCurrency(selectedAccount.installments[0].principal_amount, selectedAccount.currency)}</td>
</tr>
{/* Middle installment */}
{(() => {
const midIndex = Math.floor(selectedAccount.installments.length / 2);
const midInst = selectedAccount.installments[midIndex];
return (
<tr>
<td>{midInst.installment_number}</td>
<td>{formatCurrency(midInst.installment_amount, selectedAccount.currency)}</td>
<td className="text-danger">{formatCurrency(midInst.interest_amount, selectedAccount.currency)}</td>
<td className="text-success">{formatCurrency(midInst.principal_amount, selectedAccount.currency)}</td>
</tr>
);
})()}
{/* Last installment */}
<tr>
<td>{selectedAccount.installments[selectedAccount.installments.length - 1].installment_number}</td>
<td>{formatCurrency(selectedAccount.installments[selectedAccount.installments.length - 1].installment_amount, selectedAccount.currency)}</td>
<td className="text-danger">{formatCurrency(selectedAccount.installments[selectedAccount.installments.length - 1].interest_amount, selectedAccount.currency)}</td>
<td className="text-success">{formatCurrency(selectedAccount.installments[selectedAccount.installments.length - 1].principal_amount, selectedAccount.currency)}</td>
</tr>
</tbody>
</table>
</div>
</div>
)}
</div>
</div>
{/* Interest Rates */}
<div className="card mb-3">
<div className="card-header bg-success text-white">
<i className="bi bi-percent me-2"></i>
{t('liabilities.interestRates')}
</div>
<div className="card-body">
<div className="row">
<div className="col-md-4">
<div className="text-center p-3 border rounded">
<div className="small text-muted">{t('liabilities.monthlyRate')}</div>
<div className="h4 text-primary mb-0">{formatPercent(selectedAccount.monthly_interest_rate)}</div>
<div className="small">{t('liabilities.perMonth')}</div>
</div>
</div>
<div className="col-md-4">
<div className="text-center p-3 border rounded">
<div className="small text-muted">{t('liabilities.annualRate')}</div>
<div className="h4 text-warning mb-0">{formatPercent(selectedAccount.annual_interest_rate)}</div>
<div className="small">{t('liabilities.perYear')}</div>
</div>
</div>
<div className="col-md-4">
<div className="text-center p-3 border rounded">
<div className="small text-muted">{t('liabilities.totalRate')}</div>
<div className="h4 text-danger mb-0">{formatPercent(selectedAccount.total_interest_rate)}</div>
<div className="small">{t('liabilities.interestOverPrincipal')}</div>
</div>
</div>
</div>
</div>
</div>
{/* Contract Financial Summary */}
<div className="card mb-3">
<div className="card-header bg-secondary text-white">
<i className="bi bi-cash-coin me-2"></i>
{t('liabilities.contractCost')}
</div>
<div className="card-body">
<p>{t('liabilities.contractCostText')}</p>
<div className="bg-light p-3 rounded">
<div className="row text-center">
<div className="col-md-3">
<div className="small text-muted">{t('liabilities.principal')}</div>
<div className="fw-bold">{formatCurrency(selectedAccount.principal_amount, selectedAccount.currency)}</div>
</div>
<div className="col-md-3">
<div className="small text-muted">{t('liabilities.totalInterest')}</div>
<div className="fw-bold text-danger">+{formatCurrency(selectedAccount.total_interest, selectedAccount.currency)}</div>
</div>
<div className="col-md-3">
<div className="small text-muted">{t('liabilities.totalFees')}</div>
<div className="fw-bold text-warning">+{formatCurrency(selectedAccount.total_fees, selectedAccount.currency)}</div>
</div>
<div className="col-md-3">
<div className="small text-muted">{t('liabilities.totalContract')}</div>
<div className="fw-bold text-primary">{formatCurrency(selectedAccount.total_contract_value, selectedAccount.currency)}</div>
</div>
</div>
</div>
</div>
</div>
{/* Financial Analysis Summary */}
<div className="alert alert-success">
<h6 className="alert-heading">
<i className="bi bi-lightbulb me-2"></i>
{t('liabilities.financialSummary')}
</h6>
<ul className="mb-0 small">
<li>{t('liabilities.summaryPointDynamic1', {
ratio: selectedAccount.principal_amount > 0
? (selectedAccount.total_interest / selectedAccount.principal_amount * 100).toFixed(0)
: 0
})}</li>
<li>{t('liabilities.summaryPoint2')}</li>
<li>{t('liabilities.summaryPoint3')}</li>
<li>{t('liabilities.summaryPoint4')}</li>
</ul>
</div>
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-secondary"
onClick={() => setShowPriceAnalysisModal(false)}
>
{t('common.close')}
</button>
</div>
</div>
</div>
</div>
)}
</div>
);
};
export default LiabilityAccounts;