diff --git a/composer.lock b/composer.lock index 71b8d96f..e5f5631f 100644 --- a/composer.lock +++ b/composer.lock @@ -565,16 +565,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.5.20", + "version": "10.5.25", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3" + "reference": "831bf82312be6037e811833ddbea0b8de60ea314" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/547d314dc24ec1e177720d45c6263fb226cc2ae3", - "reference": "547d314dc24ec1e177720d45c6263fb226cc2ae3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/831bf82312be6037e811833ddbea0b8de60ea314", + "reference": "831bf82312be6037e811833ddbea0b8de60ea314", "shasum": "" }, "require": { @@ -646,7 +646,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.20" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.25" }, "funding": [ { @@ -662,7 +662,7 @@ "type": "tidelift" } ], - "time": "2024-04-24T06:32:35+00:00" + "time": "2024-07-03T05:49:17+00:00" }, { "name": "sebastian/cli-parser", @@ -1638,5 +1638,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/docs/releases/release3.md b/docs/releases/release3.md index 3f688d61..ecfc9190 100644 --- a/docs/releases/release3.md +++ b/docs/releases/release3.md @@ -44,3 +44,45 @@ O objetivo principal dessa sprint é a reestruturação dos códigos do plugin. | Customizações visuais na documentação|#149| +## **Sprint 13** + +O objetivo principal dessa sprint é o início do desenvolvimento da tela de edição de formulários na interface, atualização da documentação após a transição da ferramenta Gitpages para Docsify e a revisão dos códigos JavaScript para criação de testes e correção dos erros de console que os navegadores indicam. + +|Descrição| Nº issue| +|---------|---------| +| Remoção do bug nas telas do plugin |#74| +|Atualização da documentação do projeto |#152| +| Pesquisa para a adição da funcionalidade de buscar endereço a partir das coordenadas |#154| +| Corrigir o erro do gráfico da arquitetura na documentação do Docsify |#155| +| Implementação de testes para o código JS da página do administrador |#156| +| Implementação de testes para o código JS do shortcode |#157| +| Criação da tela básica de edição na interface do administrador |#158| +| Funcionalidades de exibição dos dados do formulário nos campos da tela de edição |#159| + +## **Sprint 14** + +O objetivo dessa sprint é a continuação do desenvolvimento da ferramenta de edição dos formulários, atualização da documentação, desenvolvimento do visual da interface do administrador, adição de um marcador personalizado nos mapas e desenvolvimento do desing da tela de edição. + +|Descrição| Nº issue| +|---------|---------| +| Adição do mapa na tela edição + funcionalidade de busca|#160| +| Atualização dos artefatos da documentação|#162| +| Desenvolvimento do desing da interface|#163| +| Desenvolvimento do design da tela de edição|#164| +| Marcador personalizado|#166| +| Campo de busca no mapa da edição |#167| +| Resultados repetidos na busca (tela de edição)|#168| +| Salvar alterações na tela de edição |#169| +| Implementação de testes para o código JS da página do administrador e refatoração parcial do código JS do shortcode|#171| + + +## **Sprint 15** + +O objetivo principal dessa sprint é a finalização da tela de edição para disponibilização da funcionalidade no ambiente de produção. Além de alguns ajustes no desenvolvimento do front end da tela de edição de acordo com o wireframe disponibilizado, resolução de bugs da tela de edição, criação do teste para a funcionalidade de editar os dados do formulário, finalizar transição da gitpages para docsify na documentação, adição da Sprint 15 na documentação. + +|Descrição| Nº issue| +|---------|---------| +| Desenvolvimento do front end da tela de edição |#173| +| Criação do teste para a funcionalidade de editar os dados do formulário|#175| +| Finalizar transição da gitpages para docsify na documentação|#176| +| Adição da Sprint 15 na documentação |#177| diff --git a/lgbtq_connect/assets/imgs/custom_marker.png b/lgbtq_connect/assets/imgs/custom_marker.png new file mode 100644 index 00000000..902fc3bc Binary files /dev/null and b/lgbtq_connect/assets/imgs/custom_marker.png differ diff --git a/lgbtq_connect/assets/index.html b/lgbtq_connect/assets/index.html index 0a6e6975..321f2f87 100644 --- a/lgbtq_connect/assets/index.html +++ b/lgbtq_connect/assets/index.html @@ -11,7 +11,7 @@
- +
@@ -26,7 +26,7 @@
- +
+ @@ -49,7 +50,7 @@
- +
diff --git a/lgbtq_connect/assets/js/formulario.js b/lgbtq_connect/assets/js/formulario.js index 610c42ff..6d285291 100644 --- a/lgbtq_connect/assets/js/formulario.js +++ b/lgbtq_connect/assets/js/formulario.js @@ -1,23 +1,53 @@ var ajaxUrl = my_ajax_object.ajax_url; document.addEventListener('DOMContentLoaded', function () { + // Verifica se há dados no localStorage e os exibe + if (localStorage.getItem('formData')) { + console.log('Dados enviados anteriormente:'); + console.log(JSON.parse(localStorage.getItem('formData'))); + localStorage.removeItem('formData'); // Limpa os dados após exibi-los + } + $('#meu_formulario').on('submit', function (e) { - e.preventDefault(); // Previne que o formulário dê submit na forma padrão - // Verifica se os campos estão preenchidos + e.preventDefault(); + var nome = document.getElementById('nome').value; var email = document.getElementById('email_f').value; var latitude = document.getElementById('latitude').value; var longitude = document.getElementById('longitude').value; var servico = document.getElementById('servico').value; var descricao = document.getElementById('descricao').value; - var outroServico = document.getElementById('servico_outro').value + var outroServico = document.getElementById('servico_outro').value; + + // Função para verificar caracteres especiais + function hasSpecialChars(str) { + return /[!#$%&()*+\/<=>?@[\\\]_{|}]/.test(str); + } + + + if (nome === '' || email === '' || latitude === '' || longitude === '' || (servico === 'outro' && outroServico === '')) { alert('Por favor, preencha todos os campos.'); - console.log(nome,email,latitude,longitude,servico,descricao,outroServico) return; - }else { + } else if (hasSpecialChars(nome) || hasSpecialChars(descricao) || hasSpecialChars(outroServico)) { + alert("Não insira caracteres especiais"); + console.log('Campos com caracteres especiais:', { nome, descricao, outroServico }); + return; + } else { // Serializa os dados do formulário var formData = $(this).serialize(); + var formDataObject = { + nome: nome, + email: email, + latitude: latitude, + longitude: longitude, + servico: servico, + descricao: descricao, + outroServico: outroServico + }; + + // Armazena os dados no localStorage + localStorage.setItem('formData', JSON.stringify(formDataObject)); // Envia o pedido do AJAX $.ajax({ @@ -29,16 +59,15 @@ document.addEventListener('DOMContentLoaded', function () { }, success: function (response) { // Resposta caso dê certo - console.log(response); + console.log('Resposta do servidor:', response); // Se o envio for bem-sucedido, executar a função exit_page() transicaoPagina("PaginaComPopup", "div_saida"); }, error: function (xhr, status, error) { // Resposta caso dê errado - console.error(error); + console.error('Erro no envio do formulário:', error); }, }); } }); -}); - +}); \ No newline at end of file diff --git a/lgbtq_connect/assets/js/funcionalidades.js b/lgbtq_connect/assets/js/funcionalidades.js index 59f72f51..68d5546d 100644 --- a/lgbtq_connect/assets/js/funcionalidades.js +++ b/lgbtq_connect/assets/js/funcionalidades.js @@ -1,137 +1,121 @@ -var resultados = []; // Array para armazenar os locais relacionados -var isSearchingIndex = false; // Status de busca no index -var isSearchingForm = false; // Status de busca no form - -function searchButtonClicked() { - if (!isSearchingIndex) { - isSearchingIndex = true; - var searchTerm = document.getElementById('searchInputIndex').value; - searchLocations(searchTerm, 'listaResultadosIndex'); +class Pesquisador { + constructor(listaId) { + this.listaId = listaId; + this.flag = false; } - return false; -} -function searchButtonClickedForm() { - if (!isSearchingForm) { - isSearchingForm = true; - var searchTerm = document.getElementById('searchInputForm').value; - searchLocations(searchTerm, 'listaResultadosForms'); - } - return false; -} + pesquisarLocalizacoes(query) { + if(this.flag) { + return; + } + + this.flag = true; -function searchLocations(query, resultListId) { - resultados = []; - var apiUrl = 'https://nominatim.openstreetmap.org/search?format=json&q=' + encodeURIComponent(query); - fetch(apiUrl) - .then(response => response.json()) - .then(data => { - data.forEach(location => { - resultados.push({ - display_name: location.display_name, - lat: location.lat, - lon: location.lon + let resultados = []; + const self = this; + let apiUrl = 'https://nominatim.openstreetmap.org/search?format=json&q=' + encodeURIComponent(query); + fetch(apiUrl) + .then(response => response.json()) + .then(data => { + data.forEach(location => { + resultados.push({ + display_name: location.display_name, + lat: location.lat, + lon: location.lon + }); }); - }); - imprimirResultados(resultados, resultListId); + self.imprimirResultados(resultados); - // Atualiza o estado da busca após a conclusão - if (resultListId === 'listaResultadosIndex') { - isSearchingIndex = false; // Marca a busca na página inicial como concluída - } else if (resultListId === 'listaResultadosForms') { - isSearchingForm = false; // Marca a busca no formulário como concluída - } - }) - .catch(error => { - console.error('Erro ao buscar locais:', error); + self.flag = false; // Marca a busca no formulário como concluída + }) + .catch(error => { + console.error('Erro ao buscar locais:', error); - // Em caso de erro, atualiza o estado da busca para permitir novas buscas - if (resultListId === 'listaResultadosIndex') { - isSearchingIndex = false; // Marca a busca na página inicial como concluída - } else if (resultListId === 'listaResultadosForms') { - isSearchingForm = false; // Marca a busca no formulário como concluída - } - }); -} + self.flag = false; // Marca a busca no formulário como concluída + }); + } -function imprimirResultados(resultados, resultListId) { - var listaResultadosOcultados = []; - var listaResultados = document.getElementById(resultListId); - listaResultados.innerHTML = ''; - var count = 0; - var div = document.createElement('div'); - resultados.forEach(resultado => { - var divResultado = document.createElement('div'); - divResultado.classList.add('celula_resultado'); - divResultado.style.borderRadius = '3px'; - divResultado.style.margin = '5px 5px 5px 0px'; - divResultado.style.cursor = 'pointer'; - divResultado.innerHTML = '' + resultado.display_name; - divResultado.addEventListener('click', function () { - changeMapLocation(resultado.lat, resultado.lon); + imprimirResultados(resultados) { + let listaResultadosOcultados = []; + const listaResultados = document.getElementById(this.listaId); + listaResultados.innerHTML = ''; + let count = 0; + const div = document.createElement('div'); + resultados.forEach(resultado => { + const divResultado = document.createElement('div'); + divResultado.classList.add('celula_resultado'); + divResultado.style.borderRadius = '3px'; + divResultado.style.margin = '5px 5px 5px 0px'; + divResultado.style.cursor = 'pointer'; + divResultado.innerHTML = '' + resultado.display_name; + divResultado.addEventListener('click', function () { + if (pagina) { + pagina.mapa.mudarLocalizacao([resultado.lat, resultado.lon]); + } + }); + count += 1; + if(count <=5){ + div.appendChild(divResultado); + } else { + divResultado.style.display = 'none'; + listaResultadosOcultados.push(divResultado); + div.appendChild(divResultado); + } }); - count += 1; - if(count <=5){ - div.appendChild(divResultado); - } else { - divResultado.style.display = 'none'; - listaResultadosOcultados.push(divResultado); - div.appendChild(divResultado); - } - }); - listaResultados.appendChild(div); + listaResultados.appendChild(div); - if (count > 5){ - // Adicionando botão "Ver Mais" - var verMaisButton = document.createElement('button'); - verMaisButton.textContent = 'Ver Mais'; - verMaisButton.setAttribute('type', 'button'); - verMaisButton.setAttribute('class', 'ver'); - verMaisButton.addEventListener('click', function() { - MostrarMaisResultados(); - }); + if (count > 5){ + // Adicionando botão "Ver Mais" + const verMaisButton = document.createElement('button'); + verMaisButton.textContent = 'Ver Mais'; + verMaisButton.setAttribute('type', 'button'); + verMaisButton.setAttribute('class', 'ver'); + verMaisButton.addEventListener('click', function() { + MostrarMaisResultados(); + }); - listaResultados.appendChild(verMaisButton); + listaResultados.appendChild(verMaisButton); - // Adicionando botão "Ver Menos" - var verMenosButton = document.createElement('button'); - verMenosButton.textContent = 'Ver Menos'; - verMenosButton.setAttribute('type', 'button'); - verMenosButton.setAttribute('class', 'ver'); - verMenosButton.addEventListener('click', function() { - MostrarMenosResultados(); - }); - verMenosButton.style.display = 'none'; + // Adicionando botão "Ver Menos" + const verMenosButton = document.createElement('button'); + verMenosButton.textContent = 'Ver Menos'; + verMenosButton.setAttribute('type', 'button'); + verMenosButton.setAttribute('class', 'ver'); + verMenosButton.addEventListener('click', function() { + MostrarMenosResultados(); + }); + verMenosButton.style.display = 'none'; - listaResultados.appendChild(verMenosButton); + listaResultados.appendChild(verMenosButton); - // Função para mostrar mais resultados - function MostrarMaisResultados() { - listaResultadosOcultados.forEach(resultado => { - resultado.style.display = 'block'; - }); - verMaisButton.style.display = 'none'; - verMenosButton.style.display = 'block'; - } + // Função para mostrar mais resultados + function MostrarMaisResultados() { + listaResultadosOcultados.forEach(resultado => { + resultado.style.display = 'block'; + }); + verMaisButton.style.display = 'none'; + verMenosButton.style.display = 'block'; + } - // Função para mostrar menos resultados - function MostrarMenosResultados() { - listaResultadosOcultados.forEach(resultado => { - resultado.style.display = 'none'; - }); - verMaisButton.style.display = 'block'; - verMenosButton.style.display = 'none'; + // Função para mostrar menos resultados + function MostrarMenosResultados() { + listaResultadosOcultados.forEach(resultado => { + resultado.style.display = 'none'; + }); + verMaisButton.style.display = 'block'; + verMenosButton.style.display = 'none'; + } } } } -function changeMapLocation(latitude, longitude) { - if (pagina) - { - pagina.mapa.mudarLocalizacao([latitude, longitude]); - } +function pesquisar(id, listaId) { + const el = document.getElementById(id); + let query = el.value; + const pesquisador = new Pesquisador(listaId) + pesquisador.pesquisarLocalizacoes(query); } function mostrarOutro() { diff --git a/lgbtq_connect/assets/js/script.js b/lgbtq_connect/assets/js/script.js index b5b1d154..eab686e9 100644 --- a/lgbtq_connect/assets/js/script.js +++ b/lgbtq_connect/assets/js/script.js @@ -1,13 +1,20 @@ let pagina = null; - // CLASSES +// Definindo o ícone personalizado no escopo global +var personalIcon = L.icon({ + iconUrl: 'https://res.cloudinary.com/dxsx0emuu/image/upload/f_auto,q_auto/lc_marker', + iconSize: [20, 30], // tamanho do ícone + popupAnchor: [1, -10] +}); + +// CLASSES class Mapa { container; static MAPAS = { - "div_index" : "mapa_index", - "div_form" : "mapa_formulario", - "div_saida" : "mapa_saida" + "div_index": "mapa_index", + "div_form": "mapa_formulario", + "div_saida": "mapa_saida" } constructor(container) { @@ -15,9 +22,9 @@ class Mapa { this.mapa = L.map(this.container, { doubleClickZoom: false }).setView([-15.8267, -47.9218], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' + attribution: '© OpenStreetMap contributors' }).addTo(this.mapa); - + this.marcadores = []; } @@ -35,8 +42,8 @@ class Mapa { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function (position) { let user_position = []; - user_position.push(position.coords.latitude); - user_position.push(position.coords.longitude); + user_position.push(position.coords.latitude); + user_position.push(position.coords.longitude); self.mudarLocalizacao(user_position); }); } else { @@ -47,13 +54,9 @@ class Mapa { } destruirMapa() { - this.mapa.remove() + this.mapa.remove(); this.mapa = null; } - - static sum(a, b) { - return a+b; - } } class Pagina { @@ -62,7 +65,6 @@ class Pagina { this.id = id; this.div = document.getElementById(id); this.mapa = null; - } inicializar() { @@ -72,8 +74,7 @@ class Pagina { } destruir() { - if(this.mapa !== null) - { + if (this.mapa !== null) { this.mapa.destruirMapa(); } this.div.style.display = "none"; @@ -84,18 +85,17 @@ class PaginaComPopup extends Pagina { inicializar() { super.inicializar(); - for(var i = 0; i -

${formulario.nome}

- ${formulario.servico} -
-

${formulario.descricao}

- - `; - this.mapa.adicionarMarcador(L.marker([formulario.latitude, formulario.longitude]).bindPopup(popupConteudo)); +
+

${formulario.nome}

+ ${formulario.servico} +
+

${formulario.descricao}

+
+ `; + this.mapa.adicionarMarcador(L.marker([formulario.latitude, formulario.longitude], { icon: personalIcon }).bindPopup(popupConteudo)); } } @@ -105,18 +105,14 @@ class PaginaComPopup extends Pagina { } class PaginaFormulario extends Pagina { - inicializar() { super.inicializar(); this.marcador = null; var self = this; - this.mapa.mapa.on('click', function(e) { - - if(self.marcador==null) - { - self.marcador = L.marker(e.latlng).addTo(self.mapa.mapa); + this.mapa.mapa.on('click', function (e) { + if (self.marcador == null) { + self.marcador = L.marker(e.latlng, { icon: personalIcon }).addTo(self.mapa.mapa); } - self.marcador.setLatLng(e.latlng); var lat = e.latlng.lat; // Latitude @@ -125,7 +121,7 @@ class PaginaFormulario extends Pagina { // Atualiza os valores dos campos de entrada ocultos document.getElementById('latitude').value = lat; document.getElementById('longitude').value = lng; - }) + }); this.mapa.mapa.on('contextmenu', function (e) { // Verifica se existe um marcador atual @@ -138,10 +134,9 @@ class PaginaFormulario extends Pagina { } }); - for(var i = 0; iNegar + `, + "Negado": ` + + `, + "Pendente": ` + + + ` + }; + + const tbody = this.tabela.querySelector('tbody'); + + this.arr.forEach(dados => { + const linha = document.createElement('tr'); + linha.id = "formulario-" + dados.id; + let descricao; + let data = new Date(dados.data_hora); + let dataFormatada = Tabela.formatarDataHora(data); + if (dados.descricao.length > 10) { + descricao = ` + ${dados.descricao.substring(0, 10)}... + + + `; + } else { + descricao = dados.descricao; + } + + let acoes = STATUS_BOTOES[dados.situacao]; + + linha.innerHTML = ` + ${dados.nome} + ${dados.email} + ${dados.city} + ${dados.road} + ${dados.servico} + ${descricao} + ${dataFormatada} + ${dados.situacao} + +
+ + +
+ + `; + tbody.appendChild(linha); + }); + } +} + +function destacarLinhaTabela(id) { + let tabela = document.getElementById("tabela"); + let linha = document.getElementById(("formulario-" + id)); + + if (linha === null) { + return; + } + + // Loop para remover a linha-destacada de todas as linhas + for (let i = 0, row; (row = tabela.rows[i]); i++) { + row.classList.remove('linha-destacada'); + } + + linha.classList.add('linha-destacada'); // Adiciona a classe 'linha-destacada' + linha.scrollIntoView({ behavior: 'smooth' }); // Rola a página para a linha + setTimeout(function () { + linha.classList.remove('linha-destacada'); + }, 3000); } function mostrarDescricaoCompleta(id) { @@ -48,130 +190,80 @@ function mostrarDescricaoCompleta(id) { botao.innerText = 'Ver menos'; } } -function destacarLinhaTabela(id) { - var tabela = document.getElementById("tabela"); - var linha = document.getElementById(id); - - // Loop para remover a linha-destacada de todas as linhas - for (var i = 0, row; (row = tabela.rows[i]); i++) { - row.classList.remove('linha-destacada'); - } - - linha.classList.add('linha-destacada'); // Adiciona a classe 'linha-destacada' - linha.scrollIntoView({ behavior: 'smooth' }); // Rola a página para a linha - - // Remove a classe linha-destacada depois de um determinado tempo - setTimeout(function () { - linha.classList.remove('linha-destacada'); - }, 2000); -} function initMapAdmin() { - if(document.getElementById('mapa_admin') == null) - { + // Definindo o ícone personalizado no escopo global + const personalIcon = L.icon({ + iconUrl: 'https://res.cloudinary.com/dxsx0emuu/image/upload/f_auto,q_auto/lc_marker', + iconSize: [20, 30], // tamanho do ícone + popupAnchor: [1, -10] + }); + + if (document.getElementById('mapa_admin') == null) { return; } - mapAdmin = L.map('mapa_admin', {doubleClickZoom: false}).setView([-15.8267, -47.9218], 13); + mapAdmin = L.map('mapa_admin', { doubleClickZoom: false }).setView([-15.8267, -47.9218], 13); // Adiciona o provedor de mapa OpenStreetMap L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(mapAdmin); - formularios_aprovados.forEach(function(formulario) { - L.marker([formulario.latitude, formulario.longitude]).addTo(mapAdmin).on('click', function() { - + formularios_aprovados.forEach(function (formulario) { + L.marker([formulario.latitude, formulario.longitude], { icon: personalIcon }).addTo(mapAdmin).on('click', function () { destacarLinhaTabela(formulario.id); }); }); } -function initSortButtons() { - // Adiciona um evento de clique aos botões de ordenação - var sortButtons = document.querySelectorAll('.sort-btn'); - - sortButtons.forEach(function(button) { - button.addEventListener('click', function() { - var table = button.closest('table'); - var columnIndex = Array.from(button.parentNode.parentNode.children).indexOf(button.parentNode); - var order = button.getAttribute('data-order') || 'asc'; - - order = (order === 'asc') ? 'desc' : 'asc'; - button.setAttribute('data-order', order); - - // Atualiza o ícone do botão de ordenação - var icon = button.querySelector('.sort-icon'); - - // Remove e adiciona a classe do ícone com base na direção da ordenação - if (order === 'asc') { - icon.innerHTML = '▾'; // Triângulo para baixo (ordem crescente) - } else { - icon.innerHTML = '▴'; // Triângulo para cima (ordem decrescente) - } - - // Obtém todas as linhas da tabela, exceto a primeira (cabeçalho) - var rows = Array.from(table.querySelectorAll('tbody > tr')); +function initMapEdit(latitude, longitude, nome, servico, descricao) { + // Definindo o ícone personalizado no escopo global + const personalIcon = L.icon({ + iconUrl: 'https://res.cloudinary.com/dxsx0emuu/image/upload/f_auto,q_auto/lc_marker', + iconSize: [20, 30], // tamanho do ícone + popupAnchor: [1, -10] + }); - // Determina o critério de ordenação com base na classe do botão - if (button.classList.contains('sort-by-date')) { - rows.sort(function(a, b) { - var aValue = new Date(a.children[columnIndex].textContent.trim().replace(/(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})/, '$3-$2-$1T$4:$5:$6')); - var bValue = new Date(b.children[columnIndex].textContent.trim().replace(/(\d{2})\/(\d{2})\/(\d{4}) (\d{2}):(\d{2}):(\d{2})/, '$3-$2-$1T$4:$5:$6')); + // Verifica se o mapa já foi inicializado e destrói se necessário + if (mapEdit !== undefined) { + mapEdit.remove(); + } - return (order === 'asc') ? aValue - bValue : bValue - aValue; - }); - } else if (button.classList.contains('sort-by-email')) { - rows.sort(function(a, b) { - var aValue = a.children[columnIndex].textContent.trim().toLowerCase(); - var bValue = b.children[columnIndex].textContent.trim().toLowerCase(); + mapEdit = L.map('mapa_formulario_edit', { doubleClickZoom: false }).setView([-15.8267, -47.9218], 13); - return (order === 'asc') ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); - }); - } else { - // Caso padrão: ordenação por texto - rows.sort(function(a, b) { - var aValue = a.children[columnIndex].textContent.trim().toLowerCase(); - var bValue = b.children[columnIndex].textContent.trim().toLowerCase(); - - return (order === 'asc') ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue); - }); - } + // Adiciona o provedor de mapa OpenStreetMap + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(mapEdit); + + var popupConteudo = ` +
+

${nome}

+ ${servico} +
+

${descricao}

+
+ `; + + // Função para atualizar os inputs de latitude e longitude + function updateInputs(lat, lng) { + document.getElementById('editLatitude').value = lat; + document.getElementById('editLongitude').value = lng; + } - // Limpa o conteúdo da tabela antes de reordenar - while (table.querySelector('tbody').firstChild) { - table.querySelector('tbody').removeChild(table.querySelector('tbody').firstChild); - } + // Adiciona um marcador arrastável + var marker = L.marker( + [latitude, longitude], + {draggable: true, icon: personalIcon } + ).addTo(mapEdit).bindPopup(popupConteudo); - // Reinsere as linhas ordenadas na tabela - rows.forEach(function(row) { - table.querySelector('tbody').appendChild(row); - }); - }); + marker.on('dragend', function (e) { + var newPosition = marker.getLatLng(); + updateInputs(newPosition.lat, newPosition.lng); }); -} -// Limpa o conteúdo da tabela -function excluirLinhas(tabela) -{ - while (tabela.querySelector('tbody').firstChild) { - tabela.querySelector('tbody').removeChild(tabela.querySelector('tbody').firstChild); - } -} - -function adicionarZero(numero) { - return numero < 10 ? '0' + numero : numero; -} - -function formatarDataHora(data) { - const dia = adicionarZero(data.getDate()); - const mes = adicionarZero(data.getMonth() + 1); // Adiciona 1 porque os meses são indexados de 0 a 11 - const ano = data.getFullYear(); - const hora = adicionarZero(data.getHours()); - const minutos = adicionarZero(data.getMinutes()); - const segundos = adicionarZero(data.getSeconds()); - - return `${dia}/${mes}/${ano} ${hora}:${minutos}:${segundos}`; + document.getElementById('mapa_admin').style.display = "block"; } function confirmarAcao(mensagem, formulario, acao) { @@ -206,99 +298,221 @@ function confirmarAcao(mensagem, formulario, acao) { }; } -function gerarLinhas(tabela, arr) -{ - const STATUS_BOTOES = { - "Aprovado" : ` - - `, - "Negado" : ` - - `, - "Pendente" : ` - - - ` +function abrirModalEdicao(dados) { + const popup = document.getElementById("editPopup"); + const modal = document.getElementById('editModal'); + + // Preenche os campos do formulário com os dados fornecidos + document.getElementById('editId').value = dados.id; + document.getElementById('editNome').value = dados.nome; + document.getElementById('editEmail').value = dados.email; + document.getElementById('editServico').value = dados.servico; + document.getElementById('editDescricao').value = dados.descricao; + document.getElementById('editLatitude').value = dados.latitude; + document.getElementById('editLongitude').value = dados.longitude; + + initMapEdit(dados.latitude, dados.longitude, dados.nome, dados.servico, dados.descricao); + + // Exibe o modal de edição + popup.style.display = "flex"; + modal.style.display = "block"; + + // Atualiza o tamanho do mapa e define a visualização após um pequeno atraso para garantir que o modal tenha sido completamente exibido + setTimeout(function() { + mapEdit.invalidateSize(); + mapEdit.setView([dados.latitude, dados.longitude], 13); + }, 200); + + modal.scrollIntoView({ behavior: 'smooth' }); + + // Fecha o modal de edição quando o usuário clica fora do modal + window.onclick = function(event) { + if (event.target == popup) { + fecharEditor(); + } + }; +} + +function fecharEditor() { + document.getElementById('editPopup').style.display = "none"; + document.getElementById('editModal').style.display = "none"; + document.getElementById('mapa_admin').style.display = "block"; + document.getElementById('listaResultadosEdit').innerHTML = ''; + document.getElementById('searchInputFormEdit').value = ''; +} + +function searchButtonClickedEdit() { + if (isSearching) { + return; // Se uma busca já estiver em andamento, saia da função } - var tbody = tabela.querySelector('tbody'); - - arr.forEach(dados => { - var linha = document.createElement('tr'); - linha.id = dados.id; - var descricao; - var data = new Date(dados.data_hora); - var dataFormatada = formatarDataHora(data); - if (dados.descricao.length > 10){ - descricao = ` - ${dados.descricao.substring(0, 10)}... - - - ` + isSearching = true; // Indica que uma busca está em andamento + var searchTerm = document.getElementById('searchInputFormEdit').value; + searchLocations(searchTerm); +} + +function searchLocations(query) { + var resultados = []; + var apiUrl = 'https://nominatim.openstreetmap.org/search?format=json&q=' + encodeURIComponent(query); + fetch(apiUrl) + .then(response => response.json()) + .then(data => { + data.forEach(location => { + resultados.push({ + display_name: location.display_name, + lat: location.lat, + lon: location.lon + }); + }); + imprimirResultados(resultados); + isSearching = false; // Indica que a busca foi concluída + }) + .catch(error => { + console.error('Erro ao buscar locais:', error); + isSearching = false; // Indica que a busca foi concluída mesmo com erro + }); +} + +function imprimirResultados(resultados) { + var listaResultadosOcultados = []; + var listaResultados = document.getElementById('listaResultadosEdit'); + + listaResultados.innerHTML = ''; + var count = 0; + var div = document.createElement('div'); + resultados.forEach(resultado => { + var divResultado = document.createElement('div'); + divResultado.classList.add('celula_resultado'); + divResultado.style.borderRadius = '3px'; + divResultado.style.margin = '5px 5px 5px 0px'; + divResultado.style.cursor = 'pointer'; + divResultado.innerHTML = '' + resultado.display_name; + divResultado.addEventListener('click', function () { + changeMapView(resultado.lat, resultado.lon); + }); + count += 1; + if(count <= 5) { + div.appendChild(divResultado); + } else { + divResultado.style.display = 'none'; + listaResultadosOcultados.push(divResultado); + div.appendChild(divResultado); + } + }); + + listaResultados.appendChild(div); + + if (count > 5) { + // Adicionando botão "Ver Mais" + var verMaisButton = document.createElement('button'); + verMaisButton.textContent = 'Ver Mais'; + verMaisButton.setAttribute('type', 'button'); + verMaisButton.setAttribute('class', 'ver'); + verMaisButton.addEventListener('click', function() { + MostrarMaisResultados(); + }); + + listaResultados.appendChild(verMaisButton); + + // Adicionando botão "Ver Menos" + var verMenosButton = document.createElement('button'); + verMenosButton.textContent = 'Ver Menos'; + verMenosButton.setAttribute('type', 'button'); + verMenosButton.setAttribute('class', 'ver'); + verMenosButton.addEventListener('click', function() { + MostrarMenosResultados(); + }); + verMenosButton.style.display = 'none'; + + listaResultados.appendChild(verMenosButton); + + // Função para mostrar mais resultados + function MostrarMaisResultados() { + listaResultadosOcultados.forEach(resultado => { + resultado.style.display = 'block'; + }); + verMaisButton.style.display = 'none'; + verMenosButton.style.display = 'block'; } - else { - descricao = dados.descricao; + + // Função para mostrar menos resultados + function MostrarMenosResultados() { + listaResultadosOcultados.forEach(resultado => { + resultado.style.display = 'none'; + }); + verMaisButton.style.display = 'block'; + verMenosButton.style.display = 'none'; } - - acoes = STATUS_BOTOES[dados.situacao]; - - linha.innerHTML = ` - ${dados.nome} - ${dados.email} - ${dados.latitude} - ${dados.longitude} - ${dados.servico} - ${descricao} - ${dataFormatada} - ${dados.situacao} - -
- - - ${acoes} - - - - `; - tbody.appendChild(linha); - }); + } } - function filtrar(elemento) { let arr = []; const filtro_nome = document.getElementById("busca_nome"); const filtro_servico = document.getElementById("selecao_servico"); - const contador_resultados = document.getElementById("contador_resultados"); - if (elemento) { Filtro.status = elemento.value; } - if(filtro_nome) - { - Filtro.nome = filtro_nome.value.toLowerCase().trim(); + if (filtro_nome) { + Filtro.nome = filtro_nome.value; } - if (filtro_servico) - { + if (filtro_servico) { Filtro.servico = filtro_servico.value; } - arr = Filtro.realizarFiltragem(formularios_todos); contador_resultados.innerHTML = `

${arr.length} resultados encontrados

`; const tabela = document.getElementById("tabela"); - excluirLinhas(tabela); - gerarLinhas(tabela, arr); + const tabelaObj = new Tabela([], tabela); + tabelaObj.arr = arr; + + tabelaObj.excluirLinhas(); + tabelaObj.gerarLinhas(); +} + +function ordenar(elemento) { + let order = elemento.getAttribute('data-order') || 'asc'; + + order = (order === 'asc') ? 'desc' : 'asc'; + elemento.setAttribute('data-order', order); + + // Atualiza o ícone do botão de ordenação + var icon = elemento.querySelector('.sort-icon'); + + // Remove e adiciona a classe do ícone com base na direção da ordenação + if (order === 'asc') { + icon.innerHTML = '▾'; // Triângulo para baixo (ordem crescente) + } else { + icon.innerHTML = '▴'; // Triângulo para cima (ordem decrescente) + } + + Ordenador.ordem = order; + + // Determina o critério de ordenação com base na classe do botão + if (elemento.classList.contains('sort-by-date')) { + Ordenador.coluna = "data_hora"; + } else if (elemento.classList.contains('sort-by-email')) { + Ordenador.coluna = "email"; + } else { + // Caso padrão: ordenação por nome + Ordenador.coluna = "nome"; + } + + const tabelaObj = new Tabela([], tabela); + tabelaObj.arr = Ordenador.realizarOrdenacao(tabelaObj.arr); + + tabelaObj.excluirLinhas(); + tabelaObj.gerarLinhas(); } // Adiciona um evento de clique a todos os botões de "Ver mais/menos" -document.querySelectorAll('.ver-mais-btn').forEach(function(button) { - button.addEventListener('click', function() { +document.querySelectorAll('.ver-mais-btn').forEach(function (button) { + button.addEventListener('click', function () { var id = button.getAttribute('data-id'); mostrarDescricaoCompleta(id); }); @@ -306,7 +520,12 @@ document.querySelectorAll('.ver-mais-btn').forEach(function(button) { // Inicializa o mapa e os botões de ordenação quando a página carrega window.onload = function () { - initSortButtons(); initMapAdmin(); }; +// Exporta as classes +module.exports = { + Filtro, + Ordenador, + Tabela +}; \ No newline at end of file diff --git a/lgbtq_connect/includes/admin/formulario-admin-page.php b/lgbtq_connect/includes/admin/formulario-admin-page.php index 0d90f52b..34bf53c6 100644 --- a/lgbtq_connect/includes/admin/formulario-admin-page.php +++ b/lgbtq_connect/includes/admin/formulario-admin-page.php @@ -1,4 +1,36 @@ window.location.href = window.location.href;'; +} + +// Função para processar a atualização do formulário +function atualizar_formulario($wpdb, $funcao_localizacao) { + // Verifique se os dados necessários estão presentes + if (!isset($_POST['id'], $_POST['nome'], $_POST['email'], $_POST['servico'], $_POST['descricao'], $_POST['latitude'], $_POST['longitude'])) { + wp_die('Dados insuficientes'); + } + + $id = intval($_POST['id']); + $nome = sanitize_text_field($_POST['nome']); + $email = sanitize_email($_POST['email']); + $servico = sanitize_text_field($_POST['servico']); + $descricao = sanitize_textarea_field($_POST['descricao']); + $latitude = sanitize_text_field($_POST['latitude']); + $longitude = sanitize_text_field($_POST['longitude']); + + list($road, $city) = $funcao_localizacao($latitude, $longitude); + + // Atualiza os dados no banco de dados + $tabela = "lc_formulario"; + $dados = array( + 'nome' => $nome, + 'email' => $email, + 'servico' => $servico, + 'descricao' => $descricao, + 'latitude' => $latitude, + 'longitude' => $longitude, + 'road' => $road, + 'city' => $city, + ); + + $condicoes = array('id' => $id); + + $resultado = $wpdb->update($tabela, $dados, $condicoes); } \ No newline at end of file diff --git a/lgbtq_connect/includes/admin/pagina_administracao.php b/lgbtq_connect/includes/admin/pagina_administracao.php index e0d342f3..cd149683 100644 --- a/lgbtq_connect/includes/admin/pagina_administracao.php +++ b/lgbtq_connect/includes/admin/pagina_administracao.php @@ -14,14 +14,20 @@ function adicionar_pagina_administracao() { add_action('admin_menu', 'adicionar_pagina_administracao'); +require 'formulario-admin-page.php'; + // Função para mostrar os dados na página do painel de administração function mostrar_dados() { global $wpdb; + + // Exibir mensagem de sucesso se os dados foram atualizados + if (isset($_GET['status']) && $_GET['status'] == 'success') { + echo '

Formulário atualizado com sucesso!

'; + } + // Consulta os dados da tabela formulario $dados_formulario = $wpdb->get_results("SELECT * FROM lc_formulario"); - require 'formulario-admin-page.php'; - // Verifica se o parâmetro "action" foi enviado via POST if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST['action'])) { // Verifica a ação do formulário @@ -39,11 +45,53 @@ function mostrar_dados() { - - + +
+ + +
@@ -57,21 +105,36 @@ function mostrar_dados() { $aprovados = $wpdb->get_results($query_aprovados); $negados = $wpdb->get_results($query_negados); $pendentes = $wpdb->get_results($query_pendentes); - echo ''; - echo ''; - echo ''; + echo '
'; + echo ''; + echo ''; + echo ''; + echo '
'; ?>
-
+
+
- @@ -83,28 +146,46 @@ function mostrar_dados() {
-
@@ -113,6 +194,7 @@ function mostrar_dados() { + diff --git a/lgbtq_connect/includes/admin/style-admin.css b/lgbtq_connect/includes/admin/style-admin.css index d66fecb9..d4eccbb4 100644 --- a/lgbtq_connect/includes/admin/style-admin.css +++ b/lgbtq_connect/includes/admin/style-admin.css @@ -8,6 +8,7 @@ position: relative; margin: 20px 10px 0px 0px; padding: 50px; + align-items: center; } #div-mapa_botoes { @@ -21,24 +22,36 @@ #filtros { display: flex; - align-items: center; + gap: 20px; + justify-content: center; + } .filtro { flex: 1; background-color: white; + display: flex; + align-items: center; } #busca_nome_container { display: flex; border: 1px solid grey; + border-radius: 10px; + width: 351.51px; + height: 40px; } #busca_nome { flex-grow: 2; border: none; -} +} +#selecao_servico{ + border-radius: 10px; + width: 351.51px; + height: 40px; +} #busca_nome:focus { outline: none; } @@ -59,7 +72,12 @@ button[data-id]:hover { text-decoration: underline; } -.linha-destacada { +@keyframes fadeOut { + 0% { background-color: #90cc90;} + 100% { background-color: transparent;} +} + +.linha-destacada td{ animation: fadeOut 2s ease; } @@ -69,15 +87,12 @@ button[data-id]:hover { margin-right: 1.5vw; position: relative; /* Adicionado para garantir que o z-index funcione */ z-index: 1; /* Baixo z-index para o mapa */ -} - -th { - background-color: #f5f5f5; -} + width: 791px; + height: 279px; + gap: 0px; + border-radius: 20px; + opacity: 0px; -td { - background-color: white; - text-align: center; } #tabela th { @@ -88,6 +103,12 @@ td { /* border-radius: 0px !important; */ } +#tabela td{ + border: none !important; + background-color: white; + text-align: center; +} + #tabela { border: none !important; } @@ -100,6 +121,95 @@ table th:last-child { border-top-right-radius: 20px !important; } +.title{ + font-weight:bold; + font-size: 24px; + margin-bottom:20px; + text-align: center; + color: black; +} + +.blue_button, .button_search, .ver{ + width:100%; + background-color: #2a75f3; + padding:10px; + border:none; + border-radius: 10px; + color:white; + text-align:center; + align-items: center; + font-size: 16px; +} + +.button_search{ + width: 17%; +} + +.ver { + margin: auto; + display : block; + width: 10%; + height: 20px; + justify-content: center; + align-items: center; + border-radius: 5px; + font-size: 0.75rem; + padding: 0px; +} + +#editSalvar, #editCancelar { + width: 17%; + background-color: #2a75f3; + padding:10px; + border:none; + border-radius: 20px; + color:white; + text-align:center; + align-items: center; +} + +#editSalvar { + margin-right: auto; + margin-left: 21px; +} + +#editCancelar { + background-color: #F5F5F5; + color: #707070; + border: solid 2px; + margin-left: auto; + margin-right: 21px; +} + +#editFechar { + float: right; + padding: 0; + border: none; + background: none; +} + +#editNome, #editEmail, #editDescricao, #editServico, #searchInputFormEdit{ + width:97%; + resize:none; + background-color:#F5F5F5; + margin-bottom:10px; + border: 1px solid #D0D0D0; + border-radius:10px; + padding:10px; + font-size: 16px; +} + +#searchInputFormEdit{ + width: 77%; + margin: 0 auto; + padding:10px !important; + margin-left:0px; +} + +.blue_button:hover, .button_search:hover, .ver:hover, #editSalvar{ + background-color: #1266f1; +} + .modal { display: none; position: fixed; @@ -127,8 +237,175 @@ table th:last-child { } +#editPopup { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.4); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + } + + +#editModal { + position: absolute; + width: 65%; + height: auto; + background-color: white; + z-index: 1001; + border-radius: 15px; /* Adjust the value to your desired roundness */ + box-shadow: 2px 2px 5px #d0d0d0; + padding: 50px; + left: 50%; + transform: translateX(-50%); +} + +#editModal::before { + content: ""; + position: absolute; + top: -3px; /* Adjust based on border width */ + left: -3px; /* Adjust based on border width */ + width: calc(100% + 6px); /* Adjust based on border width */ + height: calc(100% + 6px); /* Adjust based on border width */ + background: linear-gradient(to bottom right, red, hotpink, blue, lime, yellow); + border-radius: 18px; /* Adjust for border radius + border width */ + z-index: -1; /* Ensure the pseudo-element is behind the modal content */ +} + +#editModal::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: white; + border-radius: 15px; /* Same as #editModal border-radius */ + z-index: -1; /* Ensure the pseudo-element is behind the modal content but above the gradient border */ + box-sizing: border-box; /* Ensure the padding and border width are considered */ +} + +#listaResultadosEdit{ + background-color: white; + margin-top:10px; + margin-bottom:10px; +} + +#listaResultadosForms, #listaResultadosIndex{ + background-color: white; + margin-top:10px; + margin-bottom:10px; +} + +.celula_resultado{ + background-color: #F5F5F5; + width:97%; + text-align:center; + font-size:16px; + padding:10px; + display:flex; + align-items:center; + justify-content: center; + margin:20px; + border-radius:10px !important; +} + +.celula_resultado:hover{ + background-color: #E6E6E6; +} + +.celula_resultado:active{ + background-color: #ccc; +} + +.search_wrapper{ + background-color: white; + display:flex; + align-items:center; + justify-content:center; +} + #confirmBtn, #cancelBtn { padding: 10px 20px; margin: 10px; cursor: pointer; } + +#tabela { + border: 1px solid #dee2e6; /* Borda da tabela */ + border-collapse: collapse; /* Colapsa as bordas */ +} + +#tabela th, +#tabela td { + border: 1px solid #dee2e6; /* Borda das células */ + padding: 8px; /* Espaçamento interno das células */ +} + +.sort-header { + cursor: pointer; +} + +.sort-header .sort-btn { + border: none; + background: none; + padding: 0; + margin-left: 5px; +} + +.sort-header .sort-icon { + font-size: 0.75rem; +} + +.table-hover tbody tr:hover { + background-color: #f1f1f1; +} +.button-container{ + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + margin-top: 50px; +} +.btn-aprovado, .btn-negado, .btn-pendente{ + border-radius: 20px; + width: 371px; + height: 70px; + color: white; + text-align:center; + border: none; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 28px; + +} +.btn-pendente{ + background: rgb(238,202,16); + background: linear-gradient(149deg, rgba(238,202,16,1) 14%, rgba(235,115,10,1) 65%, rgba(221,73,28,1) 99%); + +} +.btn-negado{ + background: rgb(238,16,24); + background: linear-gradient(149deg, rgba(238,16,24,1) 14%, rgba(153,10,235,1) 65%, rgba(221,28,145,1) 99%); +} +.btn-aprovado{ + background: rgb(64,126,0); + background: linear-gradient(149deg, rgba(64,126,0,0.9752275910364145) 17%, rgba(60,235,10,0.865983893557423) 65%, rgba(3,153,15,1) 99%); +} + + +#editDivBotoes { + width: 100%; + display: flex; + font-size: 16px; +} + +#editLabelNome, #editLabelEmail, #editLabelServico, #editLabelDescricao { + font-size: 18px; +} + diff --git a/lgbtq_connect/includes/data/auxiliar_process_form.php b/lgbtq_connect/includes/data/auxiliar_process_form.php index 96084f7a..b6fc446d 100644 --- a/lgbtq_connect/includes/data/auxiliar_process_form.php +++ b/lgbtq_connect/includes/data/auxiliar_process_form.php @@ -1,5 +1,4 @@ insert($table_name, $data); } - // Função para obter o horário atual public static function get_current_time() { return current_time('mysql'); } - // Função para obter o e-mail do administrador public static function get_admin_email() { return get_option('admin_email'); } - // Função para obter a URL do painel de administração public static function get_admin_panel_url() { return admin_url('admin.php?page=lc_admin'); } - // Função para enviar e-mails public static function send_email($to, $subject, $message) { return wp_mail($to, $subject, $message); diff --git a/lgbtq_connect/includes/data/conexao_bd.php b/lgbtq_connect/includes/data/conexao_bd.php index 6690a387..94180e6e 100644 --- a/lgbtq_connect/includes/data/conexao_bd.php +++ b/lgbtq_connect/includes/data/conexao_bd.php @@ -1,10 +1,10 @@ get_charset_collate(); if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { @@ -32,6 +32,8 @@ function criar_tabela_formulario($wpdb) { email VARCHAR(255) NOT NULL, latitude FLOAT(10, 6) NOT NULL, longitude FLOAT(10, 6) NOT NULL, + road VARCHAR(255), + city VARCHAR(255), data_hora VARCHAR(100) NOT NULL, servico VARCHAR(30) NOT NULL, descricao TEXT NOT NULL, @@ -41,8 +43,6 @@ function criar_tabela_formulario($wpdb) { } } - - // Função para retornar os formulários aprovados (Return é um array) function obter_formularios_aprovados($wpdb) { @@ -72,14 +72,15 @@ function obter_formularios($wpdb) { $query = "SELECT * FROM lc_formulario"; $dados_formulario = $wpdb->get_results($query); - // Array para armazenar os formulários aprovados + // Arraylongitude para armazenar os formulários aprovados $formularios = array(); // Itera sobre cada formulário foreach ($dados_formulario as $formulario) { - // Verifica se o formulário está aprovado + // Adiciona cada formulário ao array de formulários $formularios[] = $formulario; } return $formularios; -} \ No newline at end of file +} +?> diff --git a/lgbtq_connect/includes/data/process_form.php b/lgbtq_connect/includes/data/process_form.php index 63cb8fd9..d35bf8f7 100644 --- a/lgbtq_connect/includes/data/process_form.php +++ b/lgbtq_connect/includes/data/process_form.php @@ -11,15 +11,39 @@ function processar_formulario() { parse_str($_POST['formData'], $formFields); // Filtra o conteúdo enviado nos formulários - $nome = isset($formFields['nome']) ? Auxiliar_Process_Forms::sanitize_data($formFields['nome'], 'text') : ''; - $email = isset($formFields['email']) ? Auxiliar_Process_Forms::sanitize_data($formFields['email'], 'email') : ''; - $descricao = isset($formFields['descricao']) ? Auxiliar_Process_Forms::sanitize_data($formFields['descricao'], 'textarea') : ''; - $latitude = isset($formFields['latitude']) ? Auxiliar_Process_Forms::sanitize_data($formFields['latitude'], 'float') : 0; - $longitude = isset($formFields['longitude']) ? Auxiliar_Process_Forms::sanitize_data($formFields['longitude'], 'float') : 0; - $servico = isset($formFields['servico']) ? Auxiliar_Process_Forms::sanitize_data($formFields['servico'], 'text') : ''; - + $nome = isset($formFields['nome']) ? filter_var($formFields['nome'], FILTER_SANITIZE_STRING) : ''; + $email = isset($formFields['email']) ? filter_var($formFields['email'], FILTER_SANITIZE_EMAIL) : ''; + $descricao = isset($formFields['descricao']) ? filter_var($formFields['descricao'], FILTER_SANITIZE_STRING) : ''; + $latitude = isset($formFields['latitude']) ? filter_var($formFields['latitude'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND | FILTER_FLAG_ALLOW_SCIENTIFIC) : 0; + $longitude = isset($formFields['longitude']) ? filter_var($formFields['longitude'], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND | FILTER_FLAG_ALLOW_SCIENTIFIC) : 0; + $servico = isset($formFields['servico']) ? filter_var($formFields['servico'], FILTER_SANITIZE_STRING) : ''; + // Verifica se todos os campos necessários estão presentes if ($nome && $email && $descricao && $latitude && $longitude && $servico) { + // Obter o endereço usando a API do Nominatim com cURL + $url = "https://nominatim.openstreetmap.org/reverse?format=json&lat=$latitude&lon=$longitude&addressdetails=1"; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'); + $response = curl_exec($ch); + curl_close($ch); + $locationData = json_decode($response, true); + + // Adicione um log para a resposta da API + error_log(print_r($locationData, true)); + + if (isset($locationData['error'])) { + $road = 'Rua não encontrada'; + $city = 'Cidade não encontrada'; + } else { + $road = isset($locationData['address']['road']) ? $locationData['address']['road'] : + (isset($locationData['address']['pedestrian']) ? $locationData['address']['pedestrian'] : 'Rua não encontrada'); + $city = isset($locationData['address']['city']) ? $locationData['address']['city'] : + (isset($locationData['address']['town']) ? $locationData['address']['town'] : + (isset($locationData['address']['village']) ? $locationData['address']['village'] : 'Cidade não encontrada')); + } + $data_hora_envio = Auxiliar_Process_Forms::get_current_time(); // Insere os dados no banco de dados @@ -29,6 +53,8 @@ function processar_formulario() { 'descricao' => $descricao, 'latitude' => $latitude, 'longitude' => $longitude, + 'road' => $road, + 'city' => $city, 'data_hora' => $data_hora_envio, 'servico' => $servico )); @@ -45,8 +71,9 @@ function processar_formulario() { $local_cadastrado = 'Nome do Local: ' . $nome . "\n"; $tipo_servico = 'Tipo de Serviço: ' . $servico . "\n"; $data_hora_cadastro = 'Data e Hora do Cadastro: ' . $data_hora_formatada . "\n"; + $endereco_informado = 'Rua: ' . $road . "\n" . 'Cidade: ' . $city . "\n"; // Constrói a mensagem do e-mail - $message = 'Olá! Uma nova resposta foi feita no seu formulário. Aqui estão os detalhes:' . "\n" . $local_cadastrado . $tipo_servico . $data_hora_cadastro . 'Verifique sua área de administração para mais informações: ' . $admin_panel_url; + $message = 'Olá! Uma nova resposta foi feita no seu formulário. Aqui estão os detalhes:' . "\n" . $local_cadastrado . $tipo_servico . $data_hora_cadastro . $endereco_informado . 'Verifique sua área de administração para mais informações: ' . $admin_panel_url; $subject = 'LGBTQ+ Connect - Nova solicitação de plotagem recebida'; // Envie o e-mail de notificação para o administrador do site @@ -54,7 +81,7 @@ function processar_formulario() { // Envie o e-mail de confirmação para o usuário $subject_user = 'LGBTQ+ Connect - Sua solicitação de plotagem foi recebida'; - $message_user = 'Olá! Sua solicitação de plotagem foi recebida. Aqui estão os detalhes:' . "\n" . $local_cadastrado . $tipo_servico . $data_hora_cadastro . 'Você será notificado quando sua solicitação for processada. Obrigado!'; + $message_user = 'Olá! Sua solicitação de plotagem foi recebida. Aqui estão os detalhes:' . "\n" . $local_cadastrado . $tipo_servico . $data_hora_cadastro . $endereco_informado . 'Você será notificado quando sua solicitação for processada. Obrigado!'; Auxiliar_Process_Forms::send_email($email, $subject_user, $message_user); } else { diff --git a/lgbtq_connect/index.php b/lgbtq_connect/index.php index 61395a06..5a484da6 100644 --- a/lgbtq_connect/index.php +++ b/lgbtq_connect/index.php @@ -61,6 +61,11 @@ function enfileirar_scripts_admin() { wp_localize_script('admin_script.js', 'formularios_todos', $formularios); } +function enfileirar_styles_admin() +{ + wp_enqueue_style('admin-style', plugin_dir_url(__FILE__) . 'includes/admin/style-admin.css', array(), '1.0'); +} + // Função para criar a tabela na ativação do plugin function add_tabela_bd() { global $wpdb; @@ -91,6 +96,7 @@ function enfileirar_scripts() { } add_action('admin_enqueue_scripts', 'enfileirar_scripts_admin'); +add_action('admin_enqueue_scripts', 'enfileirar_styles_admin'); // Função para adicionar o shortcode function meu_plugin_shortcode() { diff --git a/tests/js/filtro_admin.test.js b/tests/js/filtro_admin.test.js new file mode 100644 index 00000000..5936ba26 --- /dev/null +++ b/tests/js/filtro_admin.test.js @@ -0,0 +1,63 @@ +import {Filtro} from '../../lgbtq_connect/includes/admin/admin_script.js'; + +describe("filtro (página do admin)", () => { + let arr = []; + let arr_filtrada; + + let formulario1 = { + nome: "Cabana", + situacao: "Aprovado", + servico: "entretenimento" + } + let formulario2 = { + nome: "pizza", + situacao: "Negado", + servico: "bar/restaurante" + } + let formulario3 = { + nome: "Escola", + situacao: "Pendente", + servico: "ensino" + } + + arr.push(formulario1, formulario2, formulario3); + test('filtro por nome está funcionando', () => { + Filtro.reiniciarFiltro(); + Filtro.nome="Cabana "; + arr_filtrada = Filtro.realizarFiltragem(arr); + expect(arr_filtrada).toContain(formulario1); + expect(arr_filtrada).toHaveLength(1); + }) + + test('filtro por status está funcionando', () => { + Filtro.reiniciarFiltro(); + Filtro.status="Pendente"; + arr_filtrada = Filtro.realizarFiltragem(arr); + expect(arr_filtrada).toContain(formulario3); + expect(arr_filtrada).toHaveLength(1); + }) + + test('filtro por serviço está funcionando', () => { + Filtro.reiniciarFiltro(); + Filtro.servico="ensino" + arr_filtrada = Filtro.realizarFiltragem(arr) + expect(arr_filtrada).toContain(formulario3); + expect(arr_filtrada).toHaveLength(1); + }) + + test('todos os filtros ao mesmo tempo estão funcionando com valores não-nulos', () => { + Filtro.reiniciarFiltro(); + Filtro.nome=" Cabana "; + Filtro.status="Aprovado"; + Filtro.servico="entretenimento" + arr_filtrada = Filtro.realizarFiltragem(arr) + expect(arr_filtrada).toContain(formulario1); + expect(arr_filtrada).toHaveLength(1); + }) + + test('todos os filtros ao mesmo tempo estão funcionando com valores nulos', () => { + Filtro.reiniciarFiltro(); + arr_filtrada = Filtro.realizarFiltragem(arr) + expect(arr_filtrada).toHaveLength(3); + }) +}) \ No newline at end of file diff --git a/tests/js/math.test.js b/tests/js/math.test.js deleted file mode 100644 index 6c5b0a9c..00000000 --- a/tests/js/math.test.js +++ /dev/null @@ -1,5 +0,0 @@ -import {Mapa} from '../../lgbtq_connect/assets/js/script.js'; - -test('adds 1 + 2 to equal 3', () => { - expect(Mapa.sum(1, 2)).toBe(3); -}); diff --git a/tests/js/ordenacao_admin.test.js b/tests/js/ordenacao_admin.test.js new file mode 100644 index 00000000..b7ada2ec --- /dev/null +++ b/tests/js/ordenacao_admin.test.js @@ -0,0 +1,78 @@ +import {Ordenador} from '../../lgbtq_connect/includes/admin/admin_script.js'; + +describe("ordenador (página do admin)", () => { + let arr = []; + + let formulario1 = { + "id": 1, + "nome": "Cabana", + "email": "exemplo1@gmail.com", + "latitude": 50.2, + "longitude": 20.3, + "data_hora": "2024-01-01 00:00:00", + "servico": "entretenimento", + "descricao": "Bom demais", + "situacao": "Aprovado" + } + + let formulario2 = { + "id": 1, + "nome": "Pizza", + "email": "exemplo2@gmail.com", + "latitude": 50.2, + "longitude": 20.3, + "data_hora": "2024-01-02 00:00:00", + "servico": "bar/restaurante", + "descricao": "Bom demais", + "situacao": "Aprovado" + } + + let formulario3 = { + "id": 1, + "nome": "Hamburguer", + "email": "exemplo3@gmail.com", + "latitude": 50.2, + "longitude": 20.3, + "data_hora": "2024-01-01 00:00:01", + "servico": "bar/restaurante", + "descricao": "Bom demais", + "situacao": "Aprovado" + } + + arr.push(formulario1, formulario2, formulario3); + test('ordenação por nome está funcionando', () => { + Ordenador.coluna = "nome"; + + Ordenador.ordem = "asc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario1); + + Ordenador.ordem = "desc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario2); + }) + + test('ordenação por email está funcionando', () => { + Ordenador.coluna = "email"; + + Ordenador.ordem = "asc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario1); + + Ordenador.ordem = "desc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario3); + }) + + test('ordenação por data e hora está funcionando', () => { + Ordenador.coluna = "data_hora"; + + Ordenador.ordem = "asc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario1); + + Ordenador.ordem = "desc"; + arr = Ordenador.realizarOrdenacao(arr); + expect(arr[0]).toBe(formulario2); + }) +}) \ No newline at end of file diff --git a/tests/js/tabela_admin.test.js b/tests/js/tabela_admin.test.js new file mode 100644 index 00000000..2c7f2b4d --- /dev/null +++ b/tests/js/tabela_admin.test.js @@ -0,0 +1,76 @@ +import {Tabela} from '../../lgbtq_connect/includes/admin/admin_script.js'; + +describe("manipulação da tabela do admin", () => { + + let arr=[]; + + let formulario1 = { + "id": 1, + "nome": "Cabana", + "email": "exemplo1@gmail.com", + "latitude": 50.2, + "city": "Cidade das boas", + "road": "Rua das boas", + "longitude": 20.3, + "data_hora": "2024-01-01 00:00:00", + "servico": "entretenimento", + "descricao": "Bom demais", + "situacao": "Aprovado" + } + + arr.push(formulario1); + + test('a geração de linhas está funcionando', () => { + document.body.innerHTML = + '' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' '; + + const tabela = document.getElementById('tabela'); + const tabelaObj = new Tabela(arr, tabela); + tabelaObj.gerarLinhas(); + + // Verifica se o nome está correto + expect(document.getElementById("formulario-1-nome").innerHTML).toBe("Cabana"); + + // Verifica se o email está correto + expect(document.getElementById("formulario-1-email").innerHTML).toBe("exemplo1@gmail.com"); + + // Verifica se a latitude está correta + expect(document.getElementById("formulario-1-cidade").innerHTML).toBe("Cidade das boas"); + + // Verifica se a longitude está correta + expect(document.getElementById("formulario-1-rua").innerHTML).toBe("Rua das boas"); + + // Verifica se a data e hora está correta + expect(document.getElementById("formulario-1-data_hora").innerHTML).toBe("01/01/2024 00:00:00"); + + // Verifica se o serviço está correto + expect(document.getElementById("formulario-1-servico").innerHTML).toBe("entretenimento"); + + // Verifica se a descrição está correta + expect(document.getElementById("formulario-1-descricao").innerHTML).toBe("Bom demais"); + + // Verifica se a situação está correta + expect(document.getElementById("formulario-1-situacao").innerHTML).toBe("Aprovado"); + }) + + test('a exclusão de linhas está funcionando', () => { + const tabelaObj = new Tabela(arr, tabela); + + tabelaObj.excluirLinhas(); + expect(tabela.querySelector("tbody").innerHTML).toBe(""); + }) +}) \ No newline at end of file diff --git a/tests/php/AlteraStatusTest.php b/tests/php/AlteraStatusTest.php index d7a8edda..04b1ef3e 100644 --- a/tests/php/AlteraStatusTest.php +++ b/tests/php/AlteraStatusTest.php @@ -12,8 +12,35 @@ public function prepare($query, ...$args) { public function query($query) { return true; } + public function update($table, $data, $where) { + return true; + } + } +} + +// Funções fictícias de sanitização +if (!function_exists('sanitize_text_field')) { + function sanitize_text_field($str) { + return $str; } } +if (!function_exists('sanitize_email')) { + function sanitize_email($email) { + return $email; + } +} +if (!function_exists('sanitize_textarea_field')) { + function sanitize_textarea_field($str) { + return $str; + } +} + +// Função wp_die customizada para testes +class WPDieException extends Exception {} + +function wp_die($message) { + throw new WPDieException($message); +} class AlteraStatusTest extends TestCase { private $wpdb; @@ -21,10 +48,66 @@ class AlteraStatusTest extends TestCase { protected function setUp(): void { // Mock do objeto $wpdb $this->wpdb = $this->getMockBuilder('wpdb') - ->onlyMethods(['prepare', 'query']) + ->onlyMethods(['prepare', 'query', 'update']) ->getMock(); } + // Testes para a função atualizar_formulario + public function test_atualizar_formulario_success() { + // Mock de $_POST + $_POST['id'] = 1; + $_POST['nome'] = 'Teste Nome'; + $_POST['email'] = 'teste@example.com'; + $_POST['servico'] = 'Teste Serviço'; + $_POST['descricao'] = 'Teste Descrição'; + $_POST['latitude'] = '12.345678'; + $_POST['longitude'] = '98.7654321'; + + // Mock da função conseguir_rua_e_cidade + $mock_conseguir_rua_e_cidade = function($latitude, $longitude) { + return ['Mock Rua', 'Mock Cidade']; + }; + + // Defina o que o mock do $wpdb->update deve retornar + $this->wpdb->expects($this->once()) + ->method('update') + ->with( + $this->equalTo('lc_formulario'), + $this->equalTo([ + 'nome' => 'Teste Nome', + 'email' => 'teste@example.com', + 'servico' => 'Teste Serviço', + 'descricao' => 'Teste Descrição', + 'latitude' => '12.345678', + 'longitude' => '98.7654321', + 'road' => 'Mock Rua', + 'city' => 'Mock Cidade' + ]), + $this->equalTo(['id' => 1]) + ) + ->willReturn(1); + + // Chame a função atualizar_formulario + atualizar_formulario($this->wpdb, $mock_conseguir_rua_e_cidade); + } + + public function test_atualizar_formulario_missing_data() { + // Limpe o $_POST para garantir que está vazio + $_POST = []; + + // Capture a saída para verificar se wp_die foi chamado + $this->expectException(WPDieException::class); + $this->expectExceptionMessage('Dados insuficientes'); + + $mock_conseguir_rua_e_cidade = function($latitude, $longitude) { + return ['Mock Rua', 'Mock Cidade']; + }; + + // Chame a função atualizar_formulario e verifique se wp_die é chamado + atualizar_formulario($this->wpdb, $mock_conseguir_rua_e_cidade); + } + + // Testes para a função alteraStatus public function testAlteraStatusReturnsFalseWhenWpdbNotSet() { $result = alteraStatus(null, 1, 'new_status'); $this->assertFalse($result); @@ -74,3 +157,4 @@ public function testAlteraStatusReturnsTrueWhenQuerySucceeds() { $this->assertTrue($result); } } +?>
Nome Email LatitudeLongitudeServiçoDescriçãoData e hora StatusAções