diff --git a/app.py b/app.py new file mode 100644 index 0000000..f1545d3 --- /dev/null +++ b/app.py @@ -0,0 +1,234 @@ +from flask import Flask, request, jsonify, redirect, url_for, session, render_template +from flask_sqlalchemy import SQLAlchemy +from werkzeug.security import generate_password_hash, check_password_hash +from flask_session import Session +from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user +import random + + +app = Flask(__name__) +app.config['SECRET_KEY'] = 'your_secret_key' # Ändere dies zu einem echten geheimen Schlüssel +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///vocab.db' +app.config['SESSION_TYPE'] = 'filesystem' +app.config['SESSION_PERMANENT'] = False +app.config['SESSION_USE_SIGNER'] = True + +db = SQLAlchemy(app) +Session(app) + +login_manager = LoginManager() +login_manager.init_app(app) +login_manager.login_view = 'login' + +# Models +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(150), nullable=False) + vocabularies = db.relationship('Vocabulary', backref='owner', lazy=True) + +class Vocabulary(db.Model): + id = db.Column(db.Integer, primary_key=True) + english = db.Column(db.String(100), nullable=False) + german = db.Column(db.String(100), nullable=False) + level = db.Column(db.Integer, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + +def get_random_vocab(user_id): + vocab_list = Vocabulary.query.filter_by(user_id=user_id).all() + if not vocab_list: + return None + + # Weight levels: Level 1 should be most common, Level 5 the least + weighted_vocab_list = [] + for vocab in vocab_list: + weight = max(1, 6 - vocab.level) # Weight 5 for level 1, 4 for level 2, ..., 1 for level 5 + weighted_vocab_list.extend([vocab] * weight) + + return random.choice(weighted_vocab_list) + +@app.route('/get_random_vocab', methods=['GET']) +@login_required +def get_random_vocab_route(): + vocab = get_random_vocab(current_user.id) + if vocab: + return jsonify({ + 'english': vocab.english, + 'german': vocab.german, + 'level': vocab.level, + 'id': vocab.id, + }), 200 + return jsonify({'error': 'No vocabulary found'}), 404 + +@app.route('/update_vocab_level/', methods=['POST']) +@login_required +def update_vocab_level(id): + vocab = Vocabulary.query.get(id) + if vocab and vocab.user_id == current_user.id: + if vocab.level < 5: + vocab.level += 1 + db.session.commit() + return jsonify({'success': True}), 200 + return jsonify({'message': 'Max level reached'}), 200 + return jsonify({'error': 'Not found or unauthorized'}), 404 + +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + +@app.route('/') +def index(): + return render_template('start.html') + +@app.route('/train') +@login_required +def train(): + return render_template('train.html') + +@app.route('/settings') +@login_required +def settings(): + return render_template('settings.html') + +@app.route('/vocab') +@login_required +def vocab(): + return render_template('vocab.html') + +@app.route('/register', methods=['GET', 'POST']) +def register(): + if request.method == 'POST': + username = request.form.get('username') + password = request.form.get('password') + + if not username or not password: + return render_template('register.html', error='Username and password are required'), 400 + + existing_user = User.query.filter_by(username=username).first() + if existing_user: + return render_template('register.html', error='Username already taken'), 409 # 409 Conflict + + hashed_password = generate_password_hash(password, method='pbkdf2:sha256') + new_user = User(username=username, password=hashed_password) + + db.session.add(new_user) + db.session.commit() + + return redirect(url_for('login')) + + return render_template('register.html') + +@app.route('/login', methods=['GET', 'POST']) +def login(): + if request.method == 'POST': + username = request.form.get('username') + password = request.form.get('password') + user = User.query.filter_by(username=username).first() + if user and check_password_hash(user.password, password): + login_user(user) + return jsonify({'success': True}), 200 + else: + return jsonify({'error': 'Invalid credentials'}), 401 + + # GET request: render login page + return render_template('login.html') + +@app.route('/logout', methods=['POST']) +@login_required +def logout(): + logout_user() + return redirect(url_for('index')) + +@app.route('/add_vocab', methods=['POST']) +@login_required +def add_vocab(): + english = request.form.get('english') + german = request.form.get('german') + level = int(request.form.get('level', 1)) + + if not english or not german or not level: + return jsonify({'error': 'All fields are required'}), 400 + + vocab = Vocabulary(english=english, german=german, level=level, user_id=current_user.id) + try: + db.session.add(vocab) + db.session.commit() + return jsonify({'success': True}), 201 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/update_vocab/', methods=['PUT']) +@login_required +def update_vocab(id): + vocab = Vocabulary.query.get(id) + if not vocab or vocab.user_id != current_user.id: + return jsonify({'error': 'Not found or unauthorized'}), 404 + + english = request.json.get('english') + german = request.json.get('german') + level = request.json.get('level') + + if english: + vocab.english = english + if german: + vocab.german = german + if level: + vocab.level = level + + try: + db.session.commit() + return jsonify({'success': True}), 200 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/delete_vocab/', methods=['DELETE']) +@login_required +def delete_vocab(id): + vocab = Vocabulary.query.get(id) + if not vocab or vocab.user_id != current_user.id: + return jsonify({'error': 'Not found or unauthorized'}), 404 + + try: + db.session.delete(vocab) + db.session.commit() + return jsonify({'success': True}), 200 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/get_vocab', methods=['GET']) +@login_required +def get_vocab(): + vocab_list = Vocabulary.query.filter_by(user_id=current_user.id).all() + result = [{'id': v.id, 'english': v.english, 'german': v.german, 'level': v.level} for v in vocab_list] + return jsonify(result) + +@app.route('/change_username', methods=['POST']) +@login_required +def change_username(): + new_username = request.form.get('new_username') + + if not new_username: + return jsonify({'error': 'Benutzername ist erforderlich'}), 400 + + if User.query.filter_by(username=new_username).first(): + return jsonify({'error': 'Benutzername bereits vergeben'}), 409 + + current_user.username = new_username + try: + db.session.commit() + return jsonify({'success': True}), 200 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +if __name__ == '__main__': + with app.app_context(): + db.create_all() + app.run(debug=True) + + + diff --git a/defindatabank.py b/defindatabank.py new file mode 100644 index 0000000..813c4e2 --- /dev/null +++ b/defindatabank.py @@ -0,0 +1,3 @@ +from app import db +db.create_all() + diff --git a/forms.py b/forms.py new file mode 100644 index 0000000..7ea561a --- /dev/null +++ b/forms.py @@ -0,0 +1,13 @@ +from app import db +from flask_login import UserMixin + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(150), nullable=False) + notes = db.relationship('Note', backref='author', lazy=True) + +class Note(db.Model): + id = db.Column(db.Integer, primary_key=True) + content = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) diff --git a/instance/vocab.db b/instance/vocab.db new file mode 100644 index 0000000..3cd3e0c Binary files /dev/null and b/instance/vocab.db differ diff --git a/models.py b/models.py new file mode 100644 index 0000000..40c9d0e --- /dev/null +++ b/models.py @@ -0,0 +1,18 @@ +from flask_sqlalchemy import SQLAlchemy +from flask_login import UserMixin + +db = SQLAlchemy() + +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(150), nullable=False) + notes = db.relationship('Note', backref='author', lazy=True) + +class Note(db.Model): + id = db.Column(db.Integer, primary_key=True) + content = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + + diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..3855e4b --- /dev/null +++ b/static/script.js @@ -0,0 +1,151 @@ +const canvas = document.getElementById('drawingCanvas'); +const ctx = canvas.getContext('2d'); +const textElement = document.getElementById('text'); +const wordDisplay = document.getElementById('wordDisplay'); +const textInput = document.getElementById('textInput'); +const submitAnswer = document.getElementById('submitAnswer'); +const toggleInput = document.getElementById('toggleInput'); +const clearCanvas = document.getElementById('clearCanvas'); +const previewDrawing = document.getElementById('previewDrawing'); +const recognizedText = document.getElementById('recognizedText'); + +let currentWord = null; +let currentInputMode = 'text'; // 'text' or 'drawing' +let isDrawing = false; + +// Initialize input mode +function initializeInputMode() { + textInput.style.display = 'block'; + canvas.style.display = 'none'; + clearCanvas.style.display = 'none'; + previewDrawing.style.display = 'none'; + toggleInput.textContent = 'Zu Zeichnen wechseln'; + recognizedText.textContent = ''; +} + +// Load a new word +function loadWord() { + fetch('/get_random_vocab') + .then(response => response.json()) + .then(data => { + if (data.error) { + wordDisplay.textContent = 'Keine Vokabeln gefunden.'; + } else { + currentWord = data; + const isEnglish = Math.random() < 0.5; + wordDisplay.textContent = isEnglish ? `English: ${currentWord.english}` : `Deutsch: ${currentWord.german}`; + textElement.textContent = ''; + textInput.value = ''; + recognizedText.textContent = ''; + if (currentInputMode === 'drawing') { + ctx.clearRect(0, 0, canvas.width, canvas.height); + } + } + }) + .catch(error => console.error('Fehler beim Laden der Vokabel:', error)); +} + +// Switch between input modes +toggleInput.addEventListener('click', () => { + if (currentInputMode === 'text') { + textInput.style.display = 'none'; + canvas.style.display = 'block'; + clearCanvas.style.display = 'inline-block'; + previewDrawing.style.display = 'inline-block'; + toggleInput.textContent = 'Zu Texteingabe wechseln'; + currentInputMode = 'drawing'; + } else { + textInput.style.display = 'block'; + canvas.style.display = 'none'; + clearCanvas.style.display = 'none'; + previewDrawing.style.display = 'none'; + toggleInput.textContent = 'Zu Zeichnen wechseln'; + currentInputMode = 'text'; + } +}); + +// Clear the canvas +clearCanvas.addEventListener('click', () => { + ctx.clearRect(0, 0, canvas.width, canvas.height); + recognizedText.textContent = ''; // Clear the recognized text as well +}); + +// Drawing functionality +canvas.addEventListener('mousedown', () => { + isDrawing = true; +}); + +canvas.addEventListener('mouseup', () => { + isDrawing = false; + ctx.beginPath(); +}); + +canvas.addEventListener('mousemove', draw); + +function draw(event) { + if (!isDrawing) return; + ctx.lineWidth = 5; + ctx.lineCap = 'round'; + ctx.strokeStyle = 'black'; + + ctx.lineTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop); +} + +// Preview the drawing recognition +previewDrawing.addEventListener('click', () => { + const dataURL = canvas.toDataURL('image/png'); + + fetch(dataURL) + .then(res => res.blob()) + .then(blob => { + Tesseract.recognize( + blob, + 'eng', + { logger: info => console.log(info) } + ).then(({ data: { text } }) => { + recognizedText.textContent = `Erkannter Text: ${text.trim()}`; + }); + }) + .catch(error => { + console.error('Fehler beim Erkennen des Textes:', error); + }); +}); + +// Submit answer +submitAnswer.addEventListener('click', () => { + let answer = ''; + + if (currentInputMode === 'text') { + answer = textInput.value.trim(); + } else { + answer = recognizedText.textContent.replace('Erkannter Text:', '').trim(); + } + + checkAnswer(answer); +}); + +// Check if the answer is correct +function checkAnswer(answer) { + const correctAnswer = (wordDisplay.textContent.startsWith('English:') ? currentWord.german : currentWord.english).trim().toLowerCase(); + if (answer.toLowerCase() === correctAnswer) { + textElement.textContent = 'Richtig!'; + textElement.style.color = 'green'; + // Update the vocabulary level + fetch(`/update_vocab_level/${currentWord.id}`, { method: 'POST' }) + .then(() => { + setTimeout(loadWord, 2000); // Show the result for 2 seconds before loading the next word + }); + } else { + textElement.textContent = `Falsch! Die richtige Antwort ist: ${correctAnswer}`; + textElement.style.color = 'red'; + setTimeout(loadWord, 3000); // Show the result for 3 seconds before loading the next word + } +} + +// Initialize the input mode and load the first word +initializeInputMode(); +loadWord(); + diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..b72a21c --- /dev/null +++ b/static/styles.css @@ -0,0 +1,33 @@ + +body { + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + background-color: #f4f4f4; +} + +.container { + display: flex; + flex-direction: column; + align-items: center; +} + +canvas { + border: 1px solid #000; + background-color: #fff; +} + +button { + margin-top: 10px; + padding: 10px 20px; + background-color: #007bff; + color: #fff; + border: none; + cursor: pointer; +} + +button:hover { + background-color: #0056b3; +} diff --git a/static/vocab.js b/static/vocab.js new file mode 100644 index 0000000..514eed6 --- /dev/null +++ b/static/vocab.js @@ -0,0 +1,160 @@ +document.addEventListener('DOMContentLoaded', () => { + loadVocab(); + + document.getElementById('addVocab').addEventListener('click', () => { + const englishInput = document.getElementById('englishInput').value; + const germanInput = document.getElementById('germanInput').value; + + if (englishInput && germanInput) { + fetch('/add_vocab', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: new URLSearchParams({ + english: englishInput, + german: germanInput, + level: 1 // Automatisch Level 1 setzen + }) + }).then(response => response.json()) + .then(data => { + if (data.success) { + loadVocab(); + + document.getElementById('englishInput').value = ''; + document.getElementById('germanInput').value = ''; + } else { + alert(data.error); + } + }).catch(error => { + console.error('Fehler beim Hinzufügen der Vokabel:', error); + }); + } else { + alert('Bitte alle Felder ausfüllen.'); + } + }); + + document.getElementById('backToHome').addEventListener('click', () => { + window.location.href = '/'; // Pfad zur Startseite anpassen + }); +}); + +function loadVocab() { + fetch('/get_vocab') + .then(response => response.json()) + .then(vocabList => { + const tables = [1, 2, 3, 4, 5].map(level => document.getElementById(`vocab-list-${level}`)); + tables.forEach(table => table.querySelector('tbody').innerHTML = ''); + + vocabList.forEach(vocab => { + const row = document.createElement('tr'); + row.dataset.id = vocab.id; + row.dataset.level = vocab.level; // Level in dataset speichern + row.innerHTML = ` + ${vocab.english} + ${vocab.german} + + + + + `; + + const targetTable = document.getElementById(`vocab-list-${vocab.level}`); + targetTable.querySelector('tbody').appendChild(row); + }); + + // Event-Listener für den „Löschen“-Button + document.querySelectorAll('.delete-btn').forEach(btn => { + btn.addEventListener('click', (event) => { + const vocabId = event.target.getAttribute('data-id'); + fetch(`/delete_vocab/${vocabId}`, { + method: 'DELETE' + }).then(response => response.json()) + .then(data => { + if (data.success) { + loadVocab(); + } else { + alert(data.error); + } + }).catch(error => { + console.error('Fehler beim Löschen der Vokabel:', error); + }); + }); + }); + + // Event-Listener für den „Bearbeiten“-Button + document.querySelectorAll('.edit-btn').forEach(btn => { + btn.addEventListener('click', (event) => { + const row = event.target.closest('tr'); + const id = row.dataset.id; + const english = row.children[0].textContent; + const german = row.children[1].textContent; + const level = row.dataset.level || 1; // Level aus dem dataset lesen, Fallback auf 1 + + // Setze die Zeile in den Bearbeitungsmodus + row.innerHTML = ` + + + +
+ + +
+ + + + `; + + row.querySelector('.save-btn').addEventListener('click', () => { + const englishInput = row.querySelector('.editable-input').value; + const germanInput = row.querySelectorAll('.editable-input')[1].value; + const levelInput = row.querySelector('#levelInput').value; + + fetch(`/update_vocab/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + english: englishInput, + german: germanInput, + level: parseInt(levelInput, 10) + }) + }).then(response => response.json()) + .then(data => { + if (data.success) { + loadVocab(); + } else { + alert(data.error); + } + }).catch(error => { + console.error('Fehler beim Aktualisieren der Vokabel:', error); + }); + }); + + row.querySelector('.cancel-btn').addEventListener('click', () => { + loadVocab(); + }); + }); + }); + }).catch(error => { + console.error('Fehler beim Laden der Vokabeln:', error); + }); +} + + + + + +//sqlite3 anstatt cokkies + + + + + + + + + + + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..f2a6124 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,98 @@ + + + + + + Anmelden + + + +

