from typing import Optional from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup from aiogram.utils.keyboard import InlineKeyboardBuilder from db.models import Category, Product from dto.cart import CartItemDTO def pagination_row( *, page: int, prev_cb: Optional[str] = None, next_cb: Optional[str] = None, ) -> list[InlineKeyboardButton]: row = [] if prev_cb: row.append(InlineKeyboardButton(text="⬅️", callback_data=prev_cb)) row.append(InlineKeyboardButton(text=str(page + 1), callback_data="...")) if next_cb: row.append(InlineKeyboardButton(text="➡️", callback_data=next_cb)) return row def cart_btn(cart_items: int) -> InlineKeyboardButton: return InlineKeyboardButton(text=f"🛒 Корзина ({cart_items})", callback_data="cart") def get_back_to_catalogue( cat_id: int, *, text: Optional[str] = "⬅️ Назад" ) -> InlineKeyboardMarkup: return InlineKeyboardBuilder( [[InlineKeyboardButton(text=text, callback_data=f"cat:{cat_id}")]] ).as_markup() def main_menu_kb(cart_items: int) -> InlineKeyboardMarkup: return InlineKeyboardBuilder( [ [ InlineKeyboardButton(text="📦 Каталог", callback_data="cat:root"), InlineKeyboardButton(text="🔍", callback_data="find"), ], [cart_btn(cart_items)], ] ).as_markup() def render_category( children: list[Category], parent_id: Optional[int] = None, show_menu: bool = False, ) -> InlineKeyboardMarkup: btns = [ InlineKeyboardButton( text=category.name, callback_data=f"cat:{category.id}", ) for category in children ] nav = [] if parent_id is not None: nav.append( InlineKeyboardButton(text="⬅️ Назад", callback_data=f"cat:{parent_id}") ) if show_menu: nav.append(InlineKeyboardButton(text="⬅️ Назад", callback_data="menu:main")) return InlineKeyboardBuilder( [btns[i : i + 2] for i in range(0, len(children), 2)] + [nav], ).as_markup() def render_products( products: list[Product], *, parent_id: int, cat_id: int, page: int = 0, show_prev: Optional[bool] = False, show_next: Optional[bool] = False, ) -> InlineKeyboardMarkup: btns = [ InlineKeyboardButton(text=product.name, callback_data=f"product:{product.id}") for product in products ] nav = pagination_row( page=page, prev_cb=f"products:{cat_id}:{page - 1}" if show_prev else None, next_cb=f"products:{cat_id}:{page + 1}" if show_next else None, ) return InlineKeyboardBuilder( [ [ InlineKeyboardButton( text="⬅️ Назад", callback_data=f"cat:{parent_id}", ) ] ] + [btns[i : i + 2] for i in range(0, len(products), 2)] + [nav] ).as_markup() def render_product_interactions( *, product_id: int, category_id: int, show_cart: bool = False, cart_amount: int = 0 ) -> InlineKeyboardMarkup: btns: list[list[InlineKeyboardButton]] = [] if show_cart: btns.append( [ InlineKeyboardButton( text="➖", callback_data=f"cart_action:remove:{product_id}" ), InlineKeyboardButton(text=f"🛒 {cart_amount}", callback_data="..."), InlineKeyboardButton( text="➕", callback_data=f"cart_action:add:{product_id}" ), ] ) btns.append( [ InlineKeyboardButton( text="❌ Удалить из корзины", callback_data=f"cart_action:clear:{product_id}", ) ] ) else: btns.append( [ InlineKeyboardButton( text="🛒 В корзину", callback_data=f"cart_action:add:{product_id}" ) ] ) btns.append([InlineKeyboardButton(text="⬅️", callback_data=f"cat:{category_id}")]) return InlineKeyboardBuilder(btns).as_markup() def render_cart( cart_items: list[CartItemDTO], *, page: int = 0, show_prev: Optional[bool] = False, show_next: Optional[bool] = False, ) -> InlineKeyboardMarkup: btns = [ InlineKeyboardButton( text=f"{cart_item.quantity} | {cart_item.name} | {cart_item.total}₽", callback_data=f"product:{cart_item.product_id}", ) for cart_item in cart_items ] nav = pagination_row( page=page, prev_cb=f"cart:{page - 1}" if show_prev else None, next_cb=f"cart:{page + 1}" if show_next else None, ) return InlineKeyboardBuilder( [ [ InlineKeyboardButton( text="⬅️ Назад", callback_data="menu:main", ) ] ] + [btns[i : i + 2] for i in range(0, len(cart_items), 2)] + [nav] ).as_markup()