package screens import ( "context" "fmt" "strings" "github.com/NicoNex/echotron/v3" "github.com/TelegramExchange/tgex-backend/tg_bot/backend" "github.com/TelegramExchange/tgex-backend/tg_bot/bot" "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("❌ Проект не найден", Keyboard( Row(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("%s\n\n", p.Title) // Информация о канале if p.Username != nil && *p.Username != "" { text += fmt.Sprintf("▸ Telegram: @%s\n", *p.Username) } else { text += "▸ Telegram: не привязан\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, Row( Button("Креативы", fmt.Sprintf("creatives:%s", s.Project.ID)), 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, Row( Button(linkTypeButtonText, fmt.Sprintf("link_type:%s", s.Project.ID)), )) // Нижний ряд: Назад и Архивировать buttons = append(buttons, Row( Button("← Назад", "back_to_projects"), Button("≡ Архивировать", fmt.Sprintf("archive:%s", s.Project.ID)), )) return 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, WorkspaceID: s.WorkspaceID, BackState: s, }, bot.EditMessage) 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.EditMessage) 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), Keyboard( Row(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), Keyboard( Row(Button("← Назад", "back_to_project")), )) } return } func (s *ProjectDetails) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return } func (s *ProjectDetails) Handle(_ *bot.Bot, _ *echotron.Update) { return } func (s *ProjectDetails) Exit() {}