From ffc6d8219fe8e42f2330a5d2e7a37f760da3863b Mon Sep 17 00:00:00 2001 From: Maciej Pienczyn Date: Tue, 13 Jan 2026 13:08:11 +0100 Subject: [PATCH] feat: Add toggle button to hide/show test items on B2B board - Add is_test field to Classified model - Add test-item styling (opacity + gray border + badge) - Add yellow toggle button with localStorage persistence - Add script to mark existing classifieds as test --- database.py | 1 + scripts/mark_test_classifieds.py | 51 +++++++++++++++++++++ templates/classifieds/index.html | 77 +++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 scripts/mark_test_classifieds.py diff --git a/database.py b/database.py index 973c1ee..7b17201 100644 --- a/database.py +++ b/database.py @@ -1139,6 +1139,7 @@ class Classified(Base): # Status is_active = Column(Boolean, default=True) is_ai_generated = Column(Boolean, default=False) + is_test = Column(Boolean, default=False) # Oznaczenie dla testowych ogłoszeń expires_at = Column(DateTime) # Auto-wygaśnięcie po 30 dniach views_count = Column(Integer, default=0) diff --git a/scripts/mark_test_classifieds.py b/scripts/mark_test_classifieds.py new file mode 100644 index 0000000..66f44a7 --- /dev/null +++ b/scripts/mark_test_classifieds.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +"""Oznacz wszystkie obecne ogłoszenia B2B jako testowe.""" + +import os +import sys +from dotenv import load_dotenv + +# Load .env first +load_dotenv() + +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + +from sqlalchemy import text +from database import SessionLocal, Classified + +def main(): + db = SessionLocal() + + # First, ensure the is_test column exists + try: + db.execute(text("ALTER TABLE classifieds ADD COLUMN IF NOT EXISTS is_test BOOLEAN DEFAULT FALSE")) + db.commit() + print("Kolumna is_test dodana (lub już istnieje)") + except Exception as e: + print(f"Uwaga przy dodawaniu kolumny: {e}") + db.rollback() + + # Get all classifieds + classifieds = db.query(Classified).all() + + if not classifieds: + print("Brak ogłoszeń w bazie danych.") + db.close() + return + + print(f"Znaleziono {len(classifieds)} ogłoszeń do oznaczenia jako testowe...") + print() + + for c in classifieds: + c.is_test = True + print(f" ID {c.id}: {c.title[:50]}... ({c.listing_type})") + + db.commit() + db.close() + + print() + print(f"Oznaczono {len(classifieds)} ogłoszeń jako testowe") + print("Gotowe!") + +if __name__ == "__main__": + main() diff --git a/templates/classifieds/index.html b/templates/classifieds/index.html index 542d42a..755970d 100755 --- a/templates/classifieds/index.html +++ b/templates/classifieds/index.html @@ -140,6 +140,39 @@ color: #3730a3; } + /* Test item styling */ + .classified-card.test-item { + opacity: 0.6; + border-right: 4px solid #9ca3af; + } + + .test-badge { + display: inline-block; + padding: 2px 8px; + border-radius: var(--radius-sm); + font-size: var(--font-size-xs); + font-weight: 500; + background: #f3f4f6; + color: #6b7280; + margin-left: var(--spacing-xs); + } + + .toggle-test-btn { + background: #fef3c7; + border-color: #fcd34d; + color: #92400e; + } + + .toggle-test-btn:hover { + background: #fde68a; + } + + .toggle-test-btn.active { + background: var(--primary); + border-color: var(--primary); + color: white; + } + .classified-title { font-size: var(--font-size-lg); font-weight: 600; @@ -240,15 +273,23 @@ {{ cat_label }} {% endfor %} + +
+ +
{% if classifieds %} {% for classified in classifieds %} -
+
{{ 'Szukam' if classified.listing_type == 'szukam' else 'Oferuje' }} {{ classified.category|replace('uslugi', 'Usługi')|replace('produkty', 'Produkty')|replace('wspolpraca', 'Współpraca')|replace('praca', 'Praca')|replace('inne', 'Inne')|replace('nieruchomosci', 'Nieruchomości') }} + {% if classified.is_test %}Testowe{% endif %}
{{ classified.title }} @@ -287,3 +328,37 @@
{% endif %} {% endblock %} + +{% block extra_js %} +function setTestItemsVisibility(hidden) { + const btn = document.getElementById('toggleTestBtn'); + const hideLabel = btn.querySelector('.hide-label'); + const showLabel = btn.querySelector('.show-label'); + const testItems = document.querySelectorAll('.test-item'); + + if (hidden) { + testItems.forEach(t => t.style.display = 'none'); + hideLabel.style.display = 'none'; + showLabel.style.display = ''; + btn.classList.add('active'); + } else { + testItems.forEach(t => t.style.display = ''); + hideLabel.style.display = ''; + showLabel.style.display = 'none'; + btn.classList.remove('active'); + } + localStorage.setItem('hideTestClassifieds', hidden ? 'true' : 'false'); +} + +function toggleTestItems() { + const isCurrentlyHidden = localStorage.getItem('hideTestClassifieds') === 'true'; + setTestItemsVisibility(!isCurrentlyHidden); +} + +// Apply saved preference on page load +(function() { + if (localStorage.getItem('hideTestClassifieds') === 'true') { + setTestItemsVisibility(true); + } +})(); +{% endblock %}