Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,28 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
- Shared expenses are now grouped by month (collapsible, newest first)
with a filter panel (note search, status, date range), instead of one
long flat list.
- Follow-up polish from live-testing the modal and mobile scroll fixes
above:
- The shared `FilterRow`/`FilterInlineRow` components (used by every
Outflows/Incomes/Shared-Expenses filter panel) weren't receiving the
`theme` prop they need to color their own note/date `<input>`s and any
nested `<select>` - rendering as plain unthemed white boxes with
unreadable white-on-white text in dark mode. Fixed everywhere this
pattern was used.
- The transaction-edit modal's category/typology/amount/note/date/
purpose fields still used the old inline-edit styling (a permanent
blue-tinted border, meant to flag "you're editing this" in a dense
list row) - visually inconsistent now that they live in a modal, which
already signals that. Switched them to the same neutral field style
used by the rest of the app's modals and forms.
- Removed the redundant "Annulla modifica" button from the edit modal's
footer - the header's ✕ already closes/cancels it.
- `insert-values`' content area was capped at 1100px, leaving large
unused margins on wide screens and forcing the transaction table to
horizontally scroll even when the window had room to spare. Widened it
to 1400px (matching the width already used on Comparison/Knowledge)
and let the table fill its container instead of capping at 1200px on
its own.

### Added
- Recurring transaction templates (subscriptions, rent, salary) can now pick
Expand Down
17 changes: 0 additions & 17 deletions src/components/transactionList/TransactionListStyles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,20 +310,3 @@ export const ActionBtn = styled.button`
}
`;

