From 2eada5f44c1765fa3f41774ec7ba29295b443e4a Mon Sep 17 00:00:00 2001 From: Ricardo Carneiro Date: Sun, 14 Sep 2025 13:16:50 -0300 Subject: [PATCH] fix: slug duplicado --- .../Repositories/UserPageRepository.cs | 3 +- src/BCards.Web/Views/Admin/ManagePage.cshtml | 72 ++++++++++++++++++- 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/BCards.Web/Repositories/UserPageRepository.cs b/src/BCards.Web/Repositories/UserPageRepository.cs index 708687a..7bf0e59 100644 --- a/src/BCards.Web/Repositories/UserPageRepository.cs +++ b/src/BCards.Web/Repositories/UserPageRepository.cs @@ -93,8 +93,7 @@ public class UserPageRepository : IUserPageRepository { var filter = Builders.Filter.And( Builders.Filter.Eq(x => x.Category, category), - Builders.Filter.Eq(x => x.Slug, slug), - Builders.Filter.Eq(x => x.IsActive, true) + Builders.Filter.Eq(x => x.Slug, slug) ); if (!string.IsNullOrEmpty(excludeId)) diff --git a/src/BCards.Web/Views/Admin/ManagePage.cshtml b/src/BCards.Web/Views/Admin/ManagePage.cshtml index e29ee07..7e8c26d 100644 --- a/src/BCards.Web/Views/Admin/ManagePage.cshtml +++ b/src/BCards.Web/Views/Admin/ManagePage.cshtml @@ -94,9 +94,12 @@ @SlugHelper.CreateCategorySlug(Model.Category) / + - URL gerada automaticamente + URL gerada automaticamente @@ -974,6 +977,11 @@ generateSlug(); updateProgress(); }); + + // Validar slug inicial (para páginas em edição) + if ($('#Slug').val() && $('#Category').val()) { + validateSlugAvailability($('#Category').val(), $('#Slug').val()); + } // Theme selection $('.theme-card').on('click', function() { @@ -1110,17 +1118,77 @@ function generateSlug() { const name = $('#DisplayName').val(); const category = $('#Category').val(); - + if (name && category) { $.post('@Url.Action("GenerateSlug", "Admin")', { category: category, name: name }) .done(function(data) { $('#Slug').val(data.slug); $('#slugPreview').val(data.slug); $('#categorySlug').text(data.category); + + // Validar disponibilidade do slug gerado + validateSlugAvailability(category, data.slug); }); } } + function validateSlugAvailability(category, slug) { + if (!category || !slug) return; + + const excludeId = '@Model.Id' !== '' ? '@Model.Id' : null; + + // Mostrar indicador de carregamento + showSlugValidationStatus('loading', 'Verificando disponibilidade...'); + + $.post('@Url.Action("CheckSlugAvailability", "Admin")', { + category: category, + slug: slug, + excludeId: excludeId + }) + .done(function(response) { + if (response.available) { + showSlugValidationStatus('success', 'URL disponível!'); + } else { + showSlugValidationStatus('error', response.message || 'Esta URL já está em uso.'); + } + }) + .fail(function() { + showSlugValidationStatus('error', 'Erro ao verificar disponibilidade.'); + }); + } + + function showSlugValidationStatus(type, message) { + const $icon = $('#slugIcon'); + const $message = $('#slugValidationMessage'); + const $iconContainer = $('#slugValidationIcon'); + + $iconContainer.show(); + + // Remover classes anteriores + $icon.removeClass('fas fa-check-circle fas fa-times-circle fas fa-spinner fa-spin text-success text-danger text-primary'); + $message.removeClass('text-success text-danger text-primary text-muted'); + + switch(type) { + case 'success': + $icon.addClass('fas fa-check-circle text-success'); + $message.addClass('text-success'); + break; + case 'error': + $icon.addClass('fas fa-times-circle text-danger'); + $message.addClass('text-danger'); + break; + case 'loading': + $icon.addClass('fas fa-spinner fa-spin text-primary'); + $message.addClass('text-primary'); + break; + default: + $iconContainer.hide(); + $message.addClass('text-muted'); + } + + $message.text(message); + } + function addLinkInput(title = '', url = '', description = '', icon = '', linkType = 'Normal', id='new') { // Encontrar o próximo índice disponível baseado em todos os campos Links[] existentes const existingIndexes = [];