fix: ajustes na edição
This commit is contained in:
parent
dca698e4c4
commit
cff7962cc5
@ -558,10 +558,13 @@ public class AdminController : Controller
|
|||||||
var socialLinks = new List<LinkItem>();
|
var socialLinks = new List<LinkItem>();
|
||||||
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
||||||
{
|
{
|
||||||
|
var whatsappDigits = model.WhatsAppNumber
|
||||||
|
.Replace("https://wa.me/", "").Replace("whatsapp://", "")
|
||||||
|
.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "");
|
||||||
socialLinks.Add(new LinkItem
|
socialLinks.Add(new LinkItem
|
||||||
{
|
{
|
||||||
Title = "WhatsApp",
|
Title = "WhatsApp",
|
||||||
Url = $"https://wa.me/{model.WhatsAppNumber.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "")}",
|
Url = $"https://wa.me/{whatsappDigits}",
|
||||||
Icon = "fab fa-whatsapp",
|
Icon = "fab fa-whatsapp",
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
Order = userPage.Links.Count + socialLinks.Count
|
Order = userPage.Links.Count + socialLinks.Count
|
||||||
@ -837,6 +840,16 @@ public class AdminController : Controller
|
|||||||
FileSize = d.FileSize,
|
FileSize = d.FileSize,
|
||||||
UploadedAt = d.UploadedAt
|
UploadedAt = d.UploadedAt
|
||||||
}).ToList() ?? new List<ManageDocumentViewModel>(),
|
}).ToList() ?? new List<ManageDocumentViewModel>(),
|
||||||
|
// Social media fields — extracted from Links so the edit form pre-fills correctly
|
||||||
|
WhatsAppNumber = page.Links?.FirstOrDefault(l => l.Icon?.Contains("whatsapp") == true)?.Url
|
||||||
|
?.Replace("https://wa.me/", "").Replace("whatsapp://", "") ?? string.Empty,
|
||||||
|
FacebookUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("facebook") == true)?.Url ?? string.Empty,
|
||||||
|
InstagramUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("instagram") == true)?.Url ?? string.Empty,
|
||||||
|
TwitterUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("twitter") == true)?.Url ?? string.Empty,
|
||||||
|
TiktokUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("tiktok") == true)?.Url ?? string.Empty,
|
||||||
|
PinterestUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("pinterest") == true)?.Url ?? string.Empty,
|
||||||
|
DiscordUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("discord") == true)?.Url ?? string.Empty,
|
||||||
|
KawaiUrl = page.Links?.FirstOrDefault(l => l.Icon?.Contains("kawai") == true)?.Url ?? string.Empty,
|
||||||
AvailableCategories = categories,
|
AvailableCategories = categories,
|
||||||
AvailableThemes = themes.Where(t => !t.IsPremium || userPlanType.AllowsCustomThemes()).ToList(),
|
AvailableThemes = themes.Where(t => !t.IsPremium || userPlanType.AllowsCustomThemes()).ToList(),
|
||||||
MaxLinksAllowed = userPlanType.GetMaxLinksPerPage(),
|
MaxLinksAllowed = userPlanType.GetMaxLinksPerPage(),
|
||||||
@ -892,10 +905,13 @@ public class AdminController : Controller
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
||||||
{
|
{
|
||||||
|
var whatsappDigits = model.WhatsAppNumber
|
||||||
|
.Replace("https://wa.me/", "").Replace("whatsapp://", "")
|
||||||
|
.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "");
|
||||||
socialLinks.Add(new LinkItem
|
socialLinks.Add(new LinkItem
|
||||||
{
|
{
|
||||||
Title = "WhatsApp",
|
Title = "WhatsApp",
|
||||||
Url = $"https://wa.me/{model.WhatsAppNumber.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "")}",
|
Url = $"https://wa.me/{whatsappDigits}",
|
||||||
Icon = "fab fa-whatsapp",
|
Icon = "fab fa-whatsapp",
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
Order = currentOrder++
|
Order = currentOrder++
|
||||||
@ -1241,10 +1257,13 @@ public class AdminController : Controller
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
if (!string.IsNullOrEmpty(model.WhatsAppNumber))
|
||||||
{
|
{
|
||||||
|
var whatsappDigits = model.WhatsAppNumber
|
||||||
|
.Replace("https://wa.me/", "").Replace("whatsapp://", "")
|
||||||
|
.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "");
|
||||||
socialLinks.Add(new LinkItem
|
socialLinks.Add(new LinkItem
|
||||||
{
|
{
|
||||||
Title = "WhatsApp",
|
Title = "WhatsApp",
|
||||||
Url = $"https://wa.me/{model.WhatsAppNumber.Replace("+", "").Replace(" ", "").Replace("-", "").Replace("(", "").Replace(")", "")}",
|
Url = $"https://wa.me/{whatsappDigits}",
|
||||||
Icon = "fab fa-whatsapp",
|
Icon = "fab fa-whatsapp",
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
Order = currentOrder++
|
Order = currentOrder++
|
||||||
|
|||||||
@ -82,9 +82,15 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label asp-for="Bio" class="form-label">Bio/Descrição</label>
|
<label asp-for="Bio" class="form-label">Bio/Descrição</label>
|
||||||
<textarea asp-for="Bio" class="form-control" rows="8" maxlength="3000" placeholder="Uma breve descrição sobre você ou sua empresa..."></textarea>
|
<div class="md-toolbar border rounded-top border-bottom-0 bg-light px-2 py-1 d-flex gap-1">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-btn" data-target="Bio" data-wrap="**" title="Negrito"><b>B</b></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-btn" data-target="Bio" data-wrap="*" title="Itálico"><i>I</i></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-list-btn" data-target="Bio" title="Lista">• Lista</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-link-btn" data-target="Bio" title="Link">🔗 Link</button>
|
||||||
|
</div>
|
||||||
|
<textarea asp-for="Bio" id="Bio" class="form-control rounded-0 rounded-bottom" rows="5" maxlength="3000" placeholder="Uma breve descrição sobre você ou sua empresa..." style="font-family: monospace; font-size: 0.9rem;"></textarea>
|
||||||
<span asp-validation-for="Bio" class="text-danger"></span>
|
<span asp-validation-for="Bio" class="text-danger"></span>
|
||||||
<div class="form-text">Máximo 3000 caracteres</div>
|
<div class="form-text">Máximo 3000 caracteres. Use **negrito**, *itálico*, - item para listas.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -616,4 +622,51 @@ function generatePreview() {
|
|||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
document.querySelectorAll('.md-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var wrap = this.dataset.wrap;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||||
|
var sel = ta.value.substring(start, end) || 'texto';
|
||||||
|
var before = ta.value.substring(0, start);
|
||||||
|
var after = ta.value.substring(end);
|
||||||
|
ta.value = before + wrap + sel + wrap + after;
|
||||||
|
ta.selectionStart = start + wrap.length;
|
||||||
|
ta.selectionEnd = start + wrap.length + sel.length;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.md-list-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart;
|
||||||
|
var lineStart = ta.value.lastIndexOf('\n', start - 1) + 1;
|
||||||
|
var before = ta.value.substring(0, lineStart);
|
||||||
|
var after = ta.value.substring(lineStart);
|
||||||
|
ta.value = before + '- ' + after;
|
||||||
|
ta.selectionStart = ta.selectionEnd = start + 2;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.md-link-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||||
|
var sel = ta.value.substring(start, end) || 'texto do link';
|
||||||
|
var url = prompt('URL do link:') || 'https://';
|
||||||
|
var before = ta.value.substring(0, start);
|
||||||
|
var after = ta.value.substring(end);
|
||||||
|
var md = '[' + sel + '](' + url + ')';
|
||||||
|
ta.value = before + md + after;
|
||||||
|
ta.selectionStart = ta.selectionEnd = start + md.length;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
}
|
}
|
||||||
@ -115,9 +115,15 @@
|
|||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label asp-for="Bio" class="form-label">Bio/Descrição</label>
|
<label asp-for="Bio" class="form-label">Bio/Descrição</label>
|
||||||
<textarea asp-for="Bio" class="form-control" rows="8" maxlength="3000" placeholder="Uma breve descrição sobre você ou sua empresa..."></textarea>
|
<div class="md-toolbar border rounded-top border-bottom-0 bg-light px-2 py-1 d-flex gap-1">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-btn" data-target="Bio" data-wrap="**" title="Negrito"><b>B</b></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-btn" data-target="Bio" data-wrap="*" title="Itálico"><i>I</i></button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-btn md-list-btn" data-target="Bio" title="Lista">• Lista</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary md-link-btn" data-target="Bio" title="Link">🔗 Link</button>
|
||||||
|
</div>
|
||||||
|
<textarea asp-for="Bio" id="Bio" class="form-control rounded-0 rounded-bottom" rows="5" maxlength="3000" placeholder="Uma breve descrição sobre você ou sua empresa..." style="font-family: monospace; font-size: 0.9rem;"></textarea>
|
||||||
<span asp-validation-for="Bio" class="text-danger"></span>
|
<span asp-validation-for="Bio" class="text-danger"></span>
|
||||||
<div class="form-text">Máximo 3000 caracteres</div>
|
<div class="form-text">Máximo 3000 caracteres. Use **negrito**, *itálico*, - item para listas.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Profile Image Upload -->
|
<!-- Profile Image Upload -->
|
||||||
@ -1210,7 +1216,6 @@
|
|||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const LINK_TYPES_CONFIG = @Html.Raw(linkTypesJson);
|
const LINK_TYPES_CONFIG = @Html.Raw(linkTypesJson);
|
||||||
let linkCount = @Model.Links.Count;
|
let linkCount = @Model.Links.Count;
|
||||||
@ -1219,6 +1224,9 @@
|
|||||||
const totalSteps = 5;
|
const totalSteps = 5;
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
// Initialize Markdown toolbar
|
||||||
|
initMarkdownToolbar();
|
||||||
|
|
||||||
// Initialize social media fields
|
// Initialize social media fields
|
||||||
initializeSocialMedia();
|
initializeSocialMedia();
|
||||||
|
|
||||||
@ -1337,11 +1345,11 @@
|
|||||||
updateLinkNumbers();
|
updateLinkNumbers();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Form validation
|
// Loading state — só desabilita se a validação JS não bloqueou o submit
|
||||||
$('#managePageForm').on('submit', function(e) {
|
$('#managePageForm').on('submit', function(e) {
|
||||||
console.log('Form submitted');
|
if (!e.isDefaultPrevented()) {
|
||||||
// Allow submission but add loading state
|
$(this).find('button[type="submit"]').prop('disabled', true).html('<i class="fas fa-spinner fa-spin me-2"></i>Salvando...');
|
||||||
$(this).find('button[type="submit"]').prop('disabled', true).html('<i class="fas fa-spinner fa-spin me-2"></i>Criando...');
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1943,6 +1951,53 @@
|
|||||||
}, 7000);
|
}, 7000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Markdown Toolbar
|
||||||
|
function initMarkdownToolbar() {
|
||||||
|
document.querySelectorAll('.md-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var wrap = this.dataset.wrap;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||||
|
var sel = ta.value.substring(start, end) || 'texto';
|
||||||
|
var before = ta.value.substring(0, start);
|
||||||
|
var after = ta.value.substring(end);
|
||||||
|
ta.value = before + wrap + sel + wrap + after;
|
||||||
|
ta.selectionStart = start + wrap.length;
|
||||||
|
ta.selectionEnd = start + wrap.length + sel.length;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.md-list-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart;
|
||||||
|
var lineStart = ta.value.lastIndexOf('\n', start - 1) + 1;
|
||||||
|
var before = ta.value.substring(0, lineStart);
|
||||||
|
var after = ta.value.substring(lineStart);
|
||||||
|
ta.value = before + '- ' + after;
|
||||||
|
ta.selectionStart = ta.selectionEnd = start + 2;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.querySelectorAll('.md-link-btn').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
var targetId = this.dataset.target;
|
||||||
|
var ta = document.getElementById(targetId);
|
||||||
|
var start = ta.selectionStart, end = ta.selectionEnd;
|
||||||
|
var sel = ta.value.substring(start, end) || 'texto do link';
|
||||||
|
var url = prompt('URL do link:') || 'https://';
|
||||||
|
var before = ta.value.substring(0, start);
|
||||||
|
var after = ta.value.substring(end);
|
||||||
|
var md = '[' + sel + '](' + url + ')';
|
||||||
|
ta.value = before + md + after;
|
||||||
|
ta.selectionStart = ta.selectionEnd = start + md.length;
|
||||||
|
ta.focus();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Validation Error Handling
|
// Validation Error Handling
|
||||||
function checkValidationErrors() {
|
function checkValidationErrors() {
|
||||||
// Só verificar erros se estamos em um POST-back (ou seja, se ModelState foi validado)
|
// Só verificar erros se estamos em um POST-back (ou seja, se ModelState foi validado)
|
||||||
@ -2262,8 +2317,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Atualizar campo hidden - SEMPRE string, nunca null
|
// Atualizar campo hidden - SEMPRE string, nunca null
|
||||||
|
// WhatsApp: armazena só o número (servidor adiciona https://wa.me/ ao salvar)
|
||||||
|
// Outros: armazena URL completa (servidor usa diretamente)
|
||||||
if (value) {
|
if (value) {
|
||||||
hiddenField.val(prefix + value);
|
hiddenField.val(isWhatsApp ? value : prefix + value);
|
||||||
} else {
|
} else {
|
||||||
hiddenField.val(' '); // Espaço em branco para evitar null
|
hiddenField.val(' '); // Espaço em branco para evitar null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,9 +103,11 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@if (!string.IsNullOrEmpty(Model.Page.Bio))
|
@if (!string.IsNullOrEmpty(Model.Page.Bio))
|
||||||
{
|
{
|
||||||
|
var bioPipeline = new Markdig.MarkdownPipelineBuilder().UseAutoLinks().DisableHtml().Build();
|
||||||
|
var bioHtml = Markdig.Markdown.ToHtml(Model.Page.Bio, bioPipeline);
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<strong>Biografia:</strong>
|
<strong>Biografia:</strong>
|
||||||
<p>@Model.Page.Bio</p>
|
<div>@Html.Raw(bioHtml)</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -367,7 +367,9 @@
|
|||||||
|
|
||||||
@if (!string.IsNullOrEmpty(Model.Bio))
|
@if (!string.IsNullOrEmpty(Model.Bio))
|
||||||
{
|
{
|
||||||
<p class="profile-bio">@Model.Bio</p>
|
var bioPipeline = new Markdig.MarkdownPipelineBuilder().UseAutoLinks().DisableHtml().Build();
|
||||||
|
var bioHtml = Markdig.Markdown.ToHtml(Model.Bio, bioPipeline);
|
||||||
|
<div class="profile-bio">@Html.Raw(bioHtml)</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!-- Links Container -->
|
<!-- Links Container -->
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
@using BCards.Web
|
@using BCards.Web
|
||||||
@using BCards.Web.Models
|
@using BCards.Web.Models
|
||||||
|
@using Markdig
|
||||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
Loading…
Reference in New Issue
Block a user