0% found this document useful (0 votes)
5 views

html file

The document is an HTML template for a Personal Finance Manager application, featuring a responsive design with a navigation bar and various sections for dashboard statistics, transactions, budgets, goals, reports, and settings. It includes CSS styles for layout, colors, and animations, as well as JavaScript functionality for interactivity. The dashboard showcases income, expenses, current balance, and savings with cards and charts for visual representation.

Uploaded by

geca.dawid21
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

html file

The document is an HTML template for a Personal Finance Manager application, featuring a responsive design with a navigation bar and various sections for dashboard statistics, transactions, budgets, goals, reports, and settings. It includes CSS styles for layout, colors, and animations, as well as JavaScript functionality for interactivity. The dashboard showcases income, expenses, current balance, and savings with cards and charts for visual representation.

Uploaded by

geca.dawid21
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 32

<!

DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Personal Finance Manager</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/
all.min.css" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

:root {
--primary-color: #2c3e50;
--secondary-color: #3498db;
--success-color: #27ae60;
--danger-color: #e74c3c;
--warning-color: #f39c12;
--info-color: #17a2b8;
--light-bg: #ecf0f1;
--dark-bg: #34495e;
--white: #ffffff;
--text-dark: #2c3e50;
--text-light: #7f8c8d;
--shadow: 0 4px 6px rgba(0,0,0,0.1);
}

body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-dark);
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}

/* Navigation */
.navbar {
background: rgba(44, 62, 80, 0.95);
backdrop-filter: blur(10px);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
box-shadow: var(--shadow);
}

.nav-container {
max-width: 1400px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}
.logo {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 1.5rem;
font-weight: bold;
color: var(--white);
text-decoration: none;
}

.nav-menu {
display: flex;
list-style: none;
gap: 1rem;
}

.nav-link {
color: var(--white);
text-decoration: none;
padding: 0.5rem 1rem;
border-radius: 5px;
transition: all 0.3s ease;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
}

.nav-link:hover,
.nav-link.active {
background: var(--secondary-color);
transform: translateY(-2px);
}

.hamburger {
display: none;
flex-direction: column;
cursor: pointer;
gap: 4px;
}

.hamburger span {
width: 25px;
height: 3px;
background: var(--white);
transition: 0.3s;
}

/* Main Content */
.main-content {
margin-top: 80px;
min-height: calc(100vh - 80px);
padding: 2rem;
}

.container {
max-width: 1400px;
margin: 0 auto;
}
.section {
display: none;
}

.section.active {
display: block;
animation: fadeIn 0.5s ease-in;
}

@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}

/* Cards */
.card {
background: var(--white);
border-radius: 10px;
box-shadow: var(--shadow);
padding: 1.5rem;
margin-bottom: 1.5rem;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0,0,0,0.15);
}

.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid var(--light-bg);
}

.card-title {
font-size: 1.5rem;
font-weight: bold;
color: var(--primary-color);
display: flex;
align-items: center;
gap: 0.5rem;
}

/* Dashboard Stats */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}

.stat-card {
background: var(--white);
border-radius: 10px;
padding: 1.5rem;
text-align: center;
box-shadow: var(--shadow);
position: relative;
overflow: hidden;
}

.stat-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--success-color), var(--
secondary-color));
}

.stat-icon {
font-size: 2.5rem;
margin-bottom: 1rem;
}

.stat-value {
font-size: 2rem;
font-weight: bold;
margin-bottom: 0.5rem;
}

.stat-label {
color: var(--text-light);
font-size: 0.9rem;
}

.income { color: var(--success-color); }


.expense { color: var(--danger-color); }
.balance { color: var(--info-color); }
.savings { color: var(--warning-color); }

/* Forms */
.form-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}

.form-group {
margin-bottom: 1.5rem;
}

.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--text-dark);
}

.form-control {
width: 100%;
padding: 0.75rem;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 1rem;
transition: border-color 0.3s ease;
}

.form-control:focus {
outline: none;
border-color: var(--secondary-color);
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}

.form-control.error {
border-color: var(--danger-color);
}

.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}

.checkbox-group,
.radio-group {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}

.checkbox-item,
.radio-item {
display: flex;
align-items: center;
gap: 0.5rem;
}

.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-weight: 600;
}

.btn-primary {
background: var(--secondary-color);
color: var(--white);
}

.btn-success {
background: var(--success-color);
color: var(--white);
}

.btn-danger {
background: var(--danger-color);
color: var(--white);
}

.btn-warning {
background: var(--warning-color);
color: var(--white);
}

.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}

/* Tables */
.table-container {
overflow-x: auto;
border-radius: 10px;
box-shadow: var(--shadow);
}

.table {
width: 100%;
border-collapse: collapse;
background: var(--white);
}

.table th,
.table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid #eee;
}

.table th {
background: var(--light-bg);
font-weight: 600;
color: var(--primary-color);
}

