fix: links
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 7s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Run Tests (pull_request) Successful in 3s
BCards Deployment Pipeline / Build and Push Image (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (pull_request) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (pull_request) Has been skipped
BCards Deployment Pipeline / PR Validation (pull_request) Successful in 1s
BCards Deployment Pipeline / Deployment Summary (pull_request) Successful in 1s
BCards Deployment Pipeline / Build and Push Image (push) Successful in 6m50s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (push) Successful in 10s
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 1s
All checks were successful
BCards Deployment Pipeline / Run Tests (push) Successful in 7s
BCards Deployment Pipeline / PR Validation (push) Has been skipped
BCards Deployment Pipeline / Run Tests (pull_request) Successful in 3s
BCards Deployment Pipeline / Build and Push Image (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (pull_request) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (pull_request) Has been skipped
BCards Deployment Pipeline / Cleanup Old Resources (pull_request) Has been skipped
BCards Deployment Pipeline / PR Validation (pull_request) Successful in 1s
BCards Deployment Pipeline / Deployment Summary (pull_request) Successful in 1s
BCards Deployment Pipeline / Build and Push Image (push) Successful in 6m50s
BCards Deployment Pipeline / Deploy to Production (ARM - OCI) (push) Has been skipped
BCards Deployment Pipeline / Deploy to Release Swarm (ARM) (push) Successful in 10s
BCards Deployment Pipeline / Cleanup Old Resources (push) Has been skipped
BCards Deployment Pipeline / Deployment Summary (push) Successful in 1s
This commit is contained in:
parent
b6a5329a6b
commit
37cd753a6a
@ -30,7 +30,11 @@
|
||||
"Bash(ssh:*)",
|
||||
"Bash(cat:*)",
|
||||
"Bash(dig:*)",
|
||||
"Bash(git commit:*)"
|
||||
"Bash(git commit:*)",
|
||||
"Bash(netstat:*)",
|
||||
"Bash(ss:*)",
|
||||
"Bash(lsof:*)",
|
||||
"Bash(dotnet run:*)"
|
||||
]
|
||||
},
|
||||
"enableAllProjectMcpServers": false
|
||||
|
||||
@ -535,7 +535,7 @@
|
||||
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/","").Replace("whatsapp://","") : "";
|
||||
var instagramUrl = instagram !=null ? instagram.Url.Replace("https://instagram.com/","").Replace("https://www.instagram.com/","") : "";
|
||||
var tiktokUrl = tiktok !=null ? tiktok.Url.Replace("https://tiktok.com/@@","").Replace("https://www.tiktok.com/@@","").Replace("https://vm.tiktok.com/","") : "";
|
||||
var tiktokUrl = tiktok !=null ? tiktok.Url.Replace("https://tiktok.com/@","").Replace("https://www.tiktok.com/@","").Replace("https://vm.tiktok.com/","") : "";
|
||||
var pinterestUrl = pinterest !=null ? pinterest.Url.Replace("https://pinterest.com/","").Replace("https://www.pinterest.com/","").Replace("https://pin.it/","") : "";
|
||||
var discordUrl = discord !=null ? discord.Url.Replace("https://discord.gg/","").Replace("https://discord.com/invite/","") : "";
|
||||
var kawaiUrl = kawai !=null ? kawai.Url.Replace("https://kawai.com/","").Replace("https://www.kawai.com/","") : "";
|
||||
@ -573,9 +573,12 @@
|
||||
<i class="fab fa-whatsapp text-success me-2"></i>
|
||||
https://wa.me/
|
||||
</span>
|
||||
<input type="text" class="form-control" id="whatsappNumber" placeholder="5511999999999">
|
||||
<input type="text" class="form-control" id="whatsappNumber" placeholder="11987654321">
|
||||
</div>
|
||||
<small class="form-text text-muted">Exemplo: 5511999999999 (código do país + DDD + número)</small>
|
||||
<small class="form-text text-muted">
|
||||
<strong>Brasil:</strong> Digite apenas DDD + número (ex: 11987654321). O código 55 será adicionado automaticamente.<br>
|
||||
<strong>Outros países:</strong> Digite o código do país + número completo.
|
||||
</small>
|
||||
<input asp-for="WhatsAppNumber" type="hidden" value="@(whatsappUrl ?? "")">
|
||||
<span asp-validation-for="WhatsAppNumber" class="text-danger"></span>
|
||||
</div>
|
||||
@ -1204,14 +1207,22 @@
|
||||
checkServerImageErrors();
|
||||
|
||||
// Garantir que campos não marcados sejam string vazia ao submeter
|
||||
$('form').on('submit', function() {
|
||||
$('form').on('submit', function(e) {
|
||||
ensureUncheckedFieldsAreEmpty();
|
||||
|
||||
|
||||
// Validar URLs de redes sociais antes de submeter
|
||||
const validationResult = validateSocialMediaUrls();
|
||||
if (!validationResult.valid) {
|
||||
e.preventDefault();
|
||||
alert('Erro de validação:\n\n' + validationResult.errors.join('\n'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Debug: Verificar quais campos de links estão sendo enviados
|
||||
console.log('=== DEBUG FORM SUBMISSION ===');
|
||||
const formData = new FormData(this);
|
||||
for (let [key, value] of formData.entries()) {
|
||||
if (key.includes('Links[')) {
|
||||
if (key.includes('Links[') || key.includes('Url') || key.includes('Number')) {
|
||||
console.log(`${key}: ${value}`);
|
||||
}
|
||||
}
|
||||
@ -2014,7 +2025,7 @@
|
||||
{ checkbox: '#enableDiscord', hidden: 'input[name="DiscordUrl"]' },
|
||||
{ checkbox: '#enableKawai', hidden: 'input[name="KawaiUrl"]' }
|
||||
];
|
||||
|
||||
|
||||
socialFields.forEach(field => {
|
||||
if (!$(field.checkbox).is(':checked')) {
|
||||
$(field.hidden).val(' '); // Forçar espaço para campos não marcados
|
||||
@ -2022,6 +2033,82 @@
|
||||
});
|
||||
}
|
||||
|
||||
// Validar URLs de redes sociais antes de submeter o formulário
|
||||
function validateSocialMediaUrls() {
|
||||
const errors = [];
|
||||
const userLang = navigator.language || navigator.userLanguage;
|
||||
const isBrazil = userLang.startsWith('pt-BR') || userLang.startsWith('pt');
|
||||
|
||||
// Validar WhatsApp
|
||||
if ($('#enableWhatsApp').is(':checked')) {
|
||||
const whatsappValue = $('input[name="WhatsAppNumber"]').val().trim();
|
||||
if (whatsappValue && whatsappValue !== ' ') {
|
||||
const cleanNumber = whatsappValue.replace('https://wa.me/', '').replace(/\D/g, '');
|
||||
|
||||
if (isBrazil) {
|
||||
// Brasil: deve ter 13 dígitos (55 + DDD + número)
|
||||
if (cleanNumber.length !== 13 || !cleanNumber.startsWith('55')) {
|
||||
errors.push('⚠️ WhatsApp: Número brasileiro deve ter 13 dígitos (55 + DDD + número).\nExemplo: 5511987654321');
|
||||
}
|
||||
} else {
|
||||
// Outros países: validar entre 10 e 15 dígitos
|
||||
if (cleanNumber.length < 10 || cleanNumber.length > 15) {
|
||||
errors.push('⚠️ WhatsApp: Número deve ter entre 10 e 15 dígitos (incluindo código do país).');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validar Facebook
|
||||
if ($('#enableFacebook').is(':checked')) {
|
||||
const facebookValue = $('input[name="FacebookUrl"]').val().trim();
|
||||
if (facebookValue && facebookValue !== ' ') {
|
||||
const cleanUrl = facebookValue.replace('https://facebook.com/', '').replace('https://www.facebook.com/', '');
|
||||
if (cleanUrl.length < 3) {
|
||||
errors.push('⚠️ Facebook: Nome de usuário deve ter pelo menos 3 caracteres.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validar Instagram
|
||||
if ($('#enableInstagram').is(':checked')) {
|
||||
const instagramValue = $('input[name="InstagramUrl"]').val().trim();
|
||||
if (instagramValue && instagramValue !== ' ') {
|
||||
const cleanUrl = instagramValue.replace('https://instagram.com/', '').replace('https://www.instagram.com/', '');
|
||||
if (cleanUrl.length < 3) {
|
||||
errors.push('⚠️ Instagram: Nome de usuário deve ter pelo menos 3 caracteres.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validar Twitter
|
||||
if ($('#enableTwitter').is(':checked')) {
|
||||
const twitterValue = $('input[name="TwitterUrl"]').val().trim();
|
||||
if (twitterValue && twitterValue !== ' ') {
|
||||
const cleanUrl = twitterValue.replace('https://x.com/', '').replace('https://twitter.com/', '');
|
||||
if (cleanUrl.length < 3) {
|
||||
errors.push('⚠️ Twitter/X: Nome de usuário deve ter pelo menos 3 caracteres.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validar TikTok
|
||||
if ($('#enableTiktok').is(':checked')) {
|
||||
const tiktokValue = $('input[name="TiktokUrl"]').val().trim();
|
||||
if (tiktokValue && tiktokValue !== ' ') {
|
||||
const cleanUrl = tiktokValue.replace('https://tiktok.com/@@', '').replace('https://www.tiktok.com/@@', '');
|
||||
if (cleanUrl.length < 3) {
|
||||
errors.push('⚠️ TikTok: Nome de usuário deve ter pelo menos 3 caracteres.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
valid: errors.length === 0,
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
|
||||
// Social Media Functions
|
||||
function cleanSocialPrefix(value, socialType) {
|
||||
const prefixes = {
|
||||
@ -2039,10 +2126,16 @@
|
||||
|
||||
for (let prefix of typePrefixes) {
|
||||
if (value.startsWith(prefix)) {
|
||||
return value.replace(prefix, '');
|
||||
value = value.replace(prefix, '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TikTok: remover @@ do início (o prefixo já tem @@)
|
||||
if (socialType === 'Tiktok' && value.startsWith('@@')) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -2124,9 +2217,19 @@
|
||||
if (isWhatsApp) {
|
||||
// WhatsApp: apenas números
|
||||
value = value.replace(/\D/g, '');
|
||||
|
||||
// Auto-adicionar código +55 para números brasileiros (11 dígitos sem código país)
|
||||
// Detecta cultura pt-BR para aplicar validação BR
|
||||
const userLang = navigator.language || navigator.userLanguage;
|
||||
const isBrazil = userLang.startsWith('pt-BR') || userLang.startsWith('pt');
|
||||
|
||||
if (isBrazil && value.length === 11 && !value.startsWith('55')) {
|
||||
value = '55' + value;
|
||||
}
|
||||
|
||||
$(this).val(value);
|
||||
}
|
||||
|
||||
|
||||
// Atualizar campo hidden - SEMPRE string, nunca null
|
||||
if (value) {
|
||||
hiddenField.val(prefix + value);
|
||||
@ -2142,15 +2245,29 @@
|
||||
function updateSocialFieldFeedback(input, value, isWhatsApp) {
|
||||
// Remover classes anteriores
|
||||
input.removeClass('is-valid is-invalid');
|
||||
|
||||
|
||||
if (!value) return;
|
||||
|
||||
|
||||
if (isWhatsApp) {
|
||||
// Validar WhatsApp (mínimo 10 dígitos)
|
||||
if (value.length >= 10) {
|
||||
input.addClass('is-valid');
|
||||
// Validar WhatsApp com detecção de idioma
|
||||
const userLang = navigator.language || navigator.userLanguage;
|
||||
const isBrazil = userLang.startsWith('pt-BR') || userLang.startsWith('pt');
|
||||
|
||||
if (isBrazil) {
|
||||
// Brasil: validar 13 dígitos (55 + DDD + número)
|
||||
if (value.length === 13 && value.startsWith('55')) {
|
||||
input.addClass('is-valid');
|
||||
} else if (value.length >= 10) {
|
||||
// Ainda está digitando ou formato incorreto
|
||||
input.addClass('is-invalid');
|
||||
}
|
||||
} else {
|
||||
input.addClass('is-invalid');
|
||||
// Outros países: validar mínimo 10 dígitos (genérico)
|
||||
if (value.length >= 10 && value.length <= 15) {
|
||||
input.addClass('is-valid');
|
||||
} else if (value.length > 0) {
|
||||
input.addClass('is-invalid');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Validar username (mínimo 3 caracteres, sem espaços)
|
||||
|
||||
@ -10,6 +10,84 @@
|
||||
Layout = isPreview ? "_PreviewLayout" : "_UserPageLayout";
|
||||
}
|
||||
|
||||
@functions {
|
||||
/// <summary>
|
||||
/// Normaliza URLs de redes sociais para garantir que sempre tenham protocolo HTTPS
|
||||
/// Corrige URLs que foram salvas sem prefixo HTTP(S)
|
||||
/// </summary>
|
||||
string NormalizeSocialUrl(string url, string icon)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url)) return "#";
|
||||
|
||||
// Se já tem protocolo, retorna direto
|
||||
if (url.StartsWith("http://") || url.StartsWith("https://"))
|
||||
return url;
|
||||
|
||||
// WhatsApp - garantir prefixo wa.me
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("whatsapp"))
|
||||
{
|
||||
// Remove qualquer prefixo parcial que possa existir
|
||||
var cleanUrl = url.Replace("wa.me/", "").Replace("whatsapp://", "");
|
||||
return $"https://wa.me/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Facebook
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("facebook"))
|
||||
{
|
||||
var cleanUrl = url.Replace("facebook.com/", "").Replace("fb.com/", "");
|
||||
return $"https://facebook.com/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Instagram
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("instagram"))
|
||||
{
|
||||
var cleanUrl = url.Replace("instagram.com/", "").Replace("instagr.am/", "");
|
||||
return $"https://instagram.com/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Twitter/X
|
||||
if (!string.IsNullOrEmpty(icon) && (icon.Contains("twitter") || icon.Contains("x-twitter")))
|
||||
{
|
||||
var cleanUrl = url.Replace("x.com/", "").Replace("twitter.com/", "");
|
||||
return $"https://x.com/{cleanUrl}";
|
||||
}
|
||||
|
||||
// TikTok
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("tiktok"))
|
||||
{
|
||||
var cleanUrl = url.Replace("tiktok.com/", "").Replace("tiktok.com/@", "");
|
||||
// Se não tem @, adiciona
|
||||
if (!cleanUrl.StartsWith("@"))
|
||||
cleanUrl = "@" + cleanUrl;
|
||||
return $"https://tiktok.com/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Pinterest
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("pinterest"))
|
||||
{
|
||||
var cleanUrl = url.Replace("pinterest.com/", "").Replace("pin.it/", "");
|
||||
return $"https://pinterest.com/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Discord
|
||||
if (!string.IsNullOrEmpty(icon) && icon.Contains("discord"))
|
||||
{
|
||||
var cleanUrl = url.Replace("discord.gg/", "").Replace("discord.com/invite/", "");
|
||||
return $"https://discord.gg/{cleanUrl}";
|
||||
}
|
||||
|
||||
// Kawai ou qualquer outra rede não identificada
|
||||
// Se contém domínio, apenas adiciona https://
|
||||
if (url.Contains(".") || url.Contains("/"))
|
||||
{
|
||||
return $"https://{url.TrimStart('/')}";
|
||||
}
|
||||
|
||||
// Fallback: assume que é uma URL completa que está faltando protocolo
|
||||
return $"https://{url}";
|
||||
}
|
||||
}
|
||||
|
||||
@section Head {
|
||||
@if (isLivePage)
|
||||
{
|
||||
@ -233,7 +311,7 @@
|
||||
(link.Type == BCards.Web.Models.LinkType.Product && !string.IsNullOrEmpty(link.ProductDescription)));
|
||||
|
||||
<div class="universal-link" data-link-id="@i">
|
||||
<a href="@link.Url"
|
||||
<a href="@NormalizeSocialUrl(link.Url, link.Icon)"
|
||||
class="universal-link-header"
|
||||
onclick="recordClick('@Model.Id', @i)"
|
||||
target="_blank"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user