Initial commit

This commit is contained in:
2025-05-31 14:50:40 +00:00
commit f61df12e5d
14 changed files with 1128 additions and 0 deletions

35
templates/base.html Normal file
View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Expense Tracker - Home Assistant</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
</head>
<body>
<div class="sidebar">
<div class="sidebar-header">
<i class="fas fa-cash-register"></i>
<h2>Expense Tracker</h2>
</div>
<nav>
<ul>
<li><a href="{{ url_for('index') }}"><i class="fas fa-home"></i> Dashboard</a></li>
<li><a href="{{ url_for('expenses') }}"><i class="fas fa-receipt"></i> Ausgaben</a></li>
<li><a href="{{ url_for('categories') }}"><i class="fas fa-tags"></i> Kategorien</a></li>
<!--<li><a href="{{ url_for('reports') }}"><i class="fas fa-chart-pie"></i> Berichte</a></li>-->
</ul>
</nav>
</div>
<div class="main-content">
<div class="content-wrapper">
{% block content %}{% endblock %}
</div>
</div>
<script src="{{ url_for('static', filename='js/scripts.js') }}"></script>
</body>
</html>

53
templates/categories.html Normal file
View File

@ -0,0 +1,53 @@
{% extends "base.html" %}
{% block content %}
<div class="categories-page">
<h1>Kategorien verwalten</h1>
<div class="form-container">
<h2>Neue Kategorie hinzufügen</h2>
{% if error %}
<div class="error-message">{{ error }}</div>
{% endif %}
<form action="{{ url_for('categories') }}" method="post">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="description">Beschreibung:</label>
<input type="text" id="description" name="description">
</div>
<div class="form-actions">
<button type="submit" class="button primary">Kategorie speichern</button>
</div>
</form>
</div>
<div class="categories-list">
<h2>Alle Kategorien</h2>
<table>
<thead>
<tr>
<th>Name</th>
<th>Beschreibung</th>
</tr>
</thead>
<tbody>
{% for category in categories %}
<tr>
<td>{{ category.name }}</td>
<td>{{ category.description }}</td>
</tr>
{% else %}
<tr>
<td colspan="2" class="no-data">Keine Kategorien vorhanden</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

69
templates/expenses.html Normal file
View File

@ -0,0 +1,69 @@
{% extends "base.html" %}
{% block content %}
<div class="expenses-page">
<h1>Ausgaben verwalten</h1>
<div class="form-container">
<h2>Neue Ausgabe hinzufügen</h2>
<form action="{{ url_for('expenses') }}" method="post">
<div class="form-group">
<label for="amount">Betrag (€):</label>
<input type="number" id="amount" name="amount" step="0.01" min="0.01" required>
</div>
<div class="form-group">
<label for="description">Beschreibung:</label>
<input type="text" id="description" name="description" required>
</div>
<div class="form-group">
<label for="category_id">Kategorie:</label>
<select id="category_id" name="category_id" required>
<option value="">-- Kategorie wählen --</option>
{% for category in categories %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group">
<label for="date">Datum:</label>
<input type="date" id="date" name="date" value="{{ today }}" required>
</div>
<div class="form-actions">
<button type="submit" class="button primary">Ausgabe speichern</button>
</div>
</form>
</div>
<div class="expenses-list">
<h2>Alle Ausgaben</h2>
<table>
<thead>
<tr>
<th>Datum</th>
<th>Beschreibung</th>
<th>Kategorie</th>
<th>Betrag</th>
</tr>
</thead>
<tbody>
{% for expense in expenses %}
<tr>
<td>{{ expense.date.strftime('%d.%m.%Y') }}</td>
<td>{{ expense.description }}</td>
<td>{{ expense.category.name }}</td>
<td class="amount">{{ "%.2f"|format(expense.amount) }} €</td>
</tr>
{% else %}
<tr>
<td colspan="4" class="no-data">Keine Ausgaben vorhanden</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endblock %}

110
templates/index.html Normal file
View File

