fix: ajustes de links
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 2s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Build and Push Image (push) Successful in 15m34s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Successful in 2m0s
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (push) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 0s
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 2s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Build and Push Image (push) Successful in 15m34s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Successful in 2m0s
BCards Deployment Pipeline / Deploy to Staging (x86 - Local) (push) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 0s
This commit is contained in:
parent
2eada5f44c
commit
378bcf54b6
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace BCards.Web.Controllers;
|
namespace BCards.Web.Controllers;
|
||||||
@ -203,7 +204,6 @@ public class AdminController : Controller
|
|||||||
string userId = "";
|
string userId = "";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
ViewBag.IsHomePage = false;
|
ViewBag.IsHomePage = false;
|
||||||
|
|
||||||
var user = await _authService.GetCurrentUserAsync(User);
|
var user = await _authService.GetCurrentUserAsync(User);
|
||||||
@ -214,13 +214,7 @@ public class AdminController : Controller
|
|||||||
|
|
||||||
// Limpar campos de redes sociais que são apenas espaços (tratados como vazios)
|
// Limpar campos de redes sociais que são apenas espaços (tratados como vazios)
|
||||||
CleanSocialMediaFields(model);
|
CleanSocialMediaFields(model);
|
||||||
|
AdjustModelState(ModelState, model);
|
||||||
_logger.LogInformation($"ManagePage POST: IsNewPage={model.IsNewPage}, DisplayName={model.DisplayName}, Category={model.Category}, Links={model.Links?.Count ?? 0}");
|
|
||||||
|
|
||||||
ModelState.Remove<ManagePageViewModel>(x => x.InstagramUrl);
|
|
||||||
ModelState.Remove<ManagePageViewModel>(x => x.FacebookUrl);
|
|
||||||
ModelState.Remove<ManagePageViewModel>(x => x.TwitterUrl);
|
|
||||||
ModelState.Remove<ManagePageViewModel>(x => x.WhatsAppNumber);
|
|
||||||
|
|
||||||
_logger.LogInformation($"ManagePage POST: IsNewPage={model.IsNewPage}, DisplayName={model.DisplayName}, Category={model.Category}, Links={model.Links?.Count ?? 0}");
|
_logger.LogInformation($"ManagePage POST: IsNewPage={model.IsNewPage}, DisplayName={model.DisplayName}, Category={model.Category}, Links={model.Links?.Count ?? 0}");
|
||||||
|
|
||||||
@ -276,12 +270,19 @@ public class AdminController : Controller
|
|||||||
|
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("ModelState is invalid:");
|
var sbError = new StringBuilder();
|
||||||
|
sbError.AppendLine("ModelState is invalid!");
|
||||||
foreach (var error in ModelState)
|
foreach (var error in ModelState)
|
||||||
{
|
{
|
||||||
_logger.LogWarning($"Key: {error.Key}, Errors: {string.Join(", ", error.Value.Errors.Select(e => e.ErrorMessage))}");
|
var erroMsg = string.Join(", ", error.Value.Errors.Select(e => e.ErrorMessage));
|
||||||
|
if (!string.IsNullOrEmpty(erroMsg))
|
||||||
|
{
|
||||||
|
sbError.AppendLine($"Key: {error.Key}, Errors: {erroMsg}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logger.LogWarning(sbError.ToString());
|
||||||
|
|
||||||
// Repopulate dropdowns
|
// Repopulate dropdowns
|
||||||
var slug = await _userPageService.GenerateSlugAsync(model.Category, model.DisplayName);
|
var slug = await _userPageService.GenerateSlugAsync(model.Category, model.DisplayName);
|
||||||
model.Slug = slug;
|
model.Slug = slug;
|
||||||
@ -1143,4 +1144,35 @@ public class AdminController : Controller
|
|||||||
_logger.LogInformation("KeepAlive endpoint triggered for user {User}", User.Identity?.Name ?? "Anonymous");
|
_logger.LogInformation("KeepAlive endpoint triggered for user {User}", User.Identity?.Name ?? "Anonymous");
|
||||||
return Json(new { status = "session_extended" });
|
return Json(new { status = "session_extended" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AdjustModelState(ModelStateDictionary modelState, ManagePageViewModel model)
|
||||||
|
{
|
||||||
|
modelState.Remove<ManagePageViewModel>(x => x.InstagramUrl);
|
||||||
|
modelState.Remove<ManagePageViewModel>(x => x.FacebookUrl);
|
||||||
|
modelState.Remove<ManagePageViewModel>(x => x.TwitterUrl);
|
||||||
|
modelState.Remove<ManagePageViewModel>(x => x.WhatsAppNumber);
|
||||||
|
|
||||||
|
// Remover validação de 'Description' para links do tipo 'Normal'
|
||||||
|
if (model.Links != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < model.Links.Count; i++)
|
||||||
|
{
|
||||||
|
if (model.Links[i].Type == LinkType.Normal)
|
||||||
|
{
|
||||||
|
string key = $"Links[{i}].Description";
|
||||||
|
if (ModelState.ContainsKey(key))
|
||||||
|
{
|
||||||
|
ModelState.Remove(key);
|
||||||
|
ModelState.MarkFieldValid(key);
|
||||||
|
}
|
||||||
|
key = $"Links[{i}].Url";
|
||||||
|
if (ModelState.ContainsKey(key))
|
||||||
|
{
|
||||||
|
ModelState.Remove(key);
|
||||||
|
ModelState.MarkFieldValid(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -381,10 +381,10 @@
|
|||||||
var twitter = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("twitter")).FirstOrDefault();
|
var twitter = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("twitter")).FirstOrDefault();
|
||||||
var whatsapp = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("whatsapp")).FirstOrDefault();
|
var whatsapp = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("whatsapp")).FirstOrDefault();
|
||||||
var instagram = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("instagram")).FirstOrDefault();
|
var instagram = Model.Links.Where(x => !string.IsNullOrEmpty(x.Icon) && x.Icon.Contains("instagram")).FirstOrDefault();
|
||||||
var facebookUrl = facebook !=null ? facebook.Url : "";
|
var facebookUrl = facebook !=null ? facebook.Url.Replace("https://facebook.com/","").Replace("https://www.facebook.com/","").Replace("https://fb.com/","") : "";
|
||||||
var twitterUrl = twitter !=null ? twitter.Url : "";
|
var twitterUrl = twitter !=null ? twitter.Url.Replace("https://x.com/","").Replace("https://twitter.com/","").Replace("https://www.twitter.com/","") : "";
|
||||||
var whatsappUrl = whatsapp !=null ? whatsapp.Url.Replace("https://wa.me/","") : "";
|
var whatsappUrl = whatsapp !=null ? whatsapp.Url.Replace("https://wa.me/","").Replace("whatsapp://","") : "";
|
||||||
var instagramUrl = instagram !=null ? instagram.Url : "";
|
var instagramUrl = instagram !=null ? instagram.Url.Replace("https://instagram.com/","").Replace("https://www.instagram.com/","") : "";
|
||||||
}
|
}
|
||||||
<!-- Passo 4: Redes Sociais (Opcional) -->
|
<!-- Passo 4: Redes Sociais (Opcional) -->
|
||||||
<div class="accordion-item">
|
<div class="accordion-item">
|
||||||
@ -581,27 +581,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="linkUrl" class="form-label">URL <span class="text-danger">*</span></label>
|
<label for="linkIcon" class="form-label">Tipo de Link <span class="text-danger">*</span></label>
|
||||||
<div class="input-group">
|
<select class="form-select" id="linkIcon" required>
|
||||||
<span class="input-group-text bg-primary text-white fw-bold">https://</span>
|
<option value="">Selecione o tipo de link</option>
|
||||||
<input type="text" class="form-control" id="linkUrlInput" placeholder="exemplo.com" required>
|
<option value="fas fa-globe">🌐 Site Geral</option>
|
||||||
</div>
|
<option value="fas fa-shopping-cart">🛒 Loja/E-commerce</option>
|
||||||
<input type="hidden" id="linkUrl">
|
|
||||||
<div class="form-text">Digite apenas o domínio e caminho (sem https://)</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="linkDescription" class="form-label">Descrição (opcional)</label>
|
|
||||||
<input type="text" class="form-control" id="linkDescription" placeholder="Breve descrição do link">
|
|
||||||
<div class="form-text">Texto adicional que aparece abaixo do título</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<label for="linkIcon" class="form-label">Ícone (opcional)</label>
|
|
||||||
<select class="form-select" id="linkIcon">
|
|
||||||
<option value="">Sem ícone</option>
|
|
||||||
<option value="fas fa-globe">🌐 Site</option>
|
|
||||||
<option value="fas fa-shopping-cart">🛒 Loja</option>
|
|
||||||
<option value="fas fa-briefcase">💼 Portfólio</option>
|
<option value="fas fa-briefcase">💼 Portfólio</option>
|
||||||
<option value="fas fa-envelope">✉️ Email</option>
|
<option value="fas fa-envelope">✉️ Email</option>
|
||||||
<option value="fas fa-phone">📞 Telefone</option>
|
<option value="fas fa-phone">📞 Telefone</option>
|
||||||
@ -613,6 +597,23 @@
|
|||||||
<option value="fas fa-calendar">📅 Agenda</option>
|
<option value="fas fa-calendar">📅 Agenda</option>
|
||||||
<option value="fas fa-heart">❤️ Favorito</option>
|
<option value="fas fa-heart">❤️ Favorito</option>
|
||||||
</select>
|
</select>
|
||||||
|
<div class="form-text">Escolha o tipo para obter instruções específicas</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="linkUrl" class="form-label">URL/Contato <span class="text-danger">*</span></label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text bg-primary text-white fw-bold" id="urlPrefix">https://</span>
|
||||||
|
<input type="text" class="form-control" id="linkUrlInput" placeholder="exemplo.com" required>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" id="linkUrl">
|
||||||
|
<div class="form-text" id="urlInstructions">Selecione primeiro o tipo de link acima</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="linkDescription" class="form-label">Descrição (opcional)</label>
|
||||||
|
<input type="text" class="form-control" id="linkDescription" placeholder="Breve descrição do link">
|
||||||
|
<div class="form-text">Texto adicional que aparece abaixo do título</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -995,12 +996,18 @@
|
|||||||
// Add link functionality via modal
|
// Add link functionality via modal
|
||||||
$('#addLinkBtn').on('click', function() {
|
$('#addLinkBtn').on('click', function() {
|
||||||
const maxlinks = @Model.MaxLinksAllowed;
|
const maxlinks = @Model.MaxLinksAllowed;
|
||||||
if (linkCount >= maxlinks+4) {
|
// Links do modal são limitados pelo MaxLinksAllowed (redes sociais são separadas e opcionais)
|
||||||
alert('Você atingiu o limite de links para seu plano atual.');
|
if (linkCount >= maxlinks) {
|
||||||
|
alert('Você atingiu o limite de ' + maxlinks + ' links para seu plano atual. As redes sociais do Passo 4 não contam neste limite.');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Dynamic link type functionality
|
||||||
|
$('#linkIcon').on('change', function() {
|
||||||
|
updateLinkUrlField($(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
// Toggle between link types
|
// Toggle between link types
|
||||||
$('input[name="linkType"]').on('change', function() {
|
$('input[name="linkType"]').on('change', function() {
|
||||||
const linkType = $(this).val();
|
const linkType = $(this).val();
|
||||||
@ -1606,6 +1613,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Social Media Functions
|
// Social Media Functions
|
||||||
|
function cleanSocialPrefix(value, socialType) {
|
||||||
|
const prefixes = {
|
||||||
|
'Facebook': ['https://facebook.com/', 'https://www.facebook.com/', 'https://fb.com/', 'https://www.fb.com/'],
|
||||||
|
'Instagram': ['https://instagram.com/', 'https://www.instagram.com/', 'https://instagr.am/'],
|
||||||
|
'Twitter': ['https://x.com/', 'https://twitter.com/', 'https://www.twitter.com/', 'https://www.x.com/'],
|
||||||
|
'WhatsApp': ['https://wa.me/', 'whatsapp://', 'https://api.whatsapp.com/', 'wa.me/']
|
||||||
|
};
|
||||||
|
|
||||||
|
const typePrefixes = prefixes[socialType] || [];
|
||||||
|
|
||||||
|
for (let prefix of typePrefixes) {
|
||||||
|
if (value.startsWith(prefix)) {
|
||||||
|
return value.replace(prefix, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
function initializeSocialMedia() {
|
function initializeSocialMedia() {
|
||||||
// WhatsApp
|
// WhatsApp
|
||||||
setupSocialField('WhatsApp', 'WhatsAppNumber', 'https://wa.me/', true);
|
setupSocialField('WhatsApp', 'WhatsAppNumber', 'https://wa.me/', true);
|
||||||
@ -1638,13 +1664,9 @@
|
|||||||
checkbox.prop('checked', true);
|
checkbox.prop('checked', true);
|
||||||
group.show();
|
group.show();
|
||||||
|
|
||||||
// Extrair username/número do valor atual
|
// Limpar qualquer prefixo conhecido do valor atual
|
||||||
if (currentValue.startsWith(prefix)) {
|
const cleanValue = cleanSocialPrefix(currentValue, name);
|
||||||
const userPart = currentValue.replace(prefix, '');
|
userInput.val(cleanValue);
|
||||||
userInput.val(userPart);
|
|
||||||
} else {
|
|
||||||
userInput.val(currentValue);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Se não tem valor, garantir que o hidden field seja espaço
|
// Se não tem valor, garantir que o hidden field seja espaço
|
||||||
hiddenField.val(' ');
|
hiddenField.val(' ');
|
||||||
@ -1666,10 +1688,11 @@
|
|||||||
userInput.on('input', function() {
|
userInput.on('input', function() {
|
||||||
let value = $(this).val().trim();
|
let value = $(this).val().trim();
|
||||||
|
|
||||||
// Se o usuário colou uma URL completa, extrair apenas a parte do usuário
|
// Limpar qualquer prefixo conhecido
|
||||||
if (value.startsWith(prefix)) {
|
const cleanValue = cleanSocialPrefix(value, name);
|
||||||
value = value.replace(prefix, '');
|
if (cleanValue !== value) {
|
||||||
$(this).val(value);
|
$(this).val(cleanValue);
|
||||||
|
value = cleanValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWhatsApp) {
|
if (isWhatsApp) {
|
||||||
@ -1713,6 +1736,129 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dynamic Link Type Functions
|
||||||
|
function updateLinkUrlField(iconValue) {
|
||||||
|
const $prefix = $('#urlPrefix');
|
||||||
|
const $input = $('#linkUrlInput');
|
||||||
|
const $instructions = $('#urlInstructions');
|
||||||
|
|
||||||
|
// Configurações por tipo de ícone
|
||||||
|
const linkTypes = {
|
||||||
|
'fas fa-envelope': {
|
||||||
|
prefix: 'mailto:',
|
||||||
|
placeholder: 'seuemail@@exemplo.com',
|
||||||
|
instructions: 'Digite apenas o email (sem mailto:)',
|
||||||
|
color: 'bg-success'
|
||||||
|
},
|
||||||
|
'fas fa-phone': {
|
||||||
|
prefix: 'tel:',
|
||||||
|
placeholder: '5511999999999',
|
||||||
|
instructions: 'Digite o telefone com código do país e DDD (apenas números)',
|
||||||
|
color: 'bg-success'
|
||||||
|
},
|
||||||
|
'fab fa-youtube': {
|
||||||
|
prefix: 'https://youtube.com/',
|
||||||
|
placeholder: 'watch?v=VIDEO_ID ou @@usuario ou c/CANAL',
|
||||||
|
instructions: 'Digite o ID do vídeo, @@usuário ou c/canal',
|
||||||
|
color: 'bg-danger'
|
||||||
|
},
|
||||||
|
'fab fa-linkedin': {
|
||||||
|
prefix: 'https://linkedin.com/in/',
|
||||||
|
placeholder: 'seu-perfil-linkedin',
|
||||||
|
instructions: 'Digite apenas seu nome de usuário do LinkedIn',
|
||||||
|
color: 'bg-primary'
|
||||||
|
},
|
||||||
|
'fab fa-github': {
|
||||||
|
prefix: 'https://github.com/',
|
||||||
|
placeholder: 'usuario ou usuario/repositorio',
|
||||||
|
instructions: 'Digite seu usuário ou usuário/repositório',
|
||||||
|
color: 'bg-dark'
|
||||||
|
},
|
||||||
|
'fas fa-map-marker-alt': {
|
||||||
|
prefix: 'https://maps.google.com/?q=',
|
||||||
|
placeholder: 'Rua das Flores, 123 - São Paulo, SP',
|
||||||
|
instructions: 'Digite o endereço completo (acentos e espaços serão codificados automaticamente)',
|
||||||
|
color: 'bg-warning'
|
||||||
|
},
|
||||||
|
'fas fa-globe': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'exemplo.com',
|
||||||
|
instructions: 'Digite apenas o domínio e caminho (sem https://)',
|
||||||
|
color: 'bg-primary'
|
||||||
|
},
|
||||||
|
'fas fa-shopping-cart': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'minhaloja.com/produto',
|
||||||
|
instructions: 'Digite apenas o domínio e caminho da sua loja',
|
||||||
|
color: 'bg-success'
|
||||||
|
},
|
||||||
|
'fas fa-briefcase': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'meuportifolio.com',
|
||||||
|
instructions: 'Digite apenas o domínio do seu portfólio',
|
||||||
|
color: 'bg-info'
|
||||||
|
},
|
||||||
|
'fas fa-download': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'exemplo.com/arquivo.pdf',
|
||||||
|
instructions: 'Digite o link direto para download',
|
||||||
|
color: 'bg-secondary'
|
||||||
|
},
|
||||||
|
'fas fa-calendar': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'calendly.com/seunome',
|
||||||
|
instructions: 'Digite o link do seu calendário (Calendly, etc.)',
|
||||||
|
color: 'bg-info'
|
||||||
|
},
|
||||||
|
'fas fa-heart': {
|
||||||
|
prefix: 'https://',
|
||||||
|
placeholder: 'exemplo.com',
|
||||||
|
instructions: 'Digite qualquer link especial',
|
||||||
|
color: 'bg-danger'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (iconValue && linkTypes[iconValue]) {
|
||||||
|
const config = linkTypes[iconValue];
|
||||||
|
$prefix.text(config.prefix)
|
||||||
|
.removeClass('bg-primary bg-success bg-danger bg-warning bg-info bg-secondary bg-dark')
|
||||||
|
.addClass(config.color);
|
||||||
|
$input.attr('placeholder', config.placeholder);
|
||||||
|
$instructions.text(config.instructions);
|
||||||
|
} else {
|
||||||
|
// Default
|
||||||
|
$prefix.text('https://')
|
||||||
|
.removeClass('bg-success bg-danger bg-warning bg-info bg-secondary bg-dark')
|
||||||
|
.addClass('bg-primary');
|
||||||
|
$input.attr('placeholder', 'exemplo.com');
|
||||||
|
$instructions.text('Selecione primeiro o tipo de link acima');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limpar o campo de input quando trocar tipo
|
||||||
|
$input.val('');
|
||||||
|
$('#linkUrl').val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanAnyUrlPrefix(value) {
|
||||||
|
const prefixes = [
|
||||||
|
'https://', 'http://', 'mailto:', 'tel:', 'whatsapp://',
|
||||||
|
'https://wa.me/', 'https://youtube.com/', 'https://linkedin.com/in/',
|
||||||
|
'https://github.com/', 'https://instagram.com/', 'https://facebook.com/',
|
||||||
|
'https://x.com/', 'https://twitter.com/', 'https://maps.google.com/?q=',
|
||||||
|
'https://www.youtube.com/', 'https://www.linkedin.com/in/',
|
||||||
|
'https://www.github.com/', 'https://www.instagram.com/',
|
||||||
|
'https://www.facebook.com/', 'https://www.twitter.com/'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let prefix of prefixes) {
|
||||||
|
if (value.startsWith(prefix)) {
|
||||||
|
return value.replace(prefix, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
// URL Input Functions
|
// URL Input Functions
|
||||||
function initializeUrlInputs() {
|
function initializeUrlInputs() {
|
||||||
// Setup para link normal
|
// Setup para link normal
|
||||||
@ -1730,20 +1876,37 @@
|
|||||||
|
|
||||||
// Eventos para tratar entrada do usuário
|
// Eventos para tratar entrada do usuário
|
||||||
$input.on('input paste keyup', function() {
|
$input.on('input paste keyup', function() {
|
||||||
let value = $(this).val().trim();
|
let value = $(this).val();
|
||||||
|
const currentPrefix = $('#urlPrefix').text() || 'https://';
|
||||||
|
|
||||||
// Remover https:// ou http:// se o usuário digitou
|
// Apenas processar/limpar a URL para tipos que não sejam de mapa
|
||||||
if (value.startsWith('https://')) {
|
if (currentPrefix !== 'https://maps.google.com/?q=') {
|
||||||
value = value.substring(8);
|
let processedValue = value.trim();
|
||||||
$(this).val(value);
|
processedValue = cleanAnyUrlPrefix(processedValue);
|
||||||
} else if (value.startsWith('http://')) {
|
|
||||||
value = value.substring(7);
|
// Apenas atualiza o DOM se o valor foi alterado para não atrapalhar o cursor
|
||||||
$(this).val(value);
|
if (processedValue !== value) {
|
||||||
|
$(this).val(processedValue);
|
||||||
|
}
|
||||||
|
value = processedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atualizar campo hidden com URL completa
|
// Atualizar campo hidden com URL completa
|
||||||
if (value) {
|
if (value) {
|
||||||
$hidden.val('https://' + value);
|
// Tratar casos especiais
|
||||||
|
if (currentPrefix === 'https://maps.google.com/?q=') {
|
||||||
|
// Para mapas, o usuário digita normalmente. O encoding é feito apenas na URL final.
|
||||||
|
const encodedValue = encodeURIComponent(value);
|
||||||
|
$hidden.val(currentPrefix + encodedValue);
|
||||||
|
} else if (currentPrefix === 'tel:') {
|
||||||
|
// Para telefone, apenas números
|
||||||
|
const telValue = value.replace(/\D/g, '');
|
||||||
|
$(this).val(telValue);
|
||||||
|
$hidden.val(currentPrefix + telValue);
|
||||||
|
} else {
|
||||||
|
// Para outros tipos, a URL é concatenada diretamente
|
||||||
|
$hidden.val(currentPrefix + value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$hidden.val('');
|
$hidden.val('');
|
||||||
}
|
}
|
||||||
@ -1752,15 +1915,8 @@
|
|||||||
// Para modal de edição - detectar se já tem URL e separar
|
// Para modal de edição - detectar se já tem URL e separar
|
||||||
if ($hidden.val()) {
|
if ($hidden.val()) {
|
||||||
const existingUrl = $hidden.val();
|
const existingUrl = $hidden.val();
|
||||||
if (existingUrl.startsWith('https://')) {
|
const cleanValue = cleanAnyUrlPrefix(existingUrl);
|
||||||
$input.val(existingUrl.substring(8));
|
$input.val(cleanValue);
|
||||||
} else if (existingUrl.startsWith('http://')) {
|
|
||||||
$input.val(existingUrl.substring(7));
|
|
||||||
$hidden.val('https://' + existingUrl.substring(7)); // Converter para https
|
|
||||||
} else {
|
|
||||||
$input.val(existingUrl);
|
|
||||||
$hidden.val('https://' + existingUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user