refactor(tgbot-front): moved the navigation handler to a separate file

This commit is contained in:
Kirill 2025-12-05 23:42:30 +03:00
parent a22c96e7a0
commit 19164b8d9d
3 changed files with 150 additions and 145 deletions

View file

@ -0,0 +1,147 @@
#include "handlers.hpp"
#include "KeyboardFactory.hpp"
#include "structs.hpp"
#include "constants.hpp"
void BotHandlers::handleNavigation(TgBot::CallbackQuery::Ptr query, UserContext& ctx) {
const auto& current = ctx.history.back(); // текущий экран
const std::string& data = query->data;
// Пагинация (в списках)
if ((data == BotConstants::Callback::LIST_PREV || data == BotConstants::Callback::LIST_NEXT)
&& (current.state == UserState::VIEWING_MY_TITLES || current.state == UserState::VIEWING_REVIEW_LIST ||
current.state == UserState::VIEWING_FOUND_TITLES)) {
int64_t newPayload = current.payload;
if (data == BotConstants::Callback::LIST_PREV && newPayload > 0) {
reducePayload(newPayload, current.state);
} else if (data == BotConstants::Callback::LIST_NEXT) {
increasePayload(newPayload, current.state);
} else {
if (data == BotConstants::Callback::LIST_PREV) {
std::cout << "Error: navigation:prev callback for 1st page" << std::endl;
return;
}
// TODO: log
std::cout << "Error: navigation:prev unknown error" << std::endl;
}
ctx.history.back().payload = newPayload;
auto result = renderCurrent(query, ctx);
if(result.message == "meow") return; // TODO: убрать
editMessage(query, result);
return;
}
// Обработка back по интерфейсу
if (data == BotConstants::Callback::NAV_BACK) {
if (!popState(ctx)) {
sendError(query, BotConstants::Text::SAD_ERROR);
return;
}
auto result = renderCurrent(query, ctx);
if(result.message == "meow") return; // TODO: убрать
editMessage(query, result);
return;
}
// Переходы вперёд (push)
auto newStepOpt = computeNextStep(query, current);
if (!newStepOpt.has_value()) {
sendError(query, BotConstants::Text::SAD_ERROR);
return;
}
ctx.history.push_back(*newStepOpt);
auto result = renderCurrent(query, ctx);
if(result.message == "meow") return; // TODO: убрать
editMessage(query, result);
}
HandlerResult BotHandlers::renderCurrent(TgBot::CallbackQuery::Ptr query, const UserContext& ctx) {
const auto& step = ctx.history.back();
int64_t userId = query->from->id;
switch (step.state) {
case UserState::MAIN_MENU:
return showMainMenu();
case UserState::VIEWING_MY_TITLES:
server_.fetchUserTitlesAsync(std::to_string(2)) // ALARM: тестовое значение вместо userId
.then([this, query](pplx::task<std::vector<BotStructs::Title>> t) {
try {
auto titles = t.get();
std::string message = formatTitlesList(titles);
auto keyboard = KeyboardFactory::createMyTitles(titles);
editMessage(query, {message, keyboard});
} catch (const std::exception& e) {
sendError(query, BotConstants::Text::SERVER_ERROR);
// Логирование ошибки (например, в cerr)
}
});
return {"meow", nullptr};
/*
case UserState::VIEWING_TITLE_PAGE:
return returnTitlePage(step.payload); // payload = titleId
case UserState::VIEWING_REVIEW:
return returnReview(step.payload); // payload = reviewId
case UserState::AWAITING_REVIEW:
return HandlerResult{"Пришлите текст отзыва:", nullptr};
// ...
*/
default:
return HandlerResult{BotConstants::Text::SAD_ERROR, nullptr};
}
}
std::optional<NavigationStep> BotHandlers::computeNextStep(
const TgBot::CallbackQuery::Ptr& query,
const NavigationStep& current
) {
const std::string& data = query->data;
switch (current.state) {
case UserState::MAIN_MENU:
if (data == BotConstants::Callback::MY_TITLES) {
return NavigationStep{UserState::VIEWING_MY_TITLES, 0};
}
break;
/*
case UserState::VIEWING_MY_TITLES:
if (data.starts_with("title_")) {
int64_t titleId = parseId(data);
return NavigationStep{UserState::VIEWING_TITLE_PAGE, titleId};
}
break;
case UserState::VIEWING_TITLE_PAGE:
if (data == BotConstants::Callback::ACTION_ADD_REVIEW) {
return NavigationStep{UserState::AWAITING_REVIEW, current.payload};
}
if (data.starts_with("review_")) {
int64_t reviewId = parseId(data);
return NavigationStep{UserState::VIEWING_REVIEW, reviewId};
}
break;
*/
default:
break;
}
return std::nullopt;
}
std::string BotHandlers::formatTitlesList(const std::vector<BotStructs::Title>& titles) {
if (titles.empty()) {
return "У вас пока нет тайтлов.";
}
std::string msg;
for (size_t i = 0; i < titles.size(); ++i) {
// num — 0-based, но в сообщении показываем 1-based
msg += std::to_string(i + 1) + ". " + titles[i].name + "\n";
}
return msg;
}