@ -0,0 +1,110 @@
{% extends "base.html" %}
{% block content %}
<div class="dashboard">
<h1>Dashboard</h1>
<div class="dashboard-summary">
<div class="summary-card">
<div class="card-icon">
<i class="fas fa-euro-sign"></i>
</div>
<div class="card-content">
<h3>Gesamtausgaben</h3>
<p class="amount">{{ "%.2f"|format(total_expenses) }} €</p>
</div>
</div>
<div class="summary-card">
<div class="card-icon">
<i class="fas fa-calendar-alt"></i>
</div>
<div class="card-content">
<h3>Aktuelle Periode</h3>
<p>{{ now.strftime('%B %Y') }}</p>
</div>
</div>
<div class="summary-card">
<div class="card-icon">
<i class="fas fa-tags"></i>
</div>
<div class="card-content">
<h3>Kategorien</h3>
<p>{{ categories|length }}</p>
</div>
</div>
</div>
<div class="dashboard-charts">
<div class="chart-container">
<h2>Ausgaben nach Kategorie</h2>
<div id="category-chart"></div>
</div>
</div>
<div class="recent-expenses">
<h2>Neueste Ausgaben</h2>
<table>
<thead>
<tr>
<th>Datum</th>
<th>Beschreibung</th>
<th>Kategorie</th>
<th>Betrag</th>
</tr>
</thead>
<tbody>
{% for expense in expenses %}
<tr>
<td>{{ expense.date.strftime('%d.%m.%Y') }}</td>
<td>{{ expense.description }}</td>
<td>{{ expense.category.name }}</td>
<td class="amount">{{ "%.2f"|format(expense.amount) }} €</td>
</tr>
{% else %}
<tr>
<td colspan="4" class="no-data">Keine Ausgaben vorhanden</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="action-button">
<a href="{{ url_for('expenses') }}" class="button">Alle Ausgaben anzeigen</a>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Category pie chart
const categoryNames = {{ category_names|safe }};
const categoryAmounts = {{ category_amounts|safe }};
if (categoryNames.length > 0) {
const data = [{
values: categoryAmounts,
labels: categoryNames,
type: 'pie',
marker: {
colors: [
'#4e79a7', '#f28e2c', '#e15759', '#76b7b2',
'#59a14f', '#edc949', '#af7aa1', '#ff9da7',
'#9c755f', '#bab0ab'
]
}
}];
const layout = {
height: 400,
margin: { t: 0, b: 0, l: 0, r: 0 },
showlegend: true
};
Plotly.newPlot('category-chart', data, layout);
} else {
document.getElementById('category-chart').innerHTML = '<p class="no-data">Keine Daten verfügbar</p>';
}
});
</script>
{% endblock %}

43
templates/reports.html Normal file
View File

@ -0,0 +1,43 @@
{% extends "base.html" %}
{% block content %}
<div class="reports-page">
<h1>Ausgabenberichte</h1>
<div class="filter-container">
<h2>Zeitraum filtern</h2>
<form action="{{ url_for('reports') }}" method="get">
<div class="form-group inline">
<label for="start_date">Von:</label>
<input type="date" id="start_date" name="start_date" value="{{ start_date }}">
</div>
<div class="form-group inline">
<label for="end_date">Bis:</label>
<input type="date" id="end_date" name="end_date" value="{{ end_date }}">
</div>
<div class="form-actions">
<button type="submit" class="button primary">Filter anwenden</button>
<a href="{{ url_for('reports') }}" class="button secondary">Zurücksetzen</a>
</div>
</form>
</div>
<div class="charts-container">
<div class="chart-box">
<h2>Ausgaben nach Kategorie</h2>
<div class="chart">
{{ category_chart|safe }}
</div>
</div>
<div class="chart-box">
<h2>Ausgaben im Zeitverlauf</h2>
<div class="chart">
{{ timeline_chart|safe }}
</div>
</div>
</div>
</div>
{% endblock %}