Skip to content

v0.4.0 - view mode fixes#69

Merged
kryptodrex merged 7 commits intodevelopfrom
v.0.4.0
Mar 23, 2026
Merged

v0.4.0 - view mode fixes#69
kryptodrex merged 7 commits intodevelopfrom
v.0.4.0

Conversation

@kryptodrex
Copy link
Copy Markdown
Owner

No description provided.

Introduce per-plan view mode favorites and a dedicated ViewModeSettingsModal to manage them. ViewModeSelector now accepts a plan-provided favorites prop (no longer reads global FileStorage or listens for global favorites events) and only auto-inserts cadence when appropriate. Move viewModeFavorites into BudgetSettings (removed from app-wide settings UI and types), add syncFavoritesForCadence to keep favorites in sync when pay frequency changes, and trigger a viewModeAutoSwitched event when cadence forces a displayMode change. PlanDashboard updated to use plan-specific favorites, show the new modal, and handle favorite updates. Search entries/actions updated to open the new view-mode settings modal. Misc: minor CSS tweak for selector border, tests adjusted/added for favorites sync and search behavior, and cleanup of app-level favorites handling in SettingsModal and FileStorageService.
Copilot AI review requested due to automatic review settings March 23, 2026 00:26
@github-actions
Copy link
Copy Markdown

Version File Not Updated

The version file was not modified in this PR. Please update the version file in the root directory with the new version number.

@kryptodrex kryptodrex merged commit 9b1fff3 into develop Mar 23, 2026
3 of 5 checks passed
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes and refactors “view mode” behavior by moving favorites to be plan-specific, adding a dedicated View Mode Settings modal, and syncing favorites/display mode when pay cadence changes.

Changes:

  • Introduces plan-specific view mode favorites (moved from AppSettings to BudgetSettings) and adds a View Mode Settings modal to edit them.
  • Adds syncFavoritesForCadence and auto-switch/toast behavior when pay frequency changes.
  • Updates search actions and UI wiring to open the new view mode settings modal (plus small styling/workflow tweaks).

Reviewed changes

Copilot reviewed 26 out of 26 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
vite.config.ts Injects FEEDBACK_FORM_* env values into the Electron main build via Vite define.
src/utils/viewModePreferences.ts Adds syncFavoritesForCadence helper for keeping favorites aligned to cadence changes.
src/utils/viewModePreferences.test.ts Adds unit tests for syncFavoritesForCadence.
src/utils/searchModules/settingsSearchModule.ts Updates settings search results to open the new view-mode settings experience.
src/utils/planSearch.ts Extends SearchResultAction with open-view-mode-settings.
src/utils/planSearch.test.ts Updates expected action type for view mode settings search result.
src/utils/appearanceSettings.ts Changes default stateCueMode from enhanced to minimal.
src/types/settings.ts Moves viewModeFavorites from AppSettings to BudgetSettings (plan-specific).
src/services/fileStorage.ts Removes app-settings normalization for viewModeFavorites.
src/services/fileStorage.test.ts Removes app-settings favorites test coverage; updates default state cue mode expectation.
src/contexts/ThemeContext.tsx Updates fallback stateCueMode to minimal.
src/constants/events.ts Adds viewModeAutoSwitched custom event.
src/components/modals/ViewModeSettingsModal/index.ts Adds barrel export for the new modal.
src/components/modals/ViewModeSettingsModal/ViewModeSettingsModal.tsx Implements plan-specific “View Mode Favorites” modal UI.
src/components/modals/ViewModeSettingsModal/ViewModeSettingsModal.css Adds modal-specific styling.
src/components/modals/SettingsModal/SettingsModal.tsx Removes view mode favorites UI from global Settings; renames header to “App Settings”.
src/components/modals/SettingsModal/SettingsModal.test.tsx Removes tests tied to the old view mode favorites settings section/search.
src/components/modals/PaySettingsModal/PaySettingsModal.tsx Syncs plan favorites/display mode when pay frequency changes and dispatches toast event.
src/components/_shared/layout/ViewModeSelector/ViewModeSelector.tsx Accepts plan favorites as a prop and stops reading app settings internally; adjusts cadence auto-tab behavior.
src/components/_shared/layout/ViewModeSelector/ViewModeSelector.css Adds a border around the selector container.
src/components/PlanDashboard/PlanDashboard.tsx Wires plan-specific favorites into selector + new settings modal; listens for auto-switch toast event.
.github/workflows/validate-version.yml Expands paths-ignore to include root *.md and .gitignore.
.github/workflows/test.yml Expands paths-ignore to include root *.md and .gitignore.
.github/workflows/release.yml Expands paths-ignore to include root *.md and .gitignore.
.github/workflows/build.yml Expands paths-ignore to include root *.md and .gitignore.
.github/workflows/beta-release.yml Expands paths-ignore; switches FEEDBACK_FORM_* from secrets to vars.

