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
This commit is contained in:
parent
e7d32b6b06
commit
ffc6d8219f
@ -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)
|
||||
|
||||
|
||||
51
scripts/mark_test_classifieds.py
Normal file
51
scripts/mark_test_classifieds.py
Normal file
@ -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()
|
||||
@ -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 @@
|
||||
<a href="{{ url_for('classifieds_index', type=listing_type, category=cat_value) }}" class="filter-btn {% if category_filter == cat_value %}active{% endif %}">{{ cat_label }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="filter-group" style="margin-left: auto;">
|
||||
<button type="button" id="toggleTestBtn" class="filter-btn toggle-test-btn" onclick="toggleTestItems()">
|
||||
<span class="hide-label">🙈 Ukryj testowe</span>
|
||||
<span class="show-label" style="display:none;">👁 Pokaż testowe</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="classifieds-grid">
|
||||
{% if classifieds %}
|
||||
{% for classified in classifieds %}
|
||||
<div class="classified-card {{ classified.listing_type }}">
|
||||
<div class="classified-card {{ classified.listing_type }} {% if classified.is_test %}test-item{% endif %}">
|
||||
<div class="classified-header">
|
||||
<span class="classified-type {{ classified.listing_type }}">{{ 'Szukam' if classified.listing_type == 'szukam' else 'Oferuje' }}</span>
|
||||
<span class="classified-category category-{{ classified.category }}">{{ classified.category|replace('uslugi', 'Usługi')|replace('produkty', 'Produkty')|replace('wspolpraca', 'Współpraca')|replace('praca', 'Praca')|replace('inne', 'Inne')|replace('nieruchomosci', 'Nieruchomości') }}</span>
|
||||
{% if classified.is_test %}<span class="test-badge">Testowe</span>{% endif %}
|
||||
</div>
|
||||
<div class="classified-title">
|
||||
<a href="{{ url_for('classifieds_view', classified_id=classified.id) }}">{{ classified.title }}</a>
|
||||
@ -287,3 +328,37 @@
|
||||
</div>
|
||||
{% 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 %}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user