Track imports in DB, show history in Data section, allow deleting transactions of a specific import instead of clearing all.
120 lines
3.7 KiB
TypeScript
120 lines
3.7 KiB
TypeScript
import { useState, useEffect } from 'react';
|
||
import { useNavigate } from 'react-router-dom';
|
||
import { ClearHistoryModal } from './ClearHistoryModal';
|
||
import { DeleteImportModal } from './DeleteImportModal';
|
||
import { getImports } from '../api/import';
|
||
import type { Import } from '@family-budget/shared';
|
||
|
||
function formatDate(iso: string): string {
|
||
const d = new Date(iso);
|
||
return d.toLocaleString('ru-RU', {
|
||
day: '2-digit',
|
||
month: '2-digit',
|
||
year: 'numeric',
|
||
hour: '2-digit',
|
||
minute: '2-digit',
|
||
});
|
||
}
|
||
|
||
export function DataSection() {
|
||
const [showClearModal, setShowClearModal] = useState(false);
|
||
const [imports, setImports] = useState<Import[]>([]);
|
||
const [impToDelete, setImpToDelete] = useState<Import | null>(null);
|
||
const navigate = useNavigate();
|
||
|
||
useEffect(() => {
|
||
getImports().then(setImports).catch(() => {});
|
||
}, []);
|
||
|
||
const handleImportDeleted = () => {
|
||
setImpToDelete(null);
|
||
getImports().then(setImports).catch(() => {});
|
||
navigate('/history');
|
||
};
|
||
|
||
return (
|
||
<div className="data-section">
|
||
<div className="section-block">
|
||
<h3>История импортов</h3>
|
||
<p className="section-desc">
|
||
Список импортов выписок. Можно удалить операции конкретного импорта.
|
||
</p>
|
||
{imports.length === 0 ? (
|
||
<p className="muted">Импортов пока нет.</p>
|
||
) : (
|
||
<div className="table-responsive">
|
||
<table className="table">
|
||
<thead>
|
||
<tr>
|
||
<th>Дата</th>
|
||
<th>Счёт</th>
|
||
<th>Банк</th>
|
||
<th>Импортировано</th>
|
||
<th>Дубликаты</th>
|
||
<th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{imports.map((imp) => (
|
||
<tr key={imp.id}>
|
||
<td>{formatDate(imp.importedAt)}</td>
|
||
<td>
|
||
{imp.accountAlias || imp.accountNumberMasked || '—'}
|
||
</td>
|
||
<td>{imp.bank}</td>
|
||
<td>{imp.importedCount}</td>
|
||
<td>{imp.duplicatesSkipped}</td>
|
||
<td>
|
||
<button
|
||
type="button"
|
||
className="btn btn-sm btn-danger"
|
||
onClick={() => setImpToDelete(imp)}
|
||
disabled={imp.importedCount === 0}
|
||
>
|
||
Удалить
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
))}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className="section-block">
|
||
<h3>Очистка данных</h3>
|
||
<p className="section-desc">
|
||
Очистить историю операций (все транзакции). Счета, категории и
|
||
правила сохранятся.
|
||
</p>
|
||
<button
|
||
type="button"
|
||
className="btn btn-danger"
|
||
onClick={() => setShowClearModal(true)}
|
||
>
|
||
Очистить историю
|
||
</button>
|
||
</div>
|
||
|
||
{showClearModal && (
|
||
<ClearHistoryModal
|
||
onClose={() => setShowClearModal(false)}
|
||
onDone={() => {
|
||
setShowClearModal(false);
|
||
navigate('/history');
|
||
}}
|
||
/>
|
||
)}
|
||
|
||
{impToDelete && (
|
||
<DeleteImportModal
|
||
imp={impToDelete}
|
||
onClose={() => setImpToDelete(null)}
|
||
onDone={handleImportDeleted}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|