Files
tgex-backend/telegram_bot/screens/my_placements.go
2026-01-01 19:33:37 +03:00

222 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package screens
import (
"context"
"fmt"
"strings"
"example.com/m/bot"
"github.com/NicoNex/echotron/v3"
"github.com/rs/zerolog/log"
)
const placementsPerPage = 6
type MyPlacements struct {
CurrentPage int
WorkspaceID string
BackState bot.State
}
func (s *MyPlacements) Enter(b *bot.Bot, mode bot.RenderMode) {
// Получаем или запрашиваем JWT
jwt, err := s.ensureJWT(b)
if err != nil {
log.Error().Err(err).Msg("Failed to get JWT")
b.SendNew("❌ Ошибка авторизации. Попробуйте /start login", bot.Keyboard())
return
}
// Если workspace еще не выбран, получаем список workspace'ов
if s.WorkspaceID == "" {
workspaces, err := b.Backend.GetWorkspaces(context.Background(), jwt)
if err != nil {
log.Error().Err(err).Msg("Failed to get workspaces")
b.SendNew("❌ Не удалось загрузить workspace'ы", bot.Keyboard())
return
}
if len(workspaces) == 0 {
b.SendNew("У вас пока нет workspace'ов", bot.Keyboard())
return
}
// Используем первый workspace по умолчанию
s.WorkspaceID = workspaces[0].ID
}
s.renderPlacements(b, mode, jwt)
}
func (s *MyPlacements) renderPlacements(b *bot.Bot, mode bot.RenderMode, jwt string) {
page, err := b.Backend.GetPlacements(
context.Background(),
jwt,
s.WorkspaceID,
nil, // projectID
nil, // placementChannelID
nil, // creativeID
false, // includeArchived
s.CurrentPage+1,
placementsPerPage,
)
if err != nil {
log.Error().Err(err).Msg("Failed to get placements")
b.SendNew("❌ Не удалось загрузить закупы", bot.Keyboard())
return
}
text := "Мои закупы • Управление размещениями\n\n"
var buttons [][]echotron.InlineKeyboardButton
if len(page.Items) == 0 {
text += "У вас пока нет закупов"
} else {
text += fmt.Sprintf("Выберите закуп для управления (стр. %d из %d):", s.CurrentPage+1, page.Pages)
// Закупы по 2 в ряду
for i := 0; i < len(page.Items); i += 2 {
var row []echotron.InlineKeyboardButton
// Первый закуп в ряду
placement := page.Items[i]
row = append(row, bot.Button(placement.Name, fmt.Sprintf("placement:%s", placement.ID)))
// Второй закуп в ряду (если есть)
if i+1 < len(page.Items) {
placement = page.Items[i+1]
row = append(row, bot.Button(placement.Name, fmt.Sprintf("placement:%s", placement.ID)))
} else {
// Добавляем пустую кнопку для выравнивания
row = append(row, bot.Button(" ", "empty"))
}
buttons = append(buttons, row)
}
// Кнопки пагинации с номером страницы посередине (только если есть закупы)
var navRow []echotron.InlineKeyboardButton
// Левая стрелка (активная или неактивная)
if s.CurrentPage > 0 {
navRow = append(navRow, bot.Button("←", "prev"))
} else {
navRow = append(navRow, bot.Button("·", "empty"))
}
// Кнопка с номером страницы (неактивная)
pageButton := bot.Button(fmt.Sprintf("• %d/%d •", s.CurrentPage+1, page.Pages), "page_info")
navRow = append(navRow, pageButton)
// Правая стрелка (активная или неактивная)
if s.CurrentPage+1 < page.Pages {
navRow = append(navRow, bot.Button("→", "next"))
} else {
navRow = append(navRow, bot.Button("·", "empty"))
}
buttons = append(buttons, navRow)
}
// Кнопки управления
buttons = append(buttons, bot.Row(
bot.Button("Статистика", "statistics"),
bot.Button("Создать закуп", "add_placement"),
))
// Кнопка возврата в главное меню
buttons = append(buttons, bot.Row(bot.Button("🏠 Главное меню", "menu")))
keyboard := bot.Keyboard(buttons...)
b.Render(text, keyboard, mode)
}
func (s *MyPlacements) ensureJWT(b *bot.Bot) (string, error) {
// Проверяем, есть ли JWT в сессии
if b.Session.JWT != "" {
return b.Session.JWT, nil
}
// Если нет, запрашиваем новый
jwt, err := b.Backend.GetJWTByTelegramID(context.Background(), b.ChatID)
if err != nil {
return "", err
}
// Сохраняем в сессию
b.Session.JWT = jwt
return jwt, nil
}
func (s *MyPlacements) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
data := u.CallbackQuery.Data
switch {
case data == "prev":
if s.CurrentPage > 0 {
s.CurrentPage--
}
s.Enter(b, bot.EditMessage)
case data == "next":
s.CurrentPage++
s.Enter(b, bot.EditMessage)
case data == "menu":
b.SetState(&MainMenu{}, bot.EditMessage)
case data == "page_info", data == "empty":
// Неактивные кнопки - ничего не делаем
return
case data == "statistics":
// TODO: реализовать экран статистики
b.Edit("📊 Статистика закупов\n\nЭта функция в разработке", bot.Keyboard(
bot.Row(bot.Button("« Назад", "back_to_placements")),
))
case data == "add_placement":
b.SetState(&AddPlacement{
WorkspaceID: s.WorkspaceID,
BackState: s,
}, bot.EditMessage)
case data == "back_to_placements":
s.Enter(b, bot.EditMessage)
case strings.HasPrefix(data, "placement:"):
// Открытие деталей закупа
parts := strings.Split(data, ":")
if len(parts) == 2 {
placementID := parts[1]
// TODO: реализовать экран деталей закупа
b.Edit(fmt.Sprintf("📄 Детали закупа\n\nID: %s\n\nЭта функция в разработке", placementID), bot.Keyboard(
bot.Row(bot.Button("« Назад", "back_to_placements")),
))
}
case strings.HasPrefix(data, "workspace:"):
// Позволяет переключаться между workspace'ами в будущем
parts := strings.Split(data, ":")
if len(parts) == 2 {
s.WorkspaceID = parts[1]
s.CurrentPage = 0
s.Enter(b, bot.EditMessage)
}
default:
s.Enter(b, bot.NewMessage)
}
return
}
func (s *MyPlacements) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return }
func (s *MyPlacements) Handle(_ *bot.Bot, _ *echotron.Update) { return }