package screens import ( "context" "fmt" "strings" "example.com/m/bot" "example.com/m/ui" "github.com/NicoNex/echotron/v3" "github.com/rs/zerolog/log" ) const creativesPerPage = 6 type Creatives struct { CurrentPage int ProjectID string WorkspaceID string BackState bot.State } func (s *Creatives) Enter(b *bot.Bot, mode bot.RenderMode) { // JWT уже создан в Bot.Update(), просто берем из сессии jwt := b.Session.JWT if jwt == "" { log.Error().Msg("JWT is empty in session") b.SendNew("❌ Ошибка авторизации. Попробуйте /start login", Keyboard()) return } s.renderCreatives(b, mode, jwt) } func (s *Creatives) renderCreatives(b *bot.Bot, mode bot.RenderMode, jwt string) { page, err := b.Backend.GetCreatives( context.Background(), jwt, s.WorkspaceID, &s.ProjectID, false, // includeArchived s.CurrentPage+1, creativesPerPage, ) if err != nil { log.Error().Err(err).Msg("Failed to get creatives") b.SendNew("❌ Не удалось загрузить креативы", Keyboard()) return } var text string var buttons [][]echotron.InlineKeyboardButton if len(page.Items) == 0 { text = `Креативы У вас пока нет креативов Креатив — это рекламный материал: ‣ Текст объявления ‣ Медиа контент (фото, видео) ‣ Шаблон для автопостинга ‣ Варианты для A/B тестирования Начните с добавления первого креатива` } else { text = fmt.Sprintf(`Креативы%s Управление рекламными материалами Выберите креатив`, ui.FormatPageInfo(s.CurrentPage, page.Pages)) } // Создаем слоты для креативов var slots []echotron.InlineKeyboardButton for _, creative := range page.Items { slots = append(slots, Button(creative.Name, fmt.Sprintf("creative:%s", creative.ID))) } // Если страниц >= 2, заполняем до 6 слотов пустыми кнопками if page.Pages >= 2 { for len(slots) < creativesPerPage { slots = append(slots, Button(" ", "empty")) } } // Разбиваем слоты по 2 в ряду for i := 0; i < len(slots); i += 2 { var row []echotron.InlineKeyboardButton row = append(row, slots[i]) // Второй слот в ряду (если есть) if i+1 < len(slots) { row = append(row, slots[i+1]) } else { // Если нечетное количество, добавляем пустую кнопку row = append(row, Button(" ", "empty")) } buttons = append(buttons, row) } // Ряд: Пагинация + Добавить (динамическая ширина) if navRow := ui.BuildNavigationRow(ui.PaginationConfig{ CurrentPage: s.CurrentPage, TotalPages: page.Pages, MiddleButtons: []echotron.InlineKeyboardButton{Button("+ Добавить", "add_creative")}, }); navRow != nil { buttons = append(buttons, navRow) } // Нижний ряд: Назад + Архив buttons = append(buttons, Row( Button("← Назад", "back"), Button("≡ Архив", "archive"), )) keyboard := Keyboard(buttons...) b.Render(text, keyboard, mode) } func (s *Creatives) 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 == "back": if s.BackState != nil { b.SetState(s.BackState, bot.EditMessage) } case data == "archive": // TODO: реализовать экран архива креативов b.Edit("📦 Архив креативов\n\nЭта функция в разработке", Keyboard( Row(Button("← Назад", "back")), )) case data == "add_creative": b.SetState(&AddCreativeStart{ctx: &AddCreativeCtx{ ProjectID: s.ProjectID, WorkspaceID: s.WorkspaceID, BackState: s, }}, bot.EditMessage) case strings.HasPrefix(data, "creative:"): // Открытие деталей креатива parts := strings.Split(data, ":") if len(parts) == 2 { creativeID := parts[1] b.SetState(&CreativeDetails{ CreativeID: creativeID, ProjectID: s.ProjectID, WorkspaceID: s.WorkspaceID, BackState: s, }, bot.NewMessage) } default: s.Enter(b, bot.NewMessage) } return } func (s *Creatives) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return } func (s *Creatives) Handle(_ *bot.Bot, _ *echotron.Update) { return } func (s *Creatives) Exit() {}