"""Онбординг: пошаговый тур по разделам для новых пользователей.""" from datetime import datetime, timezone from flask import render_template, request, redirect, url_for, session, jsonify from sqlmodel import Session, select from ..db import engine from ..models import UserOnboarding from ..helpers import login_required STEPS = [ {"key": "visited_schedule", "num": 1, "icon": "📅", "title": "Расписание", "url": "/schedule", "desc": "Календарь занятий, статус Никиты Сергеевича, ассистент. Спроси «Где сейчас?» — ответит."}, {"key": "visited_projects", "num": 2, "icon": "🗂", "title": "Проекты", "url": "/projects", "desc": "Каталог проектов команды: карточки, участники, канбан-доски, лента новостей."}, {"key": "visited_workshops", "num": 3, "icon": "🎓", "title": "Мастер-классы", "url": "/workshops", "desc": "Пайка, embedded, Linux, творчество. Регистрация на занятия, материалы, посещаемость."}, {"key": "visited_files", "num": 4, "icon": "📁", "title": "Файлы", "url": "/files", "desc": "Единое хранилище документов. Загружай PDF, картинки, схемы — коллеги скачают."}, {"key": "visited_feed", "num": 5, "icon": "📰", "title": "Лента", "url": "/feed", "desc": "Все новости из проектов и мастер-классов в одном потоке. Поиск и фильтры."}, {"key": "visited_profile", "num": 6, "icon": "👤", "title": "Профиль", "url": "/profile", "desc": "Подписки на уведомления, активные сессии, безопасность."}, ] _TOTAL = len(STEPS) def ensure_onboarding(db_session, user_id): """Создать запись прогресса, если её нет. Вернуть объект.""" if not user_id: return None ob = db_session.exec(select(UserOnboarding).where(UserOnboarding.user_id == user_id)).first() if not ob: ob = UserOnboarding(user_id=user_id) db_session.add(ob) db_session.commit() db_session.refresh(ob) return ob def _progress(ob): completed = sum(1 for s in STEPS if getattr(ob, s["key"])) return completed, _TOTAL def register(app): @app.route("/onboarding") @login_required def onboarding_page(): user_id = session.get("user_id") with Session(engine) as db_session: ob = ensure_onboarding(db_session, user_id) completed, total = _progress(ob) return render_template("onboarding.html", steps=STEPS, ob=ob, completed=completed, total=total, just_done=request.args.get("done") == "1") @app.route("/onboarding/mark", methods=["POST"]) @login_required def onboarding_mark(): data = request.get_json(silent=True) or {} key = data.get("key") value = bool(data.get("value", True)) if key not in {s["key"] for s in STEPS}: return jsonify({"ok": False, "error": "bad_key"}), 400 user_id = session.get("user_id") with Session(engine) as db_session: ob = ensure_onboarding(db_session, user_id) setattr(ob, key, value) all_done = all(getattr(ob, s["key"]) for s in STEPS) if all_done and ob.completed_at is None: ob.completed_at = datetime.now(timezone.utc) elif not all_done: ob.completed_at = None db_session.add(ob) db_session.commit() completed, total = _progress(ob) is_complete = ob.completed_at is not None return jsonify({"ok": True, "completed": completed, "total": total, "is_complete": is_complete}) @app.route("/onboarding/skip", methods=["POST"]) @login_required def onboarding_skip(): """Пропустить тур (не отмечать ничего).""" return redirect(url_for("index", skip_tour="1")) @app.route("/onboarding/complete", methods=["POST"]) @login_required def onboarding_complete(): """Отметить всё сразу — для тех, кто уже разобрался.""" user_id = session.get("user_id") with Session(engine) as db_session: ob = ensure_onboarding(db_session, user_id) for s in STEPS: setattr(ob, s["key"], True) ob.completed_at = datetime.now(timezone.utc) db_session.add(ob) db_session.commit() return redirect(url_for("onboarding_page", done="1"))