Skip to content
Closed
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
31 changes: 15 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
# Expensave

Expensave is an open-source application designed to help you track your personal and family expenses effortlessly, enabling better budgeting and financial management. Highly inspired by [Dollarbird](https://dollarbird.co/), Expensave offers intuitive features to monitor your spending habits and stay on top of your finances.
Expensave is an open-source application designed to help you track your personal and family expenses effortlessly, enabling better budgeting and financial management. Inspired by [Dollarbird](https://dollarbird.co/), Expensave offers intuitive features to monitor your spending habits and stay on top of your finances.

## Support

This open-source project is developed in my free time.
You can support this project by clicking the "Sponsor" button above.
Your sponsorship will help me dedicate more time and resources to improve the project, add new features, fix bugs, and stay motivated. It also helps me understand that this project is useful not only for me, but for many users like you.
This open-source project is developed in my free time.
You can support it by clicking the **Sponsor** button above.
Your sponsorship helps me dedicate more time and resources to improve the project, add new features, fix bugs, and stay motivated. It also helps me understand that this project is useful not only for me, but for many users like you.

---

# Screenshots
## Screenshots

## Desktop version
### Desktop version

<a href="https://raw.githubusercontent.com/algirdasc/expensave/main/docs/images/screenshots/desktop-calendar.png">
<img alt="Calendar view" src="https://raw.githubusercontent.com/algirdasc/expensave/main/docs/images/screenshots/desktop-calendar.png" />
Expand All @@ -25,7 +25,7 @@ Your sponsorship will help me dedicate more time and resources to improve the pr
</a>
<div style="clear: both;"></div>

## Mobile version
### Mobile version

<a href="https://raw.githubusercontent.com/algirdasc/expensave/main/docs/images/screenshots/mobile-calendar.png">
<img alt="Mobile version calendar view" src="https://raw.githubusercontent.com/algirdasc/expensave/main/docs/images/screenshots/mobile-calendar.png" style="width: 32%; float: left;" />
Expand All @@ -43,7 +43,7 @@ Your sponsorship will help me dedicate more time and resources to improve the pr
- Multiple user support
- Shared expense calendars between family members
- Multiple & unlimited expense calendars
- Import your balance from financial institutions in various [formats](https://github.com/algirdasc/expensave/wiki/Bank-statement-import#supported-banks)
- Import your balance from financial institutions in various [formats](https://github.com/algirdasc/expensave/wiki/Bank-statement-import#supported-banks)
- Reports on your spending and income habits
- Responsive design
- Mobile [PWA](https://web.dev/explore/progressive-web-apps) application
Expand All @@ -54,18 +54,17 @@ Your sponsorship will help me dedicate more time and resources to improve the pr

[![Deploy on Hostinger](https://assets.hostinger.com/vps/deploy.svg)](https://www.hostinger.com/vps/docker-hosting?compose_url=https://raw.githubusercontent.com/algirdasc/expensave/refs/heads/main/docker-compose.yml&REFERRALCODE=1ALGIRDAS48#pricing)

## Install self-hosted instance
### Install a self-hosted instance

See wiki: [Installation](https://github.com/algirdasc/expensave/wiki/Installation).
See the wiki: [Installation](https://github.com/algirdasc/expensave/wiki/Installation).

### Install the mobile version

## Installing Mobile Version

See wiki: [Using mobile version](https://github.com/algirdasc/expensave/wiki/Using-mobile-version).
See the wiki: [Using mobile version](https://github.com/algirdasc/expensave/wiki/Using-mobile-version).

## Bank Statement Import

See wiki: [Bank statement import](https://github.com/algirdasc/expensave/wiki/Bank-statement-import).
See the wiki: [Bank statement import](https://github.com/algirdasc/expensave/wiki/Bank-statement-import).

## Contributing

Expand All @@ -76,9 +75,9 @@ Contributions from the community are more than welcomed! If you'd like to contri
- Write clear and concise commit messages.
- Test your changes thoroughly.

## Support
## Help & Support

If you encounter any issues or have any questions about Expensave, feel free to [open an issue](https://github.com/algirdasc/expensave/issues) on GitHub.
If you run into issues or have questions about Expensave, feel free to [open an issue](https://github.com/algirdasc/expensave/issues) on GitHub.

## Anonymous Data Collection

Expand Down
255 changes: 255 additions & 0 deletions frontend/HEADER_REFACTORING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
# Header Component Refactoring Summary

## Overview
The header component has been successfully split into three smaller, focused sub-components to improve maintainability, testability, and prepare the codebase for TanStack Query integration.

## Before: Monolithic Header Component

### Structure
```
header/
β”œβ”€β”€ header.component.ts (103 lines)
β”œβ”€β”€ header.component.html (85 lines)
└── header.component.scss (12 lines)
```

### Issues
- **Mixed Responsibilities**: Single component handled sidebar toggle, calendar info, and date navigation
- **Complex Logic**: 100+ lines of TypeScript with multiple concerns
- **Hard to Test**: Testing individual features required testing the entire header
- **Poor Reusability**: Date navigation logic couldn't be reused elsewhere
- **Maintenance Burden**: Changes to one feature could affect others

## After: Modular Header with Sub-Components

### New Structure
```
header/
β”œβ”€β”€ header.component.ts (62 lines - 40% reduction)
β”œβ”€β”€ header.component.html (19 lines - 77% reduction)
β”œβ”€β”€ header.component.scss (4 lines - 67% reduction)
└── components/
β”œβ”€β”€ sidebar-toggle/
β”‚ β”œβ”€β”€ sidebar-toggle.component.ts (20 lines)
β”‚ β”œβ”€β”€ sidebar-toggle.component.html (9 lines)
β”‚ └── sidebar-toggle.component.scss (3 lines)
β”œβ”€β”€ calendar-info/
β”‚ β”œβ”€β”€ calendar-info.component.ts (22 lines)
β”‚ β”œβ”€β”€ calendar-info.component.html (21 lines)
β”‚ └── calendar-info.component.scss (3 lines)
└── date-navigation/
β”œβ”€β”€ date-navigation.component.ts (83 lines)
β”œβ”€β”€ date-navigation.component.html (39 lines)
└── date-navigation.component.scss (3 lines)
```

## Component Breakdown

### 1. Sidebar Toggle Component (`app-sidebar-toggle`)
**Purpose**: Sidebar menu button with notification badge

**Inputs:**
- `hasNotifications: boolean` - Shows notification badge when true

**Outputs:**
- `sidebarToggle: void` - Emitted when sidebar toggle is clicked

**Responsibility:**
- Display menu button
- Show notification badge for pending statement imports
- Emit toggle event

**Usage:**
```html
<app-sidebar-toggle
[hasNotifications]="statementImportService.expenses.length > 0"
(sidebarToggle)="toggleSidebar()">
</app-sidebar-toggle>
```

---

### 2. Calendar Info Component (`app-calendar-info`)
**Purpose**: Display calendar name and balance information

**Inputs:**
- `calendar: Calendar` - Calendar object to display
- `monthBalance: number` - Current month's balance

**Responsibility:**
- Display calendar name
- Show current balance (shortened format)
- Show monthly balance with color coding (green/red)
- Provide expense report popover on click

**Usage:**
```html
<app-calendar-info
[calendar]="calendar"
[monthBalance]="visibleDateBalance">
</app-calendar-info>
```

---

### 3. Date Navigation Component (`app-date-navigation`)
**Purpose**: Date picker and navigation controls

**Inputs:**
- `currentDate: Date` - Currently visible date

**Outputs:**
- `dateChange: Date` - Emitted when user selects a new date
- `previous: void` - Navigate to previous month
- `next: void` - Navigate to next month
- `today: void` - Navigate to today

**Responsibility:**
- Display date in various view modes (date/month/year)
- Handle year/month picker interactions
- Provide previous/today/next navigation buttons
- Manage popover state for date picker

**Usage:**
```html
<app-date-navigation
[currentDate]="visibleDate"
(dateChange)="navigateToDate($event)"
(previous)="navigatePrev()"
(next)="navigateNext()"
(today)="navigateToday()">
</app-date-navigation>
```

---

### 4. Simplified Header Component (Container)
**Purpose**: Orchestrate sub-components and handle routing

**Inputs:**
- `calendar: Calendar` - Current calendar
- `visibleDateBalance: number` - Monthly balance
- `visibleDate: Date` - Currently visible date

**Responsibility:**
- Compose sub-components
- Handle sidebar toggle logic
- Manage date navigation routing
- Update URL query parameters

**Benefits:**
- Cleaner, more focused code
- Acts as a smart container component
- Sub-components are presentational/reusable

## Benefits of Refactoring

### 1. **Single Responsibility Principle**
Each component now has one clear purpose:
- `SidebarToggleComponent` β†’ Menu toggle with notifications
- `CalendarInfoComponent` β†’ Display calendar information
- `DateNavigationComponent` β†’ Date selection and navigation
- `HeaderComponent` β†’ Orchestration and routing

### 2. **Improved Testability**
- Test sidebar toggle independently
- Test date navigation without calendar logic
- Mock sub-components in header tests
- Easier to write unit tests for focused components

### 3. **Better Reusability**
- `DateNavigationComponent` can be reused in other views
- `CalendarInfoComponent` could be used in a dashboard
- Components are decoupled from parent context

### 4. **Easier Maintenance**
- Changes to date picker don't affect sidebar
- Smaller files are easier to read and modify
- Clear component boundaries prevent coupling

### 5. **Preparation for TanStack Query**
- Each component can manage its own data needs
- Easier to add `injectQuery()` to individual components
- Clear separation makes query integration straightforward

### 6. **Code Statistics**
- **Header TypeScript**: 103 β†’ 62 lines (40% reduction)
- **Header Template**: 85 β†’ 19 lines (77% reduction)
- **Header Styles**: 12 β†’ 4 lines (67% reduction)
- **Total new component files**: 9 files (organized in logical structure)

## Migration Impact

### Breaking Changes
None - The header component API remains the same:
```html
<app-header
[calendar]="mainService.calendar"
[visibleDateBalance]="mainService.visibleDateBalance"
[visibleDate]="mainService.visibleDate">
</app-header>
```

### Compatibility
βœ… Fully backward compatible
βœ… No changes to parent components
βœ… All existing functionality preserved

## Next Steps for TanStack Query Integration

With this refactoring complete, the components are now ready for TanStack Query:

1. **CalendarInfoComponent** can use `injectQuery()` to fetch calendar data
2. **DateNavigationComponent** can invalidate queries on date change
3. **HeaderComponent** can be simplified further by removing route management

Example future enhancement:
```typescript
// calendar-info.component.ts
export class CalendarInfoComponent {
private calendarQueries = inject(CalendarQueries);

calendar = injectQuery(() =>
this.calendarQueries.get(this.calendarId())
);

monthBalance = injectQuery(() =>
this.calendarQueries.monthBalance(
this.calendarId(),
this.month()
)
);
}
```

## Files Changed

### Created (9 files):
- `header/components/sidebar-toggle/sidebar-toggle.component.ts`
- `header/components/sidebar-toggle/sidebar-toggle.component.html`
- `header/components/sidebar-toggle/sidebar-toggle.component.scss`
- `header/components/calendar-info/calendar-info.component.ts`
- `header/components/calendar-info/calendar-info.component.html`
- `header/components/calendar-info/calendar-info.component.scss`
- `header/components/date-navigation/date-navigation.component.ts`
- `header/components/date-navigation/date-navigation.component.html`
- `header/components/date-navigation/date-navigation.component.scss`

### Modified (3 files):
- `header/header.component.ts` (simplified)
- `header/header.component.html` (simplified)
- `header/header.component.scss` (simplified)

## Quality Assurance

βœ… **ESLint**: All files pass linting with zero errors
βœ… **Prettier**: Code formatting is consistent
βœ… **TypeScript**: Strict type checking passes
βœ… **Angular Standards**: Follows Angular style guide
βœ… **Naming Conventions**: Consistent with project standards

## Conclusion

This refactoring successfully transforms a monolithic 200+ line header component into a well-organized, maintainable structure with clear separation of concerns. The new architecture is more testable, reusable, and ready for TanStack Query integration.

The refactoring follows SOLID principles and Angular best practices, setting a strong foundation for future development.
Loading
Loading