.table tbody tr:hover {


background: #f8f9fa;
}

/* Error Messages */
.error-message {
color: var(--danger-color);
font-size: 0.875rem;
margin-top: 0.25rem;
display: none;
}

.error-message.show {
display: block;
}
/* Success Messages */
.success-message {
background: var(--success-color);
color: var(--white);
padding: 1rem;
border-radius: 5px;
margin-bottom: 1rem;
display: none;
}

.success-message.show {
display: block;
animation: slideDown 0.3s ease;
}

@keyframes slideDown {
from { transform: translateY(-20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}

/* Charts Container */
.chart-container {
background: var(--white);
border-radius: 10px;
padding: 1.5rem;
box-shadow: var(--shadow);
margin-bottom: 2rem;
}

.chart-placeholder {
height: 300px;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(45deg, #f0f0f0, #e0e0e0);
border-radius: 5px;
color: var(--text-light);
font-size: 1.2rem;
}

/* Loading Spinner */
.loading {
display: none;
text-align: center;
padding: 2rem;
}

.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid var(--secondary-color);
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}

@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}

/* Responsive Design */
@media (max-width: 768px) {
.nav-menu {
position: fixed;
top: 80px;
left: -100%;
width: 100%;
height: calc(100vh - 80px);
background: var(--primary-color);
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding-top: 2rem;
transition: left 0.3s ease;
}

.nav-menu.active {
left: 0;
}

.hamburger {
display: flex;
}

.hamburger.active span:nth-child(1) {
transform: rotate(45deg) translate(5px, 5px);
}

.hamburger.active span:nth-child(2) {
opacity: 0;
}

.hamburger.active span:nth-child(3) {
transform: rotate(-45deg) translate(7px, -6px);
}

.main-content {
padding: 1rem;
}

.stats-grid {
grid-template-columns: 1fr;
}

.form-grid {
grid-template-columns: 1fr;
}

.form-row {
grid-template-columns: 1fr;
}

.nav-container {
padding: 1rem;
}
}
@media (max-width: 480px) {
.card {
padding: 1rem;
}

.stat-card {
padding: 1rem;
}

.stat-icon {
font-size: 2rem;
}

.stat-value {
font-size: 1.5rem;
}
}
</style>
</head>
<body>
<!-- Navigation -->
<nav class="navbar">
<div class="nav-container">
<a href="#" class="logo">
<i class="fas fa-wallet"></i>
Finance Manager
</a>
<ul class="nav-menu">
<li><a href="#" class="nav-link active" data-section="dashboard">
<i class="fas fa-chart-pie"></i>Dashboard
</a></li>
<li><a href="#" class="nav-link" data-section="transactions">
<i class="fas fa-exchange-alt"></i>Transakcje
</a></li>
<li><a href="#" class="nav-link" data-section="budgets">
<i class="fas fa-calculator"></i>Budżety
</a></li>
<li><a href="#" class="nav-link" data-section="goals">
<i class="fas fa-bullseye"></i>Cele
</a></li>
<li><a href="#" class="nav-link" data-section="reports">
<i class="fas fa-chart-bar"></i>Raporty
</a></li>
<li><a href="#" class="nav-link" data-section="settings">
<i class="fas fa-cog"></i>Ustawienia
</a></li>
</ul>
<div class="hamburger" id="hamburger">
<span></span>
<span></span>
<span></span>
</div>
</div>
</nav>

<!-- Main Content -->


<main class="main-content">
<div class="container">
<!-- Dashboard Section -->
<section id="dashboard" class="section active">
<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon income">
<i class="fas fa-arrow-up"></i>
</div>
<div class="stat-value income" id="total-income">0,00
zł</div>
<div class="stat-label">Całkowite przychody</div>
</div>
<div class="stat-card">
<div class="stat-icon expense">
<i class="fas fa-arrow-down"></i>
</div>
<div class="stat-value expense" id="total-expenses">0,00
zł</div>
<div class="stat-label">Całkowite wydatki</div>
</div>
<div class="stat-card">
<div class="stat-icon balance">
<i class="fas fa-balance-scale"></i>
</div>
<div class="stat-value balance" id="current-balance">0,00
zł</div>
<div class="stat-label">Saldo bieżące</div>
</div>
<div class="stat-card">
<div class="stat-icon savings">
<i class="fas fa-piggy-bank"></i>
</div>
<div class="stat-value savings" id="total-savings">0,00
zł</div>
<div class="stat-label">Oszczędności</div>
</div>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-chart-line"></i>
Przegląd miesięczny
</h2>
<button class="btn btn-primary" id="refresh-data">
<i class="fas fa-sync-alt"></i>Odśwież dane
</button>
</div>
<div class="chart-container">
<div class="chart-placeholder" id="monthly-chart">
<i class="fas fa-chart-area" style="font-size: 3rem;
opacity: 0.3;"></i>
<span style="margin-left: 1rem;">Wykres miesięcznych
wydatków</span>
</div>
</div>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-clock"></i>
Ostatnie transakcje
</h2>
<a href="#" class="btn btn-primary" data-
section="transactions">Zobacz wszystkie</a>
</div>
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>Data</th>
<th>Opis</th>
<th>Kategoria</th>
<th>Kwota</th>
</tr>
</thead>
<tbody id="recent-transactions">
<tr>
<td colspan="4" style="text-align: center;
color: var(--text-light);">
Brak transakcji do wyświetlenia
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>

<!-- Transactions Section -->


<section id="transactions" class="section">
<div class="form-grid">
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-plus-circle"></i>
Dodaj transakcję
</h2>
</div>
<div class="success-message"
id="transaction-success"></div>
<form id="transaction-form">
<div class="form-group">
<label class="form-label" for="transaction-
type">Typ transakcji *</label>
<div class="radio-group">
<div class="radio-item">
<input type="radio" id="income-type"
name="transaction-type" value="income" required>
<label for="income-type">Przychód</label>
</div>
<div class="radio-item">
<input type="radio" id="expense-type"
name="transaction-type" value="expense" required>
<label for="expense-type">Wydatek</label>
</div>
</div>
<div class="error-message" id="goal-name-
error">Wprowadź nazwę celu</div>
</div>

<div class="form-row">
<div class="form-group">
<label class="form-label" for="goal-
amount">Docelowa kwota *</label>
<input type="number" id="goal-amount"
class="form-control"
placeholder="0.00" step="0.01"
min="0.01" required>
<div class="error-message" id="goal-amount-
error">Wprowadź docelową kwotę</div>
</div>
<div class="form-group">
<label class="form-label" for="goal-
deadline">Termin realizacji</label>
<input type="date" id="goal-deadline"
class="form-control">
</div>
</div>

<div class="form-group">
<label class="form-label" for="goal-
current">Aktualna kwota</label>
<input type="number" id="goal-current" class="form-
control"
placeholder="0.00" step="0.01" min="0">
</div>

<div class="form-group">
<label class="form-label" for="goal-
priority">Priorytet</label>
<div class="radio-group">
<div class="radio-item">
<input type="radio" id="priority-low"
name="goal-priority" value="low">
<label for="priority-low">Niski</label>
</div>
<div class="radio-item">
<input type="radio" id="priority-medium"
name="goal-priority" value="medium" checked>
<label for="priority-medium">Średni</label>
</div>
<div class="radio-item">
<input type="radio" id="priority-high"
name="goal-priority" value="high">
<label for="priority-high">Wysoki</label>
</div>
</div>
</div>

<div class="form-group">
<label class="form-label" for="goal-
description">Opis celu</label>
<textarea id="goal-description" class="form-
control"
placeholder="Opisz swój cel finansowy..."
rows="3"></textarea>
</div>

<button type="submit" class="btn btn-success">


<i class="fas fa-save"></i>Dodaj cel
</button>
</form>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-bullseye"></i>
Moje cele finansowe
</h2>
</div>
<div id="goals-list">
<p style="text-align: center; color: var(--text-light);
padding: 2rem;">
Brak utworzonych celów finansowych
</p>
</div>
</div>
</div>
</section>

<!-- Reports Section -->


<section id="reports" class="section">
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-chart-bar"></i>
Raporty finansowe
</h2>
<button class="btn btn-primary" id="generate-report">
<i class="fas fa-sync-alt"></i>Wygeneruj raport
</button>
</div>
<div class="loading" id="report-loading">
<div class="spinner"></div>
<p>Generowanie raportu...</p>
</div>
<div id="report-content">
<div class="chart-container">
<h3 style="margin-bottom: 1rem;">Wydatki według
kategorii</h3>
<div class="chart-placeholder">
<i class="fas fa-chart-pie" style="font-size: 3rem;
opacity: 0.3;"></i>
<span style="margin-left: 1rem;">Wykres kołowy
wydatków</span>
</div>
</div>

<div class="chart-container">
<h3 style="margin-bottom: 1rem;">Trend wydatków w
czasie</h3>
<div class="chart-placeholder">
<i class="fas fa-chart-line" style="font-size:
3rem; opacity: 0.3;"></i>
<span style="margin-left: 1rem;">Wykres liniowy
trendów</span>
</div>
</div>
</div>
</div>
</section>

<!-- Settings Section -->


<section id="settings" class="section">
<div class="form-grid">
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-user-cog"></i>
Ustawienia profilu
</h2>
</div>
<div class="success-message" id="settings-success"></div>
<form id="settings-form">
<div class="form-row">
<div class="form-group">
<label class="form-label" for="user-name">Imię
i nazwisko</label>
<input type="text" id="user-name" class="form-
control"
placeholder="Jan Kowalski">
</div>
<div class="form-group">
<label class="form-label" for="user-
email">Email</label>
<input type="email" id="user-email"
class="form-control"
placeholder="[email protected]">
</div>
</div>

<div class="form-group">
<label class="form-label" for="default-
currency">Domyślna waluta</label>
<select id="default-currency" class="form-control">
<option value="PLN">PLN - Polski złoty</option>
<option value="EUR">EUR - Euro</option>
<option value="USD">USD - Dolar
amerykański</option>
<option value="GBP">GBP - Funt
brytyjski</option>
</select>
</div>

<div class="form-group">
<label class="form-label">Powiadomienia</label>
<div class="checkbox-group">
<div class="checkbox-item">
<input type="checkbox" id="email-
notifications" checked>
<label for="email-
notifications">Powiadomienia email</label>
</div>
<div class="checkbox-item">
<input type="checkbox" id="budget-
notifications" checked>
<label for="budget-notifications">Alerty
budżetowe</label>
</div>
<div class="checkbox-item">
<input type="checkbox" id="goal-
notifications">
<label for="goal-
notifications">Przypomnienia o celach</label>
</div>
</div>
</div>

<div class="form-group">
<label class="form-label" for="data-backup">Backup
danych</label>
<div style="display: flex; gap: 1rem; flex-wrap:
wrap;">
<button type="button" class="btn btn-primary"
id="export-data">
<i class="fas fa-download"></i>Eksportuj
dane
</button>
<button type="button" class="btn btn-warning"
id="import-data">
<i class="fas fa-upload"></i>Importuj dane
</button>
<input type="file" id="import-file"
accept=".json" style="display: none;">
</div>
</div>

<button type="submit" class="btn btn-success">


<i class="fas fa-save"></i>Zapisz ustawienia
</button>
</form>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-database"></i>
Zarządzanie danymi
</h2>
</div>
<div class="form-group">
<label class="form-label">Statystyki aplikacji</label>
<div class="stats-grid" style="grid-template-columns:
1fr 1fr;">
<div class="stat-card">
<div class="stat-value" id="total-transactions-
count">0</div>
<div class="stat-label">Transakcji</div>
</div>
<div class="stat-card">
<div class="stat-value" id="total-budgets-
count">0</div>
<div class="stat-label">Budżetów</div>
</div>
</div>
</div>

<div class="form-group">
<label class="form-label">Akcje</label>
<div style="display: flex; gap: 1rem; flex-wrap:
wrap;">
<button type="button" class="btn btn-danger"
id="clear-all-data">
<i class="fas fa-trash-alt"></i>Wyczyść
wszystkie dane
</button>
<button type="button" class="btn btn-warning"
id="reset-app">
<i class="fas fa-redo"></i>Resetuj aplikację
</button>
</div>
</div>
</div>
</div>
</section>
</div>
</main>

<script>
// Data storage management
class DataManager {
constructor() {
this.transactions = this.getFromStorage('transactions') || [];
this.budgets = this.getFromStorage('budgets') || [];
this.goals = this.getFromStorage('goals') || [];
this.settings = this.getFromStorage('settings') ||
this.getDefaultSettings();
this.loadSampleData();
}

getFromStorage(key) {
try {
const data = localStorage.getItem(`finance_${key}`);
return data ? JSON.parse(data) : null;
} catch (e) {
console.error('Error loading data from storage:', e);
return null;
}
}

saveToStorage(key, data) {
try {
localStorage.setItem(`finance_${key}`, JSON.stringify(data));
} catch (e) {
console.error('Error saving data to storage:', e);
}
}

getDefaultSettings() {
return {
userName: '',
userEmail: '',
currency: 'PLN',
emailNotifications: true,
budgetNotifications: true,
goalNotifications: false
};
}

loadSampleData() {
// Load sample data asynchronously
if (this.transactions.length === 0) {
this.loadSampleTransactions();
}
}

async loadSampleTransactions() {
// Simulate async data loading
setTimeout(() => {
const sampleTransactions = [
{
id: Date.now() + 1,
type: 'income',
amount: 5000,
date: '2024-01-15',
category: 'salary',
description: 'Wynagrodzenie miesięczne',
recurring: true,
important: true
},
{
id: Date.now() + 2,
type: 'expense',
amount: 150,
date: '2024-01-16',
category: 'food',
description: 'Zakupy spożywcze',
recurring: false,
important: false
},
{
id: Date.now() + 3,
type: 'expense',
amount: 80,
date: '2024-01-17',
category: 'transport',
description: 'Paliwo do samochodu',
recurring: false,
important: false
}
];

this.transactions =
[...this.transactions, ...sampleTransactions];
this.saveTransactions();
app.updateDashboard();
app.renderTransactions();
}, 1000);
}
// Transactions
addTransaction(transaction) {
transaction.id = Date.now();
this.transactions.unshift(transaction);
this.saveTransactions();
}

deleteTransaction(id) {
this.transactions = this.transactions.filter(t => t.id !== id);
this.saveTransactions();
}

saveTransactions() {
this.saveToStorage('transactions', this.transactions);
}

clearTransactions() {
this.transactions = [];
this.saveTransactions();
}

// Budgets
addBudget(budget) {
budget.id = Date.now();
budget.spent = 0;
this.budgets.push(budget);
this.saveBudgets();
}

deleteBudget(id) {
this.budgets = this.budgets.filter(b => b.id !== id);
this.saveBudgets();
}

saveBudgets() {
this.saveToStorage('budgets', this.budgets);
}

// Goals
addGoal(goal) {
goal.id = Date.now();
this.goals.push(goal);
this.saveGoals();
}

deleteGoal(id) {
this.goals = this.goals.filter(g => g.id !== id);
this.saveGoals();
}

saveGoals() {
this.saveToStorage('goals', this.goals);
}

// Settings
saveSettings() {
this.saveToStorage('settings', this.settings);
}
// Statistics
getTotalIncome() {
return this.transactions
.filter(t => t.type === 'income')
.reduce((sum, t) => sum + t.amount, 0);
}

getTotalExpenses() {
return this.transactions
.filter(t => t.type === 'expense')
.reduce((sum, t) => sum + t.amount, 0);
}

getCurrentBalance() {
return this.getTotalIncome() - this.getTotalExpenses();
}

// Data export/import
exportData() {
const data = {
transactions: this.transactions,
budgets: this.budgets,
goals: this.goals,
settings: this.settings,
exportDate: new Date().toISOString()
};

const blob = new Blob([JSON.stringify(data, null, 2)], { type:


'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `finance_backup_${new Date().toISOString().split('T')
[0]}.json`;
a.click();
URL.revokeObjectURL(url);
}

importData(fileContent) {
try {
const data = JSON.parse(fileContent);
if (data.transactions) this.transactions = data.transactions;
if (data.budgets) this.budgets = data.budgets;
if (data.goals) this.goals = data.goals;
if (data.settings) this.settings = data.settings;

this.saveTransactions();
this.saveBudgets();
this.saveGoals();
this.saveSettings();

return true;
} catch (e) {
console.error('Error importing data:', e);
return false;
}
}

clearAllData() {
this.transactions = [];
this.budgets = [];
this.goals = [];
this.settings = this.getDefaultSettings();

localStorage.removeItem('finance_transactions');
localStorage.removeItem('finance_budgets');
localStorage.removeItem('finance_goals');
localStorage.removeItem('finance_settings');
}
}

// Main application class


class FinanceApp {
constructor() {
this.dataManager = new DataManager();
this.currentSection = 'dashboard';
this.init();
}

init() {
this.setupNavigation();
this.setupForms();
this.setupEventListeners();
this.updateDashboard();
this.renderTransactions();
this.renderBudgets();
this.renderGoals();
this.loadSettings();
}

setupNavigation() {
const hamburger = document.getElementById('hamburger');
const navMenu = document.querySelector('.nav-menu');
const navLinks = document.querySelectorAll('.nav-link');

hamburger.addEventListener('click', () => {
hamburger.classList.toggle('active');
navMenu.classList.toggle('active');
});

navLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const section = link.dataset.section;
if (section) {
this.showSection(section);
navLinks.forEach(l => l.classList.remove('active'));
link.classList.add('active');

// Close mobile menu


hamburger.classList.remove('active');
navMenu.classList.remove('active');
}
});
});
}

showSection(sectionName) {
document.querySelectorAll('.section').forEach(section => {
section.classList.remove('active');
});

const targetSection = document.getElementById(sectionName);


if (targetSection) {
targetSection.classList.add('active');
this.currentSection = sectionName;
}
}

setupForms() {
// Transaction form
const transactionForm = document.getElementById('transaction-
form');
transactionForm.addEventListener('submit', (e) => {
e.preventDefault();
this.handleTransactionSubmit();
});

// Budget form
const budgetForm = document.getElementById('budget-form');
budgetForm.addEventListener('submit', (e) => {
e.preventDefault();
this.handleBudgetSubmit();
});

// Goal form
const goalForm = document.getElementById('goal-form');
goalForm.addEventListener('submit', (e) => {
e.preventDefault();
this.handleGoalSubmit();
});

// Settings form
const settingsForm = document.getElementById('settings-form');
settingsForm.addEventListener('submit', (e) => {
e.preventDefault();
this.handleSettingsSubmit();
});

// Set current date as default


const today = new Date().toISOString().split('T')[0];
document.getElementById('transaction-date').value = today;
}

setupEventListeners() {
// Dashboard refresh
document.getElementById('refresh-data').addEventListener('click',
() => {
this.updateDashboard();
this.showSuccessMessage('Dane zostały odświeżone!');
});

// Clear transactions
document.getElementById('clear-
transactions').addEventListener('click', () => {
if (confirm('Czy na pewno chcesz usunąć wszystkie
transakcje?')) {
this.dataManager.clearTransactions();
this.updateDashboard();
this.renderTransactions();
this.showSuccessMessage('Wszystkie transakcje zostały
usunięte!');
}
});

// Generate report
document.getElementById('generate-
report').addEventListener('click', () => {
this.generateReport();
});

// Data management
document.getElementById('export-data').addEventListener('click', ()
=> {
this.dataManager.exportData();
this.showSuccessMessage('Dane zostały wyeksportowane!');
});

document.getElementById('import-data').addEventListener('click', ()
=> {
document.getElementById('import-file').click();
});

document.getElementById('import-file').addEventListener('change',
(e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
if (this.dataManager.importData(e.target.result)) {
this.updateDashboard();
this.renderTransactions();
this.renderBudgets();
this.renderGoals();
this.showSuccessMessage('Dane zostały
zaimportowane!');
} else {
alert('Błąd podczas importu danych!');
}
};
reader.readAsText(file);
}
});

document.getElementById('clear-all-data').addEventListener('click',
() => {
if (confirm('Czy na pewno chcesz usunąć wszystkie dane? Ta
operacja jest nieodwracalna!')) {
this.dataManager.clearAllData();
this.updateDashboard();
this.renderTransactions();
this.renderBudgets();
this.renderGoals();
this.showSuccessMessage('Wszystkie dane zostały
usunięte!');
}
});

document.getElementById('reset-app').addEventListener('click', ()
=> {
if (confirm('Czy na pewno chcesz zresetować aplikację?')) {
location.reload();
}
});
}

handleTransactionSubmit() {
const form = document.getElementById('transaction-form');
const formData = new FormData(form);

// Validation
if (!this.validateTransactionForm()) {
return;
}

const transaction = {
type: formData.get('transaction-type'),
amount: parseFloat(document.getElementById('transaction-
amount').value),
date: document.getElementById('transaction-date').value,
category: document.getElementById('transaction-
category').value,
description: document.getElementById('transaction-
description').value,
recurring: document.getElementById('recurring-
transaction').checked,
important: document.getElementById('important-
transaction').checked
};

this.dataManager.addTransaction(transaction);
this.updateDashboard();
this.renderTransactions();
this.showSuccessMessage('Transakcja została dodana!', 'transaction-
success');
form.reset();

// Reset date to today


const today = new Date().toISOString().split('T')[0];
document.getElementById('transaction-date').value = today;
}

validateTransactionForm() {
let isValid = true;

// Clear previous errors


document.querySelectorAll('.error-message').forEach(error => {
error.classList.remove('show');
});
document.querySelectorAll('.form-control').forEach(input => {
input.classList.remove('error');
});

// Validate transaction type


const type = document.querySelector('input[name="transaction-
type"]:checked');
if (!type) {
this.showError('type-error', 'transaction-type');
isValid = false;
}

// Validate amount
const amount = document.getElementById('transaction-amount').value;
if (!amount || parseFloat(amount) <= 0) {
this.showError('amount-error', 'transaction-amount');
isValid = false;
}

// Validate date
const date = document.getElementById('transaction-date').value;
if (!date) {
this.showError('date-error', 'transaction-date');
isValid = false;
}

// Validate category
const category = document.getElementById('transaction-
category').value;
if (!category) {
this.showError('category-error', 'transaction-category');
isValid = false;
}

return isValid;
}

handleBudgetSubmit() {
const form = document.getElementById('budget-form');

if (!this.validateBudgetForm()) {
return;
}

const budget = {
name: document.getElementById('budget-name').value,
amount: parseFloat(document.getElementById('budget-
amount').value),
period: document.getElementById('budget-period').value,
category: document.getElementById('budget-category').value,
alert50: document.getElementById('budget-alert-50').checked,
alert80: document.getElementById('budget-alert-80').checked,
alert100: document.getElementById('budget-alert-100').checked
};

this.dataManager.addBudget(budget);
this.renderBudgets();
this.showSuccessMessage('Budżet został utworzony!', 'budget-
success');
form.reset();
}

validateBudgetForm() {
let isValid = true;
const name = document.getElementById('budget-name').value;
if (!name.trim()) {
this.showError('budget-name-error', 'budget-name');
isValid = false;
}

const amount = document.getElementById('budget-amount').value;


if (!amount || parseFloat(amount) <= 0) {
this.showError('budget-amount-error', 'budget-amount');
isValid = false;
}

const period = document.getElementById('budget-period').value;


if (!period) {
this.showError('budget-period-error', 'budget-period');
isValid = false;
}

return isValid;
}

handleGoalSubmit() {
const form = document.getElementById('goal-form');

if (!this.validateGoalForm()) {
return;
}

const goal = {
name: document.getElementById('goal-name').value,
targetAmount: parseFloat(document.getElementById('goal-
amount').value),
currentAmount: parseFloat(document.getElementById('goal-
current').value) || 0,
deadline: document.getElementById('goal-deadline').value,
priority: document.querySelector('input[name="goal-
priority"]:checked').value,
description: document.getElementById('goal-description').value
};

this.dataManager.addGoal(goal);
this.renderGoals();
this.showSuccessMessage('Cel finansowy został dodany!', 'goal-
success');
form.reset();

// Reset to default priority


document.getElementById('priority-medium').checked = true;
}

validateGoalForm() {
let isValid = true;

const name = document.getElementById('goal-name').value;


if (!name.trim()) {
this.showError('goal-name-error', 'goal-name');
isValid = false;
}
const amount = document.getElementById('goal-amount').value;
if (!amount || parseFloat(amount) <= 0) {
this.showError('goal-amount-error', 'goal-amount');
isValid = false;
}

return isValid;
}

handleSettingsSubmit() {
this.dataManager.settings = {
userName: document.getElementById('user-name').value,
userEmail: document.getElementById('user-email').value,
currency: document.getElementById('default-currency').value,
emailNotifications: document.getElementById('email-
notifications').checked,
budgetNotifications: document.getElementById('budget-
notifications').checked,
goalNotifications: document.getElementById('goal-
notifications').checked
};

this.dataManager.saveSettings();
this.showSuccessMessage('Ustawienia zostały zapisane!', 'settings-
success');
}

showError(errorId, inputId) {
const errorElement = document.getElementById(errorId);
const inputElement = document.getElementById(inputId);

if (errorElement) {
errorElement.classList.add('show');
}
if (inputElement) {
inputElement.classList.add('error');
}
}

showSuccessMessage(message, containerId = null) {


if (containerId) {
const container = document.getElementById(containerId);
if (container) {
container.textContent = message;
container.classList.add('show');
setTimeout(() => container.classList.remove('show'), 3000);
}
} else {
// Show general success message
console.log(message);
}
}

updateDashboard() {
const totalIncome = this.dataManager.getTotalIncome();
const totalExpenses = this.dataManager.getTotalExpenses();
const currentBalance = this.dataManager.getCurrentBalance();
const totalSavings = Math.max(0, currentBalance * 0.1); // 10% of
balance as savings
document.getElementById('total-income').textContent =
this.formatCurrency(totalIncome);
document.getElementById('total-expenses').textContent =
this.formatCurrency(totalExpenses);
document.getElementById('current-balance').textContent =
this.formatCurrency(currentBalance);
document.getElementById('total-savings').textContent =
this.formatCurrency(totalSavings);

// Update recent transactions


this.renderRecentTransactions();

// Update statistics
document.getElementById('total-transactions-count').textContent =
this.dataManager.transactions.length;
document.getElementById('total-budgets-count').textContent =
this.dataManager.budgets.length;
}

renderRecentTransactions() {
const tbody = document.getElementById('recent-transactions');
const recentTransactions = this.dataManager.transactions.slice(0,
5);

if (recentTransactions.length === 0) {
tbody.innerHTML = `
<tr>
<td colspan="4" style="text-align: center; color:
var(--text-light);">
Brak transakcji do wyświetlenia
</td>
</tr>
`;
return;
}

tbody.innerHTML = recentTransactions.map(transaction => `


<tr>
<td>${this.formatDate(transaction.date)}</td>
<td>${transaction.description || 'Brak opisu'}</td>
<td>${this.getCategoryName(transaction.category)}</td>
<td class="${" id="type-error">Wybierz typ transakcji</div>
</div>

<div class="form-row">
<div class="form-group">
<label class="form-label" for="transaction-
amount">Kwota *</label>
<input type="number" id="transaction-amount"
class="form-control"
placeholder="0.00" step="0.01"
min="0.01" required>
<div class="error-message" id="amount-
error">Wprowadź poprawną kwotę</div>
</div>
<div class="form-group">
<label class="form-label" for="transaction-
date">Data *</label>
<input type="date" id="transaction-date"
class="form-control" required>
<div class="error-message" id="date-
error">Wybierz datę transakcji</div>
</div>
</div>

<div class="form-group">
<label class="form-label" for="transaction-
category">Kategoria *</label>
<select id="transaction-category" class="form-
control" required>
<option value="">Wybierz kategorię</option>
<optgroup label="Przychody">
<option
value="salary">Wynagrodzenie</option>
<option value="business">Działalność
gospodarcza</option>
<option
value="investment">Inwestycje</option>
<option value="gift">Prezenty</option>
<option value="other-income">Inne
przychody</option>
</optgroup>
<optgroup label="Wydatki">
<option value="food">Jedzenie</option>
<option
value="transport">Transport</option>
<option value="housing">Mieszkanie</option>
<option
value="entertainment">Rozrywka</option>
<option value="healthcare">Zdrowie</option>
<option value="shopping">Zakupy</option>
<option value="bills">Rachunki</option>
<option value="other-expense">Inne
wydatki</option>
</optgroup>
</select>
<div class="error-message" id="category-
error">Wybierz kategorię</div>
</div>

<div class="form-group">
<label class="form-label" for="transaction-
description">Opis</label>
<textarea id="transaction-description" class="form-
control"
placeholder="Opcjonalny opis
transakcji..." rows="3"></textarea>
</div>

<div class="form-group">
<label class="form-label">Dodatkowe opcje</label>
<div class="checkbox-group">
<div class="checkbox-item">
<input type="checkbox" id="recurring-
transaction">
<label for="recurring-
transaction">Transakcja cykliczna</label>
</div>
<div class="checkbox-item">
<input type="checkbox" id="important-
transaction">
<label for="important-transaction">Ważna
transakcja</label>
</div>
</div>
</div>

<button type="submit" class="btn btn-success">


<i class="fas fa-save"></i>Zapisz transakcję
</button>
</form>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-list"></i>
Wszystkie transakcje
</h2>
<button class="btn btn-warning" id="clear-
transactions">
<i class="fas fa-trash"></i>Wyczyść wszystkie
</button>
</div>
<div class="table-container">
<table class="table">
<thead>
<tr>
<th>Data</th>
<th>Typ</th>
<th>Opis</th>
<th>Kategoria</th>
<th>Kwota</th>
<th>Akcje</th>
</tr>
</thead>
<tbody id="all-transactions">
<tr>
<td colspan="6" style="text-align: center;
color: var(--text-light);">
Brak transakcji do wyświetlenia
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>

<!-- Budgets Section -->


<section id="budgets" class="section">
<div class="form-grid">
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-plus-circle"></i>
Utwórz budżet
</h2>
</div>
<div class="success-message" id="budget-success"></div>
<form id="budget-form">
<div class="form-group">
<label class="form-label" for="budget-name">Nazwa
budżetu *</label>
<input type="text" id="budget-name" class="form-
control"
placeholder="np. Budżet miesięczny"
required>
<div class="error-message" id="budget-name-
error">Wprowadź nazwę budżetu</div>
</div>

<div class="form-row">
<div class="form-group">
<label class="form-label" for="budget-
amount">Kwota budżetu *</label>
<input type="number" id="budget-amount"
class="form-control"
placeholder="0.00" step="0.01"
min="0.01" required>
<div class="error-message" id="budget-amount-
error">Wprowadź kwotę budżetu</div>
</div>
<div class="form-group">
<label class="form-label" for="budget-
period">Okres *</label>
<select id="budget-period" class="form-control"
required>
<option value="">Wybierz okres</option>
<option value="weekly">Tygodniowy</option>
<option value="monthly">Miesięczny</option>
<option
value="quarterly">Kwartalny</option>
<option value="yearly">Roczny</option>
</select>
<div class="error-message" id="budget-period-
error">Wybierz okres budżetu</div>
</div>
</div>

<div class="form-group">
<label class="form-label" for="budget-
category">Kategoria budżetu</label>
<select id="budget-category" class="form-control">
<option value="all">Wszystkie
kategorie</option>
<option value="food">Jedzenie</option>
<option value="transport">Transport</option>
<option value="housing">Mieszkanie</option>
<option value="entertainment">Rozrywka</option>
<option value="healthcare">Zdrowie</option>
<option value="shopping">Zakupy</option>
<option value="bills">Rachunki</option>
</select>
</div>

<div class="form-group">
<label class="form-label">Powiadomienia</label>
<div class="checkbox-group">
<div class="checkbox-item">
<input type="checkbox" id="budget-alert-
50">
<label for="budget-alert-50">Powiadom przy
50% budżetu</label>
</div>
<div class="checkbox-item">
<input type="checkbox" id="budget-alert-
80">
<label for="budget-alert-80">Powiadom przy
80% budżetu</label>
</div>
<div class="checkbox-item">
<input type="checkbox" id="budget-alert-
100">
<label for="budget-alert-100">Powiadom przy
przekroczeniu</label>
</div>
</div>
</div>

<button type="submit" class="btn btn-success">


<i class="fas fa-save"></i>Utwórz budżet
</button>
</form>
</div>

<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-list"></i>
Aktywne budżety
</h2>
</div>
<div id="budgets-list">
<p style="text-align: center; color: var(--text-light);
padding: 2rem;">
Brak utworzonych budżetów
</p>
</div>
</div>
</div>
</section>

<!-- Goals Section -->


<section id="goals" class="section">
<div class="form-grid">
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-plus-circle"></i>
Dodaj cel finansowy
</h2>
</div>
<div class="success-message" id="goal-success"></div>
<form id="goal-form">
<div class="form-group">
<label class="form-label" for="goal-name">Nazwa
celu *</label>
<input type="text" id="goal-name" class="form-
control"
placeholder="np. Wakacje, Nowy samochód"
required>
<div class="error-message

You might also like