Files
tgex-backend/tg_bot/screens/creative_view.go
Artem Tsyrulnikov be2d38eaf2 правки
2026-02-02 12:17:56 +03:00

211 lines
6.2 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"
"github.com/NicoNex/echotron/v3"
"github.com/TelegramExchange/tgex-backend/tg_bot/backend"
"github.com/TelegramExchange/tgex-backend/tg_bot/bot"
"github.com/rs/zerolog/log"
)
// CreativeView - экран просмотра креатива (read-only mode)
// Показывает превью креатива и кнопки действий: Редактировать, Тег, Закупить
type CreativeView struct {
CreativeEditorFields // Встраивание общих полей для отображения превью
CreativeID string
ProjectID string
// Данные проекта для передачи в AddPurchase
ProjectTitle string
ProjectTelegramID int64
ProjectUsername string
ProjectStatus string
BackState bot.State
}
const msgCreativeView = `
<b>📋 Просмотр креатива</b>
Выберите действие:
`
func (s *CreativeView) Enter(b *bot.Bot, mode bot.RenderMode) {
// Загружаем креатив
creative, err := b.Backend.GetCreative(context.Background(), b.Session.JWT, b.Session.WorkspaceID, s.CreativeID)
if err != nil {
log.Error().Err(err).Str("creative_id", s.CreativeID).Msg("Failed to get creative")
b.SendNew("<b>❌ Не удалось загрузить креатив</b>", Keyboard(
Row(Button("← Назад", "back")),
))
return
}
// Загружаем проект для получения данных
project, err := b.Backend.GetProject(context.Background(), b.Session.JWT, b.Session.WorkspaceID, s.ProjectID)
if err != nil {
log.Error().Err(err).Str("project_id", s.ProjectID).Msg("Failed to get project")
} else {
s.ProjectTitle = project.Title
s.ProjectTelegramID = project.TelegramID
s.ProjectStatus = project.Status
if project.Username != nil {
s.ProjectUsername = *project.Username
}
}
// Заполняем поля креатива для отображения превью
s.Name = &creative.Name
if creative.Text != "" {
s.Text = &creative.Text
}
s.MediaItems = nil
if len(creative.MediaItems) > 0 {
for _, item := range creative.MediaItems {
s.MediaItems = append(s.MediaItems, MediaItem{
MediaType: item.MediaType,
MediaFileID: item.MediaFileID,
})
}
}
s.Buttons = nil
for _, btn := range creative.Buttons {
s.Buttons = append(s.Buttons, InlineButton{Text: btn.Text, URL: btn.URL})
}
if creative.Tag != "" {
s.Tag = &creative.Tag
}
// Отправляем превью креатива
s.SendCreativePreview(b)
// Отправляем панель управления с кнопками действий
s.showActionPanel(b)
}
func (s *CreativeView) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
data := u.CallbackQuery.Data
switch {
case data == "back":
if s.BackState != nil {
b.SetState(s.BackState, bot.EditMessage)
}
case data == "edit":
// Переход к редактированию креатива
b.SetState(&CreativeDetails{
CreativeID: s.CreativeID,
ProjectID: s.ProjectID,
ViewMode: true, // Флаг, что мы открылись из view mode
ViewBackTo: s, // Возврат к этому экрану после сохранения
ProjectTitle: s.ProjectTitle,
BackState: s.BackState,
}, bot.EditMessage)
case data == "toggle_tag":
// Переключение тега (testing <-> production)
s.toggleTag(b)
case data == "purchase_creative":
// Переход к созданию закупа с предвыбором проекта и креатива
creativeTitle := ""
if s.Name != nil {
creativeTitle = *s.Name
}
b.SetState(&AddPurchase{
ProjectID: s.ProjectID,
ProjectTitle: s.ProjectTitle,
ProjectTelegramID: s.ProjectTelegramID,
ProjectUsername: s.ProjectUsername,
ProjectStatus: s.ProjectStatus,
CreativeID: s.CreativeID,
CreativeTitle: creativeTitle,
BackState: s,
}, bot.NewMessage)
default:
log.Warn().Str("callback", data).Msg("Unknown callback in CreativeView")
}
}
func (s *CreativeView) HandleMessage(_ *bot.Bot, _ *echotron.Update) {}
func (s *CreativeView) Handle(_ *bot.Bot, _ *echotron.Update) { return }
func (s *CreativeView) Exit() {}
// showActionPanel показывает панель действий с кнопками
func (s *CreativeView) showActionPanel(b *bot.Bot) {
tagLabel := s.GetTagLabel()
purchaseLabel := "🛒 Закупить на креатив"
// Если креатив архивирован (в будущем), можно изменить кнопки
var buttons [][]echotron.InlineKeyboardButton
// Кнопка редактирования
buttons = append(buttons, Row(
Button("✏️ Редактировать", "edit"),
))
// Кнопка тега
buttons = append(buttons, Row(
Button(tagLabel, "toggle_tag"),
))
// Кнопка закупа
buttons = append(buttons, Row(
Button(purchaseLabel, "purchase_creative"),
))
// Кнопка назад
buttons = append(buttons, Row(
Button("← Назад", "back"),
))
s.ShowControlPanel(b, msgCreativeView, buttons)
}
// toggleTag переключает тег креатива (testing <-> production)
func (s *CreativeView) toggleTag(b *bot.Bot) {
newTag := "testing"
if s.Tag != nil && *s.Tag == "testing" {
newTag = "production"
}
// Обновляем тег через backend
input := backend.UpdateCreativeInput{
Tag: &newTag,
}
_, err := b.Backend.UpdateCreative(
context.Background(),
b.Session.JWT,
b.Session.WorkspaceID,
s.CreativeID,
input,
)
if err != nil {
log.Error().Err(err).Str("creative_id", s.CreativeID).Msg("Failed to update creative tag")
s.ShowControlPanel(b, "<b>❌ Не удалось изменить тег</b>\n\nПопробуйте еще раз.", [][]echotron.InlineKeyboardButton{
Row(Button("← Назад", "back")),
Row(Button("↻ Попробовать снова", "toggle_tag")),
})
return
}
// Обновляем локальное значение
s.Tag = &newTag
// Обновляем панель (показывает новый тег)
s.showActionPanel(b)
}