Anmelden

+
+ {% with messages = get_flashed_messages(with_categories=True) %} + {% if messages %} + {% for category, message in messages %} +
{{ message }}
+ {% endfor %} + {% endif %} + {% endwith %} +
+
+ + +
+
+ + +
+ +
+ Noch kein Konto? Registrieren +
+ + diff --git a/templates/register.html b/templates/register.html new file mode 100644 index 0000000..3123801 --- /dev/null +++ b/templates/register.html @@ -0,0 +1,77 @@ + + + + + + Register + + + +

Register

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

{{ error }}

+
+
+
+ + + diff --git a/templates/settings.html b/templates/settings.html new file mode 100644 index 0000000..6b9f3e0 --- /dev/null +++ b/templates/settings.html @@ -0,0 +1,127 @@ + + + + + + Einstellungen + + + +

Einstellungen

+
+ +
+
+ + +
+ +
+
+ + +
+ +
+
+ + + + + + + + + + + diff --git a/templates/start.html b/templates/start.html new file mode 100644 index 0000000..f8f66a2 --- /dev/null +++ b/templates/start.html @@ -0,0 +1,47 @@ + + + + + + Vokabeltrainer + + + +

Vokabeltrainer

+ + + + diff --git a/templates/train.html b/templates/train.html new file mode 100644 index 0000000..55a5d57 --- /dev/null +++ b/templates/train.html @@ -0,0 +1,89 @@ + + + + + + Vokabeln trainieren + + + +

