Files
tgex-backend/telegram_bot/screens/add_purchase.go
2026-01-03 12:41:33 +03:00

300 lines
7.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"
"example.com/m/bot"
"github.com/NicoNex/echotron/v3"
"github.com/rs/zerolog/log"
)
const addPurchaseCreativesPerPage = 5
const addPurchaseProjectsPerPage = 6
type AddPurchase struct {
WorkspaceID string
ProjectID string
ProjectTitle string
CreativeID string
CreativeTitle string
ProjectPage int
CreativePage int
ActivePicker string // "" | "project_list" | "creative_list"
BackState bot.State
lastProjects map[string]string
lastCreatives map[string]string
}
func (s *AddPurchase) Enter(b *bot.Bot, mode bot.RenderMode) {
jwt, err := s.ensureJWT(b)
if err != nil {
log.Error().Err(err).Msg("Failed to get JWT")
b.SendNew("❌ Ошибка авторизации. Попробуйте /start", bot.Keyboard())
return
}
s.renderSelection(b, mode, jwt)
}
func (s *AddPurchase) renderSelection(b *bot.Bot, mode bot.RenderMode, jwt string) {
text := "<i>… Закупы Создание</i>\n\n<b>Создание закупа</b>\n\n"
text += "Выберите проект и креатив.\n\n"
var buttons [][]echotron.InlineKeyboardButton
projectLabel := "Проект: не выбрано"
if s.ProjectTitle != "" {
projectLabel = fmt.Sprintf("Проект: %s", s.ProjectTitle)
}
creativeLabel := "Креатив: не выбрано"
if s.CreativeTitle != "" {
creativeLabel = fmt.Sprintf("Креатив: %s", s.CreativeTitle)
}
if s.ActivePicker == "" {
buttons = append(buttons, bot.Row(
bot.Button(projectLabel, "pick_project"),
))
buttons = append(buttons, bot.Row(
bot.Button(creativeLabel, "pick_creative"),
))
}
switch s.ActivePicker {
case "project_list":
page, err := b.Backend.GetProjects(
context.Background(),
jwt,
s.WorkspaceID,
s.ProjectPage+1,
addPurchaseProjectsPerPage,
)
if err != nil {
log.Error().Err(err).Msg("Failed to get projects")
b.SendNew("❌ Не удалось загрузить проекты", bot.Keyboard())
return
}
s.lastProjects = make(map[string]string)
for _, project := range page.Items {
s.lastProjects[project.ID] = project.Title
}
if len(page.Items) == 0 {
text += "У вас нет проектов. Создайте проект и попробуйте снова.\n\n"
} else {
pageInfo := ""
if page.Pages > 1 {
pageInfo = fmt.Sprintf(" <i>(стр. %d/%d)</i>", page.Page, page.Pages)
}
text += fmt.Sprintf("Проекты%s\n\n", pageInfo)
for _, project := range page.Items {
buttons = append(buttons, bot.Row(
bot.Button(project.Title, fmt.Sprintf("project:%s", project.ID)),
))
}
var navRow []echotron.InlineKeyboardButton
if s.ProjectPage > 0 {
navRow = append(navRow, bot.Button("←", "prev_project"))
}
if s.ProjectPage+1 < page.Pages {
navRow = append(navRow, bot.Button("→", "next_project"))
}
if len(navRow) > 0 {
buttons = append(buttons, navRow)
}
}
buttons = append(buttons, bot.Row(
bot.Button("← Назад", "back_to_selection"),
))
case "creative_list":
if s.ProjectID == "" {
text += "Сначала выберите проект, чтобы увидеть список креативов.\n\n"
buttons = append(buttons, bot.Row(
bot.Button("← Назад", "back_to_selection"),
))
break
}
page, err := b.Backend.GetCreatives(
context.Background(),
jwt,
s.WorkspaceID,
&s.ProjectID,
false,
s.CreativePage+1,
addPurchaseCreativesPerPage,
)
if err != nil {
log.Error().Err(err).Msg("Failed to get creatives")
b.SendNew("❌ Не удалось загрузить креативы", bot.Keyboard())
return
}
s.lastCreatives = make(map[string]string)
for _, creative := range page.Items {
s.lastCreatives[creative.ID] = creative.Name
}
if len(page.Items) == 0 {
text += `Для создания закупа сначала нужно создать креатив.
Вернитесь назад и создайте креатив в разделе <b>Креативы</b>`
} else {
pageInfo := ""
if page.Pages > 1 {
pageInfo = fmt.Sprintf(" <i>(стр. %d/%d)</i>", page.Page, page.Pages)
}
text += fmt.Sprintf("Креативы%s\n\n", pageInfo)
for _, creative := range page.Items {
buttons = append(buttons, bot.Row(
bot.Button(creative.Name, fmt.Sprintf("creative:%s", creative.ID)),
))
}
var navRow []echotron.InlineKeyboardButton
if s.CreativePage > 0 {
navRow = append(navRow, bot.Button("←", "prev_creative"))
}
if s.CreativePage+1 < page.Pages {
navRow = append(navRow, bot.Button("→", "next_creative"))
}
if len(navRow) > 0 {
buttons = append(buttons, navRow)
}
}
buttons = append(buttons, bot.Row(
bot.Button("← Назад", "back_to_selection"),
))
}
if s.ActivePicker == "" {
if s.ProjectID != "" && s.CreativeID != "" {
buttons = append(buttons, bot.Row(
bot.Button("← Отмена", "back"),
bot.Button("→ Далее", "next"),
))
} else {
buttons = append(buttons, bot.Row(
bot.Button("← Отмена", "back"),
))
}
}
keyboard := bot.Keyboard(buttons...)
b.Render(text, keyboard, mode)
}
func (s *AddPurchase) ensureJWT(b *bot.Bot) (string, error) {
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 *AddPurchase) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
data := u.CallbackQuery.Data
switch data {
case "back":
if s.BackState != nil {
b.SetState(s.BackState, bot.EditMessage)
}
case "pick_project":
s.ActivePicker = "project_list"
s.Enter(b, bot.EditMessage)
case "pick_creative":
s.ActivePicker = "creative_list"
s.Enter(b, bot.EditMessage)
case "back_to_selection":
s.ActivePicker = ""
s.Enter(b, bot.EditMessage)
case "prev_project":
if s.ProjectPage > 0 {
s.ProjectPage--
}
s.Enter(b, bot.EditMessage)
case "next_project":
s.ProjectPage++
s.Enter(b, bot.EditMessage)
case "prev_creative":
if s.CreativePage > 0 {
s.CreativePage--
}
s.Enter(b, bot.EditMessage)
case "next_creative":
s.CreativePage++
s.Enter(b, bot.EditMessage)
case "next":
if s.ProjectID != "" && s.CreativeID != "" {
b.SetState(&SelectChannelsForPurchase{
WorkspaceID: s.WorkspaceID,
ProjectID: s.ProjectID,
ProjectTitle: s.ProjectTitle,
CreativeID: s.CreativeID,
CreativeTitle: s.CreativeTitle,
Channels: []PurchaseChannelInput{},
BackState: s.BackState,
}, bot.EditMessage)
}
default:
if len(data) > 8 && data[:8] == "project:" {
projectID := data[8:]
if s.lastProjects != nil {
s.ProjectTitle = s.lastProjects[projectID]
}
s.ProjectID = projectID
s.CreativeID = ""
s.CreativeTitle = ""
s.CreativePage = 0
s.ActivePicker = ""
s.Enter(b, bot.EditMessage)
return
}
if len(data) > 9 && data[:9] == "creative:" {
creativeID := data[9:]
if s.lastCreatives != nil {
s.CreativeTitle = s.lastCreatives[creativeID]
}
s.CreativeID = creativeID
s.ActivePicker = ""
s.Enter(b, bot.EditMessage)
return
} else {
s.Enter(b, bot.NewMessage)
}
}
}
func (s *AddPurchase) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return }
func (s *AddPurchase) Handle(_ *bot.Bot, _ *echotron.Update) { return }