Files
tgex-backend/telegram_bot/screens/project_details.go
2026-01-03 11:29:44 +03:00

208 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("<i>… Мои проекты %s</i>\n\n", p.Title)
text += fmt.Sprintf("<b>%s</b>\n\n", p.Title)
// Информация о канале
if p.Username != nil && *p.Username != "" {
text += fmt.Sprintf("▸ Telegram: @%s\n", *p.Username)
} else {
text += "▸ Telegram: <i>не привязан</i>\n"
}
// Статус проекта
var statusSymbol string
var statusText string
switch p.Status {
case "active":
statusSymbol = "●"
statusText = "Активный"
case "inactive":
statusSymbol = "○"
statusText = "Неактивен"
case "archived":
statusSymbol = "■"
statusText = "Архивный"
case "paused":
statusSymbol = "◐"
statusText = "Приостановлен"
default:
statusSymbol = "○"
statusText = p.Status
}
text += fmt.Sprintf("▸ Статус: %s %s\n", statusSymbol, statusText)
text += "\nУправление проектом"
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("purchases:%s", s.Project.ID)),
))
// Второй ряд: Тип вступления по умолчанию для закупов (с подтверждением)
var linkTypeButtonText string
if s.confirmingLinkTypeChange {
// Показываем подтверждение
var newType string
if s.Project.PurchaseInviteTypeDefault == "public" {
newType = "По заявке"
} else {
newType = "Свободное"
}
linkTypeButtonText = fmt.Sprintf("Изменить → %s", newType)
} else {
// Показываем текущий тип вступления
var currentType string
if s.Project.PurchaseInviteTypeDefault == "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("← Назад", "back_to_projects"),
bot.Button("≡ Архивировать", fmt.Sprintf("archive:%s", s.Project.ID)),
))
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 strings.HasPrefix(data, "creatives:"):
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
b.SetState(&Creatives{
ProjectID: s.Project.ID,
ProjectTitle: s.Project.Title,
WorkspaceID: s.WorkspaceID,
BackState: s,
}, bot.NewMessage)
case strings.HasPrefix(data, "purchases:"):
s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения
b.SetState(&Purchases{
WorkspaceID: s.WorkspaceID,
ProjectID: s.Project.ID,
ProjectTitle: s.Project.Title,
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.PurchaseInviteTypeDefault == "public" {
newType = "approval"
} else {
newType = "public"
}
log.Info().
Str("workspace_id", s.WorkspaceID).
Str("project_id", s.Project.ID).
Str("old_type", s.Project.PurchaseInviteTypeDefault).
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 }