13 Commits
Author SHA1 Message Date
tabedzkiandClaude Opus 5.5 c59c4979e0 [AI] docs: link experimental features to feedback issues, drop Discord (#9186)
Remove "or post a message in the Discord" from the shared
ExperimentalFeatureWarning so feedback goes to GitHub issues.

- Monte Carlo analysis docs now link to feedback issue #8571.
- Multi-currency docs use the shared warning component, linked to the
  rule action templating feedback issue (#3606).
- Budget Analysis toggle in Settings links to /issues/6742 instead of
  /pull/6742.

Assisted-by: ClaudeCode:claude-opus-5-5

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-11 21:43:28 +00:00
tabedzki ddee2cca98 [AI] fix: bump brace-expansion to resolve HIGH CVEs (#9179)
Refresh yarn.lock with `yarn up -R brace-expansion` so the 2.x range
(^2.0.1, ^2.0.2, pulled in via minimatch@5/9 and shipped in the
sync-server image through migrate) resolves to 2.1.7 instead of 2.0.3.
This clears CVE-2026-13149, CVE-2026-14257, CVE-2026-69152,
CVE-2026-102276 and CVE-2026-102278. The 5.x range moves from 5.0.5 to
5.0.12 as part of the same refresh; 1.x is already at the latest 1.1.21.

No resolutions override is needed; both versions are in range of the
existing specifiers. Fixes #9166.

Assisted-by: ClaudeCode:claude-opus-5-5
2026-10-11 20:27:29 +00:00
tabedzki aa5c8841c1 docs: add @tabedzki as a main contributor (#9183)
Add @tabedzki to the Main Contributors list in the contributing docs
and include an upcoming release note.

Assisted-by: ClaudeCode:claude-opus-5-5
2026-10-11 17:40:18 +00:00
tabedzkiandClaude Sonnet 4.6 30e671b3ec [AI] feat(budget analysis report): allow selecting future months in date range (#8722)
* [AI] feat(budget-report): allow selecting future months in date range

Extend the allMonths picker list 12 months past the current month so
users can select future months for long-term goal planning.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): preserve running balance for future months with no budget data

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): fix balance zeroing for future months with no budget data

Use monthBalance as the next month's running balance instead of
carryoverToNextMonth, which is 0 for months where no category has
any budget or spending data.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): fix import path in budget-analysis-spreadsheet test

* [AI] fix: added in release note

Assisted-by: ClaudeCode:claude-opus-5

* [AI] fix(budget-report): address CodeRabbit review findings

Addresses both review comments from CodeRabbit on PR #8722:

1. "Keep later-dated transaction months selectable" — the month-range
endpoint now takes the later of the latest transaction month and December
of next year, so existing future-dated transactions are no longer hidden
from the picker. This PR had replaced latestMonth with a hardcoded
December-of-next-year, which dropped transactions dated beyond it.

2. "Preserve the no-carryover reset when propagating balances" —
running-balance propagation goes back to carrying over only what actually
carries over, instead of the full month balance. Using monthBalance had
re-included negative balances for categories with carryover disabled, so
an overspend both dragged forward through later months and still surfaced
as an overspending adjustment. A month with no budget data at all now
passes the running balance through untouched, which fixes the original
future-month bug without defeating the carryover reset.

Extracts summarizeMonthCategories, getNextRunningBalance and
getLastSelectableMonth so this logic is unit-testable, and replaces the
self-referential range tests with ones that exercise the real functions.

Assisted-by: ClaudeCode:claude-opus-5

* [AI] test(budget-report): cover never-budgeted months in data detection

CodeRabbit's follow-up review on PR #8722 suggested setting hasBudgetData
from cell presence rather than cell value. That change would be wrong here:
envelope-budget-month builds its response by iterating the category list, so
it emits a cell for every category in every month and normalizes missing
sheet values to 0 (see loot-core/src/server/budget/app.ts). Cells are always
present, so presence-based detection would report every month as populated
and re-introduce the running-balance bug the previous commit fixed.

The zero-value case it worries about is not reachable in a way that changes
the result: leftover already folds in the previous month's balance, so a
month with a real balance carrying in always has a non-zero cell and is
detected correctly. When all three are zero there is nothing to carry, and
both detection strategies agree.

Adds a regression test pinning the never-budgeted month to
hasBudgetData=false, and documents why detection is value-based so the
suggestion is not re-applied later.

Assisted-by: ClaudeCode:claude-opus-5

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-08-16 20:36:11 +00:00
fe363a2643 [AI]: Replacing month picker with day picker (#8427)
* [AI] feat(reports): add browser-independent month range picker

Replace the report date dropdowns with a popover month range picker built
from React and Actual's own components instead of a native month input
(which does not work in Firefox). Includes start/end month grids,
quick-select presets folded into the popover, a draft selection that only
recomputes the report on close, today highlighting, and an unbounded future
range.

Assisted-by: ClaudeCode:claude-opus-4.8
Co-authored-by: rznn7 <[email protected]>

* [AI] refactor(desktop-client): replace pikaday with react-aria in DateSelect

Swap the Pikaday-based day picker in DateSelect for react-aria-components'
Calendar primitives (backed by @internationalized/date). The user's
firstDayOfWeekIdx preference is encoded via the Unicode 'fw' locale
extension, and the prev/next arrows now use the existing SvgCheveron
icons instead of the two bundled PNGs.

Removes the pikaday and @types/pikaday dependencies, deletes the unused
DateSelect.left/right.png assets, and adds @internationalized/date as a
direct dependency.

Assisted-by: ClaudeCode:claude-opus-4.8

* [AI] fix(desktop-client): resolve CI failures in month picker PR

Remove four devDependencies (@juggle/resize-observer, @types/lodash, @types/promise-retry, memoize-one) that were added but never used, fixing the knip check. Dedupe the split @codemirror/state and @codemirror/view resolutions that the added/removed deps introduced, fixing typecheck. Pin shell-quote (a transitive dependency of launch-editor/npm-run-all) to >=1.8.4 via resolutions, matching the existing socks/serialize-javascript overrides, to clear the critical CVE flagged by Dependency Review.

Assisted-by: ClaudeCode:claude-sonnet-5

* updated yarn.lock

* Updated yarn.lock to address dependency issue

* address more dependency issues

* `yarn up -R '**'` to hopefully address all dependency issues

* fixed donutgraph.tsx typing

* [AI] feat(reports): add Month/Day granularity toggle to range picker

Add a Month/Day toggle above the quick-select column in the report range
picker so users can pick exact days, not just whole months. Switching to Day
expands the range to cover whole days (start -> first of month, end -> last of
month); switching back collapses to months. In day mode the picker emits
yyyy-MM-dd start/end.

Make the month-based reports tolerate day-level values: month range helpers in
monthUtils already coerce day strings to months, and this replaces the few
fragile 'start + "-01"' concatenations (BalanceForecast, BalanceForecastCard,
BudgetAnalysis, balanceForecastChartData) with firstDayOfMonth/getMonth so a
yyyy-MM-dd value is normalized instead of corrupted.

Assisted-by: ClaudeCode:claude-opus-4.8

* [AI] feat(reports): honor day granularity, live end-offset, format-aware picker

Task 3: derive the range picker trigger's display format from the committed
value's shape (yyyy-MM-dd vs yyyy-MM) via a new valueIsDay() helper instead of
the granularity flag, so the label stays correct (day vs month) after the
popover closes.

Task 1: let a live/sliding range end before the current month.
getLatestRange(offset, endOffset=0) and calculateTimeRange's sliding-window
branch derives endOffset from the saved frame (clamped >= 0) so the window's
gap-from-now is preserved as months roll over. Surface it with an 'Exclude
current month' checkbox in the picker popover (shifts the whole range back one
month, keeping its width), enabled for past ranges only.

Task 2: add a maintainer-facing granularities prop on MonthRangePicker (threaded
through Header), defaulting to ['month','day']. Pass ['month'] to hide the Day
toggle on month-only reports; Budget Analysis is locked to month. AgeOfMoney's
granularity stays a distinct concept.

Add unit tests for getLatestRange/calculateTimeRange endOffset and the picker
util helpers. Use named imports throughout.

Assisted-by: ClaudeCode:claude-opus-4.8
Co-authored-by: rznn7 <[email protected]>

* [AI] feat(reports): single-calendar range picker, fix granularity reset on remount

Replaces the two side-by-side Start/End calendar grids in the reports date-range picker with a single calendar (RangeSelector) supporting click-to-pick range selection with a live hover preview, for both Month and Day granularity.

Also fixes the Month/Day toggle silently reverting after a pick: CashFlow, NetWorth, AgeOfMoney, and BalanceForecast unmount their Header/MonthRangePicker subtree on every date change (useReport nulls out data during refetch), which wiped the picker's internal granularity state. Lifted that state into each report so it survives the remount.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): persist sliding-window endOffset so live ranges actually slide forward

calculateTimeRange's sliding-window branch re-derived the gap between a saved end date and 'now' on every call, using the stale, decaying persisted end. Since most reports only rewrite that persisted end when the user explicitly saves the widget, the derived gap grew by however much time had passed since the last save — meaning a live range never actually advanced once its gap was nonzero; it stayed pinned to the last-saved dates indefinitely. Caught by useFormulaExecution.test.ts's 'shifts each formula report query window when the current month changes' test, which was failing on this branch.

Adds TimeFrame.endOffset, persisted explicitly alongside start/end/mode instead of re-derived from decaying absolute dates. getLatestRange and calculateTimeRange now return the resolved endOffset as a 4th tuple element; MonthRangePicker computes it at commit time and threads it through Header's onChangeDates into every report that persists a timeFrame (CashFlow, NetWorth, AgeOfMoney, BalanceForecast, Calendar, Sankey, Crossover, Summary, BudgetAnalysis). Legacy saved widgets without endOffset fall back to the old derivation once, as a migration.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): route day-grid clicks through pick directly

DayGrid's per-day onSelect was wired to selectMonth, a handler meant for
month-grid clicks and month-navigation day-carry-over. Fed a full day
string it built a malformed candidate (e.g. 2026-07-20-10) that never
string-matched the clicked day, so the range endpoint lost its selected
(primary) styling and only showed as part of the in-range band.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): keep day-mode range width when reopening picker

openPopover unconditionally expanded start/end to the full month via
toDayStart/toDayEnd whenever reopening in day mode, even when the range
was already day-shaped from a prior precise pick. Only expand when the
incoming value is still month-shaped (an actual month-to-day switch).

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): address code review findings on month/day range picker

