Files
tgex-backend/telegram_bot/screens/project_details.go
Artem Tsyrulnikov 2fb8c83041 new telegram bot
2025-12-30 19:50:15 +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"
"fmt"
"strings"
"example.com/m/adapter/backend"
"example.com/m/bot"
"github.com/NicoNex/echotron/v3"
"github.com/rs/zerolog/log"
)
type ProjectDetails struct {
Project *backend.Project
WorkspaceID string
BackState bot.State
confirmingLinkTypeChange bool // Флаг для двухшагового подтверждения смены типа ссылки
}
func (s *ProjectDetails) Enter(b *bot.Bot, mode bot.RenderMode) {
if s.Project == nil {
b.SendNew("❌ Проект не найден", bot.Keyboard(
bot.Row(bot.Button("« Назад", "back_to_projects")),
))
return
}
text := s.formatProjectDetails()
keyboard := s.buildKeyboard()
b.Render(text, keyboard, mode)
}
func (s *ProjectDetails) formatProjectDetails() string {
p := s.Project
// Заголовок
text := fmt.Sprintf(`<b>%s</b>`, p.Title)
// Информация о канале
if p.Username != nil && *p.Username != "" {
text += fmt.Sprintf(`
<b>Канал:</b> @%s`, *p.Username)
} else {
text += `
<b>Канал:</b> <i>не привязан</i>`
}
// Статус проекта
var statusText string
switch p.Status {
case "active":
statusText = "Активный"
case "inactive":
statusText = "Неактивен"
case "archived":
statusText = "Архивный"
case "paused":
statusText = "Приостановлен"
default:
statusText = p.Status
}
text += fmt.Sprintf(`
<b>Статус:</b> %s`, statusText)
// ID проекта (для технических целей)
text += fmt.Sprintf(`
<b>ID:</b> <code>%s</code>`, p.ID)
return text
}
func (s *ProjectDetails) buildKeyboard() echotron.InlineKeyboardMarkup {
var buttons [][]echotron.InlineKeyboardButton
// Первый ряд: Креативы и Создать закуп
buttons = append(buttons, bot.Row(
bot.Button("Креативы", fmt.Sprintf("creatives:%s", s.Project.ID)),
bot.Button("Создать закуп", fmt.Sprintf("create_purchase:%s", s.Project.ID)),
))
// Второй ряд: План закупов
buttons = append(buttons, bot.Row(
bot.Button("План закупов", fmt.Sprintf("purchase_plan:%s", s.Project.ID)),
))
// Третий ряд: Тип ссылки по умолчанию
var linkTypeButtonText string
if s.confirmingLinkTypeChange {
// Показываем текст подтверждения с противоположным типом
var newType string
if s.Project.InviteLinkType == "public" {
newType = "С одобрением"
} else {
newType = "Открытая"
}
linkTypeButtonText = fmt.Sprintf("Нажмите еще раз → %s", newType)
} else {
// Показываем текущий тип
var currentType string
if s.Project.InviteLinkType == "public" {
currentType = "Открытая"
} else {
currentType = "С одобрением"
}
linkTypeButtonText = fmt.Sprintf("Тип ссылки: %s", currentType)
}
buttons = append(buttons, bot.Row(
bot.Button(linkTypeButtonText, fmt.Sprintf("link_type:%s", s.Project.ID)),
))
// Четвертый ряд: Команда и Архивировать
buttons = append(buttons, bot.Row(
bot.Button("👥 Команда", fmt.Sprintf("team:%s", s.Project.ID)),
bot.Button("Архивировать", fmt.Sprintf("archive:%s", s.Project.ID)),
))
// Пятый ряд: Назад и Главное меню
buttons = append(buttons, bot.Row(
bot.Button("Назад", "back_to_projects"),
bot.Button("Главное меню", "main_menu"),
))
return bot.Keyboard(buttons...)
}
func (s *ProjectDetails) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
data := u.CallbackQuery.Data
switch {
case data == "back_to_projects", data == "back":
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
if s.BackState != nil {
b.SetState(s.BackState, bot.EditMessage)
}
case data == "main_menu":
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
b.SetState(&MainMenu{}, bot.NewMessage)
case strings.HasPrefix(data, "creatives:"):
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
b.SetState(&Creatives{
ProjectID: s.Project.ID,
WorkspaceID: s.WorkspaceID,
BackState: s,
}, bot.NewMessage)
case data == "back_to_project":
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
s.Enter(b, bot.EditMessage)
case strings.HasPrefix(data, "link_type:"):
if !s.confirmingLinkTypeChange {
// Первое нажатие - включаем режим подтверждения
s.confirmingLinkTypeChange = true
s.Enter(b, bot.EditMessage)
} else {
// Второе нажатие - меняем тип ссылки
var newType string
if s.Project.InviteLinkType == "public" {
newType = "approval"
} else {
newType = "public"
}
log.Info().
Str("workspace_id", s.WorkspaceID).
Str("project_id", s.Project.ID).
Str("old_type", s.Project.InviteLinkType).
Str("new_type", newType).
Msg("Updating project invite link type")
updatedProject, err := b.Backend.UpdateProjectInviteLinkType(
context.Background(),
b.Session.JWT,
s.WorkspaceID,
s.Project.ID,
newType,
)
if err != nil {
b.SendNew(fmt.Sprintf("❌ Ошибка при изменении типа ссылки: %v", err), bot.Keyboard(
bot.Row(bot.Button("« Назад", "back_to_project")),
))
return
}
// Обновляем проект и сбрасываем флаг подтверждения
s.Project = updatedProject
s.confirmingLinkTypeChange = false
s.Enter(b, bot.EditMessage)
}
default:
// Для остальных кнопок показываем заглушку
b.Edit(fmt.Sprintf("🚧 Функция в разработке\n\nCallback: %s", data), bot.Keyboard(
bot.Row(bot.Button("« Назад", "back_to_project")),
))
}
return
}
func (s *ProjectDetails) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return }
func (s *ProjectDetails) Handle(_ *bot.Bot, _ *echotron.Update) { return }