Comment on lines +41 to +45
<label>Always Show These View Modes</label>
<CheckboxGroup
selectedValues={favorites}
onChange={handleChange}
className="settings-view-mode-grid"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The <label> here isn’t programmatically associated with the CheckboxGroup, which can make the group hard to understand for screen readers. Prefer using an associated label (e.g., a fieldset/legend, or an id on the label with aria-labelledby passed to CheckboxGroup if it supports it).

Suggested change
<label>Always Show These View Modes</label>
<CheckboxGroup
selectedValues={favorites}
onChange={handleChange}
className="settings-view-mode-grid"
<label id="view-mode-settings-label">Always Show These View Modes</label>
<CheckboxGroup
selectedValues={favorites}
onChange={handleChange}
className="settings-view-mode-grid"
aria-labelledby="view-mode-settings-label"

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +12
import { MAX_VISIBLE_FAVORITE_VIEW_MODES, SELECTABLE_VIEW_MODES, sanitizeFavoriteViewModes } from '../../../utils/viewModePreferences';
import './ViewModeSettingsModal.css';

const VIEW_MODE_OPTIONS = SELECTABLE_VIEW_MODES.map((mode) => {
let label = mode.charAt(0).toUpperCase() + mode.slice(1);
if (mode === 'bi-weekly') label = 'Bi-weekly';
if (mode === 'semi-monthly') label = 'Semi-monthly';
return { value: mode, label };
});
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces label-formatting logic that’s now separate from the existing view-mode labeling used elsewhere (e.g., getDisplayModeLabel is already used in ViewModeSelector/PaySettingsModal). To avoid inconsistent labels over time, consider reusing the shared label helper instead of duplicating special-cases here.

Suggested change
import { MAX_VISIBLE_FAVORITE_VIEW_MODES, SELECTABLE_VIEW_MODES, sanitizeFavoriteViewModes } from '../../../utils/viewModePreferences';
import './ViewModeSettingsModal.css';
const VIEW_MODE_OPTIONS = SELECTABLE_VIEW_MODES.map((mode) => {
let label = mode.charAt(0).toUpperCase() + mode.slice(1);
if (mode === 'bi-weekly') label = 'Bi-weekly';
if (mode === 'semi-monthly') label = 'Semi-monthly';
return { value: mode, label };
});
import { MAX_VISIBLE_FAVORITE_VIEW_MODES, SELECTABLE_VIEW_MODES, sanitizeFavoriteViewModes, getDisplayModeLabel } from '../../../utils/viewModePreferences';
import './ViewModeSettingsModal.css';
const VIEW_MODE_OPTIONS = SELECTABLE_VIEW_MODES.map((mode) => ({
value: mode,
label: getDisplayModeLabel(mode),
}));