Fix clamp() returning granularity-mismatched bounds when min/max are month-shaped but the picker is in day mode. Add accessible labels to NavRow's prev/next icon buttons. Deduplicate the Pie shape index coercion in DonutGraph into a shared helper. Drop the unnecessary useMemo around MonthRangePicker's label string.

Skipped: the Header.tsx allMonths[allMonths.length - 1] access can't crash since every caller already guards on allMonths being non-empty before rendering Header. The RangeEndSelector.tsx dead-code finding refers to a file that no longer exists in this codebase. The DateSelect.tsx firstDayOfWeek suggestion doesn't apply: react-aria-components' public CalendarGrid props don't expose firstDayOfWeek in the installed version, so the locale '-u-fw-' extension is still the only way to configure it.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): stop widening day-shaped bounds in balance forecast chart data

buildBalanceForecastChartData's Daily branch applied firstDayOfMonth/lastDayOfMonth to start/end unconditionally, which expanded an already day-shaped range (e.g. 2024-03-15) out to its whole month. Only expand when the bound is month-shaped (isValidYearMonth), otherwise use it as-is.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] fix(reports): address CodeRabbit findings on month/day range picker (round 2)

Header: fall back minDate to the current month when allMonths is still empty (Summary/Calendar render before their async load populates it). RangeSelector/DayGrid: normalize min/max to day granularity in DayGrid so a month-shaped bound doesn't disable every day in its own month. AgeOfMoney: derive the picker's initial Month/Day mode from the restored range's shape instead of hardcoding month, since that mode isn't persisted separately from timeFrame. BudgetAnalysis: normalize start/end to yyyy-MM inside calculateIsConcise so a legacy day-shaped persisted timeFrame can't corrupt the date-fns parse. DonutGraph: read props.index directly instead of coercing a second shape-callback argument. MonthRangePicker: use && short-circuit JSX per the style guide. AgeOfMoney: drop an unnecessary useCallback with no deps, matching sibling reports. DayGrid/RangeSelector/MonthRangePicker/Header: thread firstDayOfWeekIdx through so the day grid's weekday header and alignment follow the user's configured first day of week instead of hardcoding Sunday-first.

