This commit is contained in:
2026-03-01 16:26:47 +03:00
parent 3d0dd57752
commit 52def1cb19
6 changed files with 110 additions and 7 deletions
@@ -55,6 +55,9 @@ from dutylog.application.bot.admin_dialogs.broadcast import (
broadcast_window, broadcast_window,
broadcast_confirm_window, broadcast_confirm_window,
) )
from dutylog.application.bot.admin_dialogs.faq import (
admin_faq_window,
)
admin_menu_dialog = Dialog( admin_menu_dialog = Dialog(
@@ -90,6 +93,7 @@ admin_menu_dialog = Dialog(
generate_report_select_period_window, generate_report_select_period_window,
generate_report_confirm_window, generate_report_confirm_window,
statistics_window, statistics_window,
admin_faq_window,
broadcast_window, broadcast_window,
broadcast_confirm_window, broadcast_confirm_window,
search_input_window, search_input_window,
@@ -0,0 +1,91 @@
from aiogram_dialog import Window
from aiogram_dialog.widgets.text import Format, Const
from aiogram_dialog.widgets.kbd import SwitchTo
from dutylog.application.bot.user_dialogs.states import AdminMenuSG
async def get_admin_faq_data(**kwargs) -> dict[str, str]:
content = """
<blockquote>❓ <b>Гайд по админке</b></blockquote>
Привет! Ты теперь админ, и это круто 😎
Давай разберёмся, что тут к чему.
<blockquote><b>🏠 Резиденты — твоя главная тусовка</b>
Здесь живут все жители общаги. Можешь:
• Искать кого угодно — по имени, комнате или нику в телеге
• Фильтровать по часам (кто должник, а кто молодец)
• Начислять или снимать часы (не забывай писать за что!)
• Добавлять новых людей или удалять старых
• Отвязывать юзеров от резидентов (если кто-то съехал)</blockquote>
<blockquote><b>🚪 Комнаты и 🏢 Этажи</b>
Тут всё просто — структура общежития.
Добавляй этажи, создавай комнаты, привязывай их друг к другу.
Без этого резидентов не создать!</blockquote>
<blockquote><b>📅 Отчётный период — важная штука!</b>
Система работает по месяцам. Один период = один месяц учёта.
Как это работает:
• Создаёшь новый период → старый автоматом закрывается
• Дата начала = когда создал
• Дата конца = когда создал следующий
Зачем это нужно? Чтобы потом сделать красивый отчёт за месяц и показать всем, кто сколько отработал.</blockquote>
<blockquote><b>📊 Отчёты — твоя суперсила</b>
После закрытия периода можешь сгенерить Excel-файл.
В нём будет:
• Все начисления и списания за месяц
• Кто и когда начислил/снял часы
• Примечания (поэтому их важно писать!)
• Автоматический подсчёт итогов
Отчёт можно скинуть старосте или куратору — всё наглядно.</blockquote>
<blockquote><b>📊 Статистика</b>
Быстрый взгляд на цифры:
• Сколько всего людей в системе
• Сколько админов (ты не один!)
• Общая сумма часов по всем резидентам</blockquote>
<blockquote><b>📢 Рассылка</b>
Нужно всем что-то сообщить? Жми сюда.
Сообщение улетит всем пользователям бота.
Можно использовать HTML для красоты.</blockquote>
<blockquote><b>💡 Лайфхаки:</b>
• <b>Всегда пиши примечание</b> при начислении/списании часов
Через месяц никто не вспомнит, за что было
• <b>Делай отчёты регулярно</b>
Это твоя страховка и архив данных
• <b>Проверяй статистику</b> перед закрытием периода
Вдруг что-то забыл начислить?</blockquote>
Вопросы? Пиши создателю бота 👑
"""
return {"content": content}
admin_faq_window = Window(
Format("{content}"),
SwitchTo(
Const("◀️ Назад"),
id="back_to_main_from_faq",
state=AdminMenuSG.main,
),
state=AdminMenuSG.faq,
getter=get_admin_faq_data,
)
@@ -194,7 +194,7 @@ floors_list_window = Window(
) )
floor_delete_confirm_window = Window( floor_delete_confirm_window = Window(
Format("<blockquote>⚠️ <b>Подтверждение удаления</b></blockquote>\n\nВы точно хотите удалить этаж <code>{floor_number}</code>? Это действие необратимо и удалит все комнаты на этом этаже!"), Format("<blockquote>⚠️ <b>Подтверждение удаления</b></blockquote>\n\nВы точно хотите удалить этаж <code>{floor_number}</code>?\nЭто действие необратимо и удалит все комнаты на этом этаже!"),
Row( Row(
Button( Button(
Const("✅ Да, удалить"), Const("✅ Да, удалить"),
@@ -171,10 +171,17 @@ main_menu_window = Window(
on_click=on_admins_click, on_click=on_admins_click,
when="is_creator", when="is_creator",
), ),
SwitchTo( Row(
Const("📊 Статистика"), SwitchTo(
id="stats_btn", Const("📊 Статистика"),
state=AdminMenuSG.statistics, id="stats_btn",
state=AdminMenuSG.statistics,
),
SwitchTo(
Const("❓ FAQ"),
id="faq_btn",
state=AdminMenuSG.faq,
),
), ),
SwitchTo( SwitchTo(
Const("📢 Рассылка"), Const("📢 Рассылка"),
@@ -46,6 +46,7 @@ class AdminMenuSG(StatesGroup):
generate_report_select_period = State() generate_report_select_period = State()
generate_report_confirm = State() generate_report_confirm = State()
statistics = State() statistics = State()
faq = State()
broadcast = State() broadcast = State()
broadcast_confirm = State() broadcast_confirm = State()
+2 -2
View File
@@ -1,5 +1,5 @@
from aiogram import Router from aiogram import Router
from aiogram.filters import CommandStart from aiogram.filters import CommandStart, ExceptionTypeFilter
from aiogram.types import Message, CallbackQuery, ErrorEvent from aiogram.types import Message, CallbackQuery, ErrorEvent
from aiogram_dialog import DialogManager, StartMode from aiogram_dialog import DialogManager, StartMode
from aiogram_dialog.api.exceptions import UnknownIntent from aiogram_dialog.api.exceptions import UnknownIntent
@@ -56,7 +56,7 @@ async def start_handler(
await dialog_manager.start(RegistrationSG.select_floor, mode=StartMode.RESET_STACK) await dialog_manager.start(RegistrationSG.select_floor, mode=StartMode.RESET_STACK)
@router.error() @router.error(ExceptionTypeFilter(UnknownIntent))
async def unknown_intent_handler( async def unknown_intent_handler(
event: ErrorEvent, event: ErrorEvent,
dialog_manager: DialogManager, dialog_manager: DialogManager,