All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 5s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Run Tests (pull_request) Successful in 3s
BCards Deployment Pipeline / Build and Push Image (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (pull_request) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (pull_request) Has been skipped
BCards Deployment Pipeline / PR Validation (pull_request) Successful in 0s
BCards Deployment Pipeline / Deployment Summary (pull_request) Successful in 0s
BCards Deployment Pipeline / Build and Push Image (push) Successful in 19m44s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (push) Successful in 22s
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 0s
189 lines
7.2 KiB
C#
189 lines
7.2 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using BCards.Web.Models;
|
|
|
|
namespace BCards.Web.ViewModels;
|
|
|
|
public class ManagePageViewModel
|
|
{
|
|
public string Id { get; set; } = string.Empty;
|
|
public bool IsNewPage { get; set; } = true;
|
|
|
|
[Required(ErrorMessage = "Nome é obrigatório")]
|
|
[StringLength(50, ErrorMessage = "Nome deve ter no máximo 50 caracteres")]
|
|
public string DisplayName { get; set; } = string.Empty;
|
|
|
|
[Required(ErrorMessage = "Categoria é obrigatória")]
|
|
public string Category { get; set; } = string.Empty;
|
|
|
|
[Required(ErrorMessage = "Tipo de negócio é obrigatório")]
|
|
public string BusinessType { get; set; } = "individual";
|
|
|
|
[StringLength(200, ErrorMessage = "Bio deve ter no máximo 200 caracteres")]
|
|
public string Bio { get; set; } = string.Empty;
|
|
|
|
public string Slug { get; set; } = string.Empty;
|
|
|
|
[Required(ErrorMessage = "Tema é obrigatório")]
|
|
public string SelectedTheme { get; set; } = "minimalist";
|
|
|
|
public string WhatsAppNumber { get; set; } = string.Empty;
|
|
|
|
public string FacebookUrl { get; set; } = string.Empty;
|
|
|
|
public string TwitterUrl { get; set; } = string.Empty;
|
|
|
|
public string InstagramUrl { get; set; } = string.Empty;
|
|
|
|
public string TiktokUrl { get; set; } = string.Empty;
|
|
|
|
public string PinterestUrl { get; set; } = string.Empty;
|
|
|
|
public string DiscordUrl { get; set; } = string.Empty;
|
|
|
|
public string KawaiUrl { get; set; } = string.Empty;
|
|
|
|
public List<ManageLinkViewModel> Links { get; set; } = new();
|
|
|
|
// Profile image fields
|
|
public string? ProfileImageId { get; set; }
|
|
public IFormFile? ProfileImageFile { get; set; }
|
|
|
|
// Data for dropdowns and selections
|
|
public List<Category> AvailableCategories { get; set; } = new();
|
|
public List<PageTheme> AvailableThemes { get; set; } = new();
|
|
|
|
// Plan limitations
|
|
public int MaxLinksAllowed { get; set; } = 3;
|
|
public bool AllowProductLinks { get; set; } = false;
|
|
public bool CanUseTheme(string themeName) => AvailableThemes.Any(t => t.Name.ToLower() == themeName.ToLower());
|
|
|
|
/// <summary>
|
|
/// URL da imagem de perfil ou imagem padrão se não houver upload
|
|
/// </summary>
|
|
public string ProfileImageUrl => !string.IsNullOrEmpty(ProfileImageId)
|
|
? $"/api/image/{ProfileImageId}"
|
|
: "/images/default-avatar.svg";
|
|
}
|
|
|
|
public class ManageLinkViewModel
|
|
{
|
|
public string Id { get; set; } = "new";
|
|
|
|
[Required(ErrorMessage = "Título é obrigatório")]
|
|
[StringLength(200, ErrorMessage = "Título deve ter no máximo 50 caracteres")]
|
|
public string Title { get; set; } = string.Empty;
|
|
|
|
[Required(ErrorMessage = "URL é obrigatória")]
|
|
[Url(ErrorMessage = "URL inválida")]
|
|
public string Url { get; set; } = string.Empty;
|
|
|
|
[StringLength(3000, ErrorMessage = "Descrição deve ter no máximo 100 caracteres")]
|
|
public string Description { get; set; } = string.Empty;
|
|
|
|
public string Icon { get; set; } = string.Empty;
|
|
public int Order { get; set; } = 0;
|
|
public bool IsActive { get; set; } = true;
|
|
|
|
// Campos para Links de Produto
|
|
public LinkType Type { get; set; } = LinkType.Normal;
|
|
|
|
[StringLength(200, ErrorMessage = "Título do produto deve ter no máximo 100 caracteres")]
|
|
public string ProductTitle { get; set; } = string.Empty;
|
|
|
|
public string ProductImage { get; set; } = string.Empty;
|
|
|
|
[StringLength(50, ErrorMessage = "Preço deve ter no máximo 50 caracteres")]
|
|
public string? ProductPrice { get; set; } = string.Empty;
|
|
|
|
[StringLength(3000, ErrorMessage = "Descrição do produto deve ter no máximo 200 caracteres")]
|
|
public string ProductDescription { get; set; } = string.Empty;
|
|
|
|
public DateTime? ProductDataCachedAt { get; set; }
|
|
}
|
|
|
|
public class DashboardViewModel
|
|
{
|
|
public User CurrentUser { get; set; } = new();
|
|
public List<UserPageSummary> UserPages { get; set; } = new();
|
|
public PlanInfo CurrentPlan { get; set; } = new();
|
|
public bool CanCreateNewPage { get; set; } = false;
|
|
public int DaysRemaining { get; set; } = 0;
|
|
}
|
|
|
|
public class UserPageSummary
|
|
{
|
|
public string Id { get; set; } = string.Empty;
|
|
public string DisplayName { get; set; } = string.Empty;
|
|
public string Slug { get; set; } = string.Empty;
|
|
public string Category { get; set; } = string.Empty;
|
|
public PageStatus Status { get; set; } = PageStatus.Active;
|
|
public long TotalClicks { get; set; } = 0;
|
|
public long TotalViews { get; set; } = 0;
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
public string? PreviewToken { get; set; } = string.Empty;
|
|
public string PublicUrl => $"/page/{Category.ToLower()}/{Slug.ToLower()}?preview={PreviewToken}";
|
|
public PageStatus? LastModerationStatus { get; set; } = PageStatus.PendingModeration;
|
|
public string? Motive { get; set; } = string.Empty;
|
|
}
|
|
|
|
public class PlanInfo
|
|
{
|
|
public PlanType Type { get; set; } = PlanType.Trial;
|
|
public string Name { get; set; } = string.Empty;
|
|
public int MaxPages { get; set; } = 1;
|
|
public int MaxLinksPerPage { get; set; } = 3;
|
|
public int DurationDays { get; set; } = 7;
|
|
public decimal Price { get; set; } = 0;
|
|
public bool AllowsAnalytics { get; set; } = false;
|
|
public bool AllowsCustomThemes { get; set; } = false;
|
|
}
|
|
|
|
public enum PageStatus
|
|
{
|
|
Active, // Funcionando normalmente
|
|
Expired, // Trial vencido -> 301 redirect
|
|
PendingPayment, // Pagamento atrasado -> aviso na página
|
|
Inactive, // Pausada pelo usuário
|
|
PendingModeration = 4, // Aguardando moderação
|
|
Rejected = 5, // Rejeitada na moderação
|
|
Creating = 6, // Em desenvolvimento/criação
|
|
Approved = 7, // Aprovada
|
|
SuspendedByPlanLimit = 8 // Suspensa por limite de plano (downgrade)
|
|
}
|
|
|
|
// Modelos para análise de downgrade
|
|
public class DowngradeAnalysis
|
|
{
|
|
public List<PageInfo> EligiblePages { get; set; } = new();
|
|
public List<PageInfo> AffectedPages { get; set; } = new();
|
|
public List<string> Issues { get; set; } = new();
|
|
public bool IsCritical => EligiblePages.Count == 0;
|
|
public string Summary => $"{EligiblePages.Count} mantidas, {AffectedPages.Count} suspensas";
|
|
}
|
|
|
|
public class PageInfo
|
|
{
|
|
public string Id { get; set; } = string.Empty;
|
|
public string DisplayName { get; set; } = string.Empty;
|
|
public int LinkCount { get; set; }
|
|
public DateTime CreatedAt { get; set; }
|
|
public string SuspensionReason { get; set; } = string.Empty;
|
|
}
|
|
|
|
public class DowngradeResult
|
|
{
|
|
public bool Success { get; set; }
|
|
public int KeptActive { get; set; }
|
|
public int Suspended { get; set; }
|
|
public string Message { get; set; } = string.Empty;
|
|
public List<string> Details { get; set; } = new();
|
|
}
|
|
|
|
public class DowngradeCriteria
|
|
{
|
|
public int MaxPages { get; set; }
|
|
public int MaxLinksPerPage { get; set; }
|
|
public string MaxLinksDisplay => MaxLinksPerPage == -1 ? "Ilimitado" : MaxLinksPerPage.ToString();
|
|
public string SelectionCriteria { get; set; } = "Páginas mais antigas têm prioridade";
|
|
public string LinksCriteria { get; set; } = "Páginas com muitos links são automaticamente suspensas";
|
|
} |