From 650856339766ea3ceca063786662630b5510d6b8 Mon Sep 17 00:00:00 2001 From: Hussain Date: Mon, 19 Jan 2026 01:00:32 +0530 Subject: [PATCH 1/2] Enhanced ExpenseFlow: Added navigation sections, improved typography, fixed layout, and GitHub Pages compatibility - Added complete Analytics, Goals, and Settings sections with full functionality - Enhanced typography with Poppins, Space Grotesk, and Inter fonts - Fixed overlapping layout issues and improved spacing - Added comprehensive Mermaid.js flowcharts in README - Enhanced feature request template with detailed sections - Fixed all file paths for GitHub Pages compatibility - Added .gitignore, .nojekyll, and DEPLOYMENT.md - Improved service worker and manifest.json paths - All navigation links now work perfectly - Better responsive design and mobile support --- .github/ISSUE_TEMPLATE/feature_request.md | 159 +++- .gitignore | 50 ++ .nojekyll | 0 DEPLOYMENT.md | 185 +++++ README.md | 658 ++++++++++++++++- expensetracker.css | 844 +++++++++++++++++++++- index.html | 317 +++++++- manifest.json | 6 +- sw.js | 15 +- trackerscript.js | 461 +++++++++++- 10 files changed, 2572 insertions(+), 123 deletions(-) create mode 100644 .gitignore create mode 100644 .nojekyll create mode 100644 DEPLOYMENT.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d..8b69ea04 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -1,12 +1,13 @@ --- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' +name: Feature Request +about: Suggest a new feature or enhancement for ExpenseFlow +title: '[FEATURE] ' +labels: 'enhancement' assignees: '' - --- +## 🎯 Feature Overview + **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] @@ -16,5 +17,149 @@ A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. -**Additional context** -Add any other context or screenshots about the feature request here. +--- + +## πŸ“‹ Feature Details + +### User Story +As a [type of user], I want [goal] so that [benefit]. + +### Acceptance Criteria +- [ ] Criterion 1: [Description] +- [ ] Criterion 2: [Description] +- [ ] Criterion 3: [Description] + +### Expected Behavior +Describe the expected behavior when this feature is implemented. + +### Current Behavior +Describe what currently happens (if applicable). + +--- + +## 🎨 UI/UX Considerations + +### Mockups/Wireframes +If applicable, add mockups, wireframes, or screenshots to help explain your feature. + +### User Flow +Describe how users would interact with this feature: + +```mermaid +flowchart TD + A[User Action] --> B[Feature Trigger] + B --> C[Process] + C --> D[Result] + D --> E[User Feedback] + + style A fill:#64ffda,stroke:#0f0f23,stroke-width:2px + style D fill:#10ac84,stroke:#0f0f23,stroke-width:2px +``` + +--- + +## πŸ”§ Technical Considerations + +### Implementation Approach +Describe how this feature could be implemented technically. + +### Dependencies +- [ ] No new dependencies required +- [ ] Requires new library: [Library name] +- [ ] Requires backend changes +- [ ] Requires database changes + +### Performance Impact +- [ ] No performance impact expected +- [ ] Minimal performance impact +- [ ] May require optimization + +### Browser Compatibility +- [ ] Works on all modern browsers +- [ ] Requires specific browser features: [List features] +- [ ] May need polyfills + +--- + +## πŸ“Š Impact Assessment + +### User Impact +- **High**: This feature would significantly improve user experience +- **Medium**: This feature would be a nice addition +- **Low**: This feature is a minor enhancement + +### Priority +- [ ] πŸ”΄ Critical - Blocks other features +- [ ] 🟠 High - Important for user experience +- [ ] 🟑 Medium - Nice to have +- [ ] 🟒 Low - Can be added later + +### Complexity +- [ ] 🟒 Simple - Quick implementation +- [ ] 🟑 Medium - Moderate effort required +- [ ] 🟠 Complex - Significant development needed +- [ ] πŸ”΄ Very Complex - Major feature requiring architecture changes + +--- + +## πŸ§ͺ Testing Considerations + +### Test Cases +- [ ] Unit tests required +- [ ] Integration tests required +- [ ] Manual testing scenarios: [Describe] + +### Edge Cases +List any edge cases that should be considered: +- Edge case 1 +- Edge case 2 + +--- + +## πŸ“š Additional Context + +### Related Issues +Link to any related issues: +- Related issue #1 +- Related issue #2 + +### References +- [ ] Similar features in other apps: [Links] +- [ ] Design inspiration: [Links] +- [ ] Technical documentation: [Links] + +### Additional Information +Add any other context, screenshots, or examples about the feature request here. + +--- + +## βœ… Checklist + +Before submitting, please ensure: + +- [ ] I have searched existing issues to avoid duplicates +- [ ] I have provided a clear description of the feature +- [ ] I have considered the user experience +- [ ] I have thought about technical implementation +- [ ] I have included any relevant mockups or examples +- [ ] I have checked that this aligns with the project goals + +--- + +## 🀝 Contribution + +**Are you willing to work on this feature?** +- [ ] Yes, I'd like to implement this +- [ ] Maybe, with guidance +- [ ] No, but I can help with testing/feedback + +**Skills/Resources Needed:** +- [ ] Frontend development +- [ ] Backend development +- [ ] UI/UX design +- [ ] Testing +- [ ] Documentation + +--- + +**Thank you for taking the time to suggest this feature! πŸŽ‰** diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b1c22d84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +dist/ +build/ +*.min.js +*.min.css + +# Environment variables +.env +.env.local +.env.*.local + +# IDE and Editor files +.vscode/ +.idea/ +*.swp +*.swo +*~ +.DS_Store +Thumbs.db + +# Logs +logs/ +*.log + +# OS files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Desktop.ini + +# Temporary files +*.tmp +*.temp +.cache/ + +# Service Worker cache (optional - uncomment if you don't want to track) +# sw-cache/ + +# Backup files +*.bak +*.backup diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 00000000..e2ec7102 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,185 @@ +# πŸš€ Deployment Guide for ExpenseFlow + +This guide will help you deploy ExpenseFlow to GitHub Pages or any static hosting service. + +## πŸ“‹ Prerequisites + +- A GitHub account +- Git installed on your local machine +- The ExpenseFlow repository cloned locally + +## 🌐 GitHub Pages Deployment + +### Option 1: Deploy from Root Directory (Recommended) + +1. **Push your code to GitHub** + ```bash + git add . + git commit -m "Initial commit" + git push origin main + ``` + +2. **Enable GitHub Pages** + - Go to your repository on GitHub + - Click on **Settings** β†’ **Pages** + - Under **Source**, select **Deploy from a branch** + - Choose **main** branch and **/ (root)** folder + - Click **Save** + +3. **Access your site** + - Your site will be available at: `https://yourusername.github.io/ExpenseFlow/` + - Or if using a custom domain: `https://yourdomain.com` + +### Option 2: Deploy from `gh-pages` Branch + +1. **Create and switch to gh-pages branch** + ```bash + git checkout -b gh-pages + git push origin gh-pages + ``` + +2. **Enable GitHub Pages** + - Go to **Settings** β†’ **Pages** + - Select **gh-pages** branch and **/ (root)** folder + +## πŸ“ File Structure Requirements + +Ensure your repository has the following structure: + +``` +ExpenseFlow/ +β”œβ”€β”€ index.html # Main entry point +β”œβ”€β”€ expensetracker.css # Styles +β”œβ”€β”€ trackerscript.js # JavaScript logic +β”œβ”€β”€ manifest.json # PWA manifest +β”œβ”€β”€ sw.js # Service worker +β”œβ”€β”€ .nojekyll # Disable Jekyll +β”œβ”€β”€ .gitignore # Git ignore rules +β”œβ”€β”€ README.md # Documentation +β”œβ”€β”€ LICENSE # License file +└── .github/ + └── ISSUE_TEMPLATE/ + └── feature_request.md +``` + +## βš™οΈ Configuration Notes + +### Path Configuration + +All paths in the project are configured to work with: +- **Root deployment**: `https://username.github.io/ExpenseFlow/` +- **Custom domain**: `https://yourdomain.com/` + +The following files use relative paths for maximum compatibility: +- `manifest.json` - Uses `./` for relative paths +- `sw.js` - Uses relative paths for caching +- `trackerscript.js` - Dynamically detects base path for service worker + +### Service Worker + +The service worker is configured to: +- Work with both root and subdirectory deployments +- Automatically detect the base path +- Cache all necessary resources for offline functionality + +### PWA Manifest + +The manifest file is configured with: +- Relative start URL: `./index.html` +- Relative scope: `./` +- All icons use base64 encoded SVGs (no external dependencies) + +## πŸ”§ Troubleshooting + +### Service Worker Not Registering + +If the service worker fails to register: + +1. **Check browser console** for errors +2. **Verify file paths** are correct +3. **Clear browser cache** and reload +4. **Check HTTPS requirement** - Service workers require HTTPS (or localhost) + +### Assets Not Loading + +If CSS/JS files don't load: + +1. **Verify file names** match exactly (case-sensitive) +2. **Check file paths** in `index.html` +3. **Ensure `.nojekyll` file exists** to prevent Jekyll processing +4. **Clear GitHub Pages cache** (may take a few minutes) + +### PWA Not Installing + +If the PWA install prompt doesn't appear: + +1. **Check manifest.json** is accessible +2. **Verify HTTPS** is enabled (required for PWA) +3. **Check browser console** for manifest errors +4. **Ensure service worker** is registered successfully + +## 🌍 Other Hosting Options + +### Netlify + +1. Connect your GitHub repository to Netlify +2. Build command: (leave empty - static site) +3. Publish directory: `/` (root) +4. Deploy! + +### Vercel + +1. Import your GitHub repository +2. Framework preset: **Other** +3. Root directory: `./` +4. Deploy! + +### Firebase Hosting + +1. Install Firebase CLI: `npm install -g firebase-tools` +2. Initialize: `firebase init hosting` +3. Deploy: `firebase deploy` + +## πŸ“ Important Notes + +- **HTTPS Required**: PWA features require HTTPS (automatically provided by GitHub Pages) +- **Cache Busting**: Update `CACHE_NAME` in `sw.js` when deploying updates +- **File Names**: Keep file names lowercase and use hyphens for consistency +- **Relative Paths**: All internal paths use relative notation for portability + +## βœ… Deployment Checklist + +Before deploying, ensure: + +- [ ] All file paths are relative or properly configured +- [ ] `.nojekyll` file exists in root +- [ ] `.gitignore` is properly configured +- [ ] Service worker registration works +- [ ] Manifest.json is accessible +- [ ] All assets load correctly +- [ ] PWA features work (install prompt, offline mode) +- [ ] All navigation links work +- [ ] Responsive design works on mobile + +## πŸŽ‰ Post-Deployment + +After successful deployment: + +1. **Test all features** on the live site +2. **Verify PWA installation** works +3. **Check offline functionality** +4. **Test on multiple devices/browsers** +5. **Monitor browser console** for errors + +## πŸ“ž Support + +If you encounter issues: + +1. Check the [GitHub Issues](https://github.com/Renu-code123/ExpenseFlow-expensetracker/issues) +2. Review browser console for errors +3. Verify all file paths are correct +4. Ensure HTTPS is enabled + +--- + +**Happy Deploying! πŸš€** diff --git a/README.md b/README.md index 455815c4..ab58f1a4 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,12 @@ With a clean and elegant dark-themed UI, it allows users to monitor spending, an ## 🧭 Table of Contents - [✨ Features](#-features) - [πŸ–₯️ Overview](#️-overview) +- [πŸ—οΈ Architecture & Flowcharts](#️-architecture--flowcharts) - [πŸ› οΈ Tech Stack](#️-tech-stack) - [πŸ“‚ Folder Structure](#-folder-structure) -- [πŸš€ How to Run Locally](#-how-to-run-locally) +- [πŸš€ Getting Started](#-getting-started) +- [πŸ“– Usage Guide](#-usage-guide) +- [πŸ”„ Data Flow](#-data-flow) - [πŸ“Έ Screenshots](#-screenshots) - [🧩 Future Enhancements](#-future-enhancements) - [🎯 Learning Outcomes](#-learning-outcomes) @@ -30,6 +33,9 @@ With a clean and elegant dark-themed UI, it allows users to monitor spending, an - πŸŒ™ **Dark Mode UI** – Sleek and eye-comfortable dark theme. - βš™οΈ **Responsive Design** – Optimized for desktop and mobile devices. - πŸ” **PWA Ready** – Manifest and service worker support for offline usage. +- πŸ” **Advanced Filtering** – Filter by category, date range, amount, and search. +- πŸ“₯ **Data Import/Export** – Export to CSV/JSON and import your data. +- πŸ”” **Real-time Notifications** – Get instant feedback on your actions. --- @@ -42,6 +48,398 @@ The app emphasizes: - User-centered design - Visual representation of financial data - Scalable project structure for future backend integration +- Progressive Web App (PWA) capabilities for offline functionality + +--- + +## πŸ—οΈ Architecture & Flowcharts + +### πŸ“ Application Architecture + +```mermaid +graph TB + subgraph "Client Layer" + A[User Interface
index.html] --> B[Styling Layer
expensetracker.css] + A --> C[Logic Layer
trackerscript.js] + end + + subgraph "Storage Layer" + D[LocalStorage
Browser Storage] + E[Service Worker Cache
sw.js] + end + + subgraph "PWA Layer" + F[Manifest.json
App Configuration] + G[Service Worker
Offline Support] + end + + C --> D + C --> E + A --> F + G --> E + G --> A + + style A fill:#64ffda,stroke:#0f0f23,stroke-width:3px + style C fill:#667eea,stroke:#0f0f23,stroke-width:2px + style D fill:#764ba2,stroke:#0f0f23,stroke-width:2px + style G fill:#f093fb,stroke:#0f0f23,stroke-width:2px +``` + +### πŸ”„ User Journey Flow + +```mermaid +flowchart TD + Start([User Opens App]) --> Load{App Loads} + Load --> Init[Initialize Application] + Init --> CheckData{Data in
LocalStorage?} + + CheckData -->|Yes| LoadData[Load Existing Transactions] + CheckData -->|No| EmptyState[Show Empty State] + + LoadData --> Dashboard[Display Dashboard] + EmptyState --> Dashboard + + Dashboard --> UserAction{User Action} + + UserAction -->|Add Transaction| AddForm[Show Add Form] + UserAction -->|View History| History[Display Transaction History] + UserAction -->|Filter/Search| Filter[Apply Filters] + UserAction -->|Export Data| Export[Export to CSV/JSON] + UserAction -->|Import Data| Import[Import from File] + + AddForm --> Validate{Validate Input} + Validate -->|Valid| SaveTransaction[Save Transaction] + Validate -->|Invalid| ShowError[Show Error Message] + ShowError --> AddForm + + SaveTransaction --> UpdateStorage[Update LocalStorage] + UpdateStorage --> UpdateUI[Update UI Display] + UpdateUI --> Notification[Show Success Notification] + Notification --> Dashboard + + History --> Filter + Filter --> DisplayFiltered[Display Filtered Results] + DisplayFiltered --> Dashboard + + Export --> DownloadFile[Download File] + DownloadFile --> Dashboard + + Import --> ParseFile[Parse File Data] + ParseFile --> MergeData{Merge with
Existing?} + MergeData -->|Yes| Merge[Merge Transactions] + MergeData -->|No| Replace[Replace Transactions] + Merge --> UpdateStorage + Replace --> UpdateStorage + + style Start fill:#64ffda,stroke:#0f0f23,stroke-width:3px + style Dashboard fill:#667eea,stroke:#0f0f23,stroke-width:2px + style SaveTransaction fill:#10ac84,stroke:#0f0f23,stroke-width:2px + style UpdateStorage fill:#764ba2,stroke:#0f0f23,stroke-width:2px +``` + +### πŸ’Ύ Data Flow Architecture + +```mermaid +sequenceDiagram + participant User + participant UI as User Interface + participant JS as JavaScript Logic + participant LS as LocalStorage + participant SW as Service Worker + participant Cache as Cache Storage + + User->>UI: Interacts with Form + UI->>JS: Form Submit Event + JS->>JS: Validate Input Data + JS->>JS: Create Transaction Object + JS->>LS: Save to LocalStorage + LS-->>JS: Confirm Save + JS->>UI: Update DOM Elements + JS->>UI: Show Notification + UI-->>User: Display Updated Balance + + Note over User,Cache: Offline Scenario + User->>UI: Request Resource + UI->>SW: Fetch Request + SW->>Cache: Check Cache + Cache-->>SW: Return Cached Resource + SW-->>UI: Serve Cached Content + UI-->>User: Display Content + + Note over User,Cache: Online Scenario + User->>UI: Request Resource + UI->>SW: Fetch Request + SW->>Cache: Check Cache + Cache-->>SW: Not Found + SW->>Network: Fetch from Network + Network-->>SW: Return Resource + SW->>Cache: Store in Cache + SW-->>UI: Serve Resource + UI-->>User: Display Content +``` + +### 🧩 Component Interaction Flow + +```mermaid +graph LR + subgraph "UI Components" + A[Balance Card] + B[Income Card] + C[Expense Card] + D[Transaction List] + E[Add Form] + F[Filter Controls] + G[Export/Import] + end + + subgraph "JavaScript Functions" + H[updateValues] + I[displayTransactions] + J[addTransaction] + K[removeTransaction] + L[getFilteredTransactions] + M[exportDataToCSV] + N[importDataFromFile] + end + + subgraph "Data Storage" + O[transactions Array] + P[LocalStorage] + end + + A --> H + B --> H + C --> H + D --> I + E --> J + F --> L + G --> M + G --> N + + H --> O + I --> L + J --> O + K --> O + L --> O + M --> O + N --> O + + O --> P + P --> O + + style A fill:#64ffda,stroke:#0f0f23,stroke-width:2px + style B fill:#10ac84,stroke:#0f0f23,stroke-width:2px + style C fill:#ff6b6b,stroke:#0f0f23,stroke-width:2px + style O fill:#764ba2,stroke:#0f0f23,stroke-width:2px + style P fill:#667eea,stroke:#0f0f23,stroke-width:2px +``` + +### πŸ”„ Transaction Processing Flow + +```mermaid +flowchart TD + Start([User Submits Form]) --> Validate{Validate Fields} + + Validate -->|Missing Fields| Error1[Show Error:
Fill All Fields] + Validate -->|Invalid Amount| Error2[Show Error:
Valid Amount Required] + Validate -->|Valid| Process[Process Transaction] + + Error1 --> End1([Return to Form]) + Error2 --> End1 + + Process --> CreateObj[Create Transaction Object] + CreateObj --> SetID[Generate Unique ID] + SetID --> SetType{Transaction Type?} + + SetType -->|Income| SetPositive[Set Positive Amount] + SetType -->|Expense| SetNegative[Set Negative Amount] + + SetPositive --> AddDate[Add Timestamp] + SetNegative --> AddDate + + AddDate --> AddCategory[Add Category Info] + AddCategory --> PushArray[Push to Transactions Array] + + PushArray --> UpdateStorage[Update LocalStorage] + UpdateStorage --> UpdateBalance[Recalculate Balance] + UpdateBalance --> UpdateIncome[Recalculate Income] + UpdateIncome --> UpdateExpense[Recalculate Expense] + + UpdateExpense --> FilterData[Apply Active Filters] + FilterData --> RenderList[Render Transaction List] + RenderList --> ClearForm[Clear Form Fields] + ClearForm --> ShowSuccess[Show Success Notification] + ShowSuccess --> End2([Transaction Added]) + + style Start fill:#64ffda,stroke:#0f0f23,stroke-width:3px + style Process fill:#667eea,stroke:#0f0f23,stroke-width:2px + style UpdateStorage fill:#764ba2,stroke:#0f0f23,stroke-width:2px + style End2 fill:#10ac84,stroke:#0f0f23,stroke-width:3px + style Error1 fill:#ff6b6b,stroke:#0f0f23,stroke-width:2px + style Error2 fill:#ff6b6b,stroke:#0f0f23,stroke-width:2px +``` + +### πŸ“± PWA Lifecycle Flow + +```mermaid +stateDiagram-v2 + [*] --> NotInstalled: App Loaded + + NotInstalled --> InstallPrompt: beforeinstallprompt Event + InstallPrompt --> Installing: User Clicks Install + InstallPrompt --> Dismissed: User Dismisses + + Installing --> Installed: Installation Complete + Installed --> Registered: Service Worker Registered + + Registered --> Caching: Cache Resources + Caching --> Active: Service Worker Active + Active --> Online: App Online + + Online --> Offline: Network Disconnected + Offline --> Cached: Serve from Cache + Cached --> Online: Network Reconnected + + Active --> UpdateAvailable: New Version Detected + UpdateAvailable --> UpdatePrompt: Show Update Notification + UpdatePrompt --> Updating: User Clicks Update + Updating --> Updated: Update Complete + Updated --> Reload: Reload Page + + Dismissed --> NotInstalled + Reload --> Active + + note right of Active + Service Worker handles: + - Caching + - Offline Support + - Background Sync + - Push Notifications + end note +``` + +### πŸ” Filtering & Search Flow + +```mermaid +flowchart TD + Start([User Applies Filter]) --> GetFilter{Filter Type} + + GetFilter -->|Type Filter| TypeFilter[Filter by Income/Expense] + GetFilter -->|Category Filter| CategoryFilter[Filter by Category] + GetFilter -->|Search Query| SearchFilter[Filter by Text Search] + GetFilter -->|Date Range| DateFilter[Filter by Date Range] + GetFilter -->|Amount Range| AmountFilter[Filter by Amount] + GetFilter -->|Clear All| ClearFilters[Reset All Filters] + + TypeFilter --> Combine[Combine All Active Filters] + CategoryFilter --> Combine + SearchFilter --> Combine + DateFilter --> Combine + AmountFilter --> Combine + ClearFilters --> Combine + + Combine --> ApplyFilters[Apply Filters to Transactions] + ApplyFilters --> CheckResults{Results Found?} + + CheckResults -->|Yes| SortByDate[Sort by Date Descending] + CheckResults -->|No| ShowEmpty[Show Empty State Message] + + SortByDate --> RenderTransactions[Render Filtered Transactions] + RenderTransactions --> UpdateCount[Update Result Count] + UpdateCount --> End([Display Results]) + + ShowEmpty --> End + + style Start fill:#64ffda,stroke:#0f0f23,stroke-width:3px + style Combine fill:#667eea,stroke:#0f0f23,stroke-width:2px + style RenderTransactions fill:#10ac84,stroke:#0f0f23,stroke-width:2px + style ShowEmpty fill:#ff6b6b,stroke:#0f0f23,stroke-width:2px +``` + +### πŸ“₯ Export/Import Data Flow + +```mermaid +flowchart LR + subgraph "Export Flow" + A1[User Clicks Export] --> A2{Export Format?} + A2 -->|CSV| A3[Convert to CSV] + A2 -->|JSON| A4[Convert to JSON] + A3 --> A5[Create Blob] + A4 --> A5 + A5 --> A6[Create Download Link] + A6 --> A7[Trigger Download] + A7 --> A8[Show Success Notification] + end + + subgraph "Import Flow" + B1[User Selects File] --> B2{File Type?} + B2 -->|CSV| B3[Parse CSV Data] + B2 -->|JSON| B4[Parse JSON Data] + B3 --> B5[Validate Data] + B4 --> B5 + B5 --> B6{Valid Data?} + B6 -->|No| B7[Show Error] + B6 -->|Yes| B8{Merge Option?} + B8 -->|Merge| B9[Add to Existing] + B8 -->|Replace| B10[Replace All] + B9 --> B11[Update LocalStorage] + B10 --> B11 + B11 --> B12[Refresh UI] + B12 --> B13[Show Success Notification] + end + + style A1 fill:#64ffda,stroke:#0f0f23,stroke-width:2px + style A7 fill:#10ac84,stroke:#0f0f23,stroke-width:2px + style B1 fill:#64ffda,stroke:#0f0f23,stroke-width:2px + style B11 fill:#764ba2,stroke:#0f0f23,stroke-width:2px + style B7 fill:#ff6b6b,stroke:#0f0f23,stroke-width:2px +``` + +### 🎨 State Management Flow + +```mermaid +stateDiagram-v2 + [*] --> InitialState: App Initialization + + InitialState --> LoadingState: Fetch from LocalStorage + LoadingState --> LoadedState: Data Loaded + + LoadedState --> AddingTransaction: User Adds Transaction + AddingTransaction --> Validating: Validate Input + Validating --> Valid: Input Valid + Validating --> Invalid: Input Invalid + + Valid --> Saving: Save to Storage + Invalid --> ErrorState: Show Error + ErrorState --> AddingTransaction: Retry + + Saving --> Saved: Transaction Saved + Saved --> UpdatingUI: Update UI + UpdatingUI --> LoadedState: Return to Loaded + + LoadedState --> Filtering: User Applies Filter + Filtering --> FilteredState: Display Filtered Results + FilteredState --> LoadedState: Clear Filter + + LoadedState --> Deleting: User Deletes Transaction + Deleting --> Deleted: Transaction Deleted + Deleted --> UpdatingUI + + LoadedState --> Exporting: User Exports Data + Exporting --> Exported: Data Exported + Exported --> LoadedState + + LoadedState --> Importing: User Imports Data + Importing --> Imported: Data Imported + Imported --> UpdatingUI + + note right of LoadedState + Main Application State + - Transactions Array + - Filter Settings + - UI State + end note +``` --- @@ -50,92 +448,232 @@ The app emphasizes: | Category | Technology Used | |-----------|------------------| | **Frontend** | HTML5, CSS3, JavaScript (Vanilla JS) | -| **Styling** | Tailwind CSS / Custom CSS | +| **Styling** | Custom CSS with CSS Variables | +| **Icons** | Font Awesome 6.4.0 | +| **Fonts** | Google Fonts (Inter) | +| **Storage** | LocalStorage API | +| **PWA** | Service Workers, Web App Manifest | | **Version Control** | Git, GitHub | | **Deployment** | GitHub Pages | -| **PWA Support** | manifest.json, sw.js | --- ## πŸ“‚ Folder Structure -ExpenseFlow-expensetracker/ -β”‚
-β”œβ”€β”€ expenseTracker.html # Main HTML layout
-β”œβ”€β”€
expenseTracker.css # Styling and UI components
-β”œβ”€β”€
trackerScript.js # Core JavaScript functionality
-β”œβ”€β”€
manifest.json # Manifest file for PWA
-β”œβ”€β”€
sw.js # Service Worker for offline caching
-β”œβ”€β”€
LICENSE # MIT License
-└──
README.md # Documentation
+``` +ExpenseFlow/ +β”‚ +β”œβ”€β”€ index.html # Main HTML layout +β”œβ”€β”€ expensetracker.css # Styling and UI components +β”œβ”€β”€ trackerscript.js # Core JavaScript functionality +β”œβ”€β”€ manifest.json # PWA Manifest file +β”œβ”€β”€ sw.js # Service Worker for offline caching +β”œβ”€β”€ LICENSE # MIT License +β”œβ”€β”€ README.md # Project documentation +β”œβ”€β”€ CONTRIBUTING.md # Contribution guidelines +β”œβ”€β”€ Code_of_conduct.md # Code of conduct +└── .github/ + └── ISSUE_TEMPLATE/ + └── feature_request.md # Feature request template +``` + --- -## πŸš€ How to Run Locally +## πŸš€ Getting Started + +### Prerequisites + +- A modern web browser (Chrome, Firefox, Safari, Edge) +- A code editor (VS Code, Sublime Text, etc.) +- Git (optional, for version control) + +### Installation + +Follow these simple steps to set up and view the project on your local machine: -Follow these simple steps to set up and view the project on your local machine πŸ‘‡ +#### 1️⃣ Clone the Repository -### 1️⃣ Clone the Repository ```bash git clone https://github.com/Renu-code123/ExpenseFlow-expensetracker.git -### 2️⃣ Navigate into the Project Folder +``` +#### 2️⃣ Navigate into the Project Folder + +```bash cd ExpenseFlow-expensetracker +``` -#3️⃣ Open the HTML File -Simply open the expenseTracker.html file in your browser. +#### 3️⃣ Open the Application -or run a live development server using: +**Option A: Direct Browser Opening** +- Simply open the `index.html` file in your browser. -bash -Copy code +**Option B: Using Live Server (Recommended)** + +```bash +# Using npx (no installation needed) npx live-server +# Or install globally +npm install -g live-server +live-server +``` + +The application will automatically open in your default browser at `http://localhost:8080` + +#### 4️⃣ PWA Installation (Optional) + +1. Open the application in a supported browser +2. Look for the install prompt or browser's install option +3. Click "Install" to add ExpenseFlow to your home screen +4. Enjoy offline functionality! + +--- + +## πŸ“– Usage Guide + +### Adding a Transaction + +1. Scroll to the "Add New Transaction" section +2. Fill in the transaction details: + - **Description**: Enter a brief description (e.g., "Grocery Shopping") + - **Category**: Select from available categories + - **Amount**: Enter the transaction amount + - **Type**: Select "Income" or "Expense" +3. Click "Add Transaction" +4. The transaction will appear in your history and update your balance + +### Filtering Transactions + +- **Type Filter**: Click "All", "Income", or "Expense" buttons +- **Category Filter**: Select a category from the dropdown +- **Search**: Type in the search box to find specific transactions +- **Date Range**: Select "From" and "To" dates +- **Amount Range**: Enter minimum and maximum amounts +- **Clear Filters**: Click "Clear Filters" to reset all filters + +### Exporting Data + +1. Scroll to the "Data Management" section +2. Click "Export to CSV" or "Export to JSON" +3. The file will download automatically +4. Use this file for backup or analysis in spreadsheet applications + +### Importing Data + +1. Scroll to the "Data Management" section +2. Click "Choose File" and select a CSV or JSON file +3. Choose whether to merge with existing data or replace it +4. Click "Import Data" +5. Your transactions will be imported and displayed + +### Deleting Transactions + +- Click the trash icon (πŸ—‘οΈ) next to any transaction +- The transaction will be removed and your balance will update + +--- + +## πŸ”„ Data Flow + +### Transaction Data Structure + +```javascript +{ + id: 123456789, // Unique identifier + text: "Grocery Shopping", // Transaction description + amount: -2500.00, // Amount (negative for expenses) + category: "food", // Category key + type: "expense", // Transaction type + date: "2025-01-15T10:30:00.000Z" // ISO timestamp +} +``` + +### Storage Flow + +```mermaid +graph LR + A[User Input] --> B[Form Validation] + B --> C[Create Transaction Object] + C --> D[Add to Transactions Array] + D --> E[Stringify to JSON] + E --> F[Save to LocalStorage] + F --> G[Update UI] + G --> H[Display Notification] + + style A fill:#64ffda,stroke:#0f0f23,stroke-width:2px + style D fill:#667eea,stroke:#0f0f23,stroke-width:2px + style F fill:#764ba2,stroke:#0f0f23,stroke-width:2px + style G fill:#10ac84,stroke:#0f0f23,stroke-width:2px +``` + +--- + ## πŸ“Έ Screenshots ### 🏠 Dashboard Preview **Smart Money Management – Take control of your finances with our intuitive expense tracker.** +*Note: Add your screenshots here to showcase the application* + --- ## 🧩 Future Enhancements -- πŸ”— Add backend for real-time data persistence (Firebase or Node.js) -- πŸ“Š Integrate charting tools like Chart.js for expense visualization -- 🧾 Introduce login/authentication system -- πŸ’‘ Add category filters for detailed analysis -- πŸ“± Improve PWA support for full offline functionality +- πŸ”— **Backend Integration** – Add backend for real-time data persistence (Firebase or Node.js) +- πŸ“Š **Advanced Charts** – Integrate charting tools like Chart.js for expense visualization +- πŸ” **Authentication** – Introduce login/authentication system +- πŸ’‘ **Budget Management** – Add budget limits and alerts for categories +- πŸ“± **Mobile App** – Native mobile app using React Native or Flutter +- 🌍 **Multi-currency Support** – Support for multiple currencies +- πŸ“§ **Email Reports** – Weekly/monthly expense reports via email +- πŸ€– **AI Insights** – AI-powered spending insights and recommendations +- πŸ”” **Push Notifications** – Reminders for bill payments and budget limits +- πŸ“ˆ **Investment Tracking** – Track investments and portfolio performance --- ## 🎯 Learning Outcomes -By building this project, you’ll learn: +By building this project, you'll learn: -- 🎨 Responsive UI design using CSS -- 🧠 DOM manipulation using vanilla JavaScript -- πŸ“‚ Managing and displaying dynamic user data -- βš™οΈ Working with manifests and service workers -- πŸ—οΈ Structuring a scalable frontend project +- 🎨 **Responsive UI Design** – Creating beautiful, responsive interfaces using CSS +- 🧠 **DOM Manipulation** – Working with the Document Object Model using vanilla JavaScript +- πŸ“‚ **Data Management** – Managing and displaying dynamic user data +- πŸ’Ύ **Local Storage** – Persisting data using the LocalStorage API +- βš™οΈ **PWA Development** – Working with manifests and service workers +- πŸ—οΈ **Project Structure** – Structuring a scalable frontend project +- πŸ”„ **State Management** – Managing application state without frameworks +- 🎯 **Event Handling** – Handling user interactions and events +- πŸ“Š **Data Visualization** – Displaying financial data in an intuitive way +- πŸ§ͺ **Error Handling** – Implementing proper error handling and validation --- ## 🀝 Contributing Contributions are always welcome! -If you’d like to improve **ExpenseFlow**, follow these steps πŸ‘‡ +If you'd like to improve **ExpenseFlow**, follow these steps: 1. **Fork the repository** 2. **Create a new branch** ```bash git checkout -b feature-name + ``` 3. **Commit your changes** -git commit -m "Added a new feature" - + ```bash + git commit -m "Added a new feature" + ``` 4. **Push to your branch** -git push origin feature-name - + ```bash + git push origin feature-name + ``` 5. **Open a Pull Request** +For detailed contribution guidelines, please read [CONTRIBUTING.md](./CONTRIBUTING.md) + +--- + ## 🧾 License This project is licensed under the **MIT License** – see the [LICENSE](./LICENSE) file for details. @@ -147,15 +685,55 @@ This project is licensed under the **MIT License** – see the [LICENSE](./LICEN πŸ“« **Connect with me:** - **GitHub:** [@Renu-code123](https://github.com/Renu-code123) + --- ## πŸ’¬ Quote -> β€œSmart money management begins with awareness β€” track it, plan it, and grow it with **ExpenseFlow**.” +> "Smart money management begins with awareness β€” track it, plan it, and grow it with **ExpenseFlow**." --- ## 🌟 Show Some Love -If you found this project useful, don’t forget to ⭐ **Star** the repository! -Let’s build smarter tools for financial awareness together πŸ’œ +If you found this project useful, don't forget to ⭐ **Star** the repository! +Let's build smarter tools for financial awareness together πŸ’œ + +--- + +## πŸ“Š Project Statistics +- πŸ“ **Total Files**: 8 +- πŸ’» **Lines of Code**: ~2,500+ +- 🎨 **CSS Classes**: 100+ +- ⚑ **JavaScript Functions**: 30+ +- πŸ“± **PWA Ready**: βœ… +- 🌐 **Browser Support**: All modern browsers +- πŸ“¦ **Dependencies**: Zero (Vanilla JS) + +--- + +## πŸ› Known Issues + +- Service Worker caching may require hard refresh on updates +- Large transaction lists (>1000) may experience performance issues +- Date filters use local timezone (UTC conversion coming soon) + +--- + +## πŸ”— Related Projects + +- [Expense Tracker API](https://github.com/example/expense-api) - Backend API for ExpenseFlow +- [ExpenseFlow Mobile](https://github.com/example/expenseflow-mobile) - Mobile app version + +--- + +## πŸ“ž Support + +If you encounter any issues or have questions: + +1. Check the [Issues](https://github.com/Renu-code123/ExpenseFlow-expensetracker/issues) page +2. Read the [Documentation](./CONTRIBUTING.md) +3. Create a new issue with detailed information + +--- +**Made with ❀️ for better financial management** \ No newline at end of file diff --git a/expensetracker.css b/expensetracker.css index 2de4dc25..00e67b93 100644 --- a/expensetracker.css +++ b/expensetracker.css @@ -24,6 +24,11 @@ --error: #ff5722; --warning: #ffc107; + /* Typography */ + --font-primary: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --font-heading: 'Space Grotesk', 'Poppins', sans-serif; + --font-body: 'Inter', 'Poppins', -apple-system, BlinkMacSystemFont, sans-serif; + /* Shadows */ --shadow-glass: 0 8px 32px 0 rgba(31, 38, 135, 0.37); --shadow-hover: 0 15px 35px rgba(0, 0, 0, 0.1); @@ -41,7 +46,7 @@ html { } body { - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + font-family: var(--font-body); background: var(--bg-primary); background-image: radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%), @@ -49,8 +54,16 @@ body { radial-gradient(circle at 40% 40%, rgba(100, 255, 218, 0.2) 0%, transparent 50%); min-height: 100vh; color: var(--text-primary); - line-height: 1.6; + line-height: 1.7; overflow-x: hidden; + margin: 0; + padding: 0; + width: 100%; + box-sizing: border-box; + font-weight: 400; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-rendering: optimizeLegibility; } /* Header Styles */ @@ -81,9 +94,12 @@ body { display: flex; align-items: center; gap: 0.5rem; + font-family: var(--font-heading); font-size: 1.5rem; font-weight: 700; color: var(--accent-primary); + letter-spacing: -0.5px; + text-transform: none; } .nav-logo i { @@ -103,11 +119,16 @@ body { .nav-link { color: var(--text-secondary); text-decoration: none; - font-weight: 500; + font-family: var(--font-primary); + font-weight: 600; + font-size: 0.95rem; + letter-spacing: 0.3px; padding: 0.5rem 1rem; border-radius: 0.5rem; transition: all 0.3s ease; position: relative; + text-transform: uppercase; + font-size: 0.85rem; } .nav-link:hover, @@ -130,8 +151,11 @@ body { } .username { - font-weight: 500; + font-family: var(--font-primary); + font-weight: 600; + font-size: 0.95rem; color: var(--text-primary); + letter-spacing: 0.2px; } .nav-toggle { @@ -151,42 +175,57 @@ body { /* Main Content */ .main-content { - padding-top: 100px; + padding-top: 120px; min-height: 100vh; + width: 100%; + overflow-x: hidden; } .hero-section { text-align: center; padding: 3rem 2rem; max-width: 800px; - margin: 0 auto; + margin: 0 auto 2rem auto; + width: 100%; + box-sizing: border-box; } .hero-title { - font-size: 3.5rem; - font-weight: 700; + font-family: var(--font-heading); + font-size: 4rem; + font-weight: 800; background: var(--primary-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; margin-bottom: 1rem; animation: fadeInUp 1s ease-out; + letter-spacing: -1.5px; + line-height: 1.1; + text-transform: none; } .hero-subtitle { - font-size: 1.2rem; + font-family: var(--font-body); + font-size: 1.3rem; + font-weight: 400; color: var(--text-secondary); margin-bottom: 2rem; animation: fadeInUp 1s ease-out 0.2s both; + letter-spacing: 0.2px; + line-height: 1.6; } .container { max-width: 1200px; margin: 0 auto; padding: 0 2rem; - display: grid; + display: flex; + flex-direction: column; gap: 2rem; margin-bottom: 4rem; + width: 100%; + box-sizing: border-box; } /* Balance Card */ @@ -200,6 +239,9 @@ body { box-shadow: var(--shadow-glass); transition: transform 0.3s ease, box-shadow 0.3s ease; animation: fadeInUp 1s ease-out 0.4s both; + width: 100%; + box-sizing: border-box; + margin-bottom: 0; } .balance-card:hover { @@ -221,19 +263,23 @@ body { } .balance-header h4 { + font-family: var(--font-heading); color: var(--text-secondary); - font-weight: 500; + font-weight: 600; text-transform: uppercase; - letter-spacing: 1px; - font-size: 0.9rem; + letter-spacing: 2px; + font-size: 0.85rem; } .balance-amount { - font-size: 3rem; - font-weight: 700; + font-family: var(--font-heading); + font-size: 3.5rem; + font-weight: 800; color: var(--text-primary); margin: 1rem 0; text-shadow: 0 0 20px rgba(100, 255, 218, 0.3); + letter-spacing: -1px; + line-height: 1.2; } .balance-trend { @@ -263,6 +309,9 @@ body { grid-template-columns: 1fr 1fr; gap: 1.5rem; animation: fadeInUp 1s ease-out 0.6s both; + width: 100%; + box-sizing: border-box; + margin-bottom: 0; } .income-card, @@ -305,24 +354,29 @@ body { } .card-content h4 { + font-family: var(--font-heading); color: var(--text-secondary); - font-size: 0.9rem; - font-weight: 500; + font-size: 0.85rem; + font-weight: 600; text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 2px; margin-bottom: 0.5rem; } .money-plus { + font-family: var(--font-heading); color: var(--success); - font-size: 1.5rem; - font-weight: 600; + font-size: 1.75rem; + font-weight: 700; + letter-spacing: -0.5px; } .money-minus { + font-family: var(--font-heading); color: var(--error); - font-size: 1.5rem; - font-weight: 600; + font-size: 1.75rem; + font-weight: 700; + letter-spacing: -0.5px; } /* History Section */ @@ -334,6 +388,10 @@ body { padding: 2rem; box-shadow: var(--shadow-glass); animation: fadeInUp 1s ease-out 0.8s both; + width: 100%; + box-sizing: border-box; + margin-top: 0; + margin-bottom: 0; } .section-header { @@ -344,15 +402,17 @@ body { } .section-header h3 { + font-family: var(--font-heading); color: var(--text-primary); - font-size: 1.3rem; - font-weight: 600; + font-size: 1.5rem; + font-weight: 700; display: flex; align-items: center; gap: 0.5rem; border-bottom: none; padding-bottom: 0; margin: 0; + letter-spacing: -0.3px; } .section-header h3 i { @@ -484,6 +544,7 @@ body { } .filter-btn { + font-family: var(--font-primary); padding: 0.5rem 1rem; border: 1px solid rgba(255, 255, 255, 0.2); background: transparent; @@ -492,7 +553,9 @@ body { cursor: pointer; transition: all 0.3s ease; font-size: 0.9rem; - font-weight: 500; + font-weight: 600; + letter-spacing: 0.5px; + text-transform: uppercase; } .filter-btn:hover, @@ -590,6 +653,10 @@ body { border: 1px solid rgba(255, 255, 255, 0.1); padding: 2rem; box-shadow: var(--shadow-glass); + width: 100%; + box-sizing: border-box; + margin-top: 0; + margin-bottom: 0; animation: fadeInUp 1s ease-out 0.9s both; } @@ -737,18 +804,24 @@ body { padding: 2rem; box-shadow: var(--shadow-glass); animation: fadeInUp 1s ease-out 1s both; + width: 100%; + box-sizing: border-box; + margin-top: 0; + margin-bottom: 0; } .form-section h3 { + font-family: var(--font-heading); color: var(--text-primary); - font-size: 1.3rem; - font-weight: 600; + font-size: 1.5rem; + font-weight: 700; display: flex; align-items: center; gap: 0.5rem; margin-bottom: 1.5rem; border-bottom: none; padding-bottom: 0; + letter-spacing: -0.3px; } .form-section h3 i { @@ -774,14 +847,16 @@ body { } .form-control label { + font-family: var(--font-heading); color: var(--text-secondary); - font-weight: 500; - font-size: 0.9rem; + font-weight: 600; + font-size: 0.85rem; text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 1.5px; } .form-control input { + font-family: var(--font-body); padding: 1rem; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 10px; @@ -789,7 +864,9 @@ body { backdrop-filter: blur(10px); color: var(--text-primary); font-size: 1rem; + font-weight: 400; transition: all 0.3s ease; + letter-spacing: 0.2px; } .form-control input:focus { @@ -803,6 +880,7 @@ body { } .form-control select { + font-family: var(--font-body); padding: 1rem; border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 10px; @@ -810,8 +888,10 @@ body { backdrop-filter: blur(10px); color: var(--text-primary); font-size: 1rem; + font-weight: 400; transition: all 0.3s ease; cursor: pointer; + letter-spacing: 0.2px; } .form-control select:focus { @@ -833,13 +913,14 @@ body { } .btn-submit { + font-family: var(--font-heading); padding: 1rem 2rem; background: var(--primary-gradient); color: white; border: none; border-radius: 10px; font-size: 1rem; - font-weight: 600; + font-weight: 700; cursor: pointer; transition: all 0.3s ease; display: flex; @@ -847,7 +928,7 @@ body { justify-content: center; gap: 0.5rem; text-transform: uppercase; - letter-spacing: 1px; + letter-spacing: 2px; } .btn-submit:hover { @@ -1198,6 +1279,39 @@ body { .data-actions { grid-template-columns: 1fr; } + + .container { + gap: 1.5rem; + } + + .main-content { + padding-top: 100px; + } + + .hero-section { + padding: 2rem 1rem; + } + + .hero-title { + font-size: 2.5rem; + } + + .inc-exp-container { + grid-template-columns: 1fr; + gap: 1rem; + } + + .balance-card, + .history-section, + .data-management-section, + .form-section { + padding: 1.5rem; + } + + .app-section { + width: 100%; + overflow-x: hidden; + } } /* PWA Install Prompt */ @@ -1440,3 +1554,669 @@ body { right: max(20px, env(safe-area-inset-right) + 20px); } } + +/* Section Navigation Styles */ +.app-section { + display: none; + animation: fadeIn 0.5s ease-in-out; + width: 100%; + box-sizing: border-box; + position: relative; +} + +.app-section.active { + display: block; + width: 100%; + box-sizing: border-box; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.section-header { + margin-bottom: 2rem; + text-align: center; +} + +.section-header h2 { + font-size: 2.5rem; + margin-bottom: 0.5rem; + color: var(--accent-primary); + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; +} + +.section-description { + color: var(--text-secondary); + font-size: 1.1rem; +} + +/* Analytics Section */ +.analytics-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 2rem; + margin-bottom: 2rem; +} + +.analytics-card { + background: var(--bg-secondary); + border-radius: 20px; + padding: 2rem; + border: 1px solid rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.analytics-card:hover { + transform: translateY(-5px); + box-shadow: var(--shadow-card); +} + +.analytics-card-header { + display: flex; + align-items: center; + gap: 1rem; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.analytics-card-header i { + font-size: 2rem; + color: var(--accent-primary); +} + +.analytics-card-header h3 { + font-size: 1.5rem; + color: var(--text-primary); +} + +.chart-placeholder { + text-align: center; + padding: 3rem 1rem; + color: var(--text-secondary); +} + +.chart-placeholder i { + margin-bottom: 1rem; + opacity: 0.5; +} + +.category-list { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.category-stat-item { + padding: 1rem; + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; +} + +.category-stat-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; +} + +.category-icon { + font-size: 1.1rem; +} + +.category-total { + font-weight: 600; + color: var(--accent-primary); +} + +.category-stat-bars { + display: flex; + height: 8px; + border-radius: 4px; + overflow: hidden; + background: rgba(255, 255, 255, 0.1); +} + +.stat-bar { + height: 100%; + transition: width 0.3s ease; +} + +.income-bar { + background: var(--success); +} + +.expense-bar { + background: var(--error); +} + +.analytics-summary { + margin-top: 2rem; +} + +.summary-card { + background: var(--bg-secondary); + border-radius: 20px; + padding: 2rem; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.summary-card h4 { + font-size: 1.5rem; + margin-bottom: 1.5rem; + color: var(--accent-primary); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.stats-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; +} + +.stat-item { + display: flex; + flex-direction: column; + gap: 0.5rem; + padding: 1rem; + background: rgba(255, 255, 255, 0.05); + border-radius: 10px; +} + +.stat-label { + font-size: 0.9rem; + color: var(--text-secondary); +} + +.stat-value { + font-size: 1.5rem; + font-weight: 700; + color: var(--accent-primary); +} + +/* Goals Section */ +.goals-container { + max-width: 1200px; + margin: 0 auto; +} + +.goals-header-actions { + margin-bottom: 2rem; + display: flex; + justify-content: flex-end; +} + +.goals-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 2rem; +} + +.goal-card { + background: var(--bg-secondary); + border-radius: 20px; + padding: 2rem; + border: 1px solid rgba(255, 255, 255, 0.1); + transition: transform 0.3s ease, box-shadow 0.3s ease; +} + +.goal-card:hover { + transform: translateY(-5px); + box-shadow: var(--shadow-card); +} + +.goal-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; +} + +.goal-header h3 { + font-size: 1.5rem; + color: var(--text-primary); +} + +.goal-delete { + background: transparent; + border: none; + color: var(--error); + cursor: pointer; + padding: 0.5rem; + border-radius: 5px; + transition: background 0.3s ease; +} + +.goal-delete:hover { + background: rgba(255, 87, 34, 0.2); +} + +.goal-progress { + margin-bottom: 1.5rem; +} + +.progress-bar { + height: 12px; + background: rgba(255, 255, 255, 0.1); + border-radius: 10px; + overflow: hidden; + margin-bottom: 0.5rem; +} + +.progress-fill { + height: 100%; + background: var(--primary-gradient); + border-radius: 10px; + transition: width 0.5s ease; +} + +.progress-text { + display: flex; + justify-content: space-between; + font-size: 0.9rem; + color: var(--text-secondary); +} + +.goal-details { + display: flex; + gap: 1.5rem; + margin-bottom: 1rem; +} + +.goal-detail-item { + display: flex; + align-items: center; + gap: 0.5rem; + color: var(--text-secondary); + font-size: 0.9rem; +} + +.goal-description { + color: var(--text-secondary); + font-size: 0.9rem; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid rgba(255, 255, 255, 0.1); +} + +.empty-goals { + grid-column: 1 / -1; + text-align: center; + padding: 4rem 2rem; + color: var(--text-secondary); +} + +.empty-goals i { + margin-bottom: 1rem; + opacity: 0.5; +} + +.empty-goals h3 { + margin-bottom: 0.5rem; + color: var(--text-primary); +} + +/* Modal Styles */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + backdrop-filter: blur(5px); + z-index: 10000; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.modal-content { + background: var(--bg-secondary); + border-radius: 20px; + padding: 2rem; + max-width: 500px; + width: 100%; + max-height: 90vh; + overflow-y: auto; + border: 1px solid rgba(255, 255, 255, 0.1); + animation: slideInDown 0.3s ease; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.modal-header h3 { + font-size: 1.5rem; + color: var(--accent-primary); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.modal-close { + background: transparent; + border: none; + color: var(--text-secondary); + cursor: pointer; + font-size: 1.5rem; + padding: 0.5rem; + border-radius: 5px; + transition: background 0.3s ease; +} + +.modal-close:hover { + background: rgba(255, 255, 255, 0.1); +} + +.goal-form .form-group { + margin-bottom: 1.5rem; +} + +.goal-form label { + display: block; + margin-bottom: 0.5rem; + color: var(--text-primary); + font-weight: 500; +} + +.goal-form input, +.goal-form textarea { + width: 100%; + padding: 0.75rem; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + color: var(--text-primary); + font-size: 1rem; + font-family: inherit; +} + +.goal-form input:focus, +.goal-form textarea:focus { + outline: none; + border-color: var(--accent-primary); + box-shadow: 0 0 0 3px rgba(100, 255, 218, 0.1); +} + +.modal-actions { + display: flex; + gap: 1rem; + justify-content: flex-end; + margin-top: 2rem; +} + +/* Settings Section */ +.settings-container { + max-width: 900px; + margin: 0 auto; +} + +.settings-section { + margin-bottom: 3rem; +} + +.settings-section h3 { + font-size: 1.8rem; + margin-bottom: 1.5rem; + color: var(--accent-primary); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.settings-card { + background: var(--bg-secondary); + border-radius: 20px; + padding: 2rem; + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.setting-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem 0; + border-bottom: 1px solid rgba(255, 255, 255, 0.1); +} + +.setting-item:last-child { + border-bottom: none; +} + +.setting-info { + flex: 1; +} + +.setting-info label { + display: block; + font-weight: 600; + color: var(--text-primary); + margin-bottom: 0.25rem; +} + +.setting-info p { + font-size: 0.9rem; + color: var(--text-secondary); +} + +.setting-input, +.setting-select { + padding: 0.75rem; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + color: var(--text-primary); + font-size: 1rem; + min-width: 200px; +} + +.setting-input:focus, +.setting-select:focus { + outline: none; + border-color: var(--accent-primary); + box-shadow: 0 0 0 3px rgba(100, 255, 218, 0.1); +} + +.theme-options { + display: flex; + gap: 1rem; +} + +.theme-btn { + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.05); + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + color: var(--text-primary); + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.theme-btn:hover { + background: rgba(255, 255, 255, 0.1); +} + +.theme-btn.active { + background: var(--primary-gradient); + border-color: transparent; +} + +.color-picker { + width: 60px; + height: 40px; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 10px; + cursor: pointer; + background: transparent; +} + +.toggle-switch { + position: relative; + display: inline-block; + width: 60px; + height: 30px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +.toggle-slider { + position: absolute; + cursor: pointer; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.2); + transition: 0.3s; + border-radius: 30px; +} + +.toggle-slider:before { + position: absolute; + content: ""; + height: 22px; + width: 22px; + left: 4px; + bottom: 4px; + background-color: white; + transition: 0.3s; + border-radius: 50%; +} + +.toggle-switch input:checked + .toggle-slider { + background: var(--primary-gradient); +} + +.toggle-switch input:checked + .toggle-slider:before { + transform: translateX(30px); +} + +.btn-danger { + background: linear-gradient(135deg, #ff5722 0%, #f44336 100%); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 10px; + cursor: pointer; + font-weight: 600; + transition: transform 0.3s ease, box-shadow 0.3s ease; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.btn-danger:hover { + transform: translateY(-2px); + box-shadow: 0 5px 15px rgba(255, 87, 34, 0.4); +} + +.about-info { + text-align: center; + color: var(--text-secondary); +} + +.about-info p { + margin-bottom: 1rem; +} + +.about-info strong { + color: var(--accent-primary); + font-size: 1.2rem; +} + +.about-links { + display: flex; + gap: 1rem; + justify-content: center; + margin-top: 1.5rem; +} + +.about-links a { + color: var(--accent-primary); + text-decoration: none; + padding: 0.5rem 1rem; + border: 1px solid var(--accent-primary); + border-radius: 10px; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.about-links a:hover { + background: var(--accent-primary); + color: var(--bg-primary); +} + +/* Footer Links */ +.footer-link { + transition: color 0.3s ease; +} + +.footer-link:hover { + color: var(--accent-primary); +} + +/* Responsive Design for New Sections */ +@media (max-width: 768px) { + .analytics-grid { + grid-template-columns: 1fr; + } + + .goals-grid { + grid-template-columns: 1fr; + } + + .stats-grid { + grid-template-columns: 1fr; + } + + .setting-item { + flex-direction: column; + align-items: flex-start; + gap: 1rem; + } + + .setting-input, + .setting-select { + width: 100%; + min-width: auto; + } + + .section-header h2 { + font-size: 2rem; + } + + .modal-content { + padding: 1.5rem; + } +} \ No newline at end of file diff --git a/index.html b/index.html index 25893913..ace03a0e 100644 --- a/index.html +++ b/index.html @@ -26,7 +26,7 @@ - + @@ -65,6 +65,8 @@