Skipped: the Crossover.tsx 'double shift' finding — the extra -1 month shift is pre-existing, documented, intentional business logic (excludes the current month), applied symmetrically on both load and onChangeDates regardless of whether endOffset was legacy-derived or explicitly persisted; the suggested fix wouldn't touch that code path anyway.

Assisted-by: ClaudeCode:claude-sonnet-5

* Update category and authors in release notes

Address technical debt by introducing a day picker for the calendar.

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* [AI] Address review feedback on month/day range picker and DateSelect

- Crossover: treat legacy widgets' missing endOffset as 0 (no double shift)
- Only offer "Exclude current month" in month mode for ranges ending at the
  current or previous month
- Cap past-oriented reports at the newest month; future stays for forecasts
- Don't commit on Month/Day switch so the popover survives report reloads
- Month-only picker for Calendar, Summary, Sankey and Crossover
- Transaction date picker: visible month-nav arrows that keep focus in the
  input, normal-sized heading, square day cells, tighter popover
- Give unselected grid cells a transparent border so selecting doesn't
  resize the grid
- Derive picker granularity from the committed value shape and drop the
  lifted per-report state and Header props
- Simplify per review: reuse ModeButton/monthUtils/Calendar firstDayOfWeek,
  remove allowFuture, add useLanguage, fix double render on keystroke,
  strip prose comments
