from maxapi.types.attachments.attachment import Attachment from maxapi.types.attachments.buttons import ( CallbackButton, RequestContactButton, ) from maxapi.utils.inline_keyboard import InlineKeyboardBuilder from bot.flow_config import PAYLOADS from bot.texts import Btn def main_menu_kb() -> Attachment: return ( InlineKeyboardBuilder() .row( CallbackButton(text=Btn.CREATE_TICKET, payload=PAYLOADS.CREATE_TICKET), CallbackButton(text=Btn.VIEW_TICKETS, payload=PAYLOADS.VIEW_TICKETS), ) .as_markup() ) def contact_request_kb() -> Attachment: return ( InlineKeyboardBuilder() .row(RequestContactButton(text=Btn.SHARE_CONTACT)) .as_markup() ) def confirm_ticket_kb() -> Attachment: """Клавиатура подтверждения создания заявки.""" return ( InlineKeyboardBuilder() .row(CallbackButton(text=Btn.CONFIRM_TICKET, payload=PAYLOADS.CONFIRM_TICKET)) .row( CallbackButton(text=Btn.EDIT_TICKET, payload=PAYLOADS.EDIT_TICKET), CallbackButton(text=Btn.CANCEL_TICKET, payload=PAYLOADS.CANCEL_TICKET), ) .as_markup() ) def menu_only_kb() -> Attachment: """Клавиатура с единственной кнопкой возврата в главное меню.""" return ( InlineKeyboardBuilder() .row(CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU)) .as_markup() ) def done_ticket_kb() -> Attachment: return ( InlineKeyboardBuilder() .row( CallbackButton(text=Btn.DONE_TICKET, payload=PAYLOADS.DONE_TICKET), CallbackButton(text=Btn.CANCEL_TICKET, payload=PAYLOADS.CANCEL_TICKET), ) .as_markup() ) def tickets_list_kb( tickets: list[dict], page: int, total: int, page_size: int = 8 ) -> Attachment: builder = InlineKeyboardBuilder() for t in tickets: desc_preview = (t["description"] or "")[:35] if len(t["description"] or "") > 35: desc_preview += "…" status_icon = {"open": "🔴", "in_progress": "🟡", "closed": "🟢"}.get( t["status"], "⚪" ) builder.row( CallbackButton( text=f"#{t['id']} {status_icon} {desc_preview}", payload=PAYLOADS.TICKET_DETAIL.format(id=t["id"]), ) ) nav = [] if page > 0: nav.append(CallbackButton(text=Btn.PREV_PAGE, payload=PAYLOADS.TICKETS_PAGE.format(page=page - 1))) if (page + 1) * page_size < total: nav.append(CallbackButton(text=Btn.NEXT_PAGE, payload=PAYLOADS.TICKETS_PAGE.format(page=page + 1))) if nav: builder.row(*nav) builder.row(CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU)) return builder.as_markup() def intradesk_tasks_list_kb( tasks: list[dict], page: int, total: int, page_size: int = 8 ) -> Attachment: builder = InlineKeyboardBuilder() for t in tasks: name_preview = (t.get("name") or "")[:35] if len(t.get("name") or "") > 35: name_preview += "…" sn = (t.get("status_name") or "").lower() if "выполнен" in sn: icon = "🟢" elif "работ" in sn: icon = "🟡" elif "открыт" in sn: icon = "🔴" else: icon = "⚪" label = t.get("task_number") or t["id"] builder.row( CallbackButton( text=f"#{label} {icon} {name_preview}", payload=PAYLOADS.ITICKET_DETAIL.format(id=t["id"]), ) ) nav = [] if page > 0: nav.append(CallbackButton(text=Btn.PREV_PAGE, payload=PAYLOADS.ITICKETS_PAGE.format(page=page - 1))) if (page + 1) * page_size < total: nav.append(CallbackButton(text=Btn.NEXT_PAGE, payload=PAYLOADS.ITICKETS_PAGE.format(page=page + 1))) if nav: builder.row(*nav) builder.row(CallbackButton(text=Btn.BACK_TO_MENU, payload=PAYLOADS.MAIN_MENU)) return builder.as_markup() def iticket_detail_kb(task_id: int | None = None, can_close: bool = False) -> Attachment: """Клавиатура внутри карточки Intradesk-задачи.""" builder = InlineKeyboardBuilder() action_row = [] if task_id is not None: action_row.append(CallbackButton( text=Btn.ADD_COMMENT, payload=PAYLOADS.ITICKET_COMMENT.format(task_id=task_id), )) if task_id is not None and can_close: action_row.append(CallbackButton( text=Btn.CLOSE_TICKET, payload=PAYLOADS.ITICKET_CLOSE.format(task_id=task_id), )) if action_row: builder.row(*action_row) builder.row( CallbackButton(text=Btn.BACK_TO_LIST, payload=PAYLOADS.ITICKETS_PAGE.format(page=0)), CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU), ) return builder.as_markup() def comment_input_kb(task_id: int) -> Attachment: """Клавиатура при вводе комментария — кнопка назад и меню.""" return ( InlineKeyboardBuilder() .row( CallbackButton( text=Btn.BACK_TO_TICKET, payload=PAYLOADS.ITICKET_DETAIL.format(id=task_id), ), CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU), ) .as_markup() ) def notification_kb(task_id: int, task_number: int | None = None) -> Attachment: """Клавиатура под уведомлением о новом комментарии.""" return ( InlineKeyboardBuilder() .row( CallbackButton( text=Btn.REPLY_TO_TICKET, payload=PAYLOADS.ITICKET_COMMENT.format(task_id=task_id), ), CallbackButton( text=Btn.OPEN_TICKET, payload=PAYLOADS.ITICKET_DETAIL.format(id=task_id), ), ) .row(CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU)) .as_markup() ) def reply_confirm_kb(task_id: int) -> Attachment: """Клавиатура подтверждения быстрого ответа на заявку.""" return ( InlineKeyboardBuilder() .row( CallbackButton( text=Btn.CONFIRM_REPLY, payload=PAYLOADS.CONFIRM_REPLY.format(task_id=task_id), ), CallbackButton(text=Btn.CANCEL_REPLY, payload=PAYLOADS.CANCEL_REPLY), ) .row(CallbackButton(text=Btn.CHOOSE_TICKET, payload=PAYLOADS.VIEW_TICKETS)) .as_markup() ) def ticket_detail_kb(page: int = 0) -> Attachment: return ( InlineKeyboardBuilder() .row(CallbackButton(text=Btn.BACK_TO_TICKETS, payload=PAYLOADS.TICKETS_PAGE.format(page=page))) .row(CallbackButton(text=Btn.MAIN_MENU, payload=PAYLOADS.MAIN_MENU)) .as_markup() )