Smart Money Management

+ +
@@ -239,6 +241,293 @@

Add New Transaction

+
+ + +
+
+

Analytics Dashboard

+

Visualize your spending patterns and financial insights

+
+ +
+
+
+ +

Spending by Category

+
+
+
+ +

Category breakdown will appear here

+ Add transactions to see analytics +
+
+
+ +
+
+ +

Monthly Overview

+
+
+
+ +

Monthly trends will appear here

+ Track your spending over time +
+
+
+ +
+
+ +

Top Categories

+
+
+
+

No category data available

+
+
+
+ +
+
+ +

Spending Trends

+
+ +
+
+ +
+
+

Quick Stats

+
+
+ Total Transactions + 0 +
+
+ Average Expense + β‚Ή0.00 +
+
+ Average Income + β‚Ή0.00 +
+
+ Savings Rate + 0% +
+
+
+
+
+ + +
+
+

Financial Goals

+

Set and track your financial objectives

+
+ +
+
+ +
+ +
+
+ +

No Goals Set Yet

+

Start by creating your first financial goal

+ +
+
+
+ + + +
+ + +
+
+

Settings

+

Customize your ExpenseFlow experience

+
+ +
+
+

Profile Settings

+
+
+
+ +

Change your display name

+
+ +
+
+
+ +