- Restore master's yarn.lock (only the pikaday removal remains), drop the
  shell-quote resolution, revert unrelated DonutGraph change
- Release note: describe the feature, add MatissJanis to authors

Co-Authored-By: Claude Fable 5 <[email protected]>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* [AI] Cap day-mode picking at today and clamp exclude-toggle shifts

- A month-shaped max that reaches the current month no longer widens to the
  month's last day in day mode; day cells after today are disabled and the
  Month->Day draft widening clamps its end to today
- DayGrid and clamp() keep already day-shaped bounds exact instead of
  widening them back to whole months
- toggleExcludeCurrentMonth clamps the shifted range to minDate/maxDate like
  every other draft mutation
- granFor: function declaration per code style

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Use one SpaceBetween for consistent report header spacing

The header row was two SpaceBetween groups (gap 15 and gap 3) with no gap
between them, and reports wrapped their own controls in ad-hoc gap-10 Views.
Merge the mode toggle, date picker, filter button and report controls into a
single SpaceBetween, render header children through one too, and drop the
per-report wrappers (Balance Forecast, Cash Flow, Budget Analysis, Sankey).

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Drop endOffset; sliding windows always anchor to the current month

Remove the persisted TimeFrame.endOffset and its wiring through
reportRanges, the range picker, Header and all report pages. A live
(sliding-window) range now always ends at the current month; "Exclude
current month" still shifts the draft range and commits it as static.

Also address code review findings: guard the "All time" preset while
allMonths is still loading, remount the range selector on granularity
switch so a month-shaped click-anchor can't produce a mixed-shape range,
only offer the exclude toggle when both of its states fit the configured
bounds, and give the month/day grid cells full localized accessible
names and a pressed state.

Co-Authored-By: Claude Fable 5 <[email protected]>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* [AI] Remove the "Exclude current month" checkbox

Its only unique capability was creating a live range ending last month via
endOffset, which is gone; picking the end month in the grid now does the
same thing. Deletes the toggle component, the allowExcludeCurrentMonth
prop and Header wiring, and the now-unused shiftMonths util.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Simplify month-range picker after cleanup review

