Criar Página de Registro React
Prompt
crie uma pagina de registro em react
Resultado Gerado
Mais Recomendações
Ver TodosCriar Site Loja Roupas
Desejo criar um site para uma loja de roupas feminias que seja extremamento persoasivo e com todos os recursos para ser encontrado nas buscas do google e instagram, facebook
Otimização JS e HTML
Apartir desse JS abaixo, preciso que crie um HTML com CS moderno, também preciso que otimize esse JS, para ficar mais enxuto. Não posso perder nenhum funcionalidade, só quero que ele fique enxuto e funcional. Utilizo ele com Flask em ptyhon. Então só preciso do HTML, css e esse JS otimizado. document.addEventListener("DOMContentLoaded", () => { const tabela = document.querySelector("#pedidoGrid tbody"); const botaoAdicionar = document.querySelector("#adicionarLinha"); const boletaFinalizadaCheckbox = document.querySelector("#boleta_finalizada"); // Modais e botões const botaoLupa = document.getElementById("botao-lupa"); const modalBuscarCliente = document.getElementById("modal-buscar-cliente"); const botaoBuscarCliente = document.getElementById("botao-buscar"); const campoNome = document.getElementById("campo-nome"); const campoCPF = document.getElementById("campo-cpf"); const campoCNPJ = document.getElementById("campo-cnpj"); const resultadoBusca = document.getElementById("resultado-busca"); const campoCliente = document.querySelector("#campo-cliente"); // Exemplo de clientes para busca (simulação, substitua pelos seus dados reais) const clientes = [ { id: 1, nome: "Cliente A", cpf: "123.456.789-00", cnpj: "" }, { id: 2, nome: "Cliente B", cpf: "", cnpj: "12.345.678/0001-99" }, { id: 3, nome: "Cliente C", cpf: "234.567.890-11", cnpj: "" }, { id: 4, nome: "Empresa D", cpf: "", cnpj: "98.765.432/0001-88" }, ]; // Função para abrir modal const abrirModal = () => { modalBuscarCliente.style.display = "block"; campoNome.focus(); }; // Função para fechar modal const fecharModal = () => { modalBuscarCliente.style.display = "none"; }; // Abrir modal ao clicar na lupa botaoLupa.addEventListener("click", () => { limparCamposModal(); abrirModal(); }); // Fechar modal ao clicar no botão de fechar (X) document .querySelector("#modal-buscar-cliente .close-button") .addEventListener("click", fecharModal); // Fechar modal ao pressionar a tecla ESC document.addEventListener("keydown", (event) => { if (event.key === "Escape") { fecharModal(); } }); // Limpar campos do modal function limparCamposModal() { campoNome.value = ""; campoCPF.value = ""; campoCNPJ.value = ""; resultadoBusca.innerHTML = ""; } // Máscara para CPF campoCPF.addEventListener("input", (event) => { let valor = event.target.value.replace(/\D/g, ""); valor = valor.replace(/(\d{3})(\d)/, "$1.$2"); valor = valor.replace(/(\d{3})(\d)/, "$1.$2"); valor = valor.replace(/(\d{3})(\d{1,2})$/, "$1-$2"); event.target.value = valor; }); // Máscara para CNPJ campoCNPJ.addEventListener("input", (event) => { let valor = event.target.value.replace(/\D/g, ""); valor = valor.replace(/^(\d{2})(\d)/, "$1.$2"); valor = valor.replace(/^(\d{2})\.(\d{3})(\d)/, "$1.$2.$3"); valor = valor.replace(/\.(\d{3})(\d)/, ".$1/$2"); valor = valor.replace(/(\d{4})(\d{1,2})$/, "$1-$2"); event.target.value = valor; }); let idClienteAtual = null; let pedidosData = {}; // Objeto para armazenar detalhes dos pedidos // Função para limpar a boleta (tabela) function limparBoleta() { // Seleciona a primeira linha da tabela const primeiraLinha = tabela.querySelector("tr"); // Limpa o conteúdo da primeira linha em vez de remover a linha if (primeiraLinha) { // Limpa os campos específicos da linha, mantendo o combo const comboPedidos = primeiraLinha.querySelector(".combo-pedidos"); if (comboPedidos) { comboPedidos.innerHTML = "<option value=''>Selecione o Pedido</option>"; // Reseta as opções, mas deixa o combo acessível } primeiraLinha.children[1].textContent = ""; // Filial primeiraLinha.children[2].textContent = ""; // Valor Pedido primeiraLinha.children[3].textContent = ""; // Valor Frete primeiraLinha.children[4].textContent = ""; // Valor Desconto primeiraLinha.children[5].textContent = ""; // DS (Campo Editável) primeiraLinha.children[6].textContent = ""; // Valor Final primeiraLinha.children[7].textContent = ""; // Condição Pagamento primeiraLinha.children[8].textContent = ""; // NSU primeiraLinha.children[9].textContent = ""; // OBS // Adiciona apenas a data na última coluna const dataAtual = new Date(); const dataFormatada = dataAtual.toLocaleDateString(); // Apenas a data primeiraLinha.children[10].textContent = dataFormatada; // Atualiza a última coluna com a data } // Remove quaisquer outras linhas que estejam na tabela const outrasLinhas = tabela.querySelectorAll("tr:not(:first-child)"); outrasLinhas.forEach((linha) => linha.remove()); } // Função para buscar clientes function buscarClientes() { // Converter valores dos campos para uppercase antes de enviar (Nome) const nome = campoNome.value.toUpperCase().trim(); // Manter a máscara dos campos CPF e CNPJ const cpf = campoCPF.value.toUpperCase().trim(); const cnpj = campoCNPJ.value.toUpperCase().trim(); // Garantir que pelo menos um campo seja preenchido if (!nome && !cpf && !cnpj) { resultadoBusca.innerHTML = "<p style='color: red;'>Preencha pelo menos um dos campos para buscar.</p>"; return; } // Indicar que está carregando resultadoBusca.innerHTML = "<p style='color: blue;'>Buscando clientes, por favor aguarde...</p>"; // Construir a URL da API com base nos parâmetros de busca let url = `/buscar_clientes?`; if (nome) { url += `nome=${nome}&`; } if (cpf) { url += `cpf=${cpf}&`; } if (cnpj) { url += `cnpj=${cnpj}&`; } url = url.slice(0, -1); // Remover o último '&' // Fazer a chamada AJAX para a rota /buscar_clientes do Flask fetch(url) .then((response) => { if (!response.ok) { throw new Error(`Erro na requisição: ${response.status}`); } return response.json(); }) .then((clientes) => { // Limpar o conteúdo anterior resultadoBusca.innerHTML = ""; if (clientes.length > 0) { clientes.forEach((cliente) => { const item = document.createElement("div"); item.textContent = `${cliente.nome} ${cliente.cpf ? `- CPF: ${cliente.cpf}` : `- CNPJ: ${cliente.cnpj}` }`; item.style.cursor = "pointer"; item.style.padding = "8px"; item.style.borderBottom = "1px solid #ccc"; item.addEventListener("click", () => selecionarCliente(cliente)); resultadoBusca.appendChild(item); }); } else { resultadoBusca.innerHTML = "<p style='color: red;'>Nenhum cliente encontrado.</p>"; } }) .catch((error) => { console.error("Erro ao buscar clientes:", error); resultadoBusca.innerHTML = "<p style='color: red;'>Erro ao consultar clientes. Tente novamente mais tarde.</p>"; }); } // Executar busca ao clicar no botão ou pressionar Enter botaoBuscarCliente.addEventListener("click", buscarClientes); [campoNome, campoCPF, campoCNPJ].forEach((campo) => { campo.addEventListener("keypress", (event) => { if (event.key === "Enter") { event.preventDefault(); // Evita o comportamento padrão do Enter buscarClientes(); } }); }); // Função para selecionar o cliente function selecionarCliente(cliente) { const campoCliente = document.querySelector("#campo-cliente"); campoCliente.value = `${cliente.nome} ${cliente.cpf ? `- CPF: ${cliente.cpf}` : `- CNPJ: ${cliente.cnpj}`}`; idClienteAtual = cliente.cliente; // Garante que está pegando o campo correto limparBoleta(); // Limpa a tabela antes de prosseguir fecharModal(); buscarPedidosDoCliente(idClienteAtual); console.log("ID do cliente selecionado:", idClienteAtual); // Adicionado log para depuração } function buscarPedidosDoCliente(idCliente) { const comboPedidos = document.querySelector("#combo-pedidos"); comboPedidos.innerHTML = "<option value=''>Carregando...</option>"; const url = `/buscar_pedidos_cliente?id_cliente=${idCliente}`; fetch(url) .then((response) => { if (!response.ok) { throw new Error(`Erro na requisição: ${response.status}`); } return response.json(); }) .then((data) => { pedidosData = {}; // Limpa os dados antigos comboPedidos.innerHTML = "<option value=''>Selecione o Pedido</option>"; if (data.length === 0) { comboPedidos.innerHTML = "<option value=''>Nenhum pedido encontrado</option>"; return; } // Imprime a resposta do backend no console console.log("Resposta do backend:", data); data.forEach((pedido) => { pedidosData[pedido.pedido_venda] = pedido; // Armazena detalhes do pedido usando `pedido_venda` como chave const option = document.createElement("option"); option.value = pedido.pedido_venda; // Define o valor do select option.textContent = pedido.pedido_venda; // Exibe o texto do pedido comboPedidos.appendChild(option); }); }) .catch((error) => { console.error("Erro ao buscar pedidos:", error); comboPedidos.innerHTML = "<option value=''>Erro ao carregar os pedidos</option>"; }); } document.querySelector("#combo-pedidos").addEventListener("change", function () { const pedidoSelecionado = this.value; // Verifica se o pedido foi selecionado if (!pedidoSelecionado || !pedidosData[pedidoSelecionado]) { return; } const pedidoDetalhes = pedidosData[pedidoSelecionado]; // Obtém os detalhes do pedido const linhaTabela = document.querySelector("#pedidoGrid tbody tr"); // Seleciona a linha da tabela // Preenche as colunas com os valores do pedido linhaTabela.children[1].textContent = pedidoDetalhes.filial || "N/A"; // Filial linhaTabela.children[2].textContent = `R$ ${pedidoDetalhes.valor_pedido.toFixed(2)}`; linhaTabela.children[3].textContent = `R$ ${pedidoDetalhes.frete.toFixed(2)}`; linhaTabela.children[4].textContent = `R$ ${pedidoDetalhes.desconto.toFixed(2)}`; linhaTabela.children[7].textContent = pedidoDetalhes.cond_pgto || "N/A"; // Preenche a condição de pagamento // Calcula o valor final const valorFinal = pedidoDetalhes.valor_pedido + pedidoDetalhes.frete + pedidoDetalhes.desconto; linhaTabela.children[6].textContent = `R$ ${valorFinal.toFixed(2)}`; console.log("Detalhes do pedido selecionado:", pedidoDetalhes); }); // Função para formatar o valor como moeda no padrão brasileiro function formatarMoeda(valor) { valor = valor.replace(/[^\d,]/g, ""); valor = valor.replace(",", "."); let numero = parseFloat(valor); return isNaN(numero) ? "0,00" : numero.toLocaleString("pt-BR", { minimumFractionDigits: 2, maximumFractionDigits: 2, }); } // Função para validar entrada (aceitar apenas números e vírgula) function validarEntradaNumerica(event) { if ( !/[0-9,]/.test(event.key) && !["Backspace", "Delete", "Enter", "Tab", "."].includes(event.key) ) { event.preventDefault(); } } // Função para limpar o combo de pedidos function limparPedidos() { const comboPedidos = document.querySelector("#combo-pedidos"); comboPedidos.innerHTML = "<option value=''>Selecione o Pedido</option>"; } // Adiciona comportamentos aos campos numéricos function configurarCamposNumericos(linha) { const camposNumericos = [1, 2, 3, 4].map((indice) => linha.children[indice]); camposNumericos.forEach((campo) => { campo.textContent = ""; campo.addEventListener("keydown", validarEntradaNumerica); campo.addEventListener("blur", () => (campo.textContent = formatarMoeda(campo.textContent))); campo.addEventListener("keypress", (event) => { if (event.key === "Enter") { event.preventDefault(); campo.blur(); } }); }); } // Função para limitar o número de caracteres function limitarInput(event, maxLength) { const target = event.target; if (target.textContent.length > maxLength) { target.textContent = target.textContent.slice(0, maxLength); const range = document.createRange(); range.selectNodeContents(target); range.collapse(false); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } } // Adicionar nova linha à tabela botaoAdicionar.addEventListener("click", () => adicionarLinha()); function adicionarLinha() { const novaLinha = document.createElement("tr"); const index = tabela.children.length; // Gera um índice único baseado no número de linhas novaLinha.setAttribute("data-index", index); novaLinha.innerHTML = ` <td> <select class="combo-pedidos" data-index="${index}"> <option value="">Selecione o Pedido</option> </select> </td> <td contenteditable="false"></td> <td contenteditable="false"></td> <td contenteditable="false"></td> <td contenteditable="false"></td> <td contenteditable="true"></td> <td contenteditable="false"></td> <td contenteditable="false"></td> <td contenteditable="true" class="editable" data-maxlength="30"></td> <td contenteditable="true" class="editable" data-maxlength="300"></td> <td>${new Date().toLocaleDateString()}</td>`; tabela.appendChild(novaLinha); // Recupera o combo específico da linha const comboPedidos = novaLinha.querySelector(".combo-pedidos"); comboPedidos.addEventListener("change", (event) => { const linha = comboPedidos.closest("tr"); // Encontra a linha correspondente preencherDadosPedidoNaLinha(event, linha); // Passa a linha para preenchimento }); buscarPedidosDoClienteEspecifico(idClienteAtual, comboPedidos); // Carrega os pedidos atualizarVisibilidadeLixeiras(); // Adiciona event listeners para os campos NSU e OBS da nova linha const nsuCell = novaLinha.querySelector('td[contenteditable="true"][data-maxlength="30"]'); const obsCell = novaLinha.querySelector('td[contenteditable="true"][data-maxlength="300"]'); nsuCell.addEventListener('input', limitarConteudo); obsCell.addEventListener('input', limitarConteudo); } function limitarConteudo(event) { const target = event.target; const maxLength = parseInt(target.dataset.maxlength, 10); if (isNaN(maxLength)) { return; // Se o atributo não estiver definido, não faz nada } if (target.textContent.length > maxLength) { target.textContent = target.textContent.slice(0, maxLength); // Move o cursor para o final do texto truncado const range = document.createRange(); range.selectNodeContents(target); range.collapse(false); const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } } // Adicione event listeners para os campos NSU e OBS existentes document.querySelectorAll('td[data-maxlength]').forEach(function (cell) { cell.addEventListener('input', limitarConteudo); }); function buscarPedidosDoClienteEspecifico(idCliente, comboPedidos) { comboPedidos.innerHTML = "<option value=''>Carregando...</option>"; const url = `/buscar_pedidos_cliente?id_cliente=${idCliente}`; fetch(url) .then((response) => { if (!response.ok) { throw new Error(`Erro na requisição: ${response.status}`); } return response.json(); }) .then((data) => { pedidosData = {}; // Limpa os dados antigos comboPedidos.innerHTML = "<option value=''>Selecione o Pedido</option>"; if (data.length === 0) { comboPedidos.innerHTML = "<option value=''>Nenhum pedido encontrado</option>"; return; } data.forEach((pedido) => { pedidosData[pedido.pedido_venda] = pedido; // Armazena detalhes do pedido usando `pedido_venda` como chave const option = document.createElement("option"); option.value = pedido.pedido_venda; // Define o valor do select option.textContent = pedido.pedido_venda; // Exibe o texto do pedido comboPedidos.appendChild(option); }); }) .catch((error) => { console.error("Erro ao buscar pedidos:", error); comboPedidos.innerHTML = "<option value=''>Erro ao carregar os pedidos</option>"; }); } function preencherDadosPedidoNaLinha(event, linha) { const pedidoSelecionado = event.target.value; const pedidoDetalhes = pedidosData[pedidoSelecionado]; if (!pedidoDetalhes) return; // Preenche os campos da linha com os valores do pedido linha.children[1].textContent = pedidoDetalhes.filial || "N/A"; // Filial linha.children[2].textContent = `R$ ${pedidoDetalhes.valor_pedido.toFixed(2)}`; // Valor Pedido linha.children[3].textContent = `R$ ${pedidoDetalhes.frete.toFixed(2)}`; // Valor Frete linha.children[4].textContent = `R$ ${pedidoDetalhes.desconto.toFixed(2)}`; // Valor Desconto linha.children[7].textContent = pedidoDetalhes.cond_pgto || "N/A"; // Condição Pagamento // Atualiza o Valor Final automaticamente atualizarValorFinal(linha); } function atualizarValorFinal(linha) { const valorPedido = parseFloat(linha.children[2].textContent.replace("R$", "").replace(",", ".")) || 0; const valorFrete = parseFloat(linha.children[3].textContent.replace("R$", "").replace(",", ".")) || 0; const valorDesconto = parseFloat(linha.children[4].textContent.replace("R$", "").replace(",", ".")) || 0; const ds = parseFloat(linha.children[5].textContent.replace(",", ".")) || 0; // Calcula o valor final const valorFinal = valorPedido + valorFrete - valorDesconto - ds; // Atualiza o campo Valor Final da linha linha.children[6].textContent = `R$ ${valorFinal.toFixed(2)}`; } function atualizarCalculos(linha) { const camposEditaveis = linha.querySelectorAll(".editable"); const valorFinalCell = linha.children[6]; camposEditaveis.forEach((campo, index) => { campo.removeEventListener("click", () => (campo.textContent = "")); campo.addEventListener("keydown", (event) => { if (event.key === "Enter") { event.preventDefault(); const proximoCampo = camposEditaveis[index + 1] || camposEditaveis[0]; proximoCampo.focus(); } }); campo.addEventListener("input", () => calcularValorFinal(linha, valorFinalCell)); }); } function calcularValorFinal(linha, valorFinalCell) { const valorPedido = parseFloat(linha.children[1].textContent.replace(/\./g, "").replace(",", ".")) || 0; const valorFrete = parseFloat(linha.children[2].textContent.replace(/\./g, "").replace(",", ".")) || 0; const valorDesconto = parseFloat(linha.children[3].textContent.replace(/\./g, "").replace(",", ".")) || 0; const ds = parseFloat(linha.children[4].textContent.replace(/\./g, "").replace(",", ".")) || 0; const valorFinal = valorPedido + valorFrete - valorDesconto - ds; valorFinalCell.textContent = valorFinal.toLocaleString("pt-BR", { minimumFractionDigits: 2, maximumFractionDigits: 2, }); } function adicionarLixeira(linha) { const celulaLixeira = document.createElement("td"); celulaLixeira.innerHTML = '<i class="fas fa-trash lixeira" style="cursor: pointer;"></i>'; linha.appendChild(celulaLixeira); // Adiciona evento de clique na lixeira para remover a linha celulaLixeira.addEventListener("click", () => { removerLinha(linha); }); } function removerLinha(linha) { tabela.removeChild(linha); atualizarVisibilidadeLixeiras(); } function atualizarVisibilidadeLixeiras() { const linhas = tabela.querySelectorAll("tr"); // Seleciona todas as linhas const tabelaHeader = tabela.closest("table").querySelector("thead tr"); // Cabeçalho da tabela // Verifica ou adiciona a coluna de lixeira no cabeçalho let thLixeira = tabelaHeader.querySelector(".lixeira"); if (linhas.length > 1) { if (!thLixeira) { thLixeira = document.createElement("th"); thLixeira.classList.add("lixeira"); thLixeira.style.width = "50px"; // Ajuste opcional tabelaHeader.appendChild(thLixeira); } // Adiciona lixeira a todas as linhas linhas.forEach((linha) => { let celulaLixeira = linha.querySelector("td.lixeira"); if (!celulaLixeira) { celulaLixeira = document.createElement("td"); celulaLixeira.classList.add("lixeira"); celulaLixeira.innerHTML = `<i class="fas fa-trash" style="cursor: pointer; color: red;"></i>`; // Evento para remoção da linha celulaLixeira.querySelector("i").addEventListener("click", () => { removerLinha(linha); }); linha.appendChild(celulaLixeira); // Adiciona a lixeira na linha } }); } else { // Remove a coluna e as lixeiras, pois só há uma linha if (thLixeira) { thLixeira.remove(); } linhas.forEach((linha) => { const celulaLixeira = linha.querySelector("td.lixeira"); if (celulaLixeira) { celulaLixeira.remove(); } }); } } tabela.addEventListener("click", (event) => { if (event.target.classList.contains("lixeira")) { const linha = event.target.closest("tr"); linha.remove(); atualizarVisibilidadeLixeiras(); } }); // Função para limpar o combo de pedidos function limparPedidos() { const comboPedidos = document.querySelector("#combo-pedidos"); comboPedidos.innerHTML = "<option value=''>Selecione o Pedido</option>"; } // Inicialização // atualizarVisibilidadeLixeiras(); // Evento do botão toggle "Boleta Finalizada" boletaFinalizadaCheckbox.addEventListener("change", function () { if (boletaFinalizadaCheckbox.checked) { console.log("Boleta Finalizada: true"); } else { console.log("Boleta Finalizada: false"); } }); // Inicializa o Listener para o combo de pedidos, após a criação da linha const comboPedidosInicial = document.querySelector("#combo-pedidos"); if (comboPedidosInicial) { buscarPedidosDoClienteEspecifico(idClienteAtual, comboPedidosInicial); comboPedidosInicial.addEventListener("change", preencherDadosPedidoNaLinha); } document.getElementById("limparBoleta").addEventListener("click", function (event) { event.preventDefault(); // Evita que a página seja atualizada imediatamente if (confirm("Tem certeza que deseja limpar todas as informações da boleta?")) { location.reload(); // Limpa a boleta } }); }); document.addEventListener("DOMContentLoaded", () => { const tabela = document.querySelector("#pedidoGrid tbody"); // const botaoAdicionar = document.querySelector("#adicionarLinha"); // Adiciona os eventos necessários à tabela tabela.addEventListener("input", (event) => { const target = event.target; // Se a célula editada for a coluna "DS (R$)" if (target && target.cellIndex === 5) { // Índice 4 corresponde ao "DS (R$)" formatarComoMoeda(target); // Formata como moeda recalcularLinha(target.closest("tr")); // Recalcula o valor final da linha } }); // Função para formatar uma célula como moeda function formatarComoMoeda(celula) { celula.textContent = celula.textContent.replace(/[^\d,.\-]/g, ''); // Remove caracteres não numéricos } // Função para recalcular o valor final da linha function recalcularLinha(linha) { const valorPedido = parseFloat(obterNumeroDaCelula(linha.cells[2])); // Valor Pedido (R$) const valorFrete = parseFloat(obterNumeroDaCelula(linha.cells[3])); // Valor Frete (R$) const valorDesconto = parseFloat(obterNumeroDaCelula(linha.cells[4])); // Valor Desconto (R$) const valorDS = parseFloat(obterNumeroDaCelula(linha.cells[5])); // DS (R$) // Calcula o valor final const valorFinal = valorPedido + valorFrete - valorDesconto - valorDS; // Atualiza a coluna "Valor Final (R$)" linha.cells[6].textContent = valorFinal.toLocaleString("pt-BR", { style: "currency", currency: "BRL", }); } // Função para obter o número de uma célula (removendo formatação) function obterNumeroDaCelula(celula) { if (!celula) return 0; const valor = celula.textContent.replace(/[^\d,.-]/g, "").replace(",", "."); return parseFloat(valor) || 0; } });
Criar Web App RPG Inspirado em Diablo II
Crie um web app com visual inspirado em jogos RPG estilo Diablo II. No centro da tela, exiba um personagem animado em pixel art usando esta spritesheet vertical: https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/2ab05d2c-376c-4f03-b12a-f85300e15690/dfouvz7-e626a8a6-df28-4053-ad42-989874e2214c.png/v1/fill/w_603%2Ch_1324%2Cq_70%2Cstrp/diablo__isekai_maou__sprite_sheet_v2_by_quinmf_dfouvz7-pre.jpg A spritesheet possui 8 frames verticais, com largura de 603px e altura total de 1324px. O personagem deve estar animado em loop, usando CSS keyframes para alterar a posição do background verticalmente. A imagem deve ser carregada como background-image de um div com tamanho 603x166 px. Use Tailwind CSS ou CSS puro com steps(8) para simular a animação. O fundo da página deve ter uma estética medieval dark (ex: textura de pedra, tons escuros). Adicione no topo da tela uma HUD com barra de vida (vermelha) e mana (azul), estilizadas como em jogos clássicos. Tudo deve rodar no navegador, sem dependência de APIs externas.
Catálogo de Produtos React
quero alteração desse meu catalogo seja feita por cada produto, quando estou clicando em uma cor ele clica também para o proximo produto. E sem contar que quero alguns exemplos de cores para serem selecionados e que apareça o nome da cor: import React, { useState, useEffect } from 'react'; import './App.css'; const App = () => { const [products, setProducts] = useState([]); const [selectedColor, setSelectedColor] = useState(''); const [selectedSize, setSelectedSize] = useState(''); const [price, setPrice] = useState(0); const [stock, setStock] = useState(0); useEffect(() => { // Simulando a busca de produtos do backend const fetchedProducts = [ { id: 1, name: 'Camiseta Básica', image: 'https://placehold.co/300X300', colors: ['Branco', 'Preto', 'Azul'], sizes: ['P', 'M', 'G'], prices: [29.99, 29.99, 34.99], stock: [10, 15, 8] }, { id: 2, name: 'Calça Jeans', image: 'https://placehold.co/300X300', colors: ['Azul', 'Preto'], sizes: ['38', '40', '42'], prices: [89.99, 99.99], stock: [5, 7] } ]; setProducts(fetchedProducts); if (fetchedProducts.length > 0) { setSelectedColor(fetchedProducts[0].colors[0]); setSelectedSize(fetchedProducts[0].sizes[0]); setPrice(fetchedProducts[0].prices[0]); setStock(fetchedProducts[0].stock[0]); } }, []); const handleColorChange = (productIndex, colorIndex) => { setSelectedColor(products[productIndex].colors[colorIndex]); setPrice(products[productIndex].prices[colorIndex]); setStock(products[productIndex].stock[colorIndex]); }; const handleSizeChange = (productIndex, sizeIndex) => { setSelectedSize(products[productIndex].sizes[sizeIndex]); }; return ( <div className="App min-h-screen bg-gray-100 py-8"> <div className="container mx-auto px-4"> <h1 className="text-4xl font-bold text-center mb-8">Catálogo de Vestuário</h1> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {products.map((product, productIndex) => ( <div key={product.id} className="bg-white rounded-lg shadow-md p-6"> <img src={product.image} alt={product.name} className="w-full h-64 object-cover rounded-lg mb-4" /> <h2 className="text-xl font-semibold mb-2">{product.name}</h2> <div className="mb-4"> <label className="block text-sm font-medium text-gray-700">Cor:</label> <div className="flex space-x-2 mt-1"> {product.colors.map((color, colorIndex) => ( <button key={colorIndex} onClick={() => handleColorChange(productIndex, colorIndex)} className={`w-8 h-8 rounded-full border-2 ${selectedColor === color ? 'border-blue-500' : 'border-gray-300'} focus:outline-none`} style={{ backgroundColor: color.toLowerCase() }} ></button> ))} </div> </div> <div className="mb-4"> <label className="block text-sm font-medium text-gray-700">Tamanho:</label> <div className="flex space-x-2 mt-1"> {product.sizes.map((size, sizeIndex) => ( <button key={sizeIndex} onClick={() => handleSizeChange(productIndex, sizeIndex)} className={`px-4 py-2 rounded-md ${selectedSize === size ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'} focus:outline-none`} > {size} </button> ))} </div> </div> <div className="text-lg font-semibold mb-2">Preço: R$ {price.toFixed(2)}</div> <div className="text-sm text-gray-600">Estoque: {stock} unidades</div> </div> ))} </div> <div className="mt-8 text-center text-sm text-gray-500"> © 2025 Todos os direitos reservados. </div> </div> </div> ); }; export default App;
Catálogo de Produtos React
quero alteração desse meu catalogo seja feita por cada produto, quando estou clicando em uma cor ele clica também para o proximo produto. E sem contar que quero alguns exemplos de cores para serem selecionados e que apareça o nome da cor: import React, { useState, useEffect } from 'react'; import './App.css'; const App = () => { const [products, setProducts] = useState([]); const [selectedColor, setSelectedColor] = useState(''); const [selectedSize, setSelectedSize] = useState(''); const [price, setPrice] = useState(0); const [stock, setStock] = useState(0); useEffect(() => { // Simulando a busca de produtos do backend const fetchedProducts = [ { id: 1, name: 'Camiseta Básica', image: 'https://placehold.co/300X300', colors: ['Branco', 'Preto', 'Azul'], sizes: ['P', 'M', 'G'], prices: [29.99, 29.99, 34.99], stock: [10, 15, 8] }, { id: 2, name: 'Calça Jeans', image: 'https://placehold.co/300X300', colors: ['Azul', 'Preto'], sizes: ['38', '40', '42'], prices: [89.99, 99.99], stock: [5, 7] } ]; setProducts(fetchedProducts); if (fetchedProducts.length > 0) { setSelectedColor(fetchedProducts[0].colors[0]); setSelectedSize(fetchedProducts[0].sizes[0]); setPrice(fetchedProducts[0].prices[0]); setStock(fetchedProducts[0].stock[0]); } }, []); const handleColorChange = (productIndex, colorIndex) => { setSelectedColor(products[productIndex].colors[colorIndex]); setPrice(products[productIndex].prices[colorIndex]); setStock(products[productIndex].stock[colorIndex]); }; const handleSizeChange = (productIndex, sizeIndex) => { setSelectedSize(products[productIndex].sizes[sizeIndex]); }; return ( <div className="App min-h-screen bg-gray-100 py-8"> <div className="container mx-auto px-4"> <h1 className="text-4xl font-bold text-center mb-8">Catálogo de Vestuário</h1> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> {products.map((product, productIndex) => ( <div key={product.id} className="bg-white rounded-lg shadow-md p-6"> <img src={product.image} alt={product.name} className="w-full h-64 object-cover rounded-lg mb-4" /> <h2 className="text-xl font-semibold mb-2">{product.name}</h2> <div className="mb-4"> <label className="block text-sm font-medium text-gray-700">Cor:</label> <div className="flex space-x-2 mt-1"> {product.colors.map((color, colorIndex) => ( <button key={colorIndex} onClick={() => handleColorChange(productIndex, colorIndex)} className={`w-8 h-8 rounded-full border-2 ${selectedColor === color ? 'border-blue-500' : 'border-gray-300'} focus:outline-none`} style={{ backgroundColor: color.toLowerCase() }} ></button> ))} </div> </div> <div className="mb-4"> <label className="block text-sm font-medium text-gray-700">Tamanho:</label> <div className="flex space-x-2 mt-1"> {product.sizes.map((size, sizeIndex) => ( <button key={sizeIndex} onClick={() => handleSizeChange(productIndex, sizeIndex)} className={`px-4 py-2 rounded-md ${selectedSize === size ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'} focus:outline-none`} > {size} </button> ))} </div> </div> <div className="text-lg font-semibold mb-2">Preço: R$ {price.toFixed(2)}</div> <div className="text-sm text-gray-600">Estoque: {stock} unidades</div> </div> ))} </div> <div className="mt-8 text-center text-sm text-gray-500"> © 2025 Todos os direitos reservados. </div> </div> </div> ); }; export default App;
Catálogo de Roupas em Flask
Quero um aplicativo no modelo de catalogo para o ramo de vestuário e confecção, com a possibilidade de escolhe cor e tamnho para cada produto, e traga o preço e o estoque ao selecionar cada uma delas. Ele precisa estar 100% em português. Vou utilizar o Flask do Python com backend, então tente utilizar mais CSS e html. Preciso que adicione foto nesse catalogo e que traga já uma cor e um tamanho preenchido, os primeiros da lista
