экраны закупов и креативов
This commit is contained in:
222
telegram_bot/screens/placement_purchase_plan.go
Normal file
222
telegram_bot/screens/placement_purchase_plan.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package screens
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"example.com/m/adapter/backend"
|
||||
"example.com/m/bot"
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type PlacementPurchasePlan struct {
|
||||
WorkspaceID string
|
||||
ProjectID string
|
||||
AddPlacementState *AddPlacement
|
||||
}
|
||||
|
||||
func (s *PlacementPurchasePlan) 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.renderChannels(b, mode, jwt)
|
||||
}
|
||||
|
||||
func (s *PlacementPurchasePlan) renderChannels(b *bot.Bot, mode bot.RenderMode, jwt string) {
|
||||
channels, err := b.Backend.GetPurchasePlanChannels(
|
||||
context.Background(),
|
||||
jwt,
|
||||
s.WorkspaceID,
|
||||
s.ProjectID,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to get purchase plan channels")
|
||||
b.SendNew("❌ Не удалось загрузить каналы", bot.Keyboard())
|
||||
return
|
||||
}
|
||||
|
||||
text := "<b>📋 План закупа — Каналы</b>\n\n"
|
||||
|
||||
var buttons [][]echotron.InlineKeyboardButton
|
||||
|
||||
if len(channels) == 0 {
|
||||
text += "Список каналов пуст.\n\n"
|
||||
} else {
|
||||
text += "Нажмите на канал для удаления:\n\n"
|
||||
|
||||
for _, ch := range channels {
|
||||
channelName := "Без названия"
|
||||
if ch.Channel.Title != nil {
|
||||
channelName = *ch.Channel.Title
|
||||
} else if ch.Channel.Username != nil {
|
||||
channelName = "@" + *ch.Channel.Username
|
||||
}
|
||||
|
||||
// Показываем статус и стоимость
|
||||
statusEmoji := "📌"
|
||||
switch ch.Status {
|
||||
case "planned":
|
||||
statusEmoji = "📝"
|
||||
case "approved":
|
||||
statusEmoji = "✅"
|
||||
case "rejected":
|
||||
statusEmoji = "❌"
|
||||
case "in_progress":
|
||||
statusEmoji = "🔄"
|
||||
case "completed":
|
||||
statusEmoji = "✔️"
|
||||
}
|
||||
|
||||
buttonText := fmt.Sprintf("%s %s", statusEmoji, channelName)
|
||||
if ch.PlannedCost != nil {
|
||||
buttonText += fmt.Sprintf(" (%.0f₽)", *ch.PlannedCost)
|
||||
}
|
||||
|
||||
buttons = append(buttons, bot.Row(
|
||||
bot.Button(buttonText, fmt.Sprintf("remove:%s", ch.ID)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
// Инструкция по добавлению канала
|
||||
text += "\n<b>Добавление канала:</b>\nОтправьте username канала (без @)"
|
||||
|
||||
// Навигация
|
||||
var navRow []echotron.InlineKeyboardButton
|
||||
navRow = append(navRow, bot.Button("« Назад", "back"))
|
||||
navRow = append(navRow, bot.Button("Далее →", "next"))
|
||||
buttons = append(buttons, navRow)
|
||||
|
||||
keyboard := bot.Keyboard(buttons...)
|
||||
b.Render(text, keyboard, mode)
|
||||
}
|
||||
|
||||
func (s *PlacementPurchasePlan) 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 *PlacementPurchasePlan) 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.AddPlacementState != nil {
|
||||
b.SetState(s.AddPlacementState, bot.EditMessage)
|
||||
}
|
||||
|
||||
case data == "next":
|
||||
// TODO: переход к следующему шагу (детали размещения)
|
||||
b.Edit("🚧 Следующий шаг в разработке", bot.Keyboard(
|
||||
bot.Row(bot.Button("« Назад", "back_to_purchase_plan")),
|
||||
))
|
||||
|
||||
case data == "back_to_purchase_plan":
|
||||
s.Enter(b, bot.EditMessage)
|
||||
|
||||
case strings.HasPrefix(data, "remove:"):
|
||||
parts := strings.Split(data, ":")
|
||||
if len(parts) == 2 {
|
||||
purchasePlanChannelID := parts[1] // ID записи PurchasePlanChannel
|
||||
|
||||
jwt, err := s.ensureJWT(b)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to get JWT")
|
||||
return
|
||||
}
|
||||
|
||||
// Удаляем канал из плана закупа
|
||||
err = b.Backend.RemoveChannelFromPurchasePlan(
|
||||
context.Background(),
|
||||
jwt,
|
||||
s.WorkspaceID,
|
||||
s.ProjectID,
|
||||
purchasePlanChannelID,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("purchase_plan_channel_id", purchasePlanChannelID).Msg("Failed to remove channel")
|
||||
b.Edit("❌ Не удалось удалить канал", bot.Keyboard(
|
||||
bot.Row(bot.Button("« Назад", "back_to_purchase_plan")),
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Обновляем экран
|
||||
s.Enter(b, bot.EditMessage)
|
||||
}
|
||||
|
||||
default:
|
||||
s.Enter(b, bot.NewMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PlacementPurchasePlan) HandleMessage(b *bot.Bot, u *echotron.Update) {
|
||||
if u.Message == nil || u.Message.Text == "" {
|
||||
return
|
||||
}
|
||||
|
||||
username := strings.TrimSpace(u.Message.Text)
|
||||
|
||||
// Убираем @ если пользователь его добавил
|
||||
username = strings.TrimPrefix(username, "@")
|
||||
|
||||
if username == "" {
|
||||
return
|
||||
}
|
||||
|
||||
jwt, err := s.ensureJWT(b)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Failed to get JWT")
|
||||
b.SendNew("❌ Ошибка авторизации. Попробуйте /start", bot.Keyboard())
|
||||
return
|
||||
}
|
||||
|
||||
// Отправляем запрос на добавление канала
|
||||
input := backend.AttachChannelToPurchasePlanInput{
|
||||
Username: username,
|
||||
}
|
||||
|
||||
_, err = b.Backend.AttachChannelToPurchasePlan(
|
||||
context.Background(),
|
||||
jwt,
|
||||
s.WorkspaceID,
|
||||
s.ProjectID,
|
||||
input,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("username", username).Msg("Failed to attach channel")
|
||||
|
||||
// Проверяем, содержит ли ошибка информацию о том, что канал не найден
|
||||
if strings.Contains(err.Error(), "not found") || strings.Contains(err.Error(), "404") {
|
||||
b.SendNew(fmt.Sprintf("❌ Канал @%s не найден в Telegram.\n\nПроверьте правильность username и попробуйте еще раз.", username), bot.Keyboard())
|
||||
} else {
|
||||
b.SendNew("❌ Не удалось добавить канал. Попробуйте позже.", bot.Keyboard())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Обновляем экран со списком каналов
|
||||
s.Enter(b, bot.NewMessage)
|
||||
}
|
||||
|
||||
func (s *PlacementPurchasePlan) Handle(_ *bot.Bot, _ *echotron.Update) { return }
|
||||
Reference in New Issue
Block a user