Drop the util.ts aliases of shared months.ts helpers, derive picker
granularity from the draft value's shape instead of separate state,
normalize min/max bounds once in MonthRangePicker, inline the Header
preset builders, and make month-only the default granularity with
day-capable reports opting in explicitly.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Rebuild day-mode picking on react-aria RangeCalendar

Replace the hand-rolled DayGrid with react-aria's RangeCalendar, which
adds keyboard navigation and built-in hover range preview, and use
month/year dropdowns (CalendarMonthPicker plus a bounds-based year
select) in the calendar header for quick jumping. The month grid stays
custom since react-aria has no month-granularity range picker.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Address review feedback and fix picker styling glitches

Validate the full yyyy-MM-dd shape in valueIsDay instead of negating
the year-month check, cap the year dropdown when the report has no
upper date bound (the far-future sentinel would render ~8000 options),
use the bare-button hover color so hovered dates and month/year
selects stay readable, and stretch the day grid to the calendar's
full width.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Simplify month-range picker after cleanup review

- YearSelect reads bounds from RangeCalendarStateContext instead of props
- Dedupe first-day-of-week pref decoding into getFirstDayOfWeek in DateSelect
- Hoist the day-calendar emotion css() call to module scope
- RangeSelector tracks viewYear directly instead of a month it only read the year from
- Inline the single-consumer Grid component into MonthGrid

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Let live report ranges slide by days for day-shaped windows

Day-shaped sliding-window ranges now keep their width in days and
re-anchor to today, so Live works with day granularity in reports.
Formula queries stay month-granular via asMonthSlidingTimeFrame.

Co-Authored-By: Claude Fable 5 <[email protected]>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* [AI] Move the date range picker into the component library

Extract the reports MonthRangePicker into @actual-app/components as
DateRangePicker: translated strings arrive via a labels prop, date
formatting runs on Intl.DateTimeFormat with a BCP 47 locale string
instead of loot-core's date-fns wrappers, and the first-day-of-week
pref is resolved by the caller. Header.tsx supplies all of these; the
component library gains @internationalized/date and subpath import
mappings for the picker's internals.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Add VRT for the reports date range picker

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Add VRT snapshots for the reports date range picker

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Clean up the date range picker after review

- Move ModeButton into the component library and reuse it for the
  granularity toggle instead of a near-identical SegmentButton copy
- Move the day-shaped value check into loot-core as isValidYearMonthDay
  so reportRanges no longer imports it through the picker component
- Cache Intl.DateTimeFormat instances in formatDate
- Build lastDayOfMonth/currentDay on @internationalized/date
- Pass label subsets as one labels object instead of scalar props

Co-Authored-By: Claude Fable 5 <[email protected]>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* [AI] Revert "Update VRT screenshots"

This reverts commit 8cd01e5148.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Hoist DateRangePicker to src root, add ModeButton story, respect app date format

- Move DateRangePicker.tsx and its stories out of the date-range-picker/
  folder so the story sorts alphabetically in the Storybook sidenav; only
  child components remain in the folder.
- Add a Storybook file for ModeButton.
- Add an optional formatDayLabel prop so day-shaped trigger labels can
  follow the app's date format preference; reports Header now passes the
  dateFormat synced pref instead of falling back to locale-numeric dates.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Address review feedback on the date range picker

- Bound scheduled-occurrence counts to the visible chart range so day-mode
  ranges don't count occurrences outside the selected days
- Carry the running balance forward from points before a day-shaped start
  instead of starting the daily chart at zero
- Drop the day granularity from the tracking-budget forecast header, which
  only resolves monthly
- Validate the day against the month and year (incl. leap years) in
  isValidYearMonthDay
- Target the date range picker trigger by test id in the reports e2e test
- Drop a redundant useMemo in useLocale (React Compiler memoizes)

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Keep the date range picker open when a quick-select preset is clicked

Presets now preview their range in the open picker draft, like manual
selection, and commit on close so live-range modes are preserved.

Co-Authored-By: Claude Fable 5 <[email protected]>

