164 lines
6.1 KiB
Python
164 lines
6.1 KiB
Python
from __future__ import annotations
|
||
|
||
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, ReplyKeyboardMarkup
|
||
|
||
from app.categories import EXPENSE_CATEGORIES, category_label
|
||
from app.domain import BudgetCategory
|
||
|
||
|
||
MONTH_TOTAL = "📅 Итог за месяц"
|
||
ALL_TOTAL = "💰 Итог общий"
|
||
ANALYTICS = "📊 Аналитика"
|
||
RECENT = "🧾 Последние записи"
|
||
FAMILY = "👨👩👧 Семья"
|
||
DEBT = "💳 Общий долг"
|
||
CATEGORIES = "🗂 Категории"
|
||
HELP = "❓ Помощь"
|
||
|
||
|
||
def main_keyboard() -> ReplyKeyboardMarkup:
|
||
return ReplyKeyboardMarkup(
|
||
keyboard=[
|
||
[KeyboardButton(text=MONTH_TOTAL), KeyboardButton(text=ALL_TOTAL)],
|
||
[KeyboardButton(text=ANALYTICS), KeyboardButton(text=RECENT)],
|
||
[KeyboardButton(text=FAMILY), KeyboardButton(text=DEBT)],
|
||
[KeyboardButton(text=CATEGORIES), KeyboardButton(text=HELP)],
|
||
],
|
||
resize_keyboard=True,
|
||
input_field_placeholder="Например: 467 ярче",
|
||
is_persistent=True,
|
||
)
|
||
|
||
|
||
def family_setup_keyboard() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="Создать общий бюджет", callback_data="family:create")],
|
||
[InlineKeyboardButton(text="Ввести код супруга", callback_data="family:join")],
|
||
]
|
||
)
|
||
|
||
|
||
def family_approval_keyboard(candidate_user_id: int) -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text="✅ Подтвердить",
|
||
callback_data=f"family:approve:{candidate_user_id}",
|
||
),
|
||
InlineKeyboardButton(
|
||
text="🚫 Отклонить",
|
||
callback_data=f"family:reject:{candidate_user_id}",
|
||
),
|
||
]
|
||
]
|
||
)
|
||
|
||
|
||
def debt_keyboard(can_edit: bool) -> InlineKeyboardMarkup | None:
|
||
if not can_edit:
|
||
return None
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="✏️ Указать текущий долг", callback_data="debt:set")]
|
||
]
|
||
)
|
||
|
||
|
||
def category_tree_keyboard(
|
||
transaction_id: int, categories: list[BudgetCategory]
|
||
) -> InlineKeyboardMarkup:
|
||
rows: list[list[InlineKeyboardButton]] = []
|
||
for category in categories:
|
||
if category.parent_name:
|
||
text = f"↳ {category.icon} {category.name}"
|
||
else:
|
||
text = f"{category.icon} {category.name}"
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=text,
|
||
callback_data=f"bcat:{transaction_id}:{category.id}",
|
||
)
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="Отмена", callback_data=f"cancel:{transaction_id}")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def category_management_keyboard() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[InlineKeyboardButton(text="➕ Добавить категорию", callback_data="catmanage:add-main")],
|
||
[InlineKeyboardButton(text="↳ Добавить подкатегорию", callback_data="catmanage:add-sub")],
|
||
]
|
||
)
|
||
|
||
|
||
def category_kind_keyboard() -> InlineKeyboardMarkup:
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(text="↘️ Расход", callback_data="catmanage:kind:expense"),
|
||
InlineKeyboardButton(text="↗️ Доход", callback_data="catmanage:kind:income"),
|
||
],
|
||
[InlineKeyboardButton(text="Отмена", callback_data="catmanage:cancel")],
|
||
]
|
||
)
|
||
|
||
|
||
def parent_category_keyboard(categories: list[BudgetCategory]) -> InlineKeyboardMarkup:
|
||
parents = [category for category in categories if category.parent_id is None]
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(
|
||
text=f"{category.icon} {category.name}",
|
||
callback_data=f"catmanage:parent:{category.id}",
|
||
)
|
||
]
|
||
for category in parents
|
||
]
|
||
+ [[InlineKeyboardButton(text="Отмена", callback_data="catmanage:cancel")]]
|
||
)
|
||
|
||
|
||
def transaction_actions(transaction_id: int, *, is_expense: bool) -> InlineKeyboardMarkup:
|
||
# In a family budget, selecting a category may also change the operation type.
|
||
# Keep this action available for both current expenses and current incomes.
|
||
buttons: list[InlineKeyboardButton] = [
|
||
InlineKeyboardButton(text="Изменить категорию", callback_data=f"choose:{transaction_id}")
|
||
]
|
||
buttons.append(InlineKeyboardButton(text="Удалить", callback_data=f"delete:{transaction_id}"))
|
||
return InlineKeyboardMarkup(inline_keyboard=[buttons])
|
||
|
||
|
||
def category_keyboard(transaction_id: int) -> InlineKeyboardMarkup:
|
||
rows = []
|
||
categories = list(EXPENSE_CATEGORIES)
|
||
for index in range(0, len(categories), 2):
|
||
rows.append(
|
||
[
|
||
InlineKeyboardButton(
|
||
text=category_label(category),
|
||
callback_data=f"category:{transaction_id}:{category.value}",
|
||
)
|
||
for category in categories[index : index + 2]
|
||
]
|
||
)
|
||
rows.append([InlineKeyboardButton(text="Отмена", callback_data=f"cancel:{transaction_id}")])
|
||
return InlineKeyboardMarkup(inline_keyboard=rows)
|
||
|
||
|
||
def analytics_period_keyboard(active: str = "month") -> InlineKeyboardMarkup:
|
||
month_label = "✓ Этот месяц" if active == "month" else "Этот месяц"
|
||
all_label = "✓ Всё время" if active == "all" else "Всё время"
|
||
return InlineKeyboardMarkup(
|
||
inline_keyboard=[
|
||
[
|
||
InlineKeyboardButton(text=month_label, callback_data="analytics:month"),
|
||
InlineKeyboardButton(text=all_label, callback_data="analytics:all"),
|
||
]
|
||
]
|
||
)
|