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("%s\n\n", p.Title) // Информация о канале if p.Username != nil && *p.Username != "" { text += fmt.Sprintf("Telegram-канал: @%s\n", *p.Username) } else { text += "Telegram-канал: не привязан\n" } // Статус проекта 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("Статус: %s\n", 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("create_placement:%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("← Назад", "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, WorkspaceID: s.WorkspaceID, BackState: s, }, bot.NewMessage) case strings.HasPrefix(data, "create_placement:"): s.confirmingLinkTypeChange = false // Сбрасываем флаг подтверждения // TODO: реализовать создание закупа b.Edit("🚧 Создать закуп\n\nФункция в разработке", bot.Keyboard( bot.Row(bot.Button("← Назад", "back_to_project")), )) 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 }