* [AI] Improve date range picker colors and highlight the active preset

Style the calendar header dropdown options so they stay readable in dark
themes, introduce a datePickerRangeBackground theme variable so the light
theme's range band is purple like the other themes, and derive the active
quick-select preset from the current range so it stays highlighted when
reopening.

Co-Authored-By: Claude Fable 5 <[email protected]>

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #8427

---------

Co-authored-by: rznn7 <[email protected]>
Co-authored-by: rznn7 <[email protected]>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <[email protected]>
Co-authored-by: Claude Fable 5 <[email protected]>
2026-07-18 16:49:07 +00:00
tabedzki 1dbe1b78a1 [AI] Add tooltips to titlebar theme, privacy, and server status icons (#8440)
* [AI] Add tooltips to titlebar theme, privacy, and server status icons

Explain what the theme switcher, amount-visibility toggle, and server sync/status indicators do on hover, including what having a server connected means when none is configured yet.

Assisted-by: ClaudeCode:claude-sonnet-5

* [AI] Merge duplicate server status branching in LoggedInUser

Combine serverMessage() and serverTooltip() into a single getServerStatus() resolver so the button label and tooltip stay in sync as server states change.

Assisted-by: ClaudeCode:claude-sonnet-5

* Add in requested line break
2026-07-15 13:53:16 +00:00
6519bbecb6 [AI] feat(budget analysis report): export csv feature (#8163)
* [AI] feat(budget-report): add CSV export for budget analysis report

Add an 'Export CSV' button that downloads a CSV file containing Month,
Budgeted, Spent, Overspending Adjustment, and Balance columns for the
currently displayed date range.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] feat(budget-report): replace CSV export button with download icon

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] refactor(csv-export): centralize CSV utility to loot-core with formula injection protection

Extracts CSV field escaping and row building into a shared
loot-core/shared/csv.ts module so desktop-client and cli packages can
reuse it without duplication. Adds single-quote prefix guard against
spreadsheet formula injection for values starting with =, +, -, @, tab,
or carriage-return.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(csv-export): fix loot-core import path and remove over-broad formula injection protection for negative numbers

* fix: added in release note

* Update packages/desktop-client/src/components/reports/reports/BudgetAnalysis.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update BudgetAnalysis.tsx

removed extra </Tooltip> introduced by coderabbitai

* fix: applied coderabbitai's suggestions for this PR

* [autofix.ci] apply automated fixes

* [AI] fix: resolve typecheck errors and test failures in csv export

- Make labels param optional with English defaults in buildBudgetAnalysisCsv
- Pass translated labels from BudgetAnalysis component call site
- Fix escapeCsvField: remove tab from quote-wrapping check (formula prefix handles it)

Assisted-by: ClaudeCode:claude-sonnet-4-6

* [AI] refactor(budget-analysis-export): use csv-stringify, move labels inside buildBudgetAnalysisCsv

- Replace custom buildCsv with csv-stringify/sync (already used in loot-core)
- Move translated column labels inside buildBudgetAnalysisCsv; callers no longer pass labels
- Pass numbers directly to csv-stringify instead of converting with toFixed(2)
- Add csv-stringify to desktop-client package.json deps
- Fix release notes title to user-facing prose

Assisted-by: ClaudeCode:claude-sonnet-4-6

* [AI] fix: remove orphaned csv.ts, fix release note wording

- Delete loot-core/src/shared/csv.ts and csv.test.ts (orphaned after switch to csv-stringify)
- Remove [AI] prefix from release note body (commit-style prefix inappropriate in release note content)

Assisted-by: ClaudeCode:claude-sonnet-4-6

* [AI] fix: add csv-stringify to yarn.lock to fix immutable install

The rebase onto main reset yarn.lock without the csv-stringify entry under the @actual-app/web workspace, while package.json still declared it. CI runs yarn install --immutable, which refused to reconcile the mismatch and failed the build.

Assisted-by: ClaudeCode:claude-opus-4.8

* attempt to resolve the hanging error

* [AI] fix: restore Tooltip import dropped during rebase

