nordabiz/blueprints/community/classifieds/routes.py
Maciej Pienczyn e6acc2ec6f feat: Dodano moderację tablicy B2B dla administratora
- Przycisk usuwania ogłoszenia z potwierdzeniem
- Przycisk aktywacji/dezaktywacji ogłoszenia
- Endpointy: /delete, /toggle-active
- Badge "Nieaktywne" dla dezaktywowanych ogłoszeń

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 20:31:37 +01:00

200 lines
6.2 KiB
Python

"""
Classifieds Routes
==================
B2B bulletin board endpoints.
"""
from datetime import datetime, timedelta
from flask import render_template, request, redirect, url_for, flash, jsonify
from flask_login import login_required, current_user
from . import bp
from database import SessionLocal, Classified
from utils.helpers import sanitize_input
@bp.route('/', endpoint='classifieds_index')
@login_required
def index():
"""Tablica ogłoszeń B2B"""
listing_type = request.args.get('type', '')
category = request.args.get('category', '')
page = request.args.get('page', 1, type=int)
per_page = 20
db = SessionLocal()
try:
query = db.query(Classified).filter(
Classified.is_active == True
)
# Filtry
if listing_type:
query = query.filter(Classified.listing_type == listing_type)
if category:
query = query.filter(Classified.category == category)
# Sortowanie - najnowsze pierwsze
query = query.order_by(Classified.created_at.desc())
total = query.count()
classifieds = query.limit(per_page).offset((page - 1) * per_page).all()
# Kategorie do filtrów
categories = [
('uslugi', 'Usługi'),
('produkty', 'Produkty'),
('wspolpraca', 'Współpraca'),
('praca', 'Praca'),
('inne', 'Inne')
]
return render_template('classifieds/index.html',
classifieds=classifieds,
categories=categories,
listing_type=listing_type,
category_filter=category,
page=page,
total_pages=(total + per_page - 1) // per_page
)
finally:
db.close()
@bp.route('/nowe', methods=['GET', 'POST'], endpoint='classifieds_new')
@login_required
def new():
"""Dodaj nowe ogłoszenie"""
if request.method == 'POST':
listing_type = request.form.get('listing_type', '')
category = request.form.get('category', '')
title = sanitize_input(request.form.get('title', ''), 255)
description = request.form.get('description', '').strip()
budget_info = sanitize_input(request.form.get('budget_info', ''), 255)
location_info = sanitize_input(request.form.get('location_info', ''), 255)
if not listing_type or not category or not title or not description:
flash('Wszystkie wymagane pola muszą być wypełnione.', 'error')
return render_template('classifieds/new.html')
db = SessionLocal()
try:
# Automatyczne wygaśnięcie po 30 dniach
expires = datetime.now() + timedelta(days=30)
classified = Classified(
author_id=current_user.id,
company_id=current_user.company_id,
listing_type=listing_type,
category=category,
title=title,
description=description,
budget_info=budget_info,
location_info=location_info,
expires_at=expires
)
db.add(classified)
db.commit()
flash('Ogłoszenie dodane.', 'success')
return redirect(url_for('.classifieds_index'))
finally:
db.close()
return render_template('classifieds/new.html')
@bp.route('/<int:classified_id>', endpoint='classifieds_view')
@login_required
def view(classified_id):
"""Szczegóły ogłoszenia"""
db = SessionLocal()
try:
classified = db.query(Classified).filter(
Classified.id == classified_id
).first()
if not classified:
flash('Ogłoszenie nie istnieje.', 'error')
return redirect(url_for('.classifieds_index'))
# Zwiększ licznik wyświetleń (handle NULL)
classified.views_count = (classified.views_count or 0) + 1
db.commit()
return render_template('classifieds/view.html', classified=classified)
finally:
db.close()
@bp.route('/<int:classified_id>/zakoncz', methods=['POST'], endpoint='classifieds_close')
@login_required
def close(classified_id):
"""Zamknij ogłoszenie"""
db = SessionLocal()
try:
classified = db.query(Classified).filter(
Classified.id == classified_id,
Classified.author_id == current_user.id
).first()
if not classified:
return jsonify({'success': False, 'error': 'Ogłoszenie nie istnieje lub brak uprawnień'}), 404
classified.is_active = False
db.commit()
return jsonify({'success': True, 'message': 'Ogłoszenie zamknięte'})
finally:
db.close()
@bp.route('/<int:classified_id>/delete', methods=['POST'], endpoint='classifieds_delete')
@login_required
def delete(classified_id):
"""Usuń ogłoszenie (admin only)"""
if not current_user.is_admin:
return jsonify({'success': False, 'error': 'Brak uprawnień'}), 403
db = SessionLocal()
try:
classified = db.query(Classified).filter(
Classified.id == classified_id
).first()
if not classified:
return jsonify({'success': False, 'error': 'Ogłoszenie nie istnieje'}), 404
db.delete(classified)
db.commit()
return jsonify({'success': True, 'message': 'Ogłoszenie usunięte'})
finally:
db.close()
@bp.route('/<int:classified_id>/toggle-active', methods=['POST'], endpoint='classifieds_toggle_active')
@login_required
def toggle_active(classified_id):
"""Aktywuj/dezaktywuj ogłoszenie (admin only)"""
if not current_user.is_admin:
return jsonify({'success': False, 'error': 'Brak uprawnień'}), 403
db = SessionLocal()
try:
classified = db.query(Classified).filter(
Classified.id == classified_id
).first()
if not classified:
return jsonify({'success': False, 'error': 'Ogłoszenie nie istnieje'}), 404
classified.is_active = not classified.is_active
db.commit()
status = 'aktywowane' if classified.is_active else 'dezaktywowane'
return jsonify({'success': True, 'message': f'Ogłoszenie {status}', 'is_active': classified.is_active})
finally:
db.close()