Copilot uses AI. Check for mistakes.
const optionsWithCadence = useMemo(() => {
if (!payCadenceMode || options) {
// Only auto-add cadence tab when the user has not explicitly configured
// favorites (favouritesProp absent). When plan-specific favorites are
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the spelling of 'favouritesProp' to 'favoritesProp' to match the actual prop name used in this component.

Suggested change
// favorites (favouritesProp absent). When plan-specific favorites are
// favorites (favoritesProp absent). When plan-specific favorites are

Copilot uses AI. Check for mistakes.
});

it('inserts cadence in canonical order when dropped item is not at position 0', () => {
// [monthly, yearly] at cap=3? No, only 2 — room available, add quarterly
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests implicitly assume the maximum favorites “capacity” is 3 (and encode that in the test data/comments). To make the tests resilient if MAX_VISIBLE_FAVORITE_VIEW_MODES changes, consider importing the constant and constructing inputs based on it (or at least avoid “at cap=3” style assumptions in comments).

Suggested change
// [monthly, yearly] at cap=3? No, only 2 — room available, add quarterly
// [monthly, yearly] is not at capacity — room available, add quarterly

Copilot uses AI. Check for mistakes.
Comment on lines +77 to +81
FEEDBACK_FORM_URL: ${{ vars.FEEDBACK_FORM_URL }}
FEEDBACK_FORM_ENTRY_EMAIL: ${{ vars.FEEDBACK_FORM_ENTRY_EMAIL }}
FEEDBACK_FORM_ENTRY_CATEGORY: ${{ vars.FEEDBACK_FORM_ENTRY_CATEGORY }}
FEEDBACK_FORM_ENTRY_SUBJECT: ${{ vars.FEEDBACK_FORM_ENTRY_SUBJECT }}
FEEDBACK_FORM_ENTRY_DETAILS: ${{ vars.FEEDBACK_FORM_ENTRY_DETAILS }}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switches FEEDBACK_FORM_* from secrets to vars. If any of these values are sensitive (tokens, private endpoints, etc.), GitHub Variables are not the right storage mechanism compared to Secrets. If they’re truly non-sensitive configuration, add a short comment in the workflow clarifying that these are safe to be public-as-config; otherwise revert to secrets.*.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to +21
vite: {
define: {
'process.env.FEEDBACK_FORM_URL': JSON.stringify(process.env.FEEDBACK_FORM_URL ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_EMAIL': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_EMAIL ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_CATEGORY': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_CATEGORY ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_SUBJECT': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_SUBJECT ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_DETAILS': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_DETAILS ?? ''),
},
},
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Vite define here will inline these env values at build time into the bundled Electron main output, which prevents changing them at runtime via environment variables (and may also embed values into distributables). If the intent is runtime-configurable main-process behavior, prefer reading process.env.FEEDBACK_FORM_* directly at runtime (and avoid define for main). If the intent is to bake config into the build, consider documenting that expectation so releases don’t accidentally ship unexpected values.

Suggested change
vite: {
define: {
'process.env.FEEDBACK_FORM_URL': JSON.stringify(process.env.FEEDBACK_FORM_URL ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_EMAIL': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_EMAIL ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_CATEGORY': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_CATEGORY ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_SUBJECT': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_SUBJECT ?? ''),
'process.env.FEEDBACK_FORM_ENTRY_DETAILS': JSON.stringify(process.env.FEEDBACK_FORM_ENTRY_DETAILS ?? ''),
},
},

Copilot uses AI. Check for mistakes.
Comment on lines 24 to 28
};
activeTab?: string;
keyMetricsBreakdownView?: KeyMetricsBreakdownView;
viewModeFavorites?: SelectableViewMode[];
}
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewModeFavorites has moved from AppSettings to BudgetSettings (plan-specific), and corresponding app-settings normalization/tests were removed. That means existing users’ stored app-wide favorites will be ignored after upgrade unless there’s a migration path elsewhere. Consider adding a one-time migration strategy (e.g., on first load of a budget missing settings.viewModeFavorites, seed it from legacy app settings if present) to avoid silently dropping user preferences.

Copilot uses AI. Check for mistakes.
kryptodrex added a commit that referenced this pull request Mar 23, 2026
Merge pull request #69 from kryptodrex/v.0.4.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants