feat: account always sorted by name feat: categories in budgets always sorted
This commit is contained in:
@@ -12,6 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Changed
|
||||
- Budgets now survives months and years, allowing to set a budget for a category and have it applied to the next months.
|
||||
- `.state-figure` now changes its size on mobile.
|
||||
- Date format in the credit-bills page from 2026-08-1 to Aug 1.
|
||||
- Categories in budgets page are now sorted alphabetically.
|
||||
- All account dropdowns to display sorted accounts.
|
||||
|
||||
### Fixed
|
||||
- Bug making transactions change place after editing.
|
||||
- Bug making the page flash a white screen during page transition.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -39,7 +39,9 @@ export default function Budgets() {
|
||||
const categoriesQuery = useQuery({ queryKey: ['categories'], queryFn: CategoriesApi.list });
|
||||
const categories = [...(categoriesQuery.data || [])].sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const budgets = budgetsQuery.data || [];
|
||||
const budgets = [...(budgetsQuery.data || [])].sort((a, b) =>
|
||||
(a.category?.name || '').localeCompare(b.category?.name || '')
|
||||
);
|
||||
const spendByCategory = Object.fromEntries(
|
||||
(spendQuery.data || []).map((s) => [s.categoryId, Number(s.spent)])
|
||||
);
|
||||
|
||||
@@ -92,7 +92,10 @@ export default function CardBills() {
|
||||
const { sentinelRef, progress, isStuck } = useStickyHeader();
|
||||
|
||||
const accountsQuery = useQuery({ queryKey: ['accounts'], queryFn: AccountsApi.list });
|
||||
const accounts = useMemo(() => accountsQuery.data || [], [accountsQuery.data]);
|
||||
const accounts = useMemo(
|
||||
() => [...(accountsQuery.data || [])].sort((a, b) => a.name.localeCompare(b.name)),
|
||||
[accountsQuery.data]
|
||||
);
|
||||
const allCards = useMemo(() => accounts.filter((a) => a.kind === 'CREDIT_CARD'), [accounts]);
|
||||
const eligibleCards = useMemo(() => allCards.filter((c) => c.dueDayOfMonth != null), [allCards]);
|
||||
|
||||
@@ -792,7 +795,12 @@ export default function CardBills() {
|
||||
<div className="txn-meta">
|
||||
<span>{catName || 'Uncategorized'}</span>
|
||||
<span className="dot-sep" />
|
||||
<span>{t.occurredOn}</span>
|
||||
<span className="txn-date">
|
||||
{parseLocalDate(t.occurredOn).toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="txn-right">
|
||||
|
||||
@@ -33,7 +33,10 @@ export default function Import() {
|
||||
const fileInputRef = useRef(null);
|
||||
|
||||
const accountsQuery = useQuery({ queryKey: ['accounts'], queryFn: AccountsApi.list });
|
||||
const accounts = useMemo(() => accountsQuery.data || [], [accountsQuery.data]);
|
||||
const accounts = useMemo(
|
||||
() => [...(accountsQuery.data || [])].sort((a, b) => a.name.localeCompare(b.name)),
|
||||
[accountsQuery.data]
|
||||
);
|
||||
const categoriesQuery = useQuery({ queryKey: ['categories'], queryFn: CategoriesApi.list });
|
||||
const categories = useMemo(
|
||||
() => [...(categoriesQuery.data || [])].sort((a, b) => a.name.localeCompare(b.name)),
|
||||
|
||||
@@ -269,7 +269,10 @@ export default function Transactions() {
|
||||
const accountsQuery = useQuery({ queryKey: ['accounts'], queryFn: AccountsApi.list });
|
||||
// Credit cards are handled entirely on the dedicated Card Bills page.
|
||||
const accounts = useMemo(
|
||||
() => (accountsQuery.data || []).filter((a) => a.kind !== 'CREDIT_CARD'),
|
||||
() =>
|
||||
(accountsQuery.data || [])
|
||||
.filter((a) => a.kind !== 'CREDIT_CARD')
|
||||
.sort((a, b) => a.name.localeCompare(b.name)),
|
||||
[accountsQuery.data]
|
||||
);
|
||||
const categoriesQuery = useQuery({ queryKey: ['categories'], queryFn: CategoriesApi.list });
|
||||
@@ -535,7 +538,11 @@ export default function Transactions() {
|
||||
.filter((t) => !filterCategoryId || String(t.category?.id) === filterCategoryId)
|
||||
.filter((t) => !start || parseLocalDate(t.occurredOn) >= start)
|
||||
.filter((t) => !end || parseLocalDate(t.occurredOn) <= end)
|
||||
.sort((a, b) => parseLocalDate(b.occurredOn) - parseLocalDate(a.occurredOn));
|
||||
.sort((a, b) => {
|
||||
const dateDiff = parseLocalDate(b.occurredOn) - parseLocalDate(a.occurredOn);
|
||||
if (dateDiff !== 0) return dateDiff;
|
||||
return b.id - a.id;
|
||||
});
|
||||
}, [txnQueries, search, filterAccountId, filterCategoryId, filterRange, filterStartDate, filterEndDate, monthOffset]);
|
||||
|
||||
const grouped = useMemo(() => {
|
||||
@@ -557,7 +564,11 @@ export default function Transactions() {
|
||||
.filter((t) => !filterAccountId || String(t.account?.id) === filterAccountId)
|
||||
.filter((t) => !start || parseLocalDate(t.occurredOn) >= start)
|
||||
.filter((t) => !end || parseLocalDate(t.occurredOn) <= end)
|
||||
.sort((a, b) => parseLocalDate(b.occurredOn) - parseLocalDate(a.occurredOn));
|
||||
.sort((a, b) => {
|
||||
const dateDiff = parseLocalDate(b.occurredOn) - parseLocalDate(a.occurredOn);
|
||||
if (dateDiff !== 0) return dateDiff;
|
||||
return b.id - a.id;
|
||||
});
|
||||
}, [txnQueries, filterAccountId, filterRange, filterStartDate, filterEndDate, monthOffset]);
|
||||
|
||||
const monthlyCredits = monthlyFlat.reduce(
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
@import './tokens';
|
||||
@import 'bootstrap/scss/bootstrap';
|
||||
|
||||
html,
|
||||
body {
|
||||
background: var(--bg);
|
||||
background: #0e1116;
|
||||
color: var(--text);
|
||||
font-size: 14px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
#root {
|
||||
view-transition-name: root;
|
||||
}
|
||||
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
background: #0e1116;
|
||||
}
|
||||
|
||||
.serif {
|
||||
font-family: 'Fraunces', Georgia, serif;
|
||||
}
|
||||
@@ -445,6 +455,10 @@ body {
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.txn-meta .txn-date {
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
}
|
||||
.txn-meta .dot-sep {
|
||||
width: 2px;
|
||||
height: 2px;
|
||||
|
||||
Reference in New Issue
Block a user