Resolving the import-collision conflict against master accidentally dropped
the Tooltip import used by the CSV export button. Restore it.

Assisted-by: ClaudeCode:claude-opus-4.8

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-06 20:19:20 +00:00
tabedzkiandClaude Sonnet 4.6 644256ddc1 [AI] feat(budget analysis report): show hidden categories (#8164)
* [AI] feat(budget-report): add toggle to include hidden categories

Add a 'Show hidden categories' button that includes hidden expense
categories in the Budget Analysis report. This prevents historic data
from being misrepresented when a category (e.g. a car fund) is hidden.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] feat(budget-report): replace hidden categories button with icon toggle

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-analysis): use correct package alias in test import

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* fix: added in release note

* [AI] refactor(budget-analysis): extract isBaseCategory helper and reuse in tests

Assisted-by: ClaudeCode:claude-sonnet-4-6

* [AI] feat(budget-report): clarify hidden categories toggle state

Replace the ambiguous icon-only toggle with a highlighted active state
and explicit click-to-show/hide tooltip text so the current selection is
clear. Add aria-pressed for accessibility.

Assisted-by: ClaudeCode:claude-opus-4.8

* [AI] feat(budget-report): consolidate chart options into Options dropdown menu

Replace the separate chart-type icon toggle, balance/category Select dropdown,
and hidden-categories eye icon with a single Options popover (Popover + Menu)
matching the pattern used by other reports (Sankey). The menu contains:
- Switch to line/bar chart
- Show balance (toggle)
- Show categories (toggle, replaces balanceOnly)
- Show hidden categories (toggle)

Also rebases onto upstream/master to incorporate the balanceOnly/Select
changes from #8162 before consolidating them.

Assisted-by: ClaudeCode:claude-sonnet-4-6

* [AI] fix(budget-report): use static 'Bar chart' toggle in Options menu for i18n

Replace the dynamic 'Switch to line/bar chart' string with a static
'Bar chart' label and a boolean toggle (on = bar, off = line), matching
the toggle pattern used by other menu items and making the string
straightforward to translate.

Assisted-by: ClaudeCode:claude-sonnet-4-6

* Enhance budget analysis report with dropdown options

Introduced a dropdown to group options and added the ability to show hidden categories in the budget analysis report.

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-06-25 20:12:36 +00:00
tabedzkiandClaude Sonnet 4.6 37ac0adea0 [AI] feat(budget analysis report): Add Balance & Category selector (#8162)
* [AI] feat(budget-report): add balance-only view mode

Add a 'Balance only' toggle to the Budget Analysis report that hides the
Budgeted, Spent, and Overspending Adjustment series and renders the balance
as a plain line chart, similar to the Net Worth graph.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): always display ending balance for consistent header spacing

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] feat(budget-report): replace balance toggle buttons with series dropdown

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): capitalize Categories in balance mode dropdown

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* [AI] fix(budget-report): fix test imports and lint errors in BudgetAnalysisGraph test

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>

* fix: added in release note