Vokabeln trainieren

+
Lade...
+ +
+ + + +
+ + + + + +
+ +
+

+    
+ Zurück zur Startseite + + + + + + diff --git a/templates/vocab.html b/templates/vocab.html new file mode 100644 index 0000000..44c99a4 --- /dev/null +++ b/templates/vocab.html @@ -0,0 +1,268 @@ + + + + + + Meine Vokabeln + + + + +

Meine Vokabeln

+
+ +
+ + + + +
+ + + + + + + + + + + + + + +
Neue Vokabeln
EnglischDeutschAktionen
+ + + + + + + + + + + + + +
Vokabeln, die noch nicht sitzen
EnglischDeutschAktionen
+ + + + + + + + + + + + + +
Vokabeln, die fast sitzen
EnglischDeutschAktionen
+ + + + + + + + + + + + + +
Vokabeln, die gut sitzen
EnglischDeutschAktionen
+ + + + + + + + + + + + + +
Perfekte Vokabeln
EnglischDeutschAktionen
+
+ + + + + + + + + + + + + + + + + + + + diff --git a/test.txt b/test.txt new file mode 100644 index 0000000..39bd657 --- /dev/null +++ b/test.txt @@ -0,0 +1,168 @@ +from flask import Flask, request, jsonify, redirect, url_for, session, render_template +from flask_sqlalchemy import SQLAlchemy +from werkzeug.security import generate_password_hash, check_password_hash +from flask_session import Session +from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user, login_manager + +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///vocab.db' +app.config['SECRET_KEY'] = 'your_secret_key' # Ändere dies zu einem echten geheimen Schlüssel +app.config['SESSION_TYPE'] = 'filesystem' +app.config['SESSION_PERMANENT'] = False +app.config['SESSION_USE_SIGNER'] = True + +db = SQLAlchemy(app) +Session(app) + +# Flask-Login Setup +login_manager = LoginManager() +login_manager.init_app(app) +login_manager.login_view = 'login' + +# Models +class User(db.Model, UserMixin): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(150), unique=True, nullable=False) + password = db.Column(db.String(150), nullable=False) + vocabularies = db.relationship('Vocabulary', backref='owner', lazy=True) + +class Vocabulary(db.Model): + id = db.Column(db.Integer, primary_key=True) + english = db.Column(db.String(100), nullable=False) + german = db.Column(db.String(100), nullable=False) + level = db.Column(db.Integer, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + +# User loader callback for Flask-Login +@login_manager.user_loader +def load_user(user_id): + return User.query.get(int(user_id)) + +# Route Handlers +@app.route('/') +def index(): + return render_template('start.html') + +@app.route('/train') +@login_required +def train(): + return render_template('train.html') # Stelle sicher, dass diese Datei existiert + +@app.route('/settings') +@login_required +def settings(): + return render_template('settings.html') # Stelle sicher, dass diese Datei existiert + +@app.route('/vocab') +@login_required +def vocab(): + return render_template('vocab.html') + +@app.route('/register', methods=['POST']) +def register(): + username = request.form.get('username') + password = request.form.get('password') + if not username or not password: + return jsonify({'error': 'Username and password are required'}), 400 + + hashed_password = generate_password_hash(password, method='pbkdf2:sha256') + user = User(username=username, password=hashed_password) + + try: + db.session.add(user) + db.session.commit() + return jsonify({'success': True}), 201 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/login', methods=['POST']) +def login(): + username = request.form['username'] + password = request.form['password'] + + user = User.query.filter_by(username=username).first() + if user and check_password_hash(user.password, password): + session['logged_in'] = True + session['user_id'] = user.id + return redirect('/settings') + else: + return jsonify({"error": "Invalid credentials"}), 401 + + +@app.route('/logout', methods=['POST']) +@login_required +def logout(): + logout_user() + return redirect(url_for('index')) + +@app.route('/add_vocab', methods=['POST']) +@login_required +def add_vocab(): + english = request.form.get('english') + german = request.form.get('german') + level = int(request.form.get('level')) + + if not english or not german or not level: + return jsonify({'error': 'All fields are required'}), 400 + + vocab = Vocabulary(english=english, german=german, level=level, user_id=current_user.id) + try: + db.session.add(vocab) + db.session.commit() + return jsonify({'success': True}), 201 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/update_vocab/', methods=['PUT']) +@login_required +def update_vocab(id): + vocab = Vocabulary.query.get(id) + if not vocab or vocab.user_id != current_user.id: + return jsonify({'error': 'Not found or unauthorized'}), 404 + + english = request.json.get('english') + german = request.json.get('german') + level = request.json.get('level') + + if english: + vocab.english = english + if german: + vocab.german = german + if level: + vocab.level = level + + try: + db.session.commit() + return jsonify({'success': True}), 200 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/delete_vocab/', methods=['DELETE']) +@login_required +def delete_vocab(id): + vocab = Vocabulary.query.get(id) + if not vocab or vocab.user_id != current_user.id: + return jsonify({'error': 'Not found or unauthorized'}), 404 + + try: + db.session.delete(vocab) + db.session.commit() + return jsonify({'success': True}), 200 + except Exception as e: + db.session.rollback() + return jsonify({'error': str(e)}), 500 + +@app.route('/get_vocab', methods=['GET']) +@login_required +def get_vocab(): + vocab_list = Vocabulary.query.filter_by(user_id=current_user.id).all() + result = [{'id': v.id, 'english': v.english, 'german': v.german, 'level': v.level} for v in vocab_list] + return jsonify(result) + +if __name__ == '__main__': + with app.app_context(): + db.create_all() + app.run(debug=True)