правки
This commit is contained in:
@@ -570,9 +570,13 @@ type CreateChannelResult struct {
|
||||
}
|
||||
|
||||
type ProjectOutput struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
Channel Channel `json:"channel"`
|
||||
ID string `json:"id"`
|
||||
TelegramID int64 `json:"telegram_id"`
|
||||
Title string `json:"title"`
|
||||
Username *string `json:"username"`
|
||||
Status string `json:"status"`
|
||||
PurchaseInviteTypeDefault string `json:"purchase_invite_type_default"`
|
||||
Channel Channel `json:"channel"`
|
||||
}
|
||||
|
||||
type CreateChannelsOutput struct {
|
||||
@@ -598,18 +602,18 @@ type PlacementDetails struct {
|
||||
}
|
||||
|
||||
type PlacementOutput struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
CreativeID *string `json:"creative_id,omitempty"`
|
||||
CreativeName *string `json:"creative_name,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
InviteLink *string `json:"invite_link,omitempty"`
|
||||
InviteLinkType string `json:"invite_link_type"`
|
||||
Channel Channel `json:"channel"`
|
||||
Project *ProjectOutput `json:"project"`
|
||||
PlacementNumber int `json:"placement_number"`
|
||||
Details *PlacementDetails `json:"details,omitempty"`
|
||||
PlacementPost *PlacementPostOutput `json:"placement_post,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
CreativeID *string `json:"creative_id,omitempty"`
|
||||
CreativeName *string `json:"creative_name,omitempty"`
|
||||
Comment *string `json:"comment,omitempty"`
|
||||
InviteLink *string `json:"invite_link,omitempty"`
|
||||
InviteLinkType string `json:"invite_link_type"`
|
||||
Channel Channel `json:"channel"`
|
||||
Project *ProjectOutput `json:"project"`
|
||||
ShortID string `json:"short_id"`
|
||||
Details *PlacementDetails `json:"details,omitempty"`
|
||||
PlacementPost *PlacementPostOutput `json:"placement_post,omitempty"`
|
||||
}
|
||||
|
||||
type PlacementPostOutput struct {
|
||||
|
||||
@@ -55,7 +55,7 @@ const msgDownloadMediaError = `
|
||||
const msgInviteLinkRequired = `
|
||||
<b>❌ Ошибка валидации</b>
|
||||
|
||||
Текст должен содержать <b>ОДНУ</b> инвайт-ссылку вашего канала!
|
||||
Текст должен содержать <b>хотя бы одну</b> инвайт-ссылку вашего канала!
|
||||
|
||||
<b>Формат ссылки:</b>
|
||||
<code>https://t.me/+xxx</code>
|
||||
|
||||
@@ -16,9 +16,15 @@ import (
|
||||
type CreativeDetails struct {
|
||||
CreativeEditorFields // Встраивание общих полей
|
||||
|
||||
CreativeID string
|
||||
ProjectID string
|
||||
BackState bot.State
|
||||
CreativeID string
|
||||
ProjectID string
|
||||
ProjectTitle string // Название проекта для сообщений
|
||||
|
||||
BackState bot.State
|
||||
|
||||
// View mode: открыты из режима просмотра
|
||||
ViewMode bool // Открыты из CreativeView
|
||||
ViewBackTo bot.State // Состояние для возврата (CreativeView)
|
||||
|
||||
// Флаг подтверждения удаления
|
||||
confirmingDelete bool
|
||||
@@ -89,7 +95,10 @@ func (s *CreativeDetails) HandleCallback(b *bot.Bot, u *echotron.Update) {
|
||||
switch {
|
||||
case data == "cancel", data == "back":
|
||||
// Отмена - возвращаемся назад
|
||||
if s.BackState != nil {
|
||||
if s.ViewMode && s.ViewBackTo != nil {
|
||||
// Если открыты из view mode, возвращаемся к просмотру
|
||||
b.SetState(s.ViewBackTo, bot.EditMessage)
|
||||
} else if s.BackState != nil {
|
||||
b.SetState(s.BackState, bot.EditMessage)
|
||||
}
|
||||
|
||||
@@ -355,7 +364,12 @@ func (s *CreativeDetails) updateCreative(b *bot.Bot) {
|
||||
log.Info().Str("creative_id", s.CreativeID).Msg("Creative updated successfully")
|
||||
|
||||
// Возвращаемся назад
|
||||
if s.BackState != nil {
|
||||
if s.ViewMode && s.ViewBackTo != nil {
|
||||
// Если открыты из view mode, возвращаемся к просмотру
|
||||
b.SendNew("✅ Креатив успешно обновлен!", Keyboard())
|
||||
b.SetState(s.ViewBackTo, bot.EditMessage)
|
||||
} else if s.BackState != nil {
|
||||
// Иначе возвращаемся к BackState
|
||||
b.SendNew("✅ Креатив успешно обновлен!", Keyboard())
|
||||
b.SetState(s.BackState, bot.EditMessage)
|
||||
}
|
||||
|
||||
218
tg_bot/screens/creative_view.go
Normal file
218
tg_bot/screens/creative_view.go
Normal file
@@ -0,0 +1,218 @@
|
||||
package screens
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// CreativeView - экран просмотра креатива (read-only mode)
|
||||
// Показывает превью креатива и кнопки действий: Редактировать, Тег, Закупить
|
||||
type CreativeView struct {
|
||||
CreativeEditorFields // Встраивание общих полей для отображения превью
|
||||
|
||||
CreativeID string
|
||||
ProjectID string
|
||||
|
||||
// Данные проекта для передачи в AddPurchase
|
||||
ProjectTitle string
|
||||
ProjectTelegramID int64
|
||||
ProjectUsername string
|
||||
ProjectStatus string
|
||||
|
||||
BackState bot.State
|
||||
}
|
||||
|
||||
const msgCreativeView = `
|
||||
<b>📋 Просмотр креатива</b>
|
||||
|
||||
Выберите действие:
|
||||
`
|
||||
|
||||
func (s *CreativeView) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
// Загружаем креатив
|
||||
creative, err := b.Backend.GetCreative(context.Background(), b.Session.JWT, b.Session.WorkspaceID, s.CreativeID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("creative_id", s.CreativeID).Msg("Failed to get creative")
|
||||
b.SendNew("<b>❌ Не удалось загрузить креатив</b>", Keyboard(
|
||||
Row(Button("← Назад", "back")),
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Загружаем проект для получения данных
|
||||
project, err := b.Backend.GetProject(context.Background(), b.Session.JWT, b.Session.WorkspaceID, s.ProjectID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("project_id", s.ProjectID).Msg("Failed to get project")
|
||||
} else {
|
||||
s.ProjectTitle = project.Title
|
||||
s.ProjectTelegramID = project.TelegramID
|
||||
s.ProjectStatus = project.Status
|
||||
if project.Username != nil {
|
||||
s.ProjectUsername = *project.Username
|
||||
}
|
||||
}
|
||||
|
||||
// Заполняем поля креатива для отображения превью
|
||||
s.Name = &creative.Name
|
||||
if creative.Text != "" {
|
||||
s.Text = &creative.Text
|
||||
}
|
||||
s.MediaItems = nil
|
||||
if len(creative.MediaItems) > 0 {
|
||||
for _, item := range creative.MediaItems {
|
||||
s.MediaItems = append(s.MediaItems, MediaItem{
|
||||
MediaType: item.MediaType,
|
||||
MediaFileID: item.MediaFileID,
|
||||
})
|
||||
}
|
||||
}
|
||||
s.Buttons = nil
|
||||
for _, btn := range creative.Buttons {
|
||||
s.Buttons = append(s.Buttons, InlineButton{Text: btn.Text, URL: btn.URL})
|
||||
}
|
||||
if creative.Tag != "" {
|
||||
s.Tag = &creative.Tag
|
||||
}
|
||||
|
||||
// Отправляем превью креатива
|
||||
s.SendCreativePreview(b)
|
||||
|
||||
// Отправляем панель управления с кнопками действий
|
||||
s.showActionPanel(b)
|
||||
}
|
||||
|
||||
func (s *CreativeView) HandleCallback(b *bot.Bot, u *echotron.Update) {
|
||||
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
|
||||
return
|
||||
}
|
||||
|
||||
data := u.CallbackQuery.Data
|
||||
|
||||
switch {
|
||||
case data == "back":
|
||||
if s.BackState != nil {
|
||||
b.SetState(s.BackState, bot.EditMessage)
|
||||
}
|
||||
|
||||
case data == "edit":
|
||||
// Переход к редактированию креатива
|
||||
b.SetState(&CreativeDetails{
|
||||
CreativeID: s.CreativeID,
|
||||
ProjectID: s.ProjectID,
|
||||
ViewMode: true, // Флаг, что мы открылись из view mode
|
||||
ViewBackTo: s, // Возврат к этому экрану после сохранения
|
||||
ProjectTitle: s.ProjectTitle,
|
||||
BackState: s.BackState,
|
||||
}, bot.NewMessage)
|
||||
|
||||
case data == "toggle_tag":
|
||||
// Переключение тега (testing <-> production)
|
||||
s.toggleTag(b)
|
||||
|
||||
case data == "purchase_creative":
|
||||
// Переход к созданию закупа с предвыбором проекта и креатива
|
||||
creativeTitle := ""
|
||||
if s.Name != nil {
|
||||
creativeTitle = *s.Name
|
||||
}
|
||||
|
||||
b.SetState(&AddPurchase{
|
||||
ProjectID: s.ProjectID,
|
||||
ProjectTitle: s.ProjectTitle,
|
||||
ProjectTelegramID: s.ProjectTelegramID,
|
||||
ProjectUsername: s.ProjectUsername,
|
||||
ProjectStatus: s.ProjectStatus,
|
||||
CreativeID: s.CreativeID,
|
||||
CreativeTitle: creativeTitle,
|
||||
BackState: s,
|
||||
}, bot.NewMessage)
|
||||
|
||||
default:
|
||||
log.Warn().Str("callback", data).Msg("Unknown callback in CreativeView")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *CreativeView) HandleMessage(_ *bot.Bot, _ *echotron.Update) {}
|
||||
|
||||
func (s *CreativeView) Handle(_ *bot.Bot, _ *echotron.Update) { return }
|
||||
|
||||
func (s *CreativeView) Exit() {}
|
||||
|
||||
// showActionPanel показывает панель действий с кнопками
|
||||
func (s *CreativeView) showActionPanel(b *bot.Bot) {
|
||||
tagLabel := s.GetTagLabel()
|
||||
purchaseLabel := "🛒 Закупить на креатив"
|
||||
|
||||
// Если креатив архивирован (в будущем), можно изменить кнопки
|
||||
var buttons [][]echotron.InlineKeyboardButton
|
||||
|
||||
// Кнопка редактирования
|
||||
buttons = append(buttons, Row(
|
||||
Button("✏️ Редактировать", "edit"),
|
||||
))
|
||||
|
||||
// Кнопка тега
|
||||
buttons = append(buttons, Row(
|
||||
Button(tagLabel, "toggle_tag"),
|
||||
))
|
||||
|
||||
// Кнопка закупа
|
||||
buttons = append(buttons, Row(
|
||||
Button(purchaseLabel, "purchase_creative"),
|
||||
))
|
||||
|
||||
// Кнопка назад
|
||||
buttons = append(buttons, Row(
|
||||
Button("← Назад", "back"),
|
||||
))
|
||||
|
||||
s.ShowControlPanel(b, msgCreativeView, buttons)
|
||||
}
|
||||
|
||||
// toggleTag переключает тег креатива (testing <-> production)
|
||||
func (s *CreativeView) toggleTag(b *bot.Bot) {
|
||||
newTag := "testing"
|
||||
if s.Tag != nil && *s.Tag == "testing" {
|
||||
newTag = "production"
|
||||
}
|
||||
|
||||
// Обновляем тег через backend
|
||||
input := backend.UpdateCreativeInput{
|
||||
Tag: &newTag,
|
||||
}
|
||||
|
||||
_, err := b.Backend.UpdateCreative(
|
||||
context.Background(),
|
||||
b.Session.JWT,
|
||||
b.Session.WorkspaceID,
|
||||
s.CreativeID,
|
||||
input,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("creative_id", s.CreativeID).Msg("Failed to update creative tag")
|
||||
s.ShowControlPanel(b, "<b>❌ Не удалось изменить тег</b>\n\nПопробуйте еще раз.", [][]echotron.InlineKeyboardButton{
|
||||
Row(Button("← Назад", "back")),
|
||||
Row(Button("↻ Попробовать снова", "toggle_tag")),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Обновляем локальное значение
|
||||
s.Tag = &newTag
|
||||
|
||||
// Показываем успех и обновляем панель
|
||||
tagText := "🧪 Тестовый"
|
||||
if newTag == "production" {
|
||||
tagText = "🚀 Рабочий"
|
||||
}
|
||||
b.SendNew(fmt.Sprintf("✅ Тег изменен на «%s»", tagText), Keyboard())
|
||||
|
||||
// Обновляем панель
|
||||
s.showActionPanel(b)
|
||||
}
|
||||
@@ -120,10 +120,16 @@ func (s *Creatives) HandleCallback(b *bot.Bot, u *echotron.Update) {
|
||||
return
|
||||
}
|
||||
|
||||
b.SetState(&CreativeDetails{
|
||||
// Открываем CreativeView вместо CreativeDetails
|
||||
b.SetState(&CreativeView{
|
||||
CreativeID: creativeID,
|
||||
ProjectID: s.ProjectID,
|
||||
BackState: s,
|
||||
// Данные проекта для передачи в AddPurchase
|
||||
ProjectTitle: s.ProjectTitle,
|
||||
ProjectTelegramID: s.ProjectTelegramID,
|
||||
ProjectUsername: s.ProjectUsername,
|
||||
ProjectStatus: s.ProjectStatus,
|
||||
BackState: s,
|
||||
}, bot.NewMessage)
|
||||
|
||||
default:
|
||||
|
||||
@@ -29,7 +29,7 @@ type Help struct{}
|
||||
|
||||
func (s *Help) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
keyboard := Keyboard(
|
||||
Row(URLButton("Поддержка", "https://example.com")),
|
||||
Row(URLButton("Поддержка", "https://t.me/SmartpostSupport")),
|
||||
Row(Button("↩ В главное меню", "main_menu")),
|
||||
)
|
||||
|
||||
|
||||
@@ -14,14 +14,22 @@ type MainMenu struct{}
|
||||
const msgAbout = `
|
||||
<i>Главное меню</i>
|
||||
|
||||
Smartpost — платформа для покупки и продажи рекламы без ЛС и ручных таблиц.
|
||||
<pre>
|
||||
За что отвечает каждая кнопка в этом окне:
|
||||
|
||||
• Внутренний счёт и безопасные сделки
|
||||
• Фиксация цен, дат и форматов
|
||||
• Автоматические отчёты
|
||||
• Повторные закупки в пару кликов
|
||||
<b>• Рабочее пространство</b> — Одно можно использовать для своих проектов, а другое, например, для проектов, где вы являетесь закупщиком.
|
||||
|
||||
Комиссия — 7%. Без скрытых платежей.
|
||||
<b>• Мои проекты</b> — Управляйте вашими телеграм-каналами: добавляйте новые, привязывайте к ним креативы, создавайте закупы.
|
||||
|
||||
<b>• Размещения</b> — Просматривайте статистику по всем сделанным размещениям или создавайте новые (бот автоматически сформирует для вас креатив и заменит в нём пригласительную ссылку).
|
||||
|
||||
<b>• Веб-платформа</b> — Используйте функционал нашего сервиса на все 100%: планируйте размещения, просматривайте аналитику, следите за показателями проектов.
|
||||
|
||||
<b>• Помощь</b> — Изучите инструкции, как пользоваться нашим сервисом или напишите в поддержку, если возникли какие-то вопросы.
|
||||
</pre>
|
||||
|
||||
Чтобы делать закупы, добавьте канал и креатив:
|
||||
<b>/addchannel</b> — новый канал
|
||||
`
|
||||
|
||||
func (s *MainMenu) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
@@ -65,8 +73,8 @@ func (s *MainMenu) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
|
||||
keyboard := Keyboard(
|
||||
Row(Button(fmt.Sprintf("Рабочее пространство: %s", workspaceName), "workspace_menu")),
|
||||
Row(Button("Мои проекты", "my_projects"), URLButton("Поддержка", "https://example.com")),
|
||||
Row(Button("Размещения", "placements"), URLButton("Дашборд", "https://example.com")),
|
||||
Row(Button("Мои проекты", "my_projects"), URLButton("Поддержка", "https://t.me/SmartpostSupport")),
|
||||
Row(Button("Размещения", "placements"), URLButton("Дашборд", fmt.Sprintf("https://app.smart-post.ru/dashboard/%s", b.Session.WorkspaceID))),
|
||||
)
|
||||
|
||||
b.Render(msg, keyboard, mode)
|
||||
|
||||
@@ -57,9 +57,9 @@ func (s *PlacementDetails) renderDetails(b *bot.Bot, mode bot.RenderMode) {
|
||||
// Тип ссылки
|
||||
text += fmt.Sprintf("🔓 <b>Тип ссылки:</b> %s\n", formatInviteLinkType(placement.InviteLinkType))
|
||||
|
||||
// Порядковый номер размещения
|
||||
if placement.PlacementNumber > 0 {
|
||||
text += fmt.Sprintf("🔢 <b>Размещение №%d</b> в этом канале\n", placement.PlacementNumber)
|
||||
// Short ID
|
||||
if placement.ShortID != "" {
|
||||
text += fmt.Sprintf("🔢 <b>ID:</b> %s\n", placement.ShortID)
|
||||
}
|
||||
|
||||
// Креатив
|
||||
@@ -242,15 +242,63 @@ func formatDateTime(value string) string {
|
||||
if value == "" {
|
||||
return value
|
||||
}
|
||||
if parsed, err := time.Parse(time.RFC3339, value); err == nil {
|
||||
return parsed.Format("02.01.2006 15:04")
|
||||
var parsed time.Time
|
||||
var err error
|
||||
|
||||
// Try parsing with timezone
|
||||
if parsed, err = time.Parse(time.RFC3339, value); err == nil {
|
||||
return formatCompactDateTime(parsed)
|
||||
}
|
||||
if parsed, err := time.Parse(time.RFC3339Nano, value); err == nil {
|
||||
return parsed.Format("02.01.2006 15:04")
|
||||
if parsed, err = time.Parse(time.RFC3339Nano, value); err == nil {
|
||||
return formatCompactDateTime(parsed)
|
||||
}
|
||||
if parsed, err = time.Parse("2006-01-02T15:04:05", value); err == nil {
|
||||
return formatCompactDateTime(parsed)
|
||||
}
|
||||
if parsed, err = time.Parse("2006-01-02", value); err == nil {
|
||||
return formatCompactDateTime(parsed)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func WeekdayName(day time.Weekday) string {
|
||||
switch day {
|
||||
case time.Monday:
|
||||
return "Пн"
|
||||
case time.Tuesday:
|
||||
return "Вт"
|
||||
case time.Wednesday:
|
||||
return "Ср"
|
||||
case time.Thursday:
|
||||
return "Чт"
|
||||
case time.Friday:
|
||||
return "Пт"
|
||||
case time.Saturday:
|
||||
return "Сб"
|
||||
case time.Sunday:
|
||||
return "Вс"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func MonthShort(month time.Month) string {
|
||||
months := []string{
|
||||
"янв", "фев", "мар", "апр", "май", "июн",
|
||||
"июл", "авг", "сен", "окт", "ноя", "дек",
|
||||
}
|
||||
if int(month) < 1 || int(month) > len(months) {
|
||||
return ""
|
||||
}
|
||||
return months[int(month)-1]
|
||||
}
|
||||
|
||||
func formatCompactDateTime(value time.Time) string {
|
||||
weekday := WeekdayName(value.Weekday())
|
||||
month := MonthShort(value.Month())
|
||||
return fmt.Sprintf("%s %02d %s %s", weekday, value.Day(), month, value.Format("15:04"))
|
||||
}
|
||||
|
||||
func (s *PlacementDetails) HandleCallback(b *bot.Bot, u *echotron.Update) {
|
||||
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
|
||||
return
|
||||
|
||||
@@ -30,7 +30,7 @@ func (s *Placements) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
|
||||
rows = append(rows, Row(Button("+ Создать размещение", "add_purchase")))
|
||||
rows = append(rows, Row(Button("Размещения", "placements_list")))
|
||||
rows = append(rows, Row(URLButton("План закупов", "https://example.com")))
|
||||
rows = append(rows, Row(URLButton("План закупов", fmt.Sprintf("https://app.smart-post.ru/dashboard/%s/purchase-plans/%s", b.Session.WorkspaceID, s.ProjectID))))
|
||||
rows = append(rows, Row(Button("← Назад", "back")))
|
||||
|
||||
keyboard := Keyboard(rows...)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package screens
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/NicoNex/echotron/v3"
|
||||
"github.com/TelegramExchange/tgex-backend/tg_bot/bot"
|
||||
)
|
||||
@@ -17,7 +19,7 @@ type PlatformLink struct{}
|
||||
|
||||
func (s *PlatformLink) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
keyboard := Keyboard(
|
||||
Row(URLButton("Открыть платформу", "https://example.com")),
|
||||
Row(URLButton("Открыть платформу", fmt.Sprintf("https://app.smart-post.ru/dashboard/%s", b.Session.WorkspaceID))),
|
||||
Row(Button("↩ В главное меню", "main_menu")),
|
||||
)
|
||||
|
||||
|
||||
@@ -111,12 +111,6 @@ func (s *PurchaseOptionalDetails) Enter(b *bot.Bot, mode bot.RenderMode) {
|
||||
s.inviteLinkTypeButton(),
|
||||
))
|
||||
|
||||
if row := s.costBeforeDeleteRow(); row != nil {
|
||||
rows = append(rows, row)
|
||||
}
|
||||
if row := s.commentDeleteRow(); row != nil {
|
||||
rows = append(rows, row)
|
||||
}
|
||||
rows = append(rows, Row(Button("Назад", "back"), Button("Далее", "next")))
|
||||
|
||||
keyboard := Keyboard(rows...)
|
||||
@@ -683,10 +677,21 @@ func (s *PurchaseOptionalDetails) renderInputPrompt(b *bot.Bot, mode bot.RenderM
|
||||
}
|
||||
|
||||
typeLabel := s.costBeforeTypeLabelForCurrent()
|
||||
keyboard := Keyboard(
|
||||
Row(Button(fmt.Sprintf("Тип: %s", typeLabel), "cost_before_type_toggle")),
|
||||
Row(Button("← Назад", s.backAction())),
|
||||
)
|
||||
var keyboard echotron.InlineKeyboardMarkup
|
||||
|
||||
// Показываем кнопку удаления только если есть значение и это не режим per-channel
|
||||
if s.CurrentChannel == "" && s.CostBeforeBargain != nil && s.CostBeforeBargain.Value != nil {
|
||||
keyboard = Keyboard(
|
||||
Row(Button(fmt.Sprintf("Тип: %s", typeLabel), "cost_before_type_toggle")),
|
||||
Row(Button("⌫ Удалить до торга", "delete_cost_before")),
|
||||
Row(Button("← Назад", s.backAction())),
|
||||
)
|
||||
} else {
|
||||
keyboard = Keyboard(
|
||||
Row(Button(fmt.Sprintf("Тип: %s", typeLabel), "cost_before_type_toggle")),
|
||||
Row(Button("← Назад", s.backAction())),
|
||||
)
|
||||
}
|
||||
|
||||
if mode == bot.EditMessage {
|
||||
b.Edit(text, keyboard)
|
||||
@@ -750,6 +755,19 @@ func (s *PurchaseOptionalDetails) renderInputPrompt(b *bot.Bot, mode bot.RenderM
|
||||
return
|
||||
case "comment":
|
||||
text += "<b>Введите комментарий</b>"
|
||||
keyboard := Keyboard(Row(Button("← Назад", s.backAction())))
|
||||
if s.Comment != "" {
|
||||
keyboard = Keyboard(
|
||||
Row(Button("⌫ Удалить комментарий", "delete_comment")),
|
||||
Row(Button("← Назад", s.backAction())),
|
||||
)
|
||||
}
|
||||
if mode == bot.EditMessage {
|
||||
b.Edit(text, keyboard)
|
||||
} else {
|
||||
b.SendNew(text, keyboard)
|
||||
}
|
||||
return
|
||||
default:
|
||||
s.InputMode = ""
|
||||
s.Enter(b, mode)
|
||||
|
||||
Reference in New Issue
Block a user