×
Ir ao conteúdo
  • Cadastre-se

GabrielSennaMs

Membro Pleno
  • Posts

    299
  • Cadastrado em

  • Última visita

  • Qualificações

    0%

Tópicos solucionados

  1. O post de GabrielSennaMs em Erro no sistema de login PHP foi marcado como solução   
    @Impts
     
    O erro apontado pelo interpretador está no seu echo, falto às aspas duplas(") no final.
     
     
     
    Tem outro erro no tipo(type) do seu botão de submit no formulario, no caso tem duas propriedade type e o correto é 'type="submit"'
     
     
     
    Fiz outras modificações que você pode testar para melhorar o seu código
     
    <?php require_once __DIR__ . DIRECTORY_SEPARATOR . "conection.php"; $errors = []; $data = [ "email" => "", "password" => "" ]; function filter_input_string($input) { $value = filter_input(INPUT_POST, $input, FILTER_SANITIZE_STRING); if (is_null($value)) { return $value; } elseif (!is_string($value)) { return null; } $value = trim($value); $value = stripslashes($value); $value = htmlspecialchars($value); return $value; } function validation_value_is_null(&$errors, &$data, $index, $field) { if (is_null($data[$index]) or empty($data[$index])) { $errors[$index] = "<p>O campo '{$field}' é obrigatorio</p>"; } } function validation_data_authentication_user(&$errors, &$data) { $data["email"] = filter_input_string("email"); $data["password"] = filter_input_string("password"); validation_value_is_null($errors, $data, "email", "E-mail"); validation_value_is_null($errors, $data, "password", "Senha"); if (count($errors) === 0) { if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) { $errors["email"] = "<p>O valor informado no campo email não corresponde a um email valido</p>"; } if (count($errors) === 0) { return true; } } return false; } if ($_SERVER["REQUEST_METHOD"] == "POST") { if (session_status() == 1) { session_start(); } if (validation_data_authentication_user($errors, $data)) { $stmt = $mysqli->prepare("SELECT `id`, `password` FROM `users` WHERE `email` = ? LIMIT 1;"); $stmt->bind_param("s", $data['email']); if ($stmt->execute()) { $result = $stmt->get_result(); if ($result->num_rows === 1) { $user = $result->fetch_object(); if (password_verify($data['password'], $user->password)) { $_SESSION["id"] = $user->id; header("Location: /success.php"); die(); } } } $errors["all"] = "<p>Usuário ou/e senha invalido/s</p>"; } http_response_code(401); } ?> <!DOCTYPE html> <html lang="pt-BR"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> html, body, main, section { width: 100%; padding: 0px; margin: 0px; height: 100%; background: #eee; font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; } a { color: #000; text-decoration: none; border-bottom: solid 1px transparent; transition: 0.4s; } a:hover { text-decoration: none; transition: 0.4s; border-bottom: solid 1px; } section { display: flex; justify-content: center; align-content: center; align-items: center; } form { width: 100%; max-width: 300px; padding: 2em; border-radius: 0.5em; transition: 0.2s; box-shadow: 3px 3px 10px #777; background: #fff; } fieldset { padding: 0px; margin: 0px; border: none; } input[type="text"], input[type="password"] { width: calc(100% - 20px); } input { width: 100%; display: block; margin: 2em 0; padding: 10px; } #msg-errors > p { color: red; font-size: 12px; } </style> </head> <body> <main> <section> <form action="<?= htmlspecialchars($_SERVER["PHP_SELF"]) ?>" method="POST"> <h2>LOGIN</h2> <div id="msg-errors"> <?php if (count($errors) > 0): ?> <?= implode("", array_values($errors)); ?> <?php endif; ?> </div> <fieldset> <input value="<?= $data['email'] ?>" autocomplete="username" name="email" type="text" placeholder="E-mail" > <input autocomplete="current-password" name="password" type="password" placeholder="Senha" > <a href="#">Esqueceu a sua senha?</a> <input type="submit" value="Entrar"> </fieldset> </form> </section> </main> </body> </html>  
  2. O post de GabrielSennaMs em menu dropdown não funciona foi marcado como solução   
    @Alice Braga Se esse for o caso então seu HTML está errado porque na versão Boostrap <= 4 a propriedade para utilizar o 'dropdown' é "data-toggle="dropdown"
     
    De uma olhada na documentação do navbar aqui no site oficial https://getbootstrap.com/docs/4.6/components/navbar/
  3. O post de GabrielSennaMs em Qual a melhor forma de fazer campos separados para por informação? foi marcado como solução   
    @Impts Esses tutoriais podem te ajudar nisso:
    https://www.w3schools.com/howto/howto_js_sidenav.asp,
    https://www.w3schools.com/css/css_float.asp,
    https://www.w3schools.com/css/css3_flexbox.asp,
    https://www.w3schools.com/css/css_rwd_intro.asp
  4. O post de GabrielSennaMs em Como manipular (class e aria-expanded) com javascript foi marcado como solução   
    @EddK
     
    Isso aqui deve resolver o seu problema
    window.onload = function () { const acc = document.getElementsByClassName("accordion-item"); const expanders = document.getElementsByClassName("expander"); for (let i = 0; i < acc.length; i++) { acc[i].addEventListener("click", function () { const panel = this.getElementsByClassName("panel")[0], btn = this.getElementsByClassName("accordion")[0]; this.classList.toggle("active"); if (!this.classList.contains("active")) { panel.style.display = "none"; btn.setAttribute('aria-expanded', 'false') } else { panel.style.display = "block"; btn.setAttribute('aria-expanded', 'true') } }); } }  
    Uma boa opção seria você também no elemento com a class 'panel' trabalhar com uma class como 'show', e com essa class criar uma animação para o elemento.
  5. O post de GabrielSennaMs em Upload simples de imagem com $_FILES não executa nada foi marcado como solução   
    @SethC Adiciona o
    error_reporting(E_ALL); ini_set("display_errors", 1); e verifica se ele retorna algum erro
  6. O post de GabrielSennaMs em Como alterar valor do aria-expanded com javascript puro foi marcado como solução   
    @EddK Bom isso aqui deve servir
     
    <button type="button" id="btn" aria-expanded="false"> teste </button> <script> document.querySelector("#btn").addEventListener("click", function(event) { let value = event.target.getAttribute("aria-expanded"); event.target.setAttribute("aria-expanded", (value == "true") ? "false" : "true"); }); </script>  
    Agora você deve modificar o seletor para o seu botão no caso eu usei ID como o meu seletor
  7. O post de GabrielSennaMs em Sistema de Cadastro com PHP foi marcado como solução   
    @JoaoE Falto você adicionar o catch do tratamento try...catch para trabalhar possíveis Exception.
     
    Aqui tem um tutorial falando sobre e como usar, https://www.w3schools.com/php/php_exceptions.asp.
     
    try { require_once "../../php/conexao.php"; $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "INSERT INTO `usuario` VALUE(NULL, :nomeUsuario, :nome, :email, senha, :formacao: :idade);"; } catch(Exception $e) { echo $e->getMessage(); }  
  8. O post de GabrielSennaMs em Criar elemento e fazer ele desaparecer em segundos com JS foi marcado como solução   
    @edureoli
     
    Existe sim, e pela descrição me parece que você quer criar um Snackbar.
     
    Aqui tem um tutorial: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_snackbar
     
    Ou
     
    <button onclick="myFunction()">Show Snackbar</button> <div id="snackbar" style="display: none;">Some text some message..</div> <script> function myFunction() { let x = document.getElementById("snackbar"); x.style.display = 'block'; setTimeout(function(){ x.style.display = 'none';}, 3000); } </script>  
  9. O post de GabrielSennaMs em Como exibir erros PHP? | PHP não imprimi funções como print_r(); foi marcado como solução   
    @Midoriya_Porcelana Bom amigo, para fazer Debug você pode usar o método var_dump(), ele vai mostrar todo o conteúdo e o tipo do argumento que ele recebe.
     
    Você também pode tentar usar isso no seu arquivo php
    // Exibe todos os erros PHP error_reporting(-1); // Mesmo que error_reporting(E_ALL); ini_set('error_reporting', E_ALL);  
    Obs..: Uma coisa que eu achei estranha é que no seu html o "Olá, Mundo!" está ali dentro do elemento p, e olhando o elemento body no css que ele recebe, o elemento body está recebendo a propriedade, "display: none;", e por esse motivo você não está vendo o texto de echo na página.
     
    Remove isso:
    <style>body {display: none;margin: 0px;}</style>  
     
    A fim de esclarecer o uso do print e o echo:
    As diferenças são pequenas: echo não tem valor de retorno enquanto print tem valor de retorno 1, portanto, pode ser usado em expressões. echo pode ter vários parâmetros (embora esse uso seja raro), enquanto print pode ter um argumento. echo é ligeiramente mais rápido do que print.  
     
    Alguns usos de print e echo e print_r
     
    echo "This ", "string ", "was ", "made ", "with multiple parameters."; // Retorno // This string was made with multiple parameters. $x = ["Chave" => "Valor"]; print $x; // Retorno // Array print_r($x); // Retorno // Array ([Chave] => Valor)  
     
  10. O post de GabrielSennaMs em site em .asp fora do ar foi marcado como solução   
    @Bruna Siqueira pede para reiniciar o arquivo .htaccess. para default.
  11. O post de GabrielSennaMs em Não consigo colocar zeros à esquerda no número binário foi marcado como solução   
    @aleffelipe96 Até onde eu me lembro os números binários são colocados em conjuntos de oito dígitos, e como esse número pode ter zeros a esquerda e é composto só de dígitos, o javascript converte ele para tipo inteiro e remove o zero na esquerda.
     
    Você pode adicionar um 0 a esquerda e usar o método "slice" e pegar os 8 últimos caracteres da string, e como é uma string o javascript não vai remove o zero.
     
    ('00000000'+input[i].charCodeAt(0).toString(2)).slice(-8) Exemplo:
    <!DOCTYPE html> <html> <body> <p>Press a key on the keyboard in the input field to get the Unicode character code of the pressed key.</p> <input type="text" size="40" onkeypress="myFunction(event)"> <p id="demo"></p> <script> function myFunction(event) { var x = ('00000000'+event.charCode.toString(2)).slice(-8) document.getElementById("demo").innerHTML = "The Unicode value is: " + x; } </script> </body> </html>  
  12. O post de GabrielSennaMs em forçar as li ficarem na mesma linha - menu horizontal foi marcado como solução   
    @Bruna Siqueira
     
    Bom provavelmente é devido ao "overflow: hidden;" na class ".highcharts-menu-wrapper".
     
    Para deixar o submenu na horizontal você pode adiciona na class ".highcharts-submenu-wrapper":
    { top: 42px; // Isso vai tira o btn de cima do menu flex-flow: column; // Isso vai fazer com que os btns se posicionem na vertical left: 0px; // Remove ou setar para 0px, acim o submenu vai ficar em baixo do btn principal }
     
     
  13. O post de GabrielSennaMs em duas repeticionais dentro de uma condicional foi marcado como solução   
    @Bulgarellllli O problema está na sua condição de loop nos for.
     
    Você usa menor que e igual "<=", e com essa condição o loop é executado uma vez a mais que o valor do array com os elementos.
     
    Colocando só menor que o loop vai funcionar.
    if (language == "english") { for (let i = 0; i < itemsEnglish.length; i++) { console.log(itemsEnglish[i]); itemsEnglish[i].style.display = "block"; } for (let x = 0; x < itemsPortuguese.length; x++) { itemsPortuguese[x].style.display = "none"; } } else { for (let i = 0; i < itemsEnglish.length; i++) { itemsEnglish[i].style.display = "none"; } for (let x = 0; x < itemsPortuguese.length; x++) { itemsPortuguese[x].style.display = "block"; } } Dessa forma deve funcionar!
  14. O post de GabrielSennaMs em reaproveitar valor de variável JQuery foi marcado como solução   
    @fspjonny Faz uma modificação no código
     
    // De valores['total'] = parseFloat(valores['resultado_1'] + valores['resultado_2']); // Para valores['total'] = parseFloat(valores['resultado_1']) + parseFloat(valores['resultado_2']);  
     
  15. O post de GabrielSennaMs em Requisição ao banco de dados com PHP sem refresh foi marcado como solução   
    @Julie Silveira Bom tem alguns problemas no formulário e no envio.
     
     
    Esse erro acontece porque você tenta chama uma variável chamada "categorias" na função "mostraCategorias()", e elá não existe dentro do escopo da função.
     
    Quando você chama a função "mostraCategorias()" você passa a reposta da requisição para a função, porém você não defina na função esse argumento.
     
    Para resolver esse problema basta definir um argumento na função.
     
    Exemplo:
    function mostraCategorias(categorias, request) // Agora a variável categorias existe no escopo da função e ela vai receber o resultado da request; { // Mostrando a div com o resultado, que esta originalmente como display:none document.getElementById('resultados').style.display = "block"; // Mostrando os resultados: document.getElementById('resultados').innerHTML = `<p><b>Nome da categoria: </b> ${categorias} </p>`; document.getElementById('resultados').innerHTML += `<div>${request}</div>`; } Bom feito isso o formulário ainda não vai funcionar, vai acontece os outros problemas.
     
    Um dos problemas está na função "buscarCategoria()", a função pega o valor do input, porém ele não faz uma Request usando Axios. Por que não? Porque o código do Axios está fora da função.
     
    function buscarCategoria(event) { // Escopo da função event.preventDefault(); let inputCat = document.getElementById('categoria'); let categoria = inputCat.value; /*valor será capturado aqui*/ let nome_categoria = JSON.stringify(categoria); } // Axios axios.get('http://localhost/Quimica/php/recebe_json.php', {}) .then(response => { mostraCategorias(response.data); }) .catch(error => { console.log(error) }) Com o código dessa maneira o Axios vai fazer uma Request quando a página carregar, e não vai ser chamando quando o usuário fazer uma busca.
     
    Para resolver isso, basta coloca o Axios dentro da função "buscarCategoria()", assim quando o usuário clicar no botão buscar a função vai fazer um Request usando o Axios.
    function buscarCategoria(event) { // Escopo da função event.preventDefault(); let inputCat = document.getElementById('categoria'); let categoria = inputCat.value; /*valor será capturado aqui*/ let nome_categoria = JSON.stringify(categoria); // Axios axios.get('http://localhost/Quimica/php/recebe_json.php', {}) .then(response => { mostraCategorias(categoria, response.data); // Passando o valor do input e a resposta da request para a função mostraCategorias() }) .catch(error => { console.log(error) }) }  
    Um dos ultimo problema que eu achei está na Solicitação(Request) que você faz para a URL"http://localhost/Quimica/php/recebe_json.php", esse problema é simples, você não passa o valor para fazer a pesquisa no banco de dados, e como você utiliza no seu php o método file_get_contents() com o argumento 'php://input', você só consegue ler o corpo bruto de uma solicitação do tipo POST, o outro problema aqui está no tipo de solicitação que você faz.
     
    Para resolver esses problemas basta mudar o tipo de solicitação para POST e adiciona no corpo da solicitação o valor do input.
     
    Exemplo:
    function buscarCategoria(event) { // Escopo da função event.preventDefault(); let inputCat = document.getElementById('categoria'); let categoria = inputCat.value; /*valor será capturado aqui*/ let nome_categoria = JSON.stringify(categoria); // Axios axios.post('http://localhost/Quimica/php/recebe_json.php', nome_categoria) // Agora o tipo de request é POST e no corpo está o valor do input .then(response => { mostraCategorias(categoria, response.data); // Passando o valor do input e a resposta da request para a função mostraCategorias() }) .catch(error => { console.log(error) }) }  
    Bom deixando o código mais limpo ele deve ficar +- assim;
    function buscarCategoria(event) { let inputCat = document.getElementById('categoria'), categoria = inputCat.value; event.preventDefault(); axios.post('http://localhost/Quimica/php/recebe_json.php', JSON.stringify(categoria)) .then(response => { mostraCategorias(categoria, response.data); }) .catch(error => { console.log(error) }) } function mostraCategorias(categorias, request) { let resultado = document.getElementById('resultados'); resultado.style.display = "block"; resultado.innerHTML = `<p><b>Nome da categoria: </b> ${categorias} </p>`; resultado.innerHTML += `<div>${request}</div>`; }  
    Obs..: Com o código assim você deve conseguir fazer a solicitação, porém você ainda vai ter que manipular a reposta da solicitação.
  16. O post de GabrielSennaMs em Como ajustar imagem cortada (React-Native) foi marcado como solução   
    @A.Victor Você pode modifica a propriedade resizeMode do elemento image.
     
    Aqui tem documentação https://facebook.github.io/react-native/docs/image.html
  17. O post de GabrielSennaMs em Mute não funciona (custom HTML5 player) foi marcado como solução   
    @Lerub Eu encontrei alguns erro no seu código.
     
    Quando você adiciona um evento de click no botão mute você adiciona uma função callBack que não existe.
    muteb.addEventListener("click", muted); O nome da função que você crio para mutar o player e "mute" sem o d no final
    muteb.addEventListener("click", mute);  
    Também tem dois erros na função mute() dentro do IF que verifica se o player está mutado ou não.
    function mute() { if (podcast.muted = true) { podcast.muted = false; muteb.className = ""; muteb.className = "mutedAudio"; } else { podcast.muted = false; muteb.className = ""; muteb.className = "unmutedAudio"; } } O primeiro erro está no inicio do IF, na verificação do valor do atributo muted, você colocou com um iguar, assim ele não está comparando o valor e sim atribuindo um valor ao atributo.
     
    O segundo erro está na primeira linha embaixo do ELSE, você atribui o valor false ao atributo muted do player, sendo que deveria ser o valor true.
     
    A função mute() corrigida ficaria assim:
    function mute() { if (podcast.muted == true) { podcast.muted = false; muteb.className = ""; muteb.className = "mutedAudio"; } else { podcast.muted = true; muteb.className = ""; muteb.className = "unmutedAudio"; } }  
  18. O post de GabrielSennaMs em video do yotube do topo não funciona no celular foi marcado como solução   
    @Bruna Siqueira Os navegadores mobile tem um bloquei na reprodução automática de vídeos, isso é para evitar o uso do dados moveis, isso é uma limitação dos templates. É até possível forçar usando javascript o play do vídeo, mas não é 100% eficaz, também não é nem um pouco recomendado.
  19. O post de GabrielSennaMs em Busca com vários campos foi marcado como solução   
    @JenneferBarbosa Isso é por que o SQL não encontrou nenhum resultado possível, o por que? tem outro erro no código do nosso amigo.
     
    no if
    if($edicao !== null){ $edicao_Livro = "edicao LIKE '".addslashes($autor)."%'"; } ele troco o $edicao para $autor a consulta está saindo errado.
    para corrigir isso basta trocar o $autor para $edicao
    if($edicao !== null){ $edicao_Livro = "edicao LIKE '".addslashes($edicao)."%'"; }  
  20. O post de GabrielSennaMs em Mudar valor de acordo com seleção ou não de checkbox foi marcado como solução   
    @laripereira14 Quando você faz o calculo do desconto você salva o valor com desconto no mesmo input que você pega o valor sem o desconto, nesse caso o melhor seria guardar o valor em uma variável global, para fazer isso basta você declarar uma variável fora de um método(function), assim você pode alterar e pegar ele de qualquer método.
     
    Um exemplo:
    var valorOriginal; function enabledPassagem() { var desconto=0; valortot = parseInt(window.document.ftaxi.valortot.value); parseInt(vnormal=window.document.ftaxi.valortot.value); if (document.getElementById('passagem').checked == false) { window.document.ftaxi.valortot.value = valorOriginal; document.getElementById("dataretorno").disabled = true; document.getElementById("horaretorno").disabled = true; } if (document.getElementById('passagem').checked == true) { valorOriginal = window.document.ftaxi.valortot.value; document.getElementById('dataretorno').removeAttribute('disabled'); document.getElementById('horaretorno').removeAttribute('disabled'); desconto=((valortot*2)*0.7); window.document.ftaxi.valortot.value = desconto; } } Cara dá uma olhada no seu código ele tá muito bagunçado, tenta arrumar isso.
    Esse site tem o melhor curso online de javascript, e é free, dá uma olha depois!
    https://www.w3schools.com/js/default.asp
  21. O post de GabrielSennaMs em Erro ao atualizar senha foi marcado como solução   
    @Glouk
    No arquivo php você faz a solicitação da senha atual ao banco de dados, porém você não obtêm o resultado como uma matriz na solicitação.
     
    Pra fazer isso basta você utilizar o mysqli_fetch_assoc(), e depois você seleciona o campo da matriz que você quer pegar o valor.
     
    O código ficaria assim.
    $velha = mysqli_query($con, "SELECT senha FROM registro WHERE id=$id") or print mysqli_error(); $velha = mysqli_fetch_assoc($velha); $velha = $velha['senha'];  
     
     
  22. O post de GabrielSennaMs em Formulário de contato de email foi marcado como solução   
    @Beorlegui Para fazer isso você vai precisar utilizar Ajax, com Ajax você pode fazer a requisição para a página em php que vai enviar o e-mail sem sair dá página atual.
     
    Um exemplo de código Ajax que você pode usar na sua aplicação:
    <script type="text/javascript"> var form = document.forms["sentMessage"]; form.addEventListener("submit", function(event) { let xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if(this.readyState == 4 && this.status == 200) { alert(this.responseText); } }; xhttp.open(form.getAttribute("method"), form.getAttribute("action"), true); xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhttp.send("nome="+form["nome"].value+"&email="+form["email"].value+"&telefone="+form["telefone"].value+"&msg="+form["msg"].value); event.preventDefault(); return(false); }); </script> Aqui tem um tutorial de como usar o Ajax
  23. O post de GabrielSennaMs em centralização de uma div foi marcado como solução   
    @MugenShion Esse tutorial pode te ajudar a entender o uso do display e da margin: http://pt-br.learnlayout.com/display.html, http://pt-br.learnlayout.com/margin-auto.html
  24. O post de GabrielSennaMs em Como aplicar os design do package.json na página WEB foi marcado como solução   
    Bom o npm é um gerenciador de pacotes, quando você pede para ele instalar um pacote, ele automaticamente começa a baixar os arquivos do pacote, esses arquivos ficam salvos na pasta "node_modules", essa pasta fica onde você executou o comando npm, como ele é um gerenciador de pacotes ele usa o arquivo package.json como base para gerenciar os pacotes e seu projeto.
     
    O comando 
    npm install @material é incorreto, esse comando somente é usado para baixa pequenas partes do material design e ele deve ser complementado com / e o nome da parte desejada.
    Exemplo:
    npm install @material/button Se você deseja baixar o material design completo, Recomento você a usar o comando:
    npm install material-components-web Para adicionar ele a sua página, entre na pasta "node_modules" depois em "material-components-web" depois em "dist", dentro dessa pasta você vai encontra os arquivos do material design como os arquivos reduzido(.mim) e os arquivos não reduzidos e os arquivo de mapa, depois é só adicionar o link para essa pasta ou copiar os arquivos desejados, recomendo você a copiar os arquivos "material-components-web.min.css" e "material-components-web.min", o resto você não vai usar.
     
    Você também pode usar o CDN para adicionar o material design na sua página web, sem a necessidade de usar o npm.
    <link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet"> <script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>  
     
  25. O post de GabrielSennaMs em CSS e JAVASCRIPT do Material Design não estão sendo aplicados na página Web foi marcado como solução   
    Bom utilizando o código HTML que você passo, eu consegui de boa usar os componentes do material design.
    Como eu havia comentado antes se você utiliza a ferramenta de desenvolvimento Boostrap, pro qual motivo você vai usar o material design.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Curso de Hacker Ético

LANÇAMENTO!

CLIQUE AQUI E CONFIRA!

* Este curso não é ministrado pela equipe do Clube do Hardware.