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 Links { get; set; } = new(); // Profile image fields public string? ProfileImageId { get; set; } public IFormFile? ProfileImageFile { get; set; } // Data for dropdowns and selections public List AvailableCategories { get; set; } = new(); public List 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()); /// /// URL da imagem de perfil ou imagem padrão se não houver upload /// 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 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 EligiblePages { get; set; } = new(); public List AffectedPages { get; set; } = new(); public List 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 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"; }