diff --git a/README.md b/README.md
index b59bff8..67a58d2 100644
--- a/README.md
+++ b/README.md
@@ -18,5 +18,8 @@ Beim ersten Start wird die Datenbank mit einigen Beispielkonten angelegt.
* Gewinn- und Verlustrechnung
* Bilanz
* Umsatzsteuervoranmeldung
+* Modernes, responsives Frontend mit Vue unter `/vue_app`
+
+Das Layout verwendet ein Bootswatch-Theme, wodurch die Anwendung auch auf Handy und Tablet gut aussieht.
Die Umsetzung dient nur als Demonstration und ist nicht für den produktiven Einsatz geeignet.
diff --git a/app/routes.py b/app/routes.py
index 3353bd0..ca6b62f 100644
--- a/app/routes.py
+++ b/app/routes.py
@@ -1,4 +1,4 @@
-from flask import render_template, request, redirect, url_for
+from flask import render_template, request, redirect, url_for, jsonify
from . import app, db
from .models import Account, Entry
@@ -6,6 +6,10 @@
def index():
return render_template('index.html')
+@app.route('/vue_app')
+def vue_app():
+ return render_template('vue_app.html')
+
@app.route('/accounts')
def accounts():
accounts = Account.query.order_by(Account.number).all()
@@ -26,6 +30,37 @@ def entries():
entries = Entry.query.order_by(Entry.entry_date.desc()).all()
return render_template('entries.html', entries=entries, accounts=accounts)
+@app.route('/api/accounts')
+def api_accounts():
+ accounts = Account.query.order_by(Account.number).all()
+ return jsonify([{'id': a.id, 'number': a.number, 'name': a.name, 'type': a.type} for a in accounts])
+
+@app.route('/api/entries', methods=['GET', 'POST'])
+def api_entries():
+ if request.method == 'POST':
+ data = request.get_json()
+ entry = Entry(
+ debit_id=data['debit_id'],
+ credit_id=data['credit_id'],
+ amount=data['amount'],
+ description=data.get('description', '')
+ )
+ db.session.add(entry)
+ db.session.commit()
+ return jsonify({'status': 'success'})
+ entries = Entry.query.order_by(Entry.entry_date.desc()).all()
+ result = []
+ for e in entries:
+ result.append({
+ 'id': e.id,
+ 'entry_date': e.entry_date.isoformat(),
+ 'description': e.description,
+ 'debit': {'id': e.debit.id, 'number': e.debit.number, 'name': e.debit.name},
+ 'credit': {'id': e.credit.id, 'number': e.credit.number, 'name': e.credit.name},
+ 'amount': e.amount
+ })
+ return jsonify(result)
+
@app.route('/profit_loss')
def profit_loss():
income_accounts = Account.query.filter(Account.type=='income').all()
diff --git a/app/static/js/app.js b/app/static/js/app.js
new file mode 100644
index 0000000..1c881c1
--- /dev/null
+++ b/app/static/js/app.js
@@ -0,0 +1,38 @@
+const { createApp } = Vue;
+
+createApp({
+ data() {
+ return {
+ accounts: [],
+ entries: [],
+ newEntry: {
+ debit_id: '',
+ credit_id: '',
+ amount: '',
+ description: ''
+ }
+ };
+ },
+ methods: {
+ fetchAccounts() {
+ axios.get('/api/accounts').then(res => {
+ this.accounts = res.data;
+ });
+ },
+ fetchEntries() {
+ axios.get('/api/entries').then(res => {
+ this.entries = res.data;
+ });
+ },
+ addEntry() {
+ axios.post('/api/entries', this.newEntry).then(() => {
+ this.fetchEntries();
+ this.newEntry = { debit_id: '', credit_id: '', amount: '', description: '' };
+ });
+ }
+ },
+ mounted() {
+ this.fetchAccounts();
+ this.fetchEntries();
+ }
+}).mount('#app');
diff --git a/app/templates/accounts.html b/app/templates/accounts.html
index 0365208..0e16def 100644
--- a/app/templates/accounts.html
+++ b/app/templates/accounts.html
@@ -1,10 +1,14 @@
{% extends 'base.html' %}
{% block content %}
-
Konten
-
-| Nummer | Name | Typ |
-{% for acc in accounts %}
-| {{ acc.number }} | {{ acc.name }} | {{ acc.type }} |
-{% endfor %}
+Konten
+
+
+ | Nummer | Name | Typ |
+
+
+ {% for acc in accounts %}
+ | {{ acc.number }} | {{ acc.name }} | {{ acc.type }} |
+ {% endfor %}
+
{% endblock %}
diff --git a/app/templates/balance.html b/app/templates/balance.html
index 1f89a43..a39ec6f 100644
--- a/app/templates/balance.html
+++ b/app/templates/balance.html
@@ -1,18 +1,22 @@
{% extends 'base.html' %}
{% block content %}
-Bilanz
-
-| Aktiva | Betrag | Passiva | Betrag |
-{% for left, right in rows %}
-
- | {{ left.name if left else '' }} |
- {{ '%.2f'|format(left.amount) if left else '' }} |
- {{ right.name if right else '' }} |
- {{ '%.2f'|format(right.amount) if right else '' }} |
-
-{% endfor %}
-| Summe Aktiva | {{ '%.2f'|format(asset_total) }} |
- Summe Passiva | {{ '%.2f'|format(liability_total) }} |
- | Eigenkapital | {{ '%.2f'|format(equity) }} |
+Bilanz
+
+
+ | Aktiva | Betrag | Passiva | Betrag |
+
+
+ {% for left, right in rows %}
+
+ | {{ left.name if left else '' }} |
+ {{ '%.2f'|format(left.amount) if left else '' }} |
+ {{ right.name if right else '' }} |
+ {{ '%.2f'|format(right.amount) if right else '' }} |
+
+ {% endfor %}
+ | Summe Aktiva | {{ '%.2f'|format(asset_total) }} |
+ Summe Passiva | {{ '%.2f'|format(liability_total) }} |
+ | Eigenkapital | {{ '%.2f'|format(equity) }} |
+
{% endblock %}
diff --git a/app/templates/base.html b/app/templates/base.html
index eb057ef..df1a0b4 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -2,18 +2,32 @@
+
Buchhaltung
+
-