---------

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-06-23 18:40:57 +00:00
446fde6cd9 Add Category Group filtering in Budget Analysis Report (#7116)
* feat: add FilterInclude to match FilterExclude

* feat: enhance category filtering to support category groups in budget analysis

* add release notes

* fix: applied corabbit's suggestion

* applied coderabbit's fixes

* removed duped code

* applied more coderabbit comments

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes

* fix: include docs about include parameter

* fix: contains and matches now properly filter category names instead of UUID

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: youngcw <[email protected]>
2026-04-08 14:34:26 +00:00
tabedzki 738a8cda7c Fix date range calculation in BudgetAnalysisCard (#6875)
* fix: corrected date range calculation in BudgetAnalysisCard using calculateTimeRange

* add release note

* fix: ensure correct date formatting in BudgetAnalysisCard for start and end dates

* fix: rename release note file
2026-02-06 15:58:31 +00:00
e4903ca6e3 Feat/add-budget-analysis-report (#6137)
* Add Budget Analysis report with full implementation

Co-authored-by: tabedzki <[email protected]>

* Add preset time ranges, intervals, bar chart, hide balance, and display controls

Co-authored-by: tabedzki <[email protected]>

* Fix duplicate function declaration syntax error in budget-analysis-spreadsheet.ts

Co-authored-by: tabedzki <[email protected]>

* Fix floating point precision error in daily/weekly intervals and replace interval button with dropdown

Co-authored-by: tabedzki <[email protected]>

* Make card always display monthly data and match report's chart type

Co-authored-by: tabedzki <[email protected]>

* fix: adjust widget placement and presentation

* fix: adjusted the dot presentation

* feat: added svg for line chart/barchart

* fix: added one month to the report

* added the upcoming release notes

* amended the upcoming release notes

* fix: removed unused variables

* formatted using prettier --write

* [autofix.ci] apply automated fixes

* feat: added new feature to the Reports Page in the test budget

* fix: amended the reports.test.ts file to expect Budget Analysis

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* revert: removed the inclusion of the Budget Analysis tool from the test file

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* fix: changed the display to always be monthly since budgets are monthly; removed the 1month view

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* fix: removed comment

* feat: added experimental feature flag for Budget Analysis tool

* feat: Switched option to use SVG Icons instead of words to shorten horizontal layout

* Removed interval possibilities and removed unnecessary compact variable as indicated by CodeRabbit

* Update packages/desktop-client/src/components/reports/reports/BudgetAnalysisCard.tsx

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Added basic documentation for Budget Analysis Report

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* fix: added budget-analysis doc to sidebar

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* feat(reports): improve Budget Analysis report UI and behavior

- Update chart colors to match Cash Flow report style
  (Budgeted: blue, Balance: pageTextLight)
- Remove legend items from report view for cleaner UI
- Add 1 month quick select option to header
- Pass isConcise prop to BudgetAnalysisGraph for proper date formatting
- Add dynamic daily/monthly interval switching based on date range

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* feat(reports): refactor BudgetAnalysisGraph and improve isConcise calculation according to Rabbit AI

* feat(reports): add translation support for Budget Analysis graph labels

* feat(reports): centralize translation for Budget Analysis graph labels

* feat: use the budget values directly from the budget spreadsheet/server

* feat: enhance budget analysis with overspending adjustments and detailed reporting

* style: format code for better readability in BudgetAnalysis and budget-analysis-spreadsheet components

* refactor: remove unused variables

* docs: added in the image to the docs

* fix: reimplement support for conditionsOp

* [autofix.ci] apply automated fixes

* style: simplify budget analysis labels for clarity

* fix: add the on copy function

* feat: tooltip improvements

* feat: enhance budget analysis to track overspending adjustments across months

* fix: removed the absolute value for spent

* feat: update the charts to look closer to the CashFlow report

* fix: correct financial formatting for totalSpent in BudgetAnalysis

* feat: add filterExclude prop to Header and BudgetAnalysis for improved filtering options

* feat: implement privacy mode for Y-axis values in BudgetAnalysisGraph

* feat: change default graph type to Bar in BudgetAnalysis

* feat: remove commented-out filter button code in Header component

* feat: remove commented-out code for filter exclusion in Header component

* fix: update the feedback link to the dedicated issue

* refactor: financial display components to use FinancialText for consistency in Budget Analysis reports

* fix: update the card to also start as bar graph

* docs: update Budget Analysis report to include category filtering information

* style: refactor imports and whitespace

* refactor: simplify inline content structure in BudgetAnalysis component

* [autofix.ci] apply automated fixes

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* fix: removed color descriptors from the chart

* fix: update color themes for Budget Analysis to use custom theme definitions

* [autofix.ci] apply automated fixes

* feat: update Budget Analysis merge md file

* Update VRT screenshots

Auto-generated by VRT workflow

PR: #6137

* fix: update budget analysis report image

* fix: white space adjustment in descriptor

* [autofix.ci] apply automated fixes

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: youngcw <[email protected]>
2026-01-24 20:00:10 +00:00
tabedzki e31ac3fa7c Update Feedback Link for Experimental CrossoverReport (#6148) 2025-11-15 16:23:02 +00:00