Skip to content

Commit e9194ee

Browse files
authored
Merge pull request #366 from SFTtech/milo/prevent-ui-inconsistencies
prevent UI inconsistencies
2 parents e8780b3 + 6b45a35 commit e9194ee

9 files changed

Lines changed: 49 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- prevent accounts which are not yet saved to the server from being referenced in transactions
6+
57
[Compare the full difference.](https://github.com/SFTtech/abrechnung/compare/v1.7.0...HEAD)
68

79
## 1.7.0 (2026-02-21)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ It aims to be a feature-complete, free and open source alternative to Splitwise,
2323
- Create events to manage complex expenses, e.g. multiple people buying things for a multi-day event with different participants each day
2424
- Add tags to expenses and events to quickly filter the expense and event lists
2525
- Unsaved changes are stored locally to not get lost when your internet connection drops
26+
- Export / import groups via JSON
2627
- Export expenses to CSV
2728
- Archive groups to make them readonly
2829

apps/web/src/components/AccountSelect.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const AccountSelect: React.FC<AccountSelectProps> = ({
3030
noDisabledStyling = false,
3131
...props
3232
}) => {
33-
const accounts = useSortedAccounts(groupId, "name");
33+
const accounts = useSortedAccounts(groupId, { sortMode: "name", excludeLocalOnly: true });
3434

3535
const filteredAccounts = React.useMemo<Account[]>(() => {
3636
return exclude ? accounts.filter((account) => exclude.indexOf(account.id) < 0) : accounts;

apps/web/src/pages/accounts/Balances/BalanceBarGraph.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export const BalanceBarGraph: React.FC<BalanceBarGraphProps> = ({ group }) => {
2525
const theme: Theme = useTheme();
2626
const navigate = useNavigate();
2727

28-
const personalAccounts = useSortedAccounts(group.id, "name", "personal");
28+
const personalAccounts = useSortedAccounts(group.id, {
29+
sortMode: "name",
30+
type: "personal",
31+
excludeLocalOnly: true,
32+
});
2933
const balances = useAppSelector((state) => selectAccountBalances(state, group.id));
3034

3135
const colorGreen = theme.palette.mode === "light" ? theme.palette.success.light : theme.palette.success.dark;
@@ -89,7 +93,7 @@ export const BalanceBarGraph: React.FC<BalanceBarGraphProps> = ({ group }) => {
8993
</Typography>
9094
) : (
9195
<>
92-
<Typography variant="body2" sx={{ mr: 1 }}>
96+
<Typography variant="body2" sx={{ mr: 1, textWrap: "nowrap" }}>
9397
{formatCurrency(item.balance, group.currency_identifier)}
9498
</Typography>
9599
<Box
@@ -131,7 +135,7 @@ export const BalanceBarGraph: React.FC<BalanceBarGraphProps> = ({ group }) => {
131135
borderRadius: "0 8px 8px 0",
132136
}}
133137
/>
134-
<Typography variant="body2" sx={{ ml: 1 }}>
138+
<Typography variant="body2" sx={{ ml: 1, textWrap: "nowrap" }}>
135139
{formatCurrency(item.balance, group.currency_identifier)}
136140
</Typography>
137141
</>

apps/web/src/pages/accounts/Balances/Balances.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const Balances: React.FC<Props> = ({ groupId }) => {
2727
const formatCurrency = useFormatCurrency();
2828

2929
const group = useGroup(groupId);
30-
const personalAccounts = useSortedAccounts(groupId, "name", "personal");
30+
const personalAccounts = useSortedAccounts(groupId, { sortMode: "name", type: "personal", excludeLocalOnly: true });
3131
const clearingAccounts = useGroupAccounts(groupId, "clearing");
3232
const balances = useAppSelector((state) => selectAccountBalances(state, groupId));
3333
const isGroupWritable = useIsGroupWritable(groupId);

apps/web/src/pages/accounts/ClearingAccountList/ClearingAccountList.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ export const ClearingAccountList: React.FC<Props> = ({ groupId }) => {
5858
.trim()
5959
.split(",")
6060
.filter((tag) => !!tag);
61-
const clearingAccounts = useSortedAccounts(groupId, sortMode, "clearing", searchValue, true, tagFilter);
61+
const clearingAccounts = useSortedAccounts(groupId, {
62+
sortMode,
63+
type: "clearing",
64+
searchTerm: searchValue,
65+
wipAtTop: true,
66+
tags: tagFilter,
67+
});
6268

6369
const [currentPage, setCurrentPage] = useState(0);
6470
const shouldShowPagination = clearingAccounts.length > MAX_ITEMS_PER_PAGE;

apps/web/src/pages/accounts/PersonalAccountList/PersonalAccountList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const PersonalAccountList: React.FC<Props> = ({ groupId }) => {
5252
const searchValue = filterState.searchValue.trim();
5353
const sortMode = useAppSelector(selectPersonalAccountSortMode);
5454

55-
const personalAccounts = useSortedAccounts(groupId, sortMode, "personal", searchValue);
55+
const personalAccounts = useSortedAccounts(groupId, { sortMode, type: "personal", searchTerm: searchValue });
5656

5757
const isGroupWritable = useIsGroupWritable(groupId);
5858

apps/web/src/pages/groups/settings/GroupSettingsPage.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,11 @@ const OwnedAccountSettings: React.FC<{ group: Group }> = ({ group }) => {
191191
const { t } = useTranslation();
192192
const dispatch = useAppDispatch();
193193
const currentUserId = useAppSelector(selectCurrentUserId);
194-
const personalAccounts = useSortedAccounts(group.id, "name", "personal");
194+
const personalAccounts = useSortedAccounts(group.id, {
195+
sortMode: "name",
196+
type: "personal",
197+
excludeLocalOnly: true,
198+
});
195199
const [updateOwnedAccount] = useUpdateMemberOwnedAccountMutation();
196200

197201
const onChange = (accountId: number | null) => {

libs/redux/src/lib/accounts/accountSlice.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,23 @@ const selectSortedAccounts = createSelector(
9999
wipAtTop?: boolean,
100100
tags?: string[]
101101
) => tags ?? emptyList,
102-
(accounts, sortMode, type, searchTerm, wipAtTop, tags) => {
102+
(
103+
state: IRootState,
104+
groupId: number,
105+
type: AccountType | undefined,
106+
sortMode: AccountSortMode,
107+
searchTerm?: string,
108+
wipAtTop?: boolean,
109+
tags?: string[],
110+
excludeLocalOnly?: boolean
111+
) => excludeLocalOnly,
112+
(accounts, sortMode, type, searchTerm, wipAtTop, tags, excludeLocalOnly) => {
103113
const compareFunction = getAccountSortFunc(sortMode, wipAtTop);
104114
// TODO: this has optimization potential
105115
const filterFn = (a: Account): boolean => {
116+
if (excludeLocalOnly && isAccountOnlyLocal(a)) {
117+
return false;
118+
}
106119
if (a.type === "clearing" && tags.length > 0 && a.tags) {
107120
for (const tag of tags) {
108121
if (!a.tags.includes(tag)) {
@@ -136,14 +149,18 @@ const selectSortedAccounts = createSelector(
136149

137150
export const useSortedAccounts = <T extends AccountType>(
138151
groupId: number,
139-
sortMode: AccountSortMode,
140-
type?: T,
141-
searchTerm?: string,
142-
wipAtTop?: boolean,
143-
tags: string[] = []
152+
config: {
153+
type?: T;
154+
sortMode: AccountSortMode;
155+
searchTerm?: string;
156+
wipAtTop?: boolean;
157+
excludeLocalOnly?: boolean;
158+
tags?: string[];
159+
}
144160
): T extends "personal" ? PersonalAccount[] : T extends "clearing" ? ClearingAccount[] : Account[] => {
161+
const { sortMode, type, searchTerm, wipAtTop, excludeLocalOnly = false, tags = [] } = config;
145162
return useSelector((state: IRootState) =>
146-
selectSortedAccounts(state, groupId, type, sortMode, searchTerm, wipAtTop, tags)
163+
selectSortedAccounts(state, groupId, type, sortMode, searchTerm, wipAtTop, tags, excludeLocalOnly)
147164
) as any;
148165
};
149166

0 commit comments

Comments
 (0)