package screens import ( "context" "fmt" "example.com/m/bot" "github.com/NicoNex/echotron/v3" "github.com/rs/zerolog/log" ) type Purchases struct { WorkspaceID string ProjectID string BackState bot.State } func (s *Purchases) 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.renderPurchases(b, mode, jwt) } func (s *Purchases) renderPurchases(b *bot.Bot, mode bot.RenderMode, jwt string) { purchases, err := b.Backend.GetPurchases( context.Background(), jwt, s.WorkspaceID, s.ProjectID, ) if err != nil { log.Error().Err(err).Msg("Failed to get purchases") b.SendNew("❌ Не удалось загрузить закупы", bot.Keyboard()) return } text := "📦 Закупы\n\n" var buttons [][]echotron.InlineKeyboardButton if len(purchases) == 0 { text += `Список закупов пуст. Закуп — это план размещения рекламы в каналах: ▸ Выбор креатива ▸ Список каналов для размещения ▸ Планируемая стоимость ▸ Статус выполнения Создайте первый закуп 👇` } else { text += "Управление закупами для проекта.\n\n" text += "Выберите закуп для деталей:\n\n" for i, purchase := range purchases { // Определяем статус emoji statusEmoji := "📌" switch purchase.Status { case "active": statusEmoji = "🟢" case "archived": statusEmoji = "📦" } // Считаем каналы по статусам totalChannels := len(purchase.Channels) completedChannels := 0 for _, ch := range purchase.Channels { if ch.Status == "completed" { completedChannels++ } } buttonText := fmt.Sprintf("%s Закуп #%d (%d/%d каналов)", statusEmoji, i+1, completedChannels, totalChannels, ) buttons = append(buttons, bot.Row( bot.Button(buttonText, fmt.Sprintf("purchase:%s", purchase.ID)), )) } } // Кнопка создания нового закупа buttons = append(buttons, bot.Row( bot.Button("+ Создать закуп", "add_purchase"), )) // Кнопка назад buttons = append(buttons, bot.Row( bot.Button("← Назад", "back"), )) keyboard := bot.Keyboard(buttons...) b.Render(text, keyboard, mode) } func (s *Purchases) 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 *Purchases) 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 "add_purchase": b.SetState(&AddPurchase{ WorkspaceID: s.WorkspaceID, ProjectID: s.ProjectID, BackState: s, }, bot.EditMessage) default: // Проверяем, не нажали ли на конкретный закуп if len(data) > 9 && data[:9] == "purchase:" { purchaseID := data[9:] b.SetState(&PurchaseDetails{ WorkspaceID: s.WorkspaceID, ProjectID: s.ProjectID, PurchaseID: purchaseID, BackState: s, }, bot.NewMessage) } else { s.Enter(b, bot.NewMessage) } } } func (s *Purchases) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return } func (s *Purchases) Handle(_ *bot.Bot, _ *echotron.Update) { return }