Select your preferred currency

+
+ +
+
+
+ +
+

Appearance

+
+
+
+ +

Choose your preferred theme

+
+
+ + +
+
+
+
+ +

Customize accent color

+
+
+ +
+
+
+
+ +
+

Notifications

+
+
+
+ +

Receive notifications for important updates

+
+ +
+
+
+ +

Get notified when approaching budget limits

+
+ +
+
+
+ +
+

Data Management

+
+
+
+ +

Download a backup of all your data

+
+ +
+
+
+ +

Permanently delete all transactions and settings

+
+ +
+
+
+ +
+

About

+
+
+

ExpenseFlow v1.0.0

+

Smart money management made simple

+ +
+
+
+
+
@@ -262,30 +551,30 @@

Add New Transaction

diff --git a/manifest.json b/manifest.json index dcb643f1..bf006522 100644 --- a/manifest.json +++ b/manifest.json @@ -3,12 +3,12 @@ "short_name": "ExpenseFlow", "description": "Take control of your finances with our intuitive expense tracker", "version": "1.0.0", - "start_url": "/expensetracker.html", + "start_url": "./index.html", "display": "standalone", "background_color": "#0f0f23", "theme_color": "#64ffda", "orientation": "portrait-primary", - "scope": "/", + "scope": "./", "lang": "en-US", "dir": "ltr", "categories": ["finance", "productivity", "utilities"], @@ -45,7 +45,7 @@ "name": "Add Transaction", "short_name": "Add", "description": "Quickly add a new transaction", - "url": "/expensetracker.html#form", + "url": "./index.html#dashboard", "icons": [ { "src": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOTYiIGhlaWdodD0iOTYiIHZpZXdCb3g9IjAgMCA5NiA5NiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iNDgiIGN5PSI0OCIgcj0iNDgiIGZpbGw9IiM2NGZmZGEiLz4KPHBhdGggZD0iTTQ4IDI0VjcyTTI0IDQ4SDcyIiBzdHJva2U9IiMwZjBmMjMiIHN0cm9rZS13aWR0aD0iNCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=", diff --git a/sw.js b/sw.js index dc0c4362..bb6770a9 100644 --- a/sw.js +++ b/sw.js @@ -1,9 +1,10 @@ const CACHE_NAME = 'expenseflow-v1.0.0'; const urlsToCache = [ - '/expensetracker.html', - '/expensetracker.css', - '/trackerscript.js', - '/manifest.json', + './', + './index.html', + './expensetracker.css', + './trackerscript.js', + './manifest.json', 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css' ]; @@ -80,7 +81,7 @@ self.addEventListener('fetch', (event) => { // Return a custom offline page or response for HTML requests if (event.request.destination === 'document') { - return caches.match('/expensetracker.html'); + return caches.match('./index.html') || caches.match('./'); } // For other resources, you might want to return a default response @@ -139,7 +140,7 @@ self.addEventListener('notificationclick', (event) => { if (event.action === 'explore') { // Open the app event.waitUntil( - clients.openWindow('/expensetracker.html') + clients.openWindow('./index.html') ); } else if (event.action === 'close') { // Just close the notification @@ -147,7 +148,7 @@ self.addEventListener('notificationclick', (event) => { } else { // Default action - open the app event.waitUntil( - clients.openWindow('/expensetracker.html') + clients.openWindow('./index.html') ); } }); diff --git a/trackerscript.js b/trackerscript.js index 2caad47b..abef7fd3 100644 --- a/trackerscript.js +++ b/trackerscript.js @@ -57,32 +57,71 @@ if (navToggle) { }); } +// Section Navigation System +function showSection(sectionId) { + // Hide all sections + document.querySelectorAll('.app-section').forEach(section => { + section.classList.remove('active'); + }); + + // Show target section + const targetSection = document.getElementById(sectionId); + if (targetSection) { + targetSection.classList.add('active'); + + // Update URL hash + window.history.pushState(null, null, `#${sectionId}`); + + // Update active nav link + document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active')); + const activeLink = document.querySelector(`.nav-link[href="#${sectionId}"]`); + if (activeLink) { + activeLink.classList.add('active'); + } + + // Scroll to top of page + window.scrollTo({ top: 0, behavior: 'smooth' }); + + // Update analytics if navigating to analytics section + if (sectionId === 'analytics') { + setTimeout(() => updateAnalytics(), 100); + } + + // Update goals if navigating to goals section + if (sectionId === 'goals') { + setTimeout(() => displayGoals(), 100); + } + } +} + // Navigation Links document.querySelectorAll('.nav-link').forEach(link => { link.addEventListener('click', (e) => { e.preventDefault(); - // Remove active class from all links - document.querySelectorAll('.nav-link').forEach(l => l.classList.remove('active')); - - // Add active class to clicked link - link.classList.add('active'); + const targetId = link.getAttribute('href'); + if (targetId.startsWith('#')) { + const sectionId = targetId.substring(1); + showSection(sectionId); + } // Close mobile menu if open - if (navMenu.classList.contains('active')) { + if (navMenu && navMenu.classList.contains('active')) { navMenu.classList.remove('active'); - navToggle.classList.remove('active'); + if (navToggle) navToggle.classList.remove('active'); } - - // Smooth scroll to section if it exists - const targetId = link.getAttribute('href'); - if (targetId.startsWith('#')) { - const targetElement = document.querySelector(targetId); - if (targetElement) { - targetElement.scrollIntoView({ - behavior: 'smooth', - block: 'start' - }); + }); +}); + +// Footer Links Navigation +document.querySelectorAll('.footer-link').forEach(link => { + link.addEventListener('click', (e) => { + const href = link.getAttribute('href'); + if (href && href.startsWith('#')) { + e.preventDefault(); + const sectionId = href.substring(1); + if (document.getElementById(sectionId)) { + showSection(sectionId); } } }); @@ -266,6 +305,12 @@ function addTransaction(e) { updateValues(); updateLocalStorage(); + // Update analytics if on analytics page + const analyticsSection = document.getElementById('analytics'); + if (analyticsSection && analyticsSection.classList.contains('active')) { + updateAnalytics(); + } + // Clear form text.value = ''; amount.value = ''; @@ -273,7 +318,8 @@ function addTransaction(e) { type.value = ''; // Show success notification - showNotification(`${type.value.charAt(0).toUpperCase() + type.value.slice(1)} added successfully!`, 'success'); + const transactionType = type.value || 'transaction'; + showNotification(`${transactionType.charAt(0).toUpperCase() + transactionType.slice(1)} added successfully!`, 'success'); } // Generate Random ID @@ -448,6 +494,12 @@ function removeTransaction(id) { displayTransactions(); updateValues(); + // Update analytics if on analytics page + const analyticsSection = document.getElementById('analytics'); + if (analyticsSection && analyticsSection.classList.contains('active')) { + updateAnalytics(); + } + // Show notification showNotification('Transaction deleted successfully', 'success'); } @@ -809,7 +861,11 @@ const updateButton = document.getElementById('update-button'); // Service Worker Registration if ('serviceWorker' in navigator) { window.addEventListener('load', () => { - navigator.serviceWorker.register('/sw.js') + // Get the base path for service worker registration + const basePath = window.location.pathname.split('/').slice(0, -1).join('/') || '.'; + const swPath = basePath === '.' ? './sw.js' : `${basePath}/sw.js`; + + navigator.serviceWorker.register(swPath, { scope: basePath === '.' ? './' : basePath }) .then((registration) => { console.log('SW registered: ', registration); @@ -825,6 +881,10 @@ if ('serviceWorker' in navigator) { }) .catch((registrationError) => { console.log('SW registration failed: ', registrationError); + // Fallback to simple path + navigator.serviceWorker.register('./sw.js').catch(err => { + console.log('Fallback SW registration also failed: ', err); + }); }); }); } @@ -904,7 +964,324 @@ Init(); // Event Listeners form.addEventListener('submit', addTransaction); -// Add smooth scroll behavior +// Analytics Functions +function updateAnalytics() { + if (transactions.length === 0) { + return; + } + + // Calculate category totals + const categoryTotals = {}; + transactions.forEach(transaction => { + const category = transaction.category || 'other'; + if (!categoryTotals[category]) { + categoryTotals[category] = { income: 0, expense: 0 }; + } + if (transaction.amount > 0) { + categoryTotals[category].income += transaction.amount; + } else { + categoryTotals[category].expense += Math.abs(transaction.amount); + } + }); + + // Display top categories + const categoryList = document.getElementById('category-list'); + if (categoryList) { + const sortedCategories = Object.entries(categoryTotals) + .sort((a, b) => (b[1].expense + b[1].income) - (a[1].expense + a[1].income)) + .slice(0, 5); + + if (sortedCategories.length > 0) { + categoryList.innerHTML = sortedCategories.map(([key, value]) => { + const categoryInfo = categories[key] || categories.other; + const total = value.income + value.expense; + const incomePercent = total > 0 ? (value.income / total) * 100 : 0; + const expensePercent = total > 0 ? (value.expense / total) * 100 : 0; + return ` +
+
+ ${categoryInfo.name} + β‚Ή${total.toFixed(2)} +
+
+
+
+
+
+ `; + }).join(''); + } else { + categoryList.innerHTML = '

No category data available

'; + } + } + + // Update stats + const totalTransactions = transactions.length; + const expenses = transactions.filter(t => t.amount < 0); + const incomes = transactions.filter(t => t.amount > 0); + const avgExpense = expenses.length > 0 + ? expenses.reduce((sum, t) => sum + Math.abs(t.amount), 0) / expenses.length + : 0; + const avgIncome = incomes.length > 0 + ? incomes.reduce((sum, t) => sum + t.amount, 0) / incomes.length + : 0; + const totalIncome = incomes.reduce((sum, t) => sum + t.amount, 0); + const totalExpense = expenses.reduce((sum, t) => sum + Math.abs(t.amount), 0); + const savingsRate = totalIncome > 0 ? ((totalIncome - totalExpense) / totalIncome * 100).toFixed(1) : 0; + + const totalTransactionsEl = document.getElementById('total-transactions'); + const avgExpenseEl = document.getElementById('avg-expense'); + const avgIncomeEl = document.getElementById('avg-income'); + const savingsRateEl = document.getElementById('savings-rate'); + + if (totalTransactionsEl) totalTransactionsEl.textContent = totalTransactions; + if (avgExpenseEl) avgExpenseEl.textContent = `β‚Ή${avgExpense.toFixed(2)}`; + if (avgIncomeEl) avgIncomeEl.textContent = `β‚Ή${avgIncome.toFixed(2)}`; + if (savingsRateEl) savingsRateEl.textContent = `${savingsRate}%`; +} + +// Goals Management +let goals = JSON.parse(localStorage.getItem('goals')) || []; + +function saveGoals() { + localStorage.setItem('goals', JSON.stringify(goals)); +} + +function displayGoals() { + const goalsGrid = document.getElementById('goals-grid'); + if (!goalsGrid) return; + + if (goals.length === 0) { + goalsGrid.innerHTML = ` +
+ +

No Goals Set Yet

+

Start by creating your first financial goal

+ +
+ `; + return; + } + + goalsGrid.innerHTML = goals.map((goal, index) => { + const progress = (goal.current / goal.amount) * 100; + const daysRemaining = Math.ceil((new Date(goal.deadline) - new Date()) / (1000 * 60 * 60 * 24)); + const remaining = goal.amount - goal.current; + + return ` +
+
+

${goal.title}

+ +
+
+
+
+
+
+ β‚Ή${goal.current.toFixed(2)} / β‚Ή${goal.amount.toFixed(2)} + ${progress.toFixed(1)}% +
+
+
+
+ + ${daysRemaining > 0 ? `${daysRemaining} days left` : 'Deadline passed'} +
+
+ + β‚Ή${remaining.toFixed(2)} remaining +
+
+ ${goal.description ? `

${goal.description}

` : ''} +
+ `; + }).join(''); +} + +function deleteGoal(index) { + if (confirm('Are you sure you want to delete this goal?')) { + goals.splice(index, 1); + saveGoals(); + displayGoals(); + showNotification('Goal deleted successfully', 'success'); + } +} + +// Goals Form Handler +const goalForm = document.getElementById('goal-form'); +const goalModal = document.getElementById('goal-modal'); +const addGoalBtn = document.getElementById('add-goal-btn'); +const closeGoalModal = document.getElementById('close-goal-modal'); +const cancelGoal = document.getElementById('cancel-goal'); + +if (addGoalBtn) { + addGoalBtn.addEventListener('click', () => { + if (goalModal) goalModal.style.display = 'flex'; + }); +} + +if (closeGoalModal) { + closeGoalModal.addEventListener('click', () => { + if (goalModal) goalModal.style.display = 'none'; + if (goalForm) goalForm.reset(); + }); +} + +if (cancelGoal) { + cancelGoal.addEventListener('click', () => { + if (goalModal) goalModal.style.display = 'none'; + if (goalForm) goalForm.reset(); + }); +} + +if (goalForm) { + goalForm.addEventListener('submit', (e) => { + e.preventDefault(); + + const title = document.getElementById('goal-title').value; + const amount = parseFloat(document.getElementById('goal-amount').value); + const current = parseFloat(document.getElementById('goal-current').value) || 0; + const deadline = document.getElementById('goal-deadline').value; + const description = document.getElementById('goal-description').value; + + if (!title || !amount || !deadline) { + showNotification('Please fill in all required fields', 'error'); + return; + } + + const newGoal = { + id: Date.now(), + title, + amount, + current, + deadline, + description, + createdAt: new Date().toISOString() + }; + + goals.push(newGoal); + saveGoals(); + displayGoals(); + goalForm.reset(); + if (goalModal) goalModal.style.display = 'none'; + showNotification('Goal created successfully!', 'success'); + }); +} + +// Settings Functions +const displayNameInput = document.getElementById('display-name'); +const currencySelect = document.getElementById('currency-select'); +const accentColorInput = document.getElementById('accent-color'); +const notificationsEnabled = document.getElementById('notifications-enabled'); +const budgetAlerts = document.getElementById('budget-alerts'); +const exportAllDataBtn = document.getElementById('export-all-data'); +const clearAllDataBtn = document.getElementById('clear-all-data'); + +// Load settings +function loadSettings() { + const settings = JSON.parse(localStorage.getItem('settings')) || {}; + + if (displayNameInput) displayNameInput.value = settings.displayName || 'John Doe'; + if (currencySelect) currencySelect.value = settings.currency || 'INR'; + if (accentColorInput) accentColorInput.value = settings.accentColor || '#64ffda'; + if (notificationsEnabled) notificationsEnabled.checked = settings.notificationsEnabled !== false; + if (budgetAlerts) budgetAlerts.checked = settings.budgetAlerts !== false; +} + +// Save settings +function saveSettings() { + const settings = { + displayName: displayNameInput ? displayNameInput.value : 'John Doe', + currency: currencySelect ? currencySelect.value : 'INR', + accentColor: accentColorInput ? accentColorInput.value : '#64ffda', + notificationsEnabled: notificationsEnabled ? notificationsEnabled.checked : true, + budgetAlerts: budgetAlerts ? budgetAlerts.checked : true + }; + localStorage.setItem('settings', JSON.stringify(settings)); + + // Update username display + const usernameSpan = document.querySelector('.username'); + if (usernameSpan && displayNameInput) { + usernameSpan.textContent = displayNameInput.value; + } + + showNotification('Settings saved successfully', 'success'); +} + +// Settings event listeners +if (displayNameInput) { + displayNameInput.addEventListener('change', saveSettings); +} +if (currencySelect) { + currencySelect.addEventListener('change', saveSettings); +} +if (accentColorInput) { + accentColorInput.addEventListener('change', () => { + saveSettings(); + document.documentElement.style.setProperty('--accent-primary', accentColorInput.value); + }); +} +if (notificationsEnabled) { + notificationsEnabled.addEventListener('change', saveSettings); +} +if (budgetAlerts) { + budgetAlerts.addEventListener('change', saveSettings); +} + +// Export all data +if (exportAllDataBtn) { + exportAllDataBtn.addEventListener('click', () => { + const allData = { + transactions, + goals, + settings: JSON.parse(localStorage.getItem('settings')) || {}, + exportDate: new Date().toISOString() + }; + + const blob = new Blob([JSON.stringify(allData, null, 2)], { type: 'application/json' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = `expenseflow-backup-${new Date().toISOString().split('T')[0]}.json`; + link.click(); + showNotification('All data exported successfully', 'success'); + }); +} + +// Clear all data +if (clearAllDataBtn) { + clearAllDataBtn.addEventListener('click', () => { + if (confirm('Are you sure you want to delete ALL data? This action cannot be undone!')) { + localStorage.clear(); + transactions = []; + goals = []; + updateLocalStorage(); + saveGoals(); + displayTransactions(); + updateValues(); + displayGoals(); + loadSettings(); + showNotification('All data cleared successfully', 'success'); + } + }); +} + +// Theme switcher +document.querySelectorAll('.theme-btn').forEach(btn => { + btn.addEventListener('click', () => { + document.querySelectorAll('.theme-btn').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + const theme = btn.getAttribute('data-theme'); + // Theme switching can be implemented here + showNotification(`Theme changed to ${theme}`, 'info'); + }); +}); + +// Initialize on page load document.addEventListener('DOMContentLoaded', function() { // Add loading animation document.body.style.opacity = '0'; @@ -912,4 +1289,48 @@ document.addEventListener('DOMContentLoaded', function() { document.body.style.transition = 'opacity 0.5s ease-in-out'; document.body.style.opacity = '1'; }, 100); + + // Show dashboard section by default + const hash = window.location.hash.substring(1); + if (hash && document.getElementById(hash)) { + showSection(hash); + } else { + showSection('dashboard'); + } + + // Handle hash changes + window.addEventListener('hashchange', () => { + const hash = window.location.hash.substring(1); + if (hash && document.getElementById(hash)) { + showSection(hash); + } + }); + + // Load settings + loadSettings(); + + // Display goals + displayGoals(); + + // Update analytics + updateAnalytics(); + + // Close modal when clicking outside + if (goalModal) { + goalModal.addEventListener('click', (e) => { + if (e.target === goalModal) { + goalModal.style.display = 'none'; + if (goalForm) goalForm.reset(); + } + }); + } + + // Hook into transaction updates to refresh analytics + const originalUpdateLocalStorage = updateLocalStorage; + updateLocalStorage = function() { + originalUpdateLocalStorage(); + if (document.getElementById('analytics') && document.getElementById('analytics').classList.contains('active')) { + updateAnalytics(); + } + }; }); From dfc00cab4bcf4fe29b0c840bc8b565b99a6d8a5f Mon Sep 17 00:00:00 2001 From: Hussain Date: Mon, 19 Jan 2026 21:33:33 +0530 Subject: [PATCH 2/2] Fix: Align file structure and resolve merge issues - Update expense tracker UI and functionality --- expensetracker.css | 289 ++++++++++++++++++++++++++++++++++++--------- index.html | 4 +- 2 files changed, 238 insertions(+), 55 deletions(-) diff --git a/expensetracker.css b/expensetracker.css index 00e67b93..82db8840 100644 --- a/expensetracker.css +++ b/expensetracker.css @@ -228,25 +228,55 @@ body { box-sizing: border-box; } -/* Balance Card */ +/* Balance Card - Redesigned */ .balance-card { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(20px); - border-radius: 20px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 2rem; + background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); + backdrop-filter: blur(30px); + border-radius: 24px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 2.5rem; text-align: center; - box-shadow: var(--shadow-glass); - transition: transform 0.3s ease, box-shadow 0.3s ease; + position: relative; + overflow: hidden; + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.4), + 0 0 0 1px rgba(255, 255, 255, 0.1) inset, + 0 0 60px rgba(100, 255, 218, 0.1); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); animation: fadeInUp 1s ease-out 0.4s both; width: 100%; box-sizing: border-box; margin-bottom: 0; } +.balance-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent, + var(--accent-primary), + transparent + ); + opacity: 0; + transition: opacity 0.4s ease; +} + .balance-card:hover { - transform: translateY(-5px); - box-shadow: var(--shadow-hover); + transform: translateY(-8px) scale(1.02); + box-shadow: + 0 20px 60px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(255, 255, 255, 0.2) inset, + 0 0 80px rgba(100, 255, 218, 0.2); + border-color: rgba(100, 255, 218, 0.3); +} + +.balance-card:hover::before { + opacity: 1; } .balance-header { @@ -316,33 +346,78 @@ body { .income-card, .expense-card { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(20px); - border-radius: 15px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 1.5rem; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%); + backdrop-filter: blur(25px); + border-radius: 20px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 2rem; display: flex; align-items: center; - gap: 1rem; - box-shadow: var(--shadow-glass); - transition: all 0.3s ease; + gap: 1.5rem; + position: relative; + overflow: hidden; + box-shadow: + 0 8px 24px rgba(0, 0, 0, 0.3), + 0 0 0 1px rgba(255, 255, 255, 0.08) inset; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.income-card::before, +.expense-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: radial-gradient(circle at top right, rgba(100, 255, 218, 0.1), transparent 70%); + opacity: 0; + transition: opacity 0.4s ease; + pointer-events: none; +} + +.income-card { + border-left: 3px solid var(--success); +} + +.expense-card { + border-left: 3px solid var(--error); } .income-card:hover, .expense-card:hover { - transform: translateY(-3px); - box-shadow: var(--shadow-hover); + transform: translateY(-6px) scale(1.03); + box-shadow: + 0 16px 40px rgba(0, 0, 0, 0.4), + 0 0 0 1px rgba(255, 255, 255, 0.15) inset, + 0 0 40px rgba(100, 255, 218, 0.15); + border-color: rgba(255, 255, 255, 0.2); +} + +.income-card:hover::before, +.expense-card:hover::before { + opacity: 1; } .card-icon { - width: 60px; - height: 60px; - border-radius: 15px; + width: 70px; + height: 70px; + border-radius: 18px; display: flex; align-items: center; justify-content: center; - font-size: 1.5rem; + font-size: 1.75rem; color: white; + position: relative; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3); + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.income-card:hover .card-icon, +.expense-card:hover .card-icon { + transform: scale(1.1) rotate(5deg); + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4); } .income-icon { @@ -379,19 +454,48 @@ body { letter-spacing: -0.5px; } -/* History Section */ +/* History Section - Redesigned */ .history-section { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(20px); - border-radius: 20px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 2rem; - box-shadow: var(--shadow-glass); + background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%); + backdrop-filter: blur(30px); + border-radius: 24px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 2.5rem; + position: relative; + overflow: hidden; + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.4), + 0 0 0 1px rgba(255, 255, 255, 0.1) inset; animation: fadeInUp 1s ease-out 0.8s both; width: 100%; box-sizing: border-box; margin-top: 0; margin-bottom: 0; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.history-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent, + var(--accent-primary), + transparent + ); + opacity: 0.5; +} + +.history-section:hover { + box-shadow: + 0 12px 40px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(255, 255, 255, 0.15) inset, + 0 0 60px rgba(100, 255, 218, 0.1); + border-color: rgba(100, 255, 218, 0.2); } .section-header { @@ -589,23 +693,44 @@ body { } .list li { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(10px); - border-radius: 12px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 1rem; - margin-bottom: 0.5rem; + background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%); + backdrop-filter: blur(20px); + border-radius: 16px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 1.25rem 1.5rem; + margin-bottom: 0.75rem; display: flex; justify-content: space-between; align-items: center; position: relative; - transition: all 0.3s ease; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); animation: slideInLeft 0.3s ease-out; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); + overflow: hidden; +} + +.list li::before { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 4px; + background: currentColor; + transition: width 0.4s ease; + z-index: 0; } .list li:hover { - transform: translateX(5px); - background: rgba(255, 255, 255, 0.1); + transform: translateX(8px) translateY(-2px); + background: linear-gradient(135deg, rgba(255, 255, 255, 0.12) 0%, rgba(255, 255, 255, 0.06) 100%); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); + border-color: rgba(255, 255, 255, 0.2); +} + +.list li:hover::before { + width: 6px; } .list li.plus { @@ -647,17 +772,46 @@ body { /* Data Management Section */ .data-management-section { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(20px); - border-radius: 20px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 2rem; - box-shadow: var(--shadow-glass); + background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.08) 100%); + backdrop-filter: blur(30px); + border-radius: 24px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 2.5rem; + position: relative; + overflow: hidden; + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.4), + 0 0 0 1px rgba(255, 255, 255, 0.1) inset; width: 100%; box-sizing: border-box; margin-top: 0; margin-bottom: 0; animation: fadeInUp 1s ease-out 0.9s both; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.data-management-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent, + var(--accent-primary), + transparent + ); + opacity: 0.5; +} + +.data-management-section:hover { + box-shadow: + 0 12px 40px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(255, 255, 255, 0.15) inset, + 0 0 60px rgba(100, 255, 218, 0.1); + border-color: rgba(100, 255, 218, 0.2); } .data-management-section h3 { @@ -795,19 +949,48 @@ body { accent-color: var(--accent-primary); } -/* Form Section */ +/* Form Section - Redesigned */ .form-section { - background: rgba(255, 255, 255, 0.05); - backdrop-filter: blur(20px); - border-radius: 20px; - border: 1px solid rgba(255, 255, 255, 0.1); - padding: 2rem; - box-shadow: var(--shadow-glass); + background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%); + backdrop-filter: blur(30px); + border-radius: 24px; + border: 2px solid transparent; + background-clip: padding-box; + padding: 2.5rem; + position: relative; + overflow: hidden; + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.4), + 0 0 0 1px rgba(255, 255, 255, 0.1) inset; animation: fadeInUp 1s ease-out 1s both; width: 100%; box-sizing: border-box; margin-top: 0; margin-bottom: 0; + transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); +} + +.form-section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent, + var(--accent-primary), + transparent + ); + opacity: 0.5; +} + +.form-section:hover { + box-shadow: + 0 12px 40px rgba(0, 0, 0, 0.5), + 0 0 0 1px rgba(255, 255, 255, 0.15) inset, + 0 0 60px rgba(100, 255, 218, 0.1); + border-color: rgba(100, 255, 218, 0.2); } .form-section h3 { diff --git a/index.html b/index.html index ace03a0e..bed377dd 100644 --- a/index.html +++ b/index.html @@ -23,7 +23,7 @@ ExpenseFlow - Smart Money Management - + @@ -591,7 +591,7 @@

Quick Links

- +