export const InlineInput = styled.input`
width: 100%;
min-width: 50px;
padding: 4px 6px;
border: 1.5px solid ${p => p.theme.mode === 'dark' ? 'rgba(59,130,246,0.4)' : 'rgba(59,130,246,0.3)'};
border-radius: 6px;
font-size: 0.82rem;
background: ${p => p.theme.mode === 'dark' ? 'rgba(255,255,255,0.06)' : '#f8fafc'};
color: ${p => p.theme.textColor};
box-sizing: border-box;
outline: none;
font-family: inherit;
&:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 2px rgba(59,130,246,0.15);
}
`;
29 changes: 10 additions & 19 deletions src/sections/IncomeSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { createPortal } from 'react-dom';
import { Select, MenuItem } from '@mui/material';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTimes, faCalendarAlt, faPen, faCheck, faRotateLeft, faSortUp, faSortDown, faSort, faLayerGroup, faTableCells, faThLarge, faFilter, faHandHoldingDollar } from '@fortawesome/free-solid-svg-icons';
import { faTimes, faCalendarAlt, faPen, faCheck, faSortUp, faSortDown, faSort, faLayerGroup, faTableCells, faThLarge, faFilter, faHandHoldingDollar } from '@fortawesome/free-solid-svg-icons';
import { LanguageContext } from '../contexts/LanguageContext';
import { CurrencyContext } from '../contexts/CurrencyContext';
import { translateTag } from '../data/tagTranslations';
Expand All @@ -24,7 +24,7 @@ import {
ViewSwitch, ViewButton, TableScroll, CardViewWrap,
FilterToggleRow, FilterBadge, FilterPanel, FilterRow, FilterLabel, FilterInlineRow, ClearFiltersBtn,
CardList, TxCard, CardTopRow, CardCategory, CardAmount, CardMetaRow, CardNote, CardActionsRow,
TotalCard, ActionBtn, InlineInput,
TotalCard, ActionBtn,
} from '../components/transactionList/TransactionListStyles';
import {
Overlay, ModalContainer, ModalHeader, ModalTitle, CloseButton, ModalBody, ModalFooter, SubmitButton,
Expand Down Expand Up @@ -584,7 +584,7 @@ export default function IncomeSection({
<FormField>
<FieldLabel theme={theme}>{translations.insert.incomeSection.tableColumns?.value || translations.general.amount}</FieldLabel>
<div style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
<InlineInput
<FieldInput
type="text"
theme={theme}
value={editValues.amount}
Expand All @@ -595,7 +595,7 @@ export default function IncomeSection({
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.insert.incomeSection.tableColumns?.note || 'Note'}</FieldLabel>
<InlineInput
<FieldInput
type="text"
theme={theme}
value={editValues.note}
Expand All @@ -606,7 +606,7 @@ export default function IncomeSection({
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.insert.incomeSection.tableColumns?.date || translations.general.date}</FieldLabel>
<InlineInput
<FieldInput
type="date"
theme={theme}
value={editValues.date}
Expand All @@ -615,16 +615,7 @@ export default function IncomeSection({
/>
</FormField>
</ModalBody>
<ModalFooter theme={theme}>
<ActionBtn
className="cancel"
onClick={handleCancelInline}
disabled={isSaving}
title={translations.insert.incomeSection.cancelEdit}
>
<FontAwesomeIcon icon={faRotateLeft} />
{translations.insert.incomeSection.cancelEdit}
</ActionBtn>
<ModalFooter theme={theme} style={{ justifyContent: 'flex-end' }}>
<SubmitButton theme={theme} onClick={handleSaveInline} disabled={isSaving}>
<FontAwesomeIcon icon={faCheck} />
{translations.insert.incomeSection.editButton}
Expand Down Expand Up @@ -1200,7 +1191,7 @@ export default function IncomeSection({
<FontAwesomeIcon icon={showMobileFilters ? faSortUp : faSortDown} />
</FilterToggleRow>
<FilterPanel theme={theme} $open={showMobileFilters}>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.insert.incomeSection.tableColumns.category}</FilterLabel>
<ThemedSelect
value={incomeCategoryFilter}
Expand All @@ -1211,7 +1202,7 @@ export default function IncomeSection({
{renderCategoryFilterOptions(incomesTags)}
</ThemedSelect>
</FilterRow>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.insert.incomeSection.tableColumns.note}</FilterLabel>
<input
type="text"
Expand All @@ -1221,9 +1212,9 @@ export default function IncomeSection({
style={{ width: '100%', boxSizing: 'border-box' }}
/>
</FilterRow>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.general.date || 'Data'}</FilterLabel>
<FilterInlineRow>
<FilterInlineRow theme={theme}>
<input
type="date"
value={incomeDateFilterStart || ''}
Expand Down
7 changes: 6 additions & 1 deletion src/sections/InsertValues.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ const PageContainer = styled.div`
`;

const ContentWrapper = styled.div`
max-width: 1100px;
/* Wide enough that the transaction table (which can have 6+ columns) gets
real room on a desktop monitor instead of being squeezed into a 1100px
column and forced to horizontally scroll even when the browser window
has plenty of unused space either side - matches the wider content
width already used by other data-dense pages (Comparison, Knowledge). */
max-width: 1400px;
margin: 0 auto;
width: 100%;
`;
Expand Down
89 changes: 32 additions & 57 deletions src/sections/OutflowSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
faCalendarAlt,
faPen,
faCheck,
faRotateLeft,
faSortUp,
faSortDown,
faSort,
Expand Down Expand Up @@ -43,7 +42,7 @@ import {
ViewSwitch, ViewButton, TableScroll, CardViewWrap,
FilterToggleRow, FilterBadge, FilterPanel, FilterRow, FilterLabel, FilterInlineRow, ClearFiltersBtn,
CardList, TxCard, CardTopRow, CardCategory, CardAmount, CardMetaRow, CardNote, CardActionsRow,
TotalCard, ActionBtn, InlineInput,
TotalCard, ActionBtn,
} from '../components/transactionList/TransactionListStyles';
import {
Overlay, ModalContainer, ModalHeader, ModalTitle, CloseButton, ModalBody, ModalFooter, SubmitButton,
Expand Down Expand Up @@ -693,26 +692,6 @@ const EmptyChart = styled.div`



const InlineSelect = styled.select`
width: 100%;
min-width: 80px;
padding: 4px 6px;
border: 1.5px solid ${p => p.theme.mode === 'dark' ? 'rgba(59,130,246,0.4)' : 'rgba(59,130,246,0.3)'};
border-radius: 6px;
font-size: 0.82rem;
background: ${p => p.theme.mode === 'dark' ? 'rgba(255,255,255,0.06)' : '#f8fafc'};
color: ${p => p.theme.textColor};
box-sizing: border-box;
outline: none;
cursor: pointer;
font-family: inherit;

option {
background: ${p => p.theme.mode === 'dark' ? '#1e293b' : '#ffffff'};
color: ${p => p.theme.mode === 'dark' ? '#e2e8f0' : '#1e293b'};
}
`;

const TotalRow = styled.tr`
font-weight: 700;
td { text-align: center; }
Expand Down Expand Up @@ -990,17 +969,17 @@ export default function OutflowSection({
{editValues.sharedEnabled && (
<>
<div className="shared-fields">
<InlineSelect theme={theme} value={editValues.sharedMethod}
<ThemedSelect compact value={editValues.sharedMethod}
onChange={(e) => setEditValues(prev => ({...prev, sharedMethod: e.target.value}))}>
<option value="people">{translations.insert.sharedTransactionLink.splitByPeople}</option>
<option value="share">{translations.insert.sharedTransactionLink.specifyShare}</option>
</InlineSelect>
</ThemedSelect>
{editValues.sharedMethod === 'people' ? (
<InlineInput type="number" theme={theme} min="2" step="1" value={editValues.sharedPeopleCount}
<FieldInput type="number" theme={theme} min="2" step="1" value={editValues.sharedPeopleCount}
onChange={(e) => setEditValues(prev => ({...prev, sharedPeopleCount: e.target.value}))}
aria-label={translations.insert.outflowSection.sharedExpense?.peopleLabel} />
) : (
<InlineInput type="number" theme={theme} min="0" step="0.01" value={editValues.sharedOwnShare}
<FieldInput type="number" theme={theme} min="0" step="0.01" value={editValues.sharedOwnShare}
onChange={(e) => setEditValues(prev => ({...prev, sharedOwnShare: e.target.value}))}
aria-label={translations.insert.sharedTransactionLink.ownShare} />
)}
Expand Down Expand Up @@ -1058,35 +1037,37 @@ export default function OutflowSection({
{(translations.insert.outflowSection.splitRemainderHint || '{amount} left over, paid from:')
.replace('{amount}', `${formatNumber(fromEUR(remainderAmount))}${currencySymbol}`)}
</span>
<InlineSelect
theme={theme}
<ThemedSelect
compact
value={fallbackLabel}
onChange={(e) => setEditValues(prev => ({ ...prev, splitFallbackLabel: e.target.value }))}
>
<option value="">{translations.general.selectAnOption || 'Select...'}</option>
{Object.keys(balanceOptions || {})
.filter((label) => label !== editValues.balanceSourceLabel)
.map((label) => <option key={label} value={label}>{label}</option>)}
</InlineSelect>
</ThemedSelect>
</SplitHintRow>
);
};

const renderPurposeSelect = () => {
const purposeTranslations = translations.transactionPurpose;
return (
<InlineSelect
theme={theme}
<Select
value={editValues.purpose || 'expense'}
onChange={(event) => setEditValues(prev => ({...prev, purpose: event.target.value}))}
disabled={isSaving || editValues.sharedEnabled}
aria-label={purposeTranslations.label}
title={purposeTranslations.label}
fullWidth
size="small"
sx={selectSx}
MenuProps={getMuiSelectMenuProps(theme)}
>
{['expense', 'investment', 'transfer', 'debt', 'tax', 'other'].map((purpose) => (
<option key={purpose} value={purpose}>{purposeTranslations[purpose]}</option>
<MenuItem key={purpose} value={purpose}>{purposeTranslations[purpose]}</MenuItem>
))}
</InlineSelect>
</Select>
);
};

Expand Down Expand Up @@ -1133,17 +1114,20 @@ export default function OutflowSection({
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.general.typology}</FieldLabel>
<InlineSelect
theme={theme}
<Select
value={editValues.typologyKey}
onChange={(e) => setEditValues(prev => ({ ...prev, typologyKey: Number(e.target.value) }))}
fullWidth
size="small"
sx={selectSx}
MenuProps={getMuiSelectMenuProps(theme)}
>
{sortTagsByLanguage(paymentTags, language, 'payment').filter(item => item.label !== 'none').map((item) => (
<option key={item.index} value={item.index}>
<MenuItem key={item.index} value={item.index}>
{translateTag(item.label, language, 'payment')}
</option>
</MenuItem>
))}
</InlineSelect>
</Select>
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.insert.outflowSection.tableColumns?.paymentMethod || translations.general.selectAnOption}</FieldLabel>
Expand All @@ -1166,7 +1150,7 @@ export default function OutflowSection({
<FormField>
<FieldLabel theme={theme}>{translations.insert.outflowSection.tableColumns?.value || translations.general.amount}</FieldLabel>
<div style={{ position: 'relative', width: '100%', minWidth: 0 }}>
<InlineInput
<FieldInput
type="text"
theme={theme}
value={editValues.amount}
Expand All @@ -1178,7 +1162,7 @@ export default function OutflowSection({
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.insert.outflowSection.tableColumns?.note || 'Note'}</FieldLabel>
<InlineInput
<FieldInput
type="text"
theme={theme}
value={editValues.note}
Expand All @@ -1189,7 +1173,7 @@ export default function OutflowSection({
</FormField>
<FormField>
<FieldLabel theme={theme}>{translations.insert.outflowSection.tableColumns?.date || translations.general.date}</FieldLabel>
<InlineInput
<FieldInput
type="date"
theme={theme}
value={editValues.date}
Expand All @@ -1203,16 +1187,7 @@ export default function OutflowSection({
{renderPurposeSelect()}
</FormField>
</ModalBody>
<ModalFooter theme={theme}>
<ActionBtn
className="cancel"
onClick={handleCancelInline}
disabled={isSaving}
title={translations.insert.outflowSection.cancelEdit}
>
<FontAwesomeIcon icon={faRotateLeft} />
{translations.insert.outflowSection.cancelEdit}
</ActionBtn>
<ModalFooter theme={theme} style={{ justifyContent: 'flex-end' }}>
<SubmitButton theme={theme} onClick={handleSaveInline} disabled={isSaving}>
<FontAwesomeIcon icon={faCheck} />
{translations.insert.outflowSection.editButton}
Expand Down Expand Up @@ -2243,7 +2218,7 @@ export default function OutflowSection({
<FontAwesomeIcon icon={showMobileFilters ? faSortUp : faSortDown} />
</FilterToggleRow>
<FilterPanel theme={theme} $open={showMobileFilters}>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.insert.outflowSection.tableColumns.category}</FilterLabel>
<ThemedSelect
value={outflowCategoryFilter}
Expand All @@ -2258,7 +2233,7 @@ export default function OutflowSection({
))}
</ThemedSelect>
</FilterRow>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.insert.outflowSection.tableColumns.typology}</FilterLabel>
<ThemedSelect
value={outflowTypologyFilter}
Expand All @@ -2275,7 +2250,7 @@ export default function OutflowSection({
)}
</ThemedSelect>
</FilterRow>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.insert.outflowSection.tableColumns.note}</FilterLabel>
<input
type="text"
Expand All @@ -2285,9 +2260,9 @@ export default function OutflowSection({
style={{ width: '100%', boxSizing: 'border-box' }}
/>
</FilterRow>
<FilterRow>
<FilterRow theme={theme}>
<FilterLabel theme={theme}>{translations.general.date || 'Data'}</FilterLabel>
<FilterInlineRow>
<FilterInlineRow theme={theme}>
<input
type="date"
value={outflowDateFilterStart || ''}
Expand Down
Loading
Loading