From 96fd0e282d471069140fbe5ee9538993eefb54b9 Mon Sep 17 00:00:00 2001 From: Thomas Hackner Date: Fri, 17 Jul 2026 00:01:50 +0200 Subject: [PATCH] Jobangebote: Gemerkte nicht mehr unter Offen anzeigen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Favorisierte Angebote erscheinen ausschließlich im Gemerkt-Tab und werden aus der Offen-Liste, dem Offen-Zähler (Header-Badge) und dem Tab-Zähler ausgeblendet. Auf der Offen-Seite wird die Zeile beim Merken live entfernt. Co-Authored-By: Claude --- server.js | 17 +++++++++-------- views/jobangebote.ejs | 11 ++++++----- views/partials/favorit-script.ejs | 20 +++++++++++++++----- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/server.js b/server.js index b4b60bf..115cc47 100644 --- a/server.js +++ b/server.js @@ -3630,7 +3630,7 @@ initializeDatabase().then(async () => { // Count of open offers, consumed by the header badge (no auth — just a number). app.get('/jobangebote/anzahl-offen', async (req, res) => { try { - const row = await dbGet("SELECT COUNT(*) as count FROM jobangebote WHERE user_id = ? AND status = 'offen'", [uid()]); + const row = await dbGet("SELECT COUNT(*) as count FROM jobangebote WHERE user_id = ? AND status = 'offen' AND favorit = 0", [uid()]); res.json({ count: row ? row.count : 0 }); } catch (error) { res.status(500).json({ count: 0 }); @@ -3642,9 +3642,9 @@ initializeDatabase().then(async () => { async function jobangeboteZaehler() { const row = await dbGet( `SELECT - COUNT(*) FILTER (WHERE status = 'offen') AS offen, - COUNT(*) FILTER (WHERE status = 'uebernommen') AS uebernommen, - COUNT(*) FILTER (WHERE favorit = 1) AS favoriten + COUNT(*) FILTER (WHERE status = 'offen' AND favorit = 0) AS offen, + COUNT(*) FILTER (WHERE status = 'uebernommen') AS uebernommen, + COUNT(*) FILTER (WHERE favorit = 1) AS favoriten FROM jobangebote WHERE user_id = ?`, [uid()] ); @@ -3656,16 +3656,17 @@ initializeDatabase().then(async () => { } // Main list: only OPEN offers (still to be decided on). Taken-over offers - // live on their own page (/jobangebote/uebernommen). Gemerkte Angebote stehen - // hier oben und haben zusätzlich einen eigenen Tab (/jobangebote/favoriten). + // live on their own page (/jobangebote/uebernommen). Gemerkte (favorisierte) + // Angebote erscheinen ausschließlich im eigenen Tab (/jobangebote/favoriten) + // und werden hier ausgeblendet. app.get('/jobangebote', async (req, res) => { try { const jobangebote = await dbAll( `SELECT j.*, b.datum AS bewerbung_datum FROM jobangebote j LEFT JOIN bewerbungen b ON b.id = j.verknuepfte_bewerbung_id AND b.user_id = j.user_id - WHERE j.user_id = ? AND j.status = 'offen' - ORDER BY j.favorit DESC, j.created_at DESC, j.id DESC`, + WHERE j.user_id = ? AND j.status = 'offen' AND j.favorit = 0 + ORDER BY j.created_at DESC, j.id DESC`, [uid()] ); jobangebote.forEach((j) => { j.labelsArr = parseLabels(j.labels); }); diff --git a/views/jobangebote.ejs b/views/jobangebote.ejs index 9668768..d4b0bcf 100644 --- a/views/jobangebote.ejs +++ b/views/jobangebote.ejs @@ -26,7 +26,7 @@ <%- include('partials/favorit-script') %> -
> +

<%= favAnsicht ? 'Gemerkte Jobangebote' : 'Jobangebote' %>

@@ -41,8 +41,8 @@ POST /api/v1/joboffers REST-Schnittstelle eingespielt werden. Ein Angebot lässt sich per Klick als Bewerbung-Entwurf übernehmen. Hier siehst du nur offene - Angebote — bereits übernommene findest du im Tab „Übernommen“. - Mit dem Stern gemerkte Angebote stehen oben. + Angebote, die du dir nicht gemerkt hast — bereits übernommene + findest du im Tab „Übernommen“, gemerkte im Tab „Gemerkt“. <% } %>

@@ -61,7 +61,7 @@ <% if (jobangebote && jobangebote.length) { %>
    <% jobangebote.forEach(function(j){ %> -
  • class="rounded-lg border px-4 py-4 <%= j.favorit +
  • @@ -249,7 +249,8 @@

    Noch keine Jobangebote gemerkt.

    - Klicke bei einem Angebot auf Merken — es erscheint dann hier und steht in der offenen Liste ganz oben. + Klicke bei einem Angebot auf Merken — es erscheint dann hier + und wird aus der offenen Liste ausgeblendet.

    <% } else { %> diff --git a/views/partials/favorit-script.ejs b/views/partials/favorit-script.ejs index 5611cf0..702f31e 100644 --- a/views/partials/favorit-script.ejs +++ b/views/partials/favorit-script.ejs @@ -40,9 +40,10 @@ .then(function (r) { if (r.ok && r.json && r.json.success) { setzeBtn(btn, !!r.json.favorit); - // Auf der Startseite: beim Entfernen die Zeile ausblenden - // und die ganze Sektion einräumen, wenn sie leer wird. - if (!r.json.favorit) entferneFavoritZeile(btn); + // Zeile ausblenden, sobald sie nicht mehr in die aktuelle + // Ansicht gehört: auf der Offen-Seite beim Merken (favorit=1), + // auf der Gemerkt-Seite / Startseite beim Entfernen (favorit=0). + entferneFavoritZeile(btn, !!r.json.favorit); } else { setzeBtn(btn, aktiv); // Server hat abgelehnt -> zurückrollen if (r.json && r.json.error) console.warn('Favorit:', r.json.error); @@ -62,11 +63,20 @@ if (lbl) lbl.textContent = aktiv ? 'Gemerkt' : 'Merken'; } - function entferneFavoritZeile(btn) { + function entferneFavoritZeile(btn, istFavorit) { var item = btn.closest('[data-fav-item]'); - if (!item) return; // nicht auf der Startseite -> nur optisch umschalten + if (!item) return; // keine ausblendbare Zeile -> nur optisch umschalten var card = btn.closest('[data-fav-card]') || document.getElementById('favoritenCard'); + // Offen-Seite: Zeile verschwindet beim Merken (favorit=1). + // Gemerkt-Seite / Startseite: Zeile verschwindet beim Entfernen (favorit=0). + var view = card && card.getAttribute('data-fav-view'); + var entfernenBeiFavorit = (view === 'offen'); + if (istFavorit !== entfernenBeiFavorit) return; item.remove(); + // Auf der Offen-Seite bleibt die Sektion samt Überschrift stehen — + // dort wird nur die einzelne Zeile entfernt. Auf der Gemerkt-Seite + // und Startseite räumen wir die leere Sektion ganz ein. + if (view === 'offen') return; if (card && !card.querySelectorAll('[data-fav-item]').length) { card.style.transition = 'opacity 0.2s ease'; card.style.opacity = '0';