Add support for existing transactions
This commit is contained in:
@@ -3,11 +3,13 @@ import { useStore } from "../../store/AppStore";
|
||||
import TransactionsTable from "./TransactionsTable";
|
||||
import { SkippedLines } from "./SkippedLines";
|
||||
import ImportBar from "./ImportBar";
|
||||
import type { ImportOptions } from "../../types/api";
|
||||
import { submitTransactions } from "../../services/api.service";
|
||||
import { type ImportOptions, type Transaction } from "../../types/api";
|
||||
import { getDateRangedTransactions, getLatestTransactions, submitTransactions } from "../../services/api.service";
|
||||
import { useLoader } from "../../hooks/useLoader";
|
||||
import { FilterPanel, type FilterData } from "./FilterPanel";
|
||||
import dayjs from "dayjs";
|
||||
import { ExistingTransactions } from "./ExistingTransactions";
|
||||
import classNames from "classnames";
|
||||
|
||||
|
||||
export default function PrepareTransactionsPage() {
|
||||
@@ -15,6 +17,8 @@ export default function PrepareTransactionsPage() {
|
||||
|
||||
const [userFilter, setUserFilter] = useState<FilterData>({});
|
||||
const [deselected, setDeselected] = useState<number[]>([]);
|
||||
const [enabledExistingTransactions, setEnabledExistingTransactions] = useState(true);
|
||||
const [existingTransactions, setExistingTransactions] = useState<Transaction[]>([]);
|
||||
|
||||
const select = useCallback((index: number) => setDeselected(deselected.filter(x => x !== index)), [deselected, setDeselected]);
|
||||
const deselect = useCallback((index: number) => setDeselected([...deselected, index]), [deselected, setDeselected]);
|
||||
@@ -38,9 +42,12 @@ export default function PrepareTransactionsPage() {
|
||||
|
||||
return date.isBefore(userFilter.to, 'day') || date.isSame(userFilter.to, 'day');
|
||||
})
|
||||
.slice().reverse()
|
||||
, [state.transactions, userFilter]);
|
||||
|
||||
const selectedTransactions = useMemo(() => filteredTransactions.filter((_, i) => !deselected.includes(i)), [filteredTransactions, deselected]);
|
||||
const selectedTransactions = useMemo(() =>
|
||||
filteredTransactions.filter((_, i) => !deselected.includes(i)),
|
||||
[filteredTransactions, deselected]);
|
||||
|
||||
const { fn: handleSubmit, loading } = useLoader(async (opts: ImportOptions) => {
|
||||
if(!state.server) {
|
||||
@@ -60,9 +67,36 @@ export default function PrepareTransactionsPage() {
|
||||
offset: 1
|
||||
}
|
||||
});
|
||||
}, [selectedTransactions, state]);
|
||||
}, [selectedTransactions, state]);
|
||||
|
||||
useEffect(() => setDeselected([]), [filteredTransactions]);
|
||||
const { fn: refreshExistingTransactions, loading: loadingExistingTransactions } = useLoader(async () => {
|
||||
if (!state.server || !enabledExistingTransactions) {
|
||||
setExistingTransactions([]);
|
||||
return;
|
||||
}
|
||||
|
||||
// If no "from" filter active, pull the latest 10 transactions
|
||||
if (!userFilter.from) {
|
||||
const transactions = await getLatestTransactions(state.server, 10);
|
||||
setExistingTransactions(transactions);
|
||||
return;
|
||||
}
|
||||
|
||||
const start = userFilter.from.format("YYYY-MM-DD");
|
||||
const end = (userFilter.to ?? dayjs()).format("YYYY-MM-DD");
|
||||
|
||||
const transactions = await getDateRangedTransactions(state.server, start, end);
|
||||
setExistingTransactions(transactions);
|
||||
}, [enabledExistingTransactions, state.server, userFilter]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
setDeselected([])
|
||||
}, [filteredTransactions]);
|
||||
|
||||
useEffect(() => {
|
||||
refreshExistingTransactions()
|
||||
}, [enabledExistingTransactions, state.server, userFilter]);
|
||||
|
||||
return (
|
||||
<div className="columns mt-6">
|
||||
@@ -74,15 +108,47 @@ export default function PrepareTransactionsPage() {
|
||||
<h3 className="title is-5">Filters</h3>
|
||||
<FilterPanel value={userFilter} setValue={setUserFilter} />
|
||||
</div>
|
||||
|
||||
<div className="content">
|
||||
<h3 className="title is-5">Considered transactions ({selectedTransactions.length}/{filteredTransactions.length})</h3>
|
||||
<TransactionsTable
|
||||
transactions={filteredTransactions}
|
||||
deselected={deselected}
|
||||
deselect={deselect}
|
||||
select={select} />
|
||||
</div>
|
||||
|
||||
<div className="field">
|
||||
<label className="label">Fetch existing transactions</label>
|
||||
<div className="notification is-info is-light">
|
||||
If enabled, the existing transactions will be fetched automatically basing on date filter.
|
||||
If "from" is filled, the existing transactions will be fetched basing on set date (if "to" is not filled, the todays date will be considered).
|
||||
Otherwise, the latest <abbr title="Transaction before transfer consolidation.">10 raw transactions</abbr> will be fetched. Because of transfer consolidation,
|
||||
the ultimate number of transactions can be lower.
|
||||
</div>
|
||||
<div className="control">
|
||||
<div className="buttons has-addons">
|
||||
<button
|
||||
className={classNames('button', { 'is-selected': enabledExistingTransactions, 'is-success': enabledExistingTransactions})}
|
||||
onClick={() => setEnabledExistingTransactions(true)}
|
||||
disabled={enabledExistingTransactions}>I</button>
|
||||
<button
|
||||
className={classNames('button', { 'is-selected': !enabledExistingTransactions, 'is-danger': !enabledExistingTransactions})}
|
||||
onClick={() => setEnabledExistingTransactions(false)}
|
||||
disabled={!enabledExistingTransactions}>O</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="columns">
|
||||
<div className={classNames('column', { 'is-6': enabledExistingTransactions, 'is-12': !enabledExistingTransactions })}>
|
||||
<h3 className="title is-5">Considered transactions ({selectedTransactions.length}/{filteredTransactions.length})</h3>
|
||||
<TransactionsTable
|
||||
transactions={filteredTransactions}
|
||||
deselected={deselected}
|
||||
deselect={deselect}
|
||||
select={select} />
|
||||
</div>
|
||||
|
||||
{enabledExistingTransactions &&
|
||||
<div className="column is-6">
|
||||
<h3 className="title is-5">Existing transactions ({existingTransactions.length})</h3>
|
||||
<ExistingTransactions
|
||||
loading={loadingExistingTransactions}
|
||||
transactions={existingTransactions} />
|
||||
</div>}
|
||||
</div>
|
||||
|
||||
<div className="content">
|
||||
<h3 className="title is-5">Skipped lines ({state.skipped.length})</h3>
|
||||
@@ -92,7 +158,6 @@ export default function PrepareTransactionsPage() {
|
||||
<div className="content">
|
||||
<ImportBar loading={loading} onSubmit={handleSubmit} onStartOver={() => location.reload()}/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user