19bade27b6
Инлайн-клавиатура в _send_reminders_admin не заменяла нижнюю (reply) клавиатуру предыдущего шага мастера — после создания напоминания кнопки «Разово / Каждую неделю / …» оставались висеть внизу. Теперь раздел использует обычную нижнюю клавиатуру get_reminders_admin_keyboard(), как и раздел «Быстрые ответы». Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
257 lines
12 KiB
Python
257 lines
12 KiB
Python
"""Клавиатуры интерфейса бота (VK)."""
|
||
from vk_api.keyboard import VkKeyboard, VkKeyboardColor
|
||
import config
|
||
|
||
|
||
# ==========================================
|
||
# КЛАВИАТУРЫ ДЛЯ ИНТЕРФЕЙСА (UX/UI ВКонтакте)
|
||
# ==========================================
|
||
|
||
def get_main_keyboard(is_admin: bool = False, flags: dict = None) -> str:
|
||
"""Главное меню Кибершколы БАЗА. flags — какие кнопки показывать (по умолчанию — все,
|
||
кроме вебинара). Для админа добавляется кнопка «Админка ⚙️»."""
|
||
f = {"pickup": True, "intensive": True, "prices": True, "question": True, "webinar": False}
|
||
if flags:
|
||
f.update(flags)
|
||
keyboard = VkKeyboard(one_time=False)
|
||
has = False
|
||
|
||
def row(label, color=VkKeyboardColor.SECONDARY):
|
||
nonlocal has
|
||
if has:
|
||
keyboard.add_line()
|
||
keyboard.add_button(label, color=color)
|
||
has = True
|
||
|
||
if f.get("pickup"):
|
||
row("Подобрать тренировку 🎯", VkKeyboardColor.PRIMARY)
|
||
if f.get("intensive"):
|
||
row("Летний интенсив CS2 🔥")
|
||
if f.get("webinar"):
|
||
row("Записаться на вебинар 🎓")
|
||
if f.get("prices"):
|
||
row("Посмотреть цены 💰")
|
||
if f.get("question"):
|
||
row("Задать вопрос 💬")
|
||
if is_admin:
|
||
row("Админка ⚙️", VkKeyboardColor.POSITIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
# ==========================================
|
||
# КЛАВИАТУРЫ ВОРОНКИ «ПОДОБРАТЬ ТРЕНИРОВКУ» (БАЗА)
|
||
# ==========================================
|
||
|
||
def _kb(rows, back=False, ask_manager=False, back_menu=True):
|
||
"""Хелпер: строит нижнюю клавиатуру из строк кнопок + служебные кнопки снизу.
|
||
|
||
back — кнопка «Назад ⬅️» (к предыдущему вопросу воронки);
|
||
ask_manager — кнопка «Задать вопрос менеджеру 💬»;
|
||
back_menu — кнопка «В главное меню ↩️».
|
||
"""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
has = False # была ли уже добавлена хоть одна кнопка (чтобы не создавать пустой ряд)
|
||
for row in rows:
|
||
if has:
|
||
keyboard.add_line()
|
||
for label in row:
|
||
keyboard.add_button(label, color=VkKeyboardColor.SECONDARY)
|
||
has = True
|
||
if ask_manager:
|
||
if has:
|
||
keyboard.add_line()
|
||
keyboard.add_button("Задать вопрос менеджеру 💬", color=VkKeyboardColor.SECONDARY)
|
||
has = True
|
||
if back or back_menu:
|
||
if has:
|
||
keyboard.add_line()
|
||
if back:
|
||
keyboard.add_button("Назад ⬅️", color=VkKeyboardColor.SECONDARY)
|
||
if back_menu:
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_forwho_keyboard() -> str:
|
||
return _kb([["Для себя", "Для подростка"]])
|
||
|
||
|
||
def get_baza_age_keyboard() -> str:
|
||
return _kb([["12–13 лет", "14–15 лет"], ["16 лет и старше", "Младше 12 лет"]], back=True)
|
||
|
||
|
||
def get_baza_younger12_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Обсудить с менеджером 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Вернуться назад ↩️", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_game_keyboard() -> str:
|
||
return _kb([["Counter-Strike 2", "Dota 2"], ["World of Tanks", "Другая игра"]], back=True)
|
||
|
||
|
||
def get_baza_level_keyboard() -> str:
|
||
return _kb([["Только начинает"], ["Играет для себя"],
|
||
["Есть рейтинг или ранг"], ["Играет в команде или турнирах"]], back=True)
|
||
|
||
|
||
def get_baza_format_keyboard() -> str:
|
||
return _kb([["Групповые тренировки"], ["Индивидуальные тренировки"],
|
||
["Пока не знаю, нужен совет"]], back=True)
|
||
|
||
|
||
def get_baza_group_keyboard() -> str:
|
||
return _kb([["Записаться на пробное занятие"], ["Купить 4 тренировки", "Купить 8 тренировок"]],
|
||
back=True, ask_manager=True)
|
||
|
||
|
||
def get_baza_individual_keyboard() -> str:
|
||
return _kb([["Купить 1 тренировку"],
|
||
["Купить 4 тренировки", "Купить 8 тренировок"]],
|
||
back=True, ask_manager=True)
|
||
|
||
|
||
def get_baza_menu_only_keyboard() -> str:
|
||
"""Только «В главное меню» — для шагов со свободным вводом (совет/вопрос)."""
|
||
return _kb([])
|
||
|
||
|
||
def get_baza_intensive_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Хочу участвовать 🔥", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Посмотреть другие тренировки", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_int_level_keyboard() -> str:
|
||
return _kb([["Только начинаю"], ["Уже знаю основы"],
|
||
["Играю регулярно"], ["Есть рейтинг или командный опыт"]], back=True)
|
||
|
||
|
||
def get_baza_int_pay_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Оплатить интенсив 💳", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Сначала задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Вернуться в меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_int_young_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Передать менеджеру 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Посмотреть другие тренировки", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_baza_prices_keyboard() -> str:
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Подобрать тренировку 🎯", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Записаться на пробное занятие", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Выбрать абонемент", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Задать вопрос 💬", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_admin_keyboard(is_super: bool = False, muted: bool = False) -> str:
|
||
"""Клавиатура админ-панели с разделами. Супер-админу — раздел «Администраторы»."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Статистика 📊", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Быстрые ответы 💬", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Рассылка 📣", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Ссылки 🔗", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Кнопки меню 🧩", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Уведомления: выкл 🔕" if muted else "Уведомления: вкл 🔔",
|
||
color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("⏰ Напоминалки", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
if is_super:
|
||
keyboard.add_button("Администраторы 👑", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("В главное меню ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_faq_admin_keyboard() -> str:
|
||
"""Клавиатура раздела управления быстрыми ответами."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("➕ Добавить ответ", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("✏️ Изменить ответ", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("🗑 Удалить ответ", color=VkKeyboardColor.NEGATIVE)
|
||
keyboard.add_line()
|
||
keyboard.add_button("В админку ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_reminders_admin_keyboard() -> str:
|
||
"""Клавиатура раздела «Напоминалки». Обычная (не инлайн) клавиатура — важно:
|
||
она заменяет собой нижнюю клавиатуру предыдущего шага мастера (например,
|
||
«Разово / Каждую неделю / …»), иначе старые кнопки остаются висеть после
|
||
завершения мастера."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("➕ Добавить", color=VkKeyboardColor.PRIMARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("🗑 Удалить напоминание", color=VkKeyboardColor.NEGATIVE)
|
||
keyboard.add_line()
|
||
keyboard.add_button("В админку ↩️", color=VkKeyboardColor.SECONDARY)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_pick_keyboard(items: list) -> str:
|
||
"""Клавиатура выбора из списка пар (id, label). Кнопка отправляет '<id>. <label>'."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
count = 0
|
||
for _id, label in items[:10]:
|
||
if count and count % 2 == 0:
|
||
keyboard.add_line()
|
||
short = label if len(label) <= 30 else label[:29] + "…"
|
||
keyboard.add_button(f"{_id}. {short}", color=VkKeyboardColor.SECONDARY)
|
||
count += 1
|
||
keyboard.add_line()
|
||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_cancel_admin_keyboard() -> str:
|
||
"""Кнопка отмены для админских мастеров ввода."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_reminder_period_keyboard() -> str:
|
||
"""Клавиатура выбора периодичности напоминания (шаг мастера ADMIN_REMINDER_PERIOD)."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Разово", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Каждую неделю", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_button("Каждый месяц", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Каждый год", color=VkKeyboardColor.SECONDARY)
|
||
keyboard.add_line()
|
||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|
||
def get_operator_keyboard() -> str:
|
||
"""Клавиатура при активном диалоге с оператором."""
|
||
keyboard = VkKeyboard(one_time=False)
|
||
keyboard.add_button("Завершить диалог 🚪", color=VkKeyboardColor.NEGATIVE)
|
||
return keyboard.get_keyboard()
|
||
|
||
|