From fc1b68ebb443fe83bd53edb2e2d0c6cf3787f091 Mon Sep 17 00:00:00 2001 From: Thomas Hackner Date: Tue, 14 Jul 2026 14:58:18 +0200 Subject: [PATCH] Bewerbungen favorisieren (statt Jobangebote) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stern zum Merken einzelner Bewerbungen auf der Startseiten-Liste, der Bewerbungsdetailseite und einer neuen 'Gemerkte Bewerbungen'-Sektion ganz oben — unabhaengig vom Status. Die bisherigen Jobangebot-Favoriten werden durchgaengig entfernt (Endpoint, Migration, UI, Startseiten-Sektion), da nur Bewerbungen gemerkt werden sollen. Co-Authored-By: Claude --- server.js | 41 +++++++-------- views/bewerbung.ejs | 3 ++ views/index.ejs | 5 +- views/jobangebote.ejs | 3 -- views/jobangebote_uebernommen.ejs | 3 -- views/partials/bewerbung-favoriten.ejs | 47 +++++++++++++++++ views/partials/favorit-button.ejs | 25 ++++++--- views/partials/favorit-script.ejs | 5 +- views/partials/favoriten.ejs | 72 -------------------------- 9 files changed, 94 insertions(+), 110 deletions(-) create mode 100644 views/partials/bewerbung-favoriten.ejs delete mode 100644 views/partials/favoriten.ejs diff --git a/server.js b/server.js index c711862..e3929e0 100644 --- a/server.js +++ b/server.js @@ -1441,10 +1441,12 @@ async function initializeDatabase() { // Favoriten-Merkmal (Stern): 0 = nicht gemerkt, 1 = favorisiert. Favoriten // erscheinen oben auf der Startseite — unabhängig vom Status (offen / // uebernommen / abgelehnt). Spalte wird nur bei Bedarf angelegt. + // Favoriten-Markierung für Bewerbungen. Erlaubt das Merken einzelner + // Bewerbungen, unabhängig von ihrem Status. { - const jobSpalten = await dbAll('PRAGMA table_info(jobangebote)'); - if (!jobSpalten.some((s) => s.name === 'favorit')) { - await exec('ALTER TABLE jobangebote ADD COLUMN favorit INTEGER NOT NULL DEFAULT 0'); + const bewSpalten = await dbAll('PRAGMA table_info(bewerbungen)'); + if (!bewSpalten.some((s) => s.name === 'favorit')) { + await exec('ALTER TABLE bewerbungen ADD COLUMN favorit INTEGER NOT NULL DEFAULT 0'); } } @@ -1754,14 +1756,13 @@ initializeDatabase().then(async () => { }; } - // Gemerkte Stellen (Favoriten) für die Sektion ganz oben auf der - // Startseite — unabhängig vom Angebot-Status (offen/uebernommen/…). - const favoriten = await dbAll( - `SELECT j.id, j.firma, j.stelle, j.ort, j.status, j.quelle_url, - j.verknuepfte_bewerbung_id, j.gehalt, j.favorit - FROM jobangebote j - WHERE j.user_id = ? AND j.favorit = 1 - ORDER BY j.updated_at DESC, j.id DESC`, + // Gemerkte Bewerbungen — unabhängig vom Bewerbungs-Status, ganz oben auf + // der Startseite. + const bewerbungFavoriten = await dbAll( + `SELECT b.id, b.firma, b.stelle, b.ort, b.status, b.datum, b.favorit + FROM bewerbungen b + WHERE b.user_id = ? AND b.favorit = 1 + ORDER BY b.updated_at DESC, b.id DESC`, [U] ); @@ -1782,7 +1783,7 @@ initializeDatabase().then(async () => { statusOptions: STATUS_OPTIONS, labelOptions: LABEL_OPTIONS, setupWizard, - favoriten + bewerbungFavoriten }); } catch (error) { console.error('Error:', error); @@ -3624,18 +3625,16 @@ initializeDatabase().then(async () => { } }); - // Favorit umschalten (Stern). JSON-Antwort, damit der Client den Stern - // sofort umschalten kann, ohne die Seite neu zu laden. Favoriten sind - // unabhängig vom Angebot-Status sichtbar — auch „uebernommen“ bleibt merkbar. - app.post('/jobangebote/:id/favorit', async (req, res) => { + // Bewerbung als Favorit merken/entmerken — unabhängig vom Bewerbungs-Status. + app.post('/api/bewerbungen/:id/favorit', async (req, res) => { try { - const angebot = await dbGet('SELECT favorit FROM jobangebote WHERE id = ? AND user_id = ?', [req.params.id, uid()]); - if (!angebot) return res.status(404).json({ error: 'Jobangebot nicht gefunden' }); - const neu = angebot.favorit ? 0 : 1; - await dbRun('UPDATE jobangebote SET favorit = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?', [neu, req.params.id, uid()]); + const bewerbung = await dbGet('SELECT favorit FROM bewerbungen WHERE id = ? AND user_id = ?', [req.params.id, uid()]); + if (!bewerbung) return res.status(404).json({ error: 'Bewerbung nicht gefunden' }); + const neu = bewerbung.favorit ? 0 : 1; + await dbRun('UPDATE bewerbungen SET favorit = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?', [neu, req.params.id, uid()]); res.json({ success: true, favorit: neu }); } catch (error) { - console.error('Error toggling favorite:', error); + console.error('Error toggling bewerbung favorite:', error); res.status(500).json({ error: 'Serverfehler' }); } }); diff --git a/views/bewerbung.ejs b/views/bewerbung.ejs index 50ebc43..edd129f 100644 --- a/views/bewerbung.ejs +++ b/views/bewerbung.ejs @@ -43,6 +43,7 @@ <%= aktuellerStatus %> + <%- include('partials/favorit-button', { j: application, endpoint: '/api/bewerbungen/' + application.id + '/favorit' }) %> @@ -1022,5 +1023,7 @@ })); })(); + + <%- include('partials/favorit-script') %> diff --git a/views/index.ejs b/views/index.ejs index 5a75b91..d708070 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -8,7 +8,7 @@
<% var zeigeDashboard = !(typeof setupWizard !== 'undefined' && setupWizard && setupWizard.aktiv); %> - <%- include('partials/favoriten') %> + <%- include('partials/bewerbung-favoriten') %> <% if (!zeigeDashboard) { %> <%- include('partials/einrichtung') %> <% } %> @@ -252,6 +252,7 @@ + <%- include('partials/favorit-button', { j: app, endpoint: '/api/bewerbungen/' + app.id + '/favorit', compact: true }) %> @@ -666,6 +667,8 @@ <%- include('partials/footer') %> + <%- include('partials/favorit-script') %> +