Files
tgex-backend/tg_bot/screens/placement_details.go
Artem Tsyrulnikov a90c8b7df6 refactor
2026-01-19 16:47:52 +03:00

201 lines
5.6 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"
"time"
"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 PlacementDetails struct {
WorkspaceID string
ProjectID string
PlacementID string
BackState bot.State
}
func (s *PlacementDetails) Enter(b *bot.Bot, mode bot.RenderMode) {
jwt := b.Session.JWT
if jwt == "" {
log.Error().Msg("JWT is empty in session")
b.SendNew("❌ Ошибка авторизации. Попробуйте /start", Keyboard())
return
}
s.renderDetails(b, mode, jwt)
}
func (s *PlacementDetails) renderDetails(b *bot.Bot, mode bot.RenderMode, jwt string) {
placement, err := b.Backend.GetPlacement(
context.Background(),
jwt,
s.WorkspaceID,
s.ProjectID,
s.PlacementID,
)
if err != nil {
log.Error().Err(err).Msg("Failed to get placement")
b.SendNew("❌ Не удалось загрузить размещение", Keyboard())
return
}
var placementPost *backend.PlacementPostOutput
if len(placement.PlacementPosts) > 0 {
placementPost = &placement.PlacementPosts[0]
}
text := "<b>Детали размещения</b>\n\n"
channelName := formatChannelName(placement.Channel)
text += fmt.Sprintf("• <b>Канал:</b> %s\n", channelName)
text += fmt.Sprintf("• <b>Статус:</b> %s\n", formatPlacementStatus(placement.Status))
text += fmt.Sprintf("• <b>Ссылка:</b> %s\n", formatInviteLinkType(placement.InviteLinkType))
if placement.Details != nil {
if placement.Details.PlacementType != nil {
text += fmt.Sprintf("• <b>Тип:</b> %s\n", formatPlacementType(*placement.Details.PlacementType))
}
if placement.Details.PlacementAt != nil && *placement.Details.PlacementAt != "" {
text += fmt.Sprintf("• <b>Дата размещения:</b> %s\n", formatDateTime(*placement.Details.PlacementAt))
}
if placement.Details.PaymentAt != nil && *placement.Details.PaymentAt != "" {
text += fmt.Sprintf("• <b>Дата оплаты:</b> %s\n", formatDateTime(*placement.Details.PaymentAt))
}
if placement.Details.Cost != nil {
text += fmt.Sprintf("• <b>Стоимость:</b> %s %.0f₽\n",
formatCostType(placement.Details.Cost.Type),
placement.Details.Cost.Value,
)
}
if placement.Details.CostBeforeBargain != nil {
text += fmt.Sprintf("• <b>До торга:</b> %.0f₽\n", *placement.Details.CostBeforeBargain)
}
if placement.Details.Format != nil && *placement.Details.Format != "" {
text += fmt.Sprintf("• <b>Формат:</b> %s\n", *placement.Details.Format)
}
if placement.Details.Comment != nil && *placement.Details.Comment != "" {
text += fmt.Sprintf("• <b>Комментарий:</b> %s\n", *placement.Details.Comment)
}
}
if placementPost != nil {
text += "\n<b>Пост</b>\n"
if placementPost.AdPostURL != nil && *placementPost.AdPostURL != "" {
text += fmt.Sprintf("• <b>Ссылка на пост:</b> %s\n", *placementPost.AdPostURL)
} else {
text += "• <b>Ссылка на пост:</b> не найдена\n"
}
text += fmt.Sprintf("• <b>Статус поста:</b> %s\n", formatPlacementPostStatus(placementPost.Status))
}
keyboard := Keyboard(Row(Button("← Назад", "back")))
b.Render(text, keyboard, mode)
}
func formatChannelName(channel backend.Channel) string {
if channel.Title != nil && *channel.Title != "" {
return *channel.Title
}
if channel.Username != nil && *channel.Username != "" {
return "@" + *channel.Username
}
return "Без названия"
}
func formatInviteLinkType(value string) string {
if value == "approval" {
return "с одобрением"
}
return "публичная"
}
func formatPlacementStatus(status string) string {
normalized := strings.TrimSpace(strings.ToLower(status))
switch normalized {
case "planned":
return "Планируется"
case "approved":
return "Согласовано"
case "rejected":
return "Отклонено"
case "in_progress":
return "В работе"
case "completed":
return "Размещено"
default:
return status
}
}
func formatPlacementType(value string) string {
normalized := strings.TrimSpace(strings.ToLower(value))
switch normalized {
case "self_promo":
return "Самопиар"
case "standard":
return "Стандарт"
default:
return value
}
}
func formatPlacementPostStatus(status string) string {
normalized := strings.TrimSpace(strings.ToLower(status))
switch normalized {
case "active":
return "Активен"
case "archived":
return "Архивирован"
default:
return status
}
}
func formatCostType(value string) string {
switch strings.TrimSpace(strings.ToLower(value)) {
case "cpm":
return "СРМ"
default:
return "Фикс"
}
}
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")
}
if parsed, err := time.Parse(time.RFC3339Nano, value); err == nil {
return parsed.Format("02.01.2006 15:04")
}
return value
}
func (s *PlacementDetails) HandleCallback(b *bot.Bot, u *echotron.Update) {
if u.CallbackQuery == nil || u.CallbackQuery.Data == "" {
return
}
switch u.CallbackQuery.Data {
case "back":
if s.BackState != nil {
b.SetState(s.BackState, bot.EditMessage)
}
default:
s.Enter(b, bot.NewMessage)
}
}
func (s *PlacementDetails) HandleMessage(_ *bot.Bot, _ *echotron.Update) { return }
func (s *PlacementDetails) Handle(_ *bot.Bot, _ *echotron.Update) { return }
func (s *PlacementDetails) Exit() {}