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`, p.Title) // Информация о канале if p.Username != nil && *p.Username != "" { text += fmt.Sprintf(` Канал: @%s`, *p.Username) } else { text += ` Канал: не привязан` } // Статус проекта 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`, statusText) // ID проекта (для технических целей) text += fmt.Sprintf(` ID: %s`, 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 }