Compare commits
No commits in common. "7cc8f46a1a912c01f3f17c51a09a8542c1ca9e6f" and "ce705c51ec83c2d7cd7dd746bd47426dbe7b2c7f" have entirely different histories.
7cc8f46a1a
...
ce705c51ec
@ -8,7 +8,7 @@ public class SeoService : ISeoService
|
|||||||
|
|
||||||
public SeoService(IConfiguration configuration)
|
public SeoService(IConfiguration configuration)
|
||||||
{
|
{
|
||||||
_baseUrl = configuration["BaseUrl"] ?? "https://bcards.site";
|
_baseUrl = configuration["BaseUrl"] ?? "https://vcart.me";
|
||||||
}
|
}
|
||||||
|
|
||||||
public SeoSettings GenerateSeoSettings(UserPage userPage, Category category)
|
public SeoSettings GenerateSeoSettings(UserPage userPage, Category category)
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Dashboard - BCards";
|
ViewData["Title"] = "Dashboard - BCards";
|
||||||
Layout = "_Layout";
|
Layout = "_Layout";
|
||||||
var pageInCreation = Model.UserPages.FirstOrDefault(p => (p.LastModerationStatus ?? p.Status) == BCards.Web.ViewModels.PageStatus.Creating);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="container py-4">
|
<div class="container py-4">
|
||||||
@ -16,33 +15,12 @@
|
|||||||
<div>
|
<div>
|
||||||
@if (!string.IsNullOrEmpty(Model.CurrentUser.ProfileImage))
|
@if (!string.IsNullOrEmpty(Model.CurrentUser.ProfileImage))
|
||||||
{
|
{
|
||||||
<img src="@Model.CurrentUser.ProfileImage" alt="@Model.CurrentUser.Name"
|
<img src="@Model.CurrentUser.ProfileImage" alt="@Model.CurrentUser.Name"
|
||||||
class="rounded-circle" style="width: 60px; height: 60px; object-fit: cover;">
|
class="rounded-circle" style="width: 60px; height: 60px; object-fit: cover;">
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Acordeão de Instruções -->
|
|
||||||
@if (pageInCreation != null)
|
|
||||||
{
|
|
||||||
<div class="accordion mb-4" id="instructionsAccordion">
|
|
||||||
<div class="accordion-item border-0" style="background-color: #e9ecef;">
|
|
||||||
<h2 class="accordion-header" id="instructions-heading">
|
|
||||||
<button class="accordion-button collapsed fw-bold" type="button" data-bs-toggle="collapse" data-bs-target="#instructions-collapse" aria-expanded="false" aria-controls="instructions-collapse" style="background-color: #e0e5e9;">
|
|
||||||
<i class="fas fa-info-circle me-2"></i>Página em criação! Veja como continuar
|
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div id="instructions-collapse" class="accordion-collapse collapse" aria-labelledby="instructions-heading">
|
|
||||||
<div class="accordion-body">
|
|
||||||
Você pode editar e testar sua página <b>"@pageInCreation.DisplayName"</b> quantas vezes quiser.
|
|
||||||
Ao terminar, use os botões no card da página para enviá-la para moderação.
|
|
||||||
<br><small class="text-muted">Dica: Ao segurar o dedo sobre um botão, uma dica será exibida.</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<!-- Lista de Páginas -->
|
<!-- Lista de Páginas -->
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@foreach (var pageItem in Model.UserPages)
|
@foreach (var pageItem in Model.UserPages)
|
||||||
@ -54,35 +32,53 @@
|
|||||||
@(pageItem.DisplayName)
|
@(pageItem.DisplayName)
|
||||||
<form method="post" action="/Admin/DeletePage/@(pageItem.Id)" style="display: inline;" onsubmit="return confirm('Tem certeza que deseja excluir esta página?')">
|
<form method="post" action="/Admin/DeletePage/@(pageItem.Id)" style="display: inline;" onsubmit="return confirm('Tem certeza que deseja excluir esta página?')">
|
||||||
@Html.AntiForgeryToken()
|
@Html.AntiForgeryToken()
|
||||||
<button type="submit" class="btn btn-link text-danger p-0" title="Excluir página"
|
<button type="submit" class="btn btn-link text-danger p-0" title="Excluir página"
|
||||||
style="font-size: 12px; text-decoration: none;">
|
style="font-size: 12px; text-decoration: none;">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
<input type="hidden" id="displayName_@pageItem.Id" value="@(pageItem.DisplayName)" />
|
||||||
</h6>
|
</h6>
|
||||||
<p class="text-muted small mb-2">@(pageItem.Category)/@(pageItem.Slug)</p>
|
<p class="text-muted small mb-2">@(pageItem.Category)/@(pageItem.Slug)</p>
|
||||||
|
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
@switch (pageItem.LastModerationStatus ?? pageItem.Status)
|
@{
|
||||||
|
var pageStatus = pageItem.Status;
|
||||||
|
if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Inactive)
|
||||||
|
{
|
||||||
|
if (pageItem.LastModerationStatus.HasValue)
|
||||||
|
{
|
||||||
|
pageStatus = pageItem.LastModerationStatus.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@switch (pageStatus)
|
||||||
{
|
{
|
||||||
case BCards.Web.ViewModels.PageStatus.Active:
|
case BCards.Web.ViewModels.PageStatus.Active:
|
||||||
<span class="badge bg-success">Ativa</span>
|
<span class="badge bg-success">Ativa</span>
|
||||||
break;
|
break;
|
||||||
|
case BCards.Web.ViewModels.PageStatus.Expired:
|
||||||
|
<span class="badge bg-danger">Expirada</span>
|
||||||
|
break;
|
||||||
|
case BCards.Web.ViewModels.PageStatus.PendingPayment:
|
||||||
|
<span class="badge bg-warning">Pagamento Pendente</span>
|
||||||
|
break;
|
||||||
|
case BCards.Web.ViewModels.PageStatus.Inactive:
|
||||||
|
<span class="badge bg-secondary">Inativa</span>
|
||||||
|
break;
|
||||||
case BCards.Web.ViewModels.PageStatus.PendingModeration:
|
case BCards.Web.ViewModels.PageStatus.PendingModeration:
|
||||||
<span class="badge bg-warning">Aguardando Moderação</span>
|
<span class="badge bg-warning">Aguardando</span>
|
||||||
break;
|
break;
|
||||||
case BCards.Web.ViewModels.PageStatus.Rejected:
|
case BCards.Web.ViewModels.PageStatus.Rejected:
|
||||||
<span class="badge bg-danger">Rejeitada</span>
|
<span class="badge bg-danger">Rejeitada</span>
|
||||||
break;
|
break;
|
||||||
case BCards.Web.ViewModels.PageStatus.Creating:
|
case BCards.Web.ViewModels.PageStatus.Creating:
|
||||||
<span class="badge bg-info"><i class="fas fa-edit me-1"></i>Em Criação</span>
|
<span class="badge bg-info">
|
||||||
break;
|
<i class="fas fa-edit me-1"></i>Criando
|
||||||
default:
|
</span>
|
||||||
<span class="badge bg-secondary">@pageItem.Status</span>
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (Model.CurrentPlan.AllowsAnalytics)
|
@if (Model.CurrentPlan.AllowsAnalytics)
|
||||||
{
|
{
|
||||||
<div class="row text-center small mb-3">
|
<div class="row text-center small mb-3">
|
||||||
@ -96,51 +92,151 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Cards com Hover Effect -->
|
||||||
<div class="card-footer" data-page-id="@pageItem.Id" data-status="@pageItem.Status">
|
<div class="card-footer" data-page-id="@pageItem.Id" data-status="@pageItem.Status">
|
||||||
<div class="d-grid gap-2">
|
<div class="d-flex gap-2">
|
||||||
@if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Active)
|
@if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Active)
|
||||||
{
|
{
|
||||||
<a href="/page/@pageItem.Category/@pageItem.Slug" target="_blank" class="btn btn-success">
|
<a href="/page/@pageItem.Category/@pageItem.Slug" target="_blank"
|
||||||
<i class="fas fa-eye me-1"></i>Ver Página Publicada
|
class="btn btn-success flex-fill">
|
||||||
</a>
|
<i class="fas fa-eye me-1"></i>Ver Página
|
||||||
<a href="@Url.Action("ManagePage", new { id = pageItem.Id })" class="btn btn-primary" data-bs-toggle="tooltip" title="Ir para o editor da página">
|
|
||||||
<i class="fas fa-edit me-1"></i>Editar
|
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
else if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Creating || pageItem.Status == BCards.Web.ViewModels.PageStatus.Rejected)
|
else if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Creating ||
|
||||||
|
pageItem.Status == BCards.Web.ViewModels.PageStatus.Rejected ||
|
||||||
|
pageItem.Status == BCards.Web.ViewModels.PageStatus.PendingModeration)
|
||||||
{
|
{
|
||||||
<button type="button" class="btn btn-outline-info" onclick="openPreview('@pageItem.Id')" data-page-category="@pageItem.Category" data-page-slug="@pageItem.Slug" data-bs-toggle="tooltip" title="Pré-visualizar a página antes da publicação">
|
<button type="button"
|
||||||
|
class="btn btn-outline-info flex-fill"
|
||||||
|
onclick="openPreview('@pageItem.Id')"
|
||||||
|
data-page-category="@pageItem.Category"
|
||||||
|
data-page-slug="@pageItem.Slug">
|
||||||
<i class="fas fa-vial me-1"></i>Testar Página
|
<i class="fas fa-vial me-1"></i>Testar Página
|
||||||
</button>
|
</button>
|
||||||
<a href="@Url.Action("ManagePage", new { id = pageItem.Id })" class="btn btn-primary" data-bs-toggle="tooltip" title="Ir para o editor da página">
|
|
||||||
<i class="fas fa-edit me-1"></i>Editar
|
|
||||||
</a>
|
|
||||||
<button type="button" class="btn btn-outline-info" onclick="submitForModeration('@pageItem.Id')" data-page-name="@pageItem.DisplayName" data-bs-toggle="tooltip" title="Enviar a página para revisão e aprovação">
|
|
||||||
<i class="fas fa-paper-plane"></i> Enviar para Moderação
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
else if (pageItem.Status == BCards.Web.ViewModels.PageStatus.PendingModeration)
|
|
||||||
{
|
|
||||||
<button type="button" class="btn btn-outline-info" onclick="openPreview('@pageItem.Id')" data-page-category="@pageItem.Category" data-page-slug="@pageItem.Slug" data-bs-toggle="tooltip" title="Pré-visualizar a página antes da publicação">
|
|
||||||
<i class="fas fa-vial me-1"></i>Testar Página
|
|
||||||
</button>
|
|
||||||
<button class="btn btn-secondary" disabled data-bs-toggle="tooltip" title="A página está em revisão e não pode ser editada ou enviada novamente.">
|
|
||||||
<i class="fas fa-hourglass-half me-1"></i>Aguardando Moderação
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<button class="btn btn-secondary" disabled>
|
<button class="btn btn-secondary flex-fill" disabled>
|
||||||
<i class="fas fa-ban me-1"></i>Indisponível
|
<i class="fas fa-ban me-1"></i>Indisponível
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-outline-secondary dropdown-toggle"
|
||||||
|
type="button"
|
||||||
|
id="dropdownMenuButton@(pageItem.Id)"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-expanded="false"
|
||||||
|
title="Mais opções">
|
||||||
|
<i class="fas fa-cog"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="dropdownMenuButton@(pageItem.Id)">
|
||||||
|
<!-- Editar - sempre presente -->
|
||||||
|
@if (pageItem.Status == BCards.Web.ViewModels.PageStatus.PendingModeration)
|
||||||
|
{
|
||||||
|
<li>
|
||||||
|
<span class="dropdown-item disabled">
|
||||||
|
<i class="fas fa-edit me-2"></i>Editar
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<li>
|
||||||
|
<a href="@Url.Action("ManagePage", new { id = pageItem.Id })"
|
||||||
|
class="dropdown-item">
|
||||||
|
<i class="fas fa-edit me-2"></i>Editar
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (pageItem.Status == BCards.Web.ViewModels.PageStatus.Creating ||
|
||||||
|
pageItem.Status == BCards.Web.ViewModels.PageStatus.Rejected)
|
||||||
|
{
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li>
|
||||||
|
<button type="button"
|
||||||
|
class="dropdown-item"
|
||||||
|
onclick="submitForModeration('@pageItem.Id')"
|
||||||
|
data-page-name="@pageItem.DisplayName">
|
||||||
|
<i class="fas fa-paper-plane me-2"></i>Enviar para Moderação
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
else if (pageItem.Status == BCards.Web.ViewModels.PageStatus.PendingModeration)
|
||||||
|
{
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
|
<li>
|
||||||
|
<span class="dropdown-item disabled">
|
||||||
|
<i class="fas fa-hourglass-half me-2"></i>Aguardando Moderação
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Informações da página movidas para baixo dos botões -->
|
||||||
|
<div class="px-3 pt-2 pb-1">
|
||||||
|
<small class="text-muted">Criada em @(pageItem.CreatedAt.ToString("dd/MM/yyyy"))</small>
|
||||||
|
|
||||||
|
@if ((pageItem.LastModerationStatus ?? pageItem.Status) == BCards.Web.ViewModels.PageStatus.Rejected && !string.IsNullOrEmpty(pageItem.Motive))
|
||||||
|
{
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show mt-2 mb-0" role="alert">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
<i class="fas fa-exclamation-triangle me-2 mt-1"></i>
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<strong>Motivo da rejeição:</strong><br>
|
||||||
|
<small>@(pageItem.Motive)</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else if (pageItem.LastModerationStatus == BCards.Web.ViewModels.PageStatus.Active && !string.IsNullOrEmpty(pageItem.Motive))
|
||||||
|
{
|
||||||
|
<div class="alert alert-info alert-dismissible fade show mt-2 mb-0" role="alert">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
<i class="fas fa-exclamation-triangle me-2 mt-1"></i>
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<strong>Motivo:</strong><br>
|
||||||
|
<small>@(pageItem.Motive)</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@if ((pageItem.LastModerationStatus ?? pageItem.Status) == BCards.Web.ViewModels.PageStatus.Creating)
|
||||||
|
{
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-secondary d-flex align-items-center alert-dismissible alert-permanent fade show">
|
||||||
|
<i class="fas fa-exclamation-triangle me-3"></i>
|
||||||
|
<div>
|
||||||
|
<strong>Página em criação!</strong>
|
||||||
|
Você pode editar e testar quantas vezes quiser. <br />
|
||||||
|
Ao terminar, clique em <i class="fas fa-ellipsis-v"></i> para enviar a página <b><span id="pageNameDisplay"></span></b> para moderação!
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var pageNameDisplay = document.getElementById('pageNameDisplay');
|
||||||
|
var displayName = document.getElementById('displayName_@pageItem.Id');
|
||||||
|
pageNameDisplay.innerHTML = displayName.value;
|
||||||
|
</script>
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
<!-- Card para Criar Nova Página -->
|
<!-- Card para Criar Nova Página -->
|
||||||
@if (Model.CanCreateNewPage)
|
@if (Model.CanCreateNewPage)
|
||||||
{
|
{
|
||||||
@ -150,7 +246,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<i class="fas fa-plus fa-2x text-muted mb-3"></i>
|
<i class="fas fa-plus fa-2x text-muted mb-3"></i>
|
||||||
<h6 class="text-muted">Criar Nova Página</h6>
|
<h6 class="text-muted">Criar Nova Página</h6>
|
||||||
<a href="@Url.Action("ManagePage", new { id = "new" })" class="btn btn-primary">Começar</a>
|
<a href="@Url.Action("ManagePage", new { id = "new" })"
|
||||||
|
class="btn btn-primary">Começar</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -158,89 +255,121 @@
|
|||||||
}
|
}
|
||||||
else if (!Model.UserPages.Any())
|
else if (!Model.UserPages.Any())
|
||||||
{
|
{
|
||||||
|
<!-- Primeira Página -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card border-primary">
|
<div class="card border-primary">
|
||||||
<div class="card-body text-center p-5">
|
<div class="card-body text-center p-5">
|
||||||
<div class="mb-4"><i class="display-1 text-primary">🚀</i></div>
|
<div class="mb-4">
|
||||||
|
<i class="display-1 text-primary">🚀</i>
|
||||||
|
</div>
|
||||||
<h3>Crie sua primeira página!</h3>
|
<h3>Crie sua primeira página!</h3>
|
||||||
<p class="text-muted mb-4">Comece criando sua página profissional personalizada com seus links organizados.</p>
|
<p class="text-muted mb-4">
|
||||||
<a href="@Url.Action("ManagePage", new { id = "new" })" class="btn btn-primary btn-lg">Criar Minha Página</a>
|
Comece criando sua página profissional personalizada com seus links organizados.
|
||||||
|
</p>
|
||||||
|
<a href="@Url.Action("ManagePage", new { id = "new" })" class="btn btn-primary btn-lg">
|
||||||
|
Criar Minha Página
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
<!-- Limite atingido -->
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="alert alert-warning d-flex align-items-center alert-permanent">
|
<div class="alert alert-warning d-flex align-items-center alert-permanent">
|
||||||
<i class="fas fa-exclamation-triangle me-3"></i>
|
<i class="fas fa-exclamation-triangle me-3"></i>
|
||||||
<div>
|
<div>
|
||||||
<strong>Limite atingido!</strong> Você já criou o máximo de @Model.CurrentPlan.MaxPages página(s) para seu plano atual.
|
<strong>Limite atingido!</strong>
|
||||||
|
Você já criou o máximo de @Model.CurrentPlan.MaxPages página(s) para seu plano atual.
|
||||||
<a href="@Url.Action("Pricing", "Home")" class="alert-link ms-2">Fazer upgrade</a>
|
<a href="@Url.Action("Pricing", "Home")" class="alert-link ms-2">Fazer upgrade</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<!-- Painel de Plano Atual como Acordeão -->
|
<!-- Plano Atual -->
|
||||||
<div class="accordion" id="planAccordion">
|
<div class="card mb-4 @(Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial ? "border-warning" : "")">
|
||||||
<div class="card mb-4 @(Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial ? "border-warning" : "")">
|
<div class="card-header @(Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial ? "bg-warning" : "bg-primary") text-white">
|
||||||
<div class="card-header @(Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial ? "bg-warning" : "bg-primary") text-white">
|
<h6 class="mb-0">
|
||||||
<h2 class="mb-0">
|
<i class="fas fa-crown me-2"></i>
|
||||||
<button class="btn btn-link text-white text-decoration-none w-100 d-flex justify-content-between align-items-center p-0" type="button" data-bs-toggle="collapse" data-bs-target="#plan-collapse" aria-expanded="true" aria-controls="plan-collapse">
|
Plano Atual
|
||||||
<span><i class="fas fa-crown me-2"></i>Plano Atual</span>
|
</h6>
|
||||||
<i id="plan-toggle-icon" class="fas fa-eye-slash"></i>
|
</div>
|
||||||
</button>
|
<div class="card-body">
|
||||||
</h2>
|
<h5 class="text-capitalize mb-1">@Model.CurrentPlan.Name</h5>
|
||||||
</div>
|
|
||||||
<div id="plan-collapse" class="accordion-collapse collapse">
|
@if (Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial)
|
||||||
<div class="card-body">
|
{
|
||||||
<h5 class="text-capitalize mb-1">@Model.CurrentPlan.Name</h5>
|
<p class="text-warning mb-2">
|
||||||
@if (Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial)
|
<i class="fas fa-clock me-1"></i>
|
||||||
{
|
@Model.DaysRemaining dia(s) restante(s)
|
||||||
<p class="text-warning mb-2"><i class="fas fa-clock me-1"></i>@Model.DaysRemaining dia(s) restante(s)</p>
|
</p>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<p class="text-muted small mb-2">R$ @Model.CurrentPlan.Price.ToString("F2")/mês</p>
|
<p class="text-muted small mb-2">R$ @Model.CurrentPlan.Price.ToString("F2")/mês</p>
|
||||||
}
|
}
|
||||||
<div class="mb-3">
|
|
||||||
<div class="d-flex justify-content-between small mb-1">
|
<div class="mb-3">
|
||||||
<span>Páginas</span>
|
<div class="d-flex justify-content-between small mb-1">
|
||||||
<span>@Model.UserPages.Count/@Model.CurrentPlan.MaxPages</span>
|
<span>Páginas</span>
|
||||||
</div>
|
<span>@Model.UserPages.Count/@Model.CurrentPlan.MaxPages</span>
|
||||||
<div class="progress" style="height: 6px;">
|
</div>
|
||||||
@{
|
<div class="progress" style="height: 6px;">
|
||||||
var pagesPercentage = Model.CurrentPlan.MaxPages > 0 ? (double)Model.UserPages.Count / Model.CurrentPlan.MaxPages * 100 : 0;
|
@{
|
||||||
}
|
var pagesPercentage = Model.CurrentPlan.MaxPages > 0 ?
|
||||||
<div class="progress-bar @(pagesPercentage >= 80 ? "bg-warning" : "bg-primary")" style="width: @pagesPercentage%"></div>
|
(double)Model.UserPages.Count / Model.CurrentPlan.MaxPages * 100 : 0;
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="small mb-2"><i class="fas fa-link me-2"></i>Links por página: @(Model.CurrentPlan.MaxLinksPerPage == int.MaxValue ? "Ilimitado" : Model.CurrentPlan.MaxLinksPerPage.ToString())
|
|
||||||
</div>
|
|
||||||
<div class="small mb-2"><i class="fas fa-chart-bar me-2"></i>Analytics: @(Model.CurrentPlan.AllowsAnalytics ? "✅" : "❌")</div>
|
|
||||||
<div class="small mb-3"><i class="fas fa-palette me-2"></i>Temas premium: @(Model.CurrentPlan.AllowsCustomThemes ? "✅" : "❌")</div>
|
|
||||||
@if (Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial)
|
|
||||||
{
|
|
||||||
<a href="@Url.Action("Pricing", "Home")" class="btn btn-warning w-100"><i class="fas fa-rocket me-2"></i>Fazer Upgrade</a>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<a href="@Url.Action("ManageSubscription", "Payment")" class="btn btn-outline-secondary w-100"><i class="fas fa-cog me-2"></i>Gerenciar Assinatura</a>
|
|
||||||
}
|
}
|
||||||
|
<div class="progress-bar @(pagesPercentage >= 80 ? "bg-warning" : "bg-primary")"
|
||||||
|
style="width: @pagesPercentage%"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="small mb-2">
|
||||||
|
<i class="fas fa-link me-2"></i>
|
||||||
|
Links por página: @(Model.CurrentPlan.MaxLinksPerPage == int.MaxValue ? "Ilimitado" : Model.CurrentPlan.MaxLinksPerPage.ToString())
|
||||||
|
</div>
|
||||||
|
<div class="small mb-2">
|
||||||
|
<i class="fas fa-chart-bar me-2"></i>
|
||||||
|
Analytics: @(Model.CurrentPlan.AllowsAnalytics ? "✅" : "❌")
|
||||||
|
</div>
|
||||||
|
<div class="small mb-3">
|
||||||
|
<i class="fas fa-palette me-2"></i>
|
||||||
|
Temas premium: @(Model.CurrentPlan.AllowsCustomThemes ? "✅" : "❌")
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (Model.CurrentPlan.Type == BCards.Web.Models.PlanType.Trial)
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("Pricing", "Home")" class="btn btn-warning w-100">
|
||||||
|
<i class="fas fa-rocket me-2"></i>
|
||||||
|
Fazer Upgrade
|
||||||
|
</a>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<a href="@Url.Action("ManageSubscription", "Payment")" class="btn btn-outline-secondary w-100">
|
||||||
|
<i class="fas fa-cog me-2"></i>
|
||||||
|
Gerenciar Assinatura
|
||||||
|
</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Estatísticas e Dicas (mantidos como antes) -->
|
<!-- Estatísticas Rápidas -->
|
||||||
@if (Model.CurrentPlan.AllowsAnalytics && Model.UserPages.Any())
|
@if (Model.CurrentPlan.AllowsAnalytics && Model.UserPages.Any())
|
||||||
{
|
{
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header"><h6 class="mb-0"><i class="fas fa-chart-line me-2"></i>Estatísticas Gerais</h6></div>
|
<div class="card-header">
|
||||||
|
<h6 class="mb-0">
|
||||||
|
<i class="fas fa-chart-line me-2"></i>
|
||||||
|
Estatísticas Gerais
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row text-center">
|
<div class="row text-center">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
@ -256,22 +385,46 @@
|
|||||||
{
|
{
|
||||||
<hr class="my-3">
|
<hr class="my-3">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<div class="h5 text-info mb-0">@((Model.UserPages.Sum(p => p.TotalClicks) * 100.0 / Model.UserPages.Sum(p => p.TotalViews)).ToString("F1"))%</div>
|
<div class="h5 text-info mb-0">
|
||||||
|
@((Model.UserPages.Sum(p => p.TotalClicks) * 100.0 / Model.UserPages.Sum(p => p.TotalViews)).ToString("F1"))%
|
||||||
|
</div>
|
||||||
<small class="text-muted">Taxa de Cliques</small>
|
<small class="text-muted">Taxa de Cliques</small>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- Dicas -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header"><h6 class="mb-0"><i class="fas fa-lightbulb me-2"></i>💡 Dicas</h6></div>
|
<div class="card-header">
|
||||||
|
<h6 class="mb-0">
|
||||||
|
<i class="fas fa-lightbulb me-2"></i>
|
||||||
|
💡 Dicas
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<ul class="list-unstyled small mb-0">
|
<ul class="list-unstyled small mb-0">
|
||||||
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Use uma bio clara e objetiva</li>
|
<li class="mb-2">
|
||||||
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Organize seus links por importância</li>
|
<i class="fas fa-check text-success me-2"></i>
|
||||||
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Escolha URLs fáceis de lembrar</li>
|
Use uma bio clara e objetiva
|
||||||
<li class="mb-2"><i class="fas fa-check text-success me-2"></i>Atualize regularmente seus links</li>
|
</li>
|
||||||
<li class="mb-0"><i class="fas fa-check text-success me-2"></i>Monitore suas estatísticas</li>
|
<li class="mb-2">
|
||||||
|
<i class="fas fa-check text-success me-2"></i>
|
||||||
|
Organize seus links por importância
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<i class="fas fa-check text-success me-2"></i>
|
||||||
|
Escolha URLs fáceis de lembrar
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<i class="fas fa-check text-success me-2"></i>
|
||||||
|
Atualize regularmente seus links
|
||||||
|
</li>
|
||||||
|
<li class="mb-0">
|
||||||
|
<i class="fas fa-check text-success me-2"></i>
|
||||||
|
Monitore suas estatísticas
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -281,156 +434,135 @@
|
|||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
<script>
|
<script>
|
||||||
// Funções auxiliares para cookies
|
// Função para abrir preview com token fresh
|
||||||
function setCookie(name, value, days) {
|
async function openPreview(pageId) {
|
||||||
var expires = "";
|
const button = event.target.closest('button');
|
||||||
if (days) {
|
const category = button.dataset.pageCategory;
|
||||||
var date = new Date();
|
const slug = button.dataset.pageSlug;
|
||||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
|
||||||
expires = "; expires=" + date.toUTCString();
|
// Desabilitar botão temporariamente
|
||||||
}
|
const originalText = button.innerHTML;
|
||||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
button.disabled = true;
|
||||||
}
|
button.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Carregando...';
|
||||||
function getCookie(name) {
|
|
||||||
var nameEQ = name + "=";
|
try {
|
||||||
var ca = document.cookie.split(';');
|
// Gerar novo token
|
||||||
for (var i = 0; i < ca.length; i++) {
|
const response = await fetch(`/Admin/GeneratePreviewToken/${pageId}`, {
|
||||||
var c = ca[i];
|
method: 'POST',
|
||||||
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
|
headers: {
|
||||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
'Content-Type': 'application/json',
|
||||||
}
|
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
// Inicializar tooltips
|
|
||||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
|
||||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
||||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Lógica para o acordeão de instruções
|
const result = await response.json();
|
||||||
const instructionsAccordion = document.getElementById('instructions-collapse');
|
|
||||||
if (instructionsAccordion) {
|
if (result.success) {
|
||||||
if (getCookie('instructions_collapsed') === 'true') {
|
// Abrir preview em nova aba com token novo
|
||||||
// Já começa fechado pelo `collapsed` no botão, então não fazemos nada
|
const previewUrl = `${window.location.origin}/page/${category}/${slug}?preview=${result.previewToken}`;
|
||||||
} else {
|
window.open(previewUrl, '_blank');
|
||||||
// Se não tem cookie ou está aberto, abre
|
} else {
|
||||||
new bootstrap.Collapse(instructionsAccordion, { toggle: true });
|
showToast(result.message || 'Erro ao gerar preview', 'error');
|
||||||
}
|
|
||||||
instructionsAccordion.addEventListener('show.bs.collapse', function () {
|
|
||||||
setCookie('instructions_collapsed', 'false', 365);
|
|
||||||
});
|
|
||||||
instructionsAccordion.addEventListener('hide.bs.collapse', function () {
|
|
||||||
setCookie('instructions_collapsed', 'true', 365);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro ao gerar preview:', error);
|
||||||
|
showToast('Erro ao gerar preview. Tente novamente.', 'error');
|
||||||
|
} finally {
|
||||||
|
// Reabilitar botão
|
||||||
|
button.disabled = false;
|
||||||
|
button.innerHTML = originalText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Lógica para o acordeão do plano
|
async function submitForModeration(pageId) {
|
||||||
const planAccordion = document.getElementById('plan-collapse');
|
const pageName = event.target.dataset.pageName || 'esta página';
|
||||||
const planToggleIcon = document.getElementById('plan-toggle-icon');
|
|
||||||
if (planAccordion && planToggleIcon) {
|
if (!confirm(`Enviar "${pageName}" para moderação?\n\nApós enviar, você não poderá mais editá-la até receber o resultado da análise.`)) {
|
||||||
if (getCookie('plan_collapsed') === 'true') {
|
return;
|
||||||
planToggleIcon.classList.replace('fa-eye-slash', 'fa-eye');
|
}
|
||||||
} else {
|
|
||||||
new bootstrap.Collapse(planAccordion, { toggle: true });
|
// Desabilitar botão durante envio
|
||||||
planToggleIcon.classList.replace('fa-eye', 'fa-eye-slash');
|
const button = event.target;
|
||||||
|
const originalText = button.innerHTML;
|
||||||
|
button.disabled = true;
|
||||||
|
button.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Enviando...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/Admin/SubmitForModeration/${pageId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value
|
||||||
}
|
}
|
||||||
|
});
|
||||||
planAccordion.addEventListener('show.bs.collapse', function () {
|
|
||||||
setCookie('plan_collapsed', 'false', 365);
|
const result = await response.json();
|
||||||
planToggleIcon.classList.replace('fa-eye', 'fa-eye-slash');
|
|
||||||
});
|
if (result.success) {
|
||||||
planAccordion.addEventListener('hide.bs.collapse', function () {
|
// Mostrar toast de sucesso
|
||||||
setCookie('plan_collapsed', 'true', 365);
|
showToast(result.message, 'success');
|
||||||
planToggleIcon.classList.replace('fa-eye-slash', 'fa-eye');
|
|
||||||
});
|
// Recarregar página após 2 segundos
|
||||||
|
setTimeout(() => {
|
||||||
|
location.reload();
|
||||||
|
}, 2000);
|
||||||
|
} else {
|
||||||
|
showToast(result.message || 'Erro ao enviar página', 'error');
|
||||||
|
|
||||||
|
// Reabilitar botão
|
||||||
|
button.disabled = false;
|
||||||
|
button.innerHTML = originalText;
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Erro:', error);
|
||||||
|
showToast('Erro ao enviar página para moderação', 'error');
|
||||||
|
|
||||||
|
// Reabilitar botão
|
||||||
|
button.disabled = false;
|
||||||
|
button.innerHTML = originalText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showToast(message, type) {
|
||||||
|
const toastContainer = getOrCreateToastContainer();
|
||||||
|
|
||||||
|
const bgClass = type === 'success' ? 'bg-success' : type === 'error' ? 'bg-danger' : 'bg-info';
|
||||||
|
const icon = type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-triangle' : 'fa-info-circle';
|
||||||
|
|
||||||
|
const toastHtml = `
|
||||||
|
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="5000">
|
||||||
|
<div class="toast-header ${bgClass} text-white">
|
||||||
|
<i class="fas ${icon} me-2"></i>
|
||||||
|
<strong class="me-auto">${type === 'success' ? 'Sucesso' : type === 'error' ? 'Erro' : 'Informação'}</strong>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
|
||||||
|
</div>
|
||||||
|
<div class="toast-body">${message}</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
||||||
|
|
||||||
|
const newToast = toastContainer.lastElementChild;
|
||||||
|
const toast = new bootstrap.Toast(newToast);
|
||||||
|
toast.show();
|
||||||
|
|
||||||
|
// Remover toast após ser fechado
|
||||||
|
newToast.addEventListener('hidden.bs.toast', function() {
|
||||||
|
newToast.remove();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Funções existentes (submitForModeration, openPreview, etc.)
|
function getOrCreateToastContainer() {
|
||||||
async function openPreview(pageId) {
|
let container = document.querySelector('.toast-container');
|
||||||
const button = event.target.closest('button');
|
if (!container) {
|
||||||
const category = button.dataset.pageCategory;
|
container = document.createElement('div');
|
||||||
const slug = button.dataset.pageSlug;
|
container.className = 'toast-container position-fixed top-0 end-0 p-3';
|
||||||
button.disabled = true;
|
container.style.zIndex = '1055';
|
||||||
button.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Carregando...';
|
document.body.appendChild(container);
|
||||||
try {
|
|
||||||
const response = await fetch(`/Admin/GeneratePreviewToken/${pageId}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
if (result.success) {
|
|
||||||
window.open(`${window.location.origin}/page/${category}/${slug}?preview=${result.previewToken}`, '_blank');
|
|
||||||
} else {
|
|
||||||
showToast(result.message || 'Erro ao gerar preview', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
showToast('Erro ao gerar preview. Tente novamente.', 'error');
|
|
||||||
} finally {
|
|
||||||
button.disabled = false;
|
|
||||||
button.innerHTML = '<i class="fas fa-vial me-1"></i>Testar Página';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
async function submitForModeration(pageId) {
|
|
||||||
const pageName = event.target.closest('button').dataset.pageName || 'esta página';
|
|
||||||
if (!confirm(`Enviar "${pageName}" para moderação?\n\nApós enviar, você não poderá mais editá-la até receber o resultado da análise.`)) return;
|
|
||||||
const button = event.target.closest('button');
|
|
||||||
button.disabled = true;
|
|
||||||
button.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Enviando...';
|
|
||||||
try {
|
|
||||||
const response = await fetch(`/Admin/SubmitForModeration/${pageId}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]').value }
|
|
||||||
});
|
|
||||||
const result = await response.json();
|
|
||||||
if (result.success) {
|
|
||||||
showToast(result.message, 'success');
|
|
||||||
setTimeout(() => location.reload(), 2000);
|
|
||||||
} else {
|
|
||||||
button.disabled = false;
|
|
||||||
button.innerHTML = '<i class="fas fa-paper-plane"></i><small>Enviar para Moderação</small>';
|
|
||||||
showToast(result.message || 'Erro ao enviar página', 'error');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
button.disabled = false;
|
|
||||||
button.innerHTML = '<i class="fas fa-paper-plane"></i><small>Enviar para Moderação</small>';
|
|
||||||
showToast('Erro ao enviar página para moderação', 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function showToast(message, type) {
|
|
||||||
const toastContainer = getOrCreateToastContainer();
|
|
||||||
const bgClass = type === 'success' ? 'bg-success' : type === 'error' ? 'bg-danger' : 'bg-info';
|
|
||||||
const icon = type === 'success' ? 'fa-check-circle' : type === 'error' ? 'fa-exclamation-triangle' : 'fa-info-circle';
|
|
||||||
const toastHtml =
|
|
||||||
`<div class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="5000">
|
|
||||||
<div class="toast-header ${bgClass} text-white">
|
|
||||||
<i class="fas ${icon} me-2"></i>
|
|
||||||
<strong class="me-auto">${type === 'success' ? 'Sucesso' : type === 'error' ? 'Erro' : 'Informação'}</strong>
|
|
||||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
|
|
||||||
</div>
|
|
||||||
<div class="toast-body">${message}</div>
|
|
||||||
</div>`;
|
|
||||||
toastContainer.insertAdjacentHTML('beforeend', toastHtml);
|
|
||||||
const newToast = toastContainer.lastElementChild;
|
|
||||||
const toast = new bootstrap.Toast(newToast);
|
|
||||||
toast.show();
|
|
||||||
newToast.addEventListener('hidden.bs.toast', () => newToast.remove());
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOrCreateToastContainer() {
|
|
||||||
let container = document.querySelector('.toast-container');
|
|
||||||
if (!container) {
|
|
||||||
container = document.createElement('div');
|
|
||||||
container.className = 'toast-container position-fixed top-0 end-0 p-3';
|
|
||||||
container.style.zIndex = '1055';
|
|
||||||
document.body.appendChild(container);
|
|
||||||
}
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,4 +596,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,7 +97,7 @@
|
|||||||
<i class="fs-2 text-primary">🔗</i>
|
<i class="fs-2 text-primary">🔗</i>
|
||||||
</div>
|
</div>
|
||||||
<h5>URLs Organizadas</h5>
|
<h5>URLs Organizadas</h5>
|
||||||
<p class="text-muted">Suas URLs são organizadas por categoria: bcards.site/corretor/seu-nome</p>
|
<p class="text-muted">Suas URLs são organizadas por categoria: vcart.me/corretor/seu-nome</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -55,7 +55,7 @@
|
|||||||
<li><strong>Informação sobre Compartilhamento:</strong> O direito de saber com quais entidades públicas e privadas compartilhamos seus dados.</li>
|
<li><strong>Informação sobre Compartilhamento:</strong> O direito de saber com quais entidades públicas e privadas compartilhamos seus dados.</li>
|
||||||
<li><strong>Revogação do Consentimento:</strong> O direito de revogar seu consentimento a qualquer momento.</li>
|
<li><strong>Revogação do Consentimento:</strong> O direito de revogar seu consentimento a qualquer momento.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Para exercer seus direitos, entre em contato com nosso Encarregado de Proteção de Dados (DPO) através do e-mail <a class="email-obfuscated" data-user="dpo" data-domain="bcards.site">[carregando e-mail...]</a>. O prazo para resposta é de até 15 dias, conforme a legislação.</p>
|
<p>Para exercer seus direitos, entre em contato com nosso Encarregado de Proteção de Dados (DPO) através do e-mail <a href="mailto:dpo@vcart.me">dpo@vcart.me</a>. O prazo para resposta é de até 15 dias, conforme a legislação.</p>
|
||||||
|
|
||||||
<h4 class="mt-5 fw-bold">5. Cookies e Tecnologias de Rastreamento</h4>
|
<h4 class="mt-5 fw-bold">5. Cookies e Tecnologias de Rastreamento</h4>
|
||||||
<p>Utilizamos cookies para melhorar sua experiência. Cookies são pequenos arquivos de texto armazenados em seu dispositivo. Você pode gerenciar suas preferências de cookies através do nosso banner de consentimento ou nas configurações do seu navegador.</p>
|
<p>Utilizamos cookies para melhorar sua experiência. Cookies são pequenos arquivos de texto armazenados em seu dispositivo. Você pode gerenciar suas preferências de cookies através do nosso banner de consentimento ou nas configurações do seu navegador.</p>
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
<li><strong>Oposición:</strong> El derecho a oponerse al tratamiento de sus datos para ciertos fines.</li>
|
<li><strong>Oposición:</strong> El derecho a oponerse al tratamiento de sus datos para ciertos fines.</li>
|
||||||
<li><strong>Portabilidad:</strong> El derecho a recibir sus datos en un formato estructurado.</li>
|
<li><strong>Portabilidad:</strong> El derecho a recibir sus datos en un formato estructurado.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Para ejercer sus derechos (conocidos como derechos ARCO en México y Chile), por favor contacte a nuestro Oficial de Protección de Datos (DPO) a través del correo electrónico <a class="email-obfuscated" data-user="dpo" data-domain="bcards.site">[cargando email...]</a>.</p>
|
<p>Para ejercer sus derechos (conocidos como derechos ARCO en México y Chile), por favor contacte a nuestro Oficial de Protección de Datos (DPO) a través del correo electrónico <a href="mailto:dpo@vcart.me">dpo@vcart.me</a>.</p>
|
||||||
|
|
||||||
<h4 class="mt-5 fw-bold">5. Retención de Datos</h4>
|
<h4 class="mt-5 fw-bold">5. Retención de Datos</h4>
|
||||||
<p>Mantendremos sus datos personales mientras su cuenta esté activa. Si su cuenta es desactivada o permanece inactiva por más de 12 meses, sus datos serán anonimizados o eliminados, excepto aquellos que necesitemos retener para cumplir con obligaciones legales.</p>
|
<p>Mantendremos sus datos personales mientras su cuenta esté activa. Si su cuenta es desactivada o permanece inactiva por más de 12 meses, sus datos serán anonimizados o eliminados, excepto aquellos que necesitemos retener para cumplir con obligaciones legales.</p>
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
<div class="alert alert-secondary text-center">
|
<div class="alert alert-secondary text-center">
|
||||||
<h5 class="alert-heading">Canal de Atendimento ao Titular</h5>
|
<h5 class="alert-heading">Canal de Atendimento ao Titular</h5>
|
||||||
<p class="mb-0">Envie um e-mail para:</p>
|
<p class="mb-0">Envie um e-mail para:</p>
|
||||||
<a class="email-obfuscated fs-5 fw-bold" data-user="dpo" data-domain="bcards.site">[carregando e-mail...]</a>
|
<a href="mailto:dpo@vcart.me" class="fs-5 fw-bold">dpo@vcart.me</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>No seu e-mail, por favor, inclua:</p>
|
<p>No seu e-mail, por favor, inclua:</p>
|
||||||
|
|||||||
@ -64,7 +64,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><strong>Legislação Aplicável:</strong> Estes Termos serão regidos e interpretados de acordo com as leis da República Federativa do Brasil, sem consideração com o conflito de disposições legais.</li>
|
<li><strong>Legislação Aplicável:</strong> Estes Termos serão regidos e interpretados de acordo com as leis da República Federativa do Brasil, sem consideração com o conflito de disposições legais.</li>
|
||||||
<li><strong>Alterações nos Termos:</strong> Podemos modificar estes Termos a qualquer momento. Se fizermos alterações materiais, forneceremos um aviso com antecedência razoável. Ao continuar a usar o BCards após as alterações entrarem em vigor, você concorda em ficar vinculado aos termos revisados.</li>
|
<li><strong>Alterações nos Termos:</strong> Podemos modificar estes Termos a qualquer momento. Se fizermos alterações materiais, forneceremos um aviso com antecedência razoável. Ao continuar a usar o BCards após as alterações entrarem em vigor, você concorda em ficar vinculado aos termos revisados.</li>
|
||||||
<li><strong>Contato:</strong> Para qualquer dúvida sobre estes Termos, entre em contato conosco pelo e-mail <a class="email-obfuscated" data-user="suporte" data-domain="bcards.site">[carregando e-mail...]</a>.</li>
|
<li><strong>Contato:</strong> Para qualquer dúvida sobre estes Termos, entre em contato conosco pelo e-mail <a href="mailto:suporte@vcart.me">suporte@vcart.me</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -57,7 +57,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><strong>Legislación Aplicable:</strong> Estos Términos se regirán por las leyes de Brasil para todos los usuarios. Para disputas específicas en Colombia, Chile o México, se pueden considerar las leyes locales.</li>
|
<li><strong>Legislación Aplicable:</strong> Estos Términos se regirán por las leyes de Brasil para todos los usuarios. Para disputas específicas en Colombia, Chile o México, se pueden considerar las leyes locales.</li>
|
||||||
<li><strong>Cambios en los Términos:</strong> Podemos modificar estos Términos en cualquier momento. Le notificaremos con antelación.</li>
|
<li><strong>Cambios en los Términos:</strong> Podemos modificar estos Términos en cualquier momento. Le notificaremos con antelación.</li>
|
||||||
<li><strong>Contacto:</strong> Para cualquier pregunta sobre estos Términos, contáctenos en <a class="email-obfuscated" data-user="suporte" data-domain="bcards.site">[cargando email...]</a>.</li>
|
<li><strong>Contacto:</strong> Para cualquier pregunta sobre estos Términos, contáctenos en <a href="mailto:suporte@vcart.me">suporte@vcart.me</a>.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -242,8 +242,6 @@
|
|||||||
<script src="~/lib/jquery/jquery.min.js"></script>
|
<script src="~/lib/jquery/jquery.min.js"></script>
|
||||||
<script src="~/lib/bootstrap/js/bootstrap.bundle.min.js"></script>
|
<script src="~/lib/bootstrap/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="~/js/site.js" asp-append-version="true"></script>
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
<script src="~/js/cookie-consent.js" asp-append-version="true"></script>
|
|
||||||
<script src="~/js/email-handler.js" asp-append-version="true"></script>
|
|
||||||
|
|
||||||
<!-- Scripts para menu ativo e barra de carregamento -->
|
<!-- Scripts para menu ativo e barra de carregamento -->
|
||||||
<script>
|
<script>
|
||||||
@ -348,3 +346,4 @@
|
|||||||
@await RenderSectionAsync("Scripts", required: false)
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
</html>
|
||||||
@ -1,24 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Script para Ofuscação de E-mail
|
|
||||||
* BCards - 2025
|
|
||||||
*/
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
const emailElements = document.querySelectorAll('.email-obfuscated');
|
|
||||||
|
|
||||||
emailElements.forEach(el => {
|
|
||||||
try {
|
|
||||||
const user = el.getAttribute('data-user');
|
|
||||||
const domain = el.getAttribute('data-domain');
|
|
||||||
|
|
||||||
if (user && domain) {
|
|
||||||
const email = user + '@' + domain;
|
|
||||||
el.href = 'mailto:' + email;
|
|
||||||
el.textContent = email;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Falha ao ofuscar e-mail:', e);
|
|
||||||
el.textContent = 'E-mail indisponível';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue
Block a user