0% found this document useful (0 votes)
2 views8 pages

ItemprojetoHTML e Js

The document is an HTML page for a project item management interface, featuring a form to add, update, and delete project items. It includes a navigation bar, a form for item entry, and a table displaying registered items, with JavaScript handling data fetching and user interactions. The page utilizes Bootstrap for styling and layout, and communicates with a backend API for project and material data management.

Uploaded by

Duke doidao
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views8 pages

ItemprojetoHTML e Js

The document is an HTML page for a project item management interface, featuring a form to add, update, and delete project items. It includes a navigation bar, a form for item entry, and a table displaying registered items, with JavaScript handling data fetching and user interactions. The page utilizes Bootstrap for styling and layout, and communicates with a backend API for project and material data management.

Uploaded by

Duke doidao
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 8

<!

DOCTYPE html>
<html lang="pt-BR" data-bs-theme="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Itens do Projeto</title>
<link

href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
rel="stylesheet"
crossorigin="anonymous"
/>
<style>
body {
padding-top: 56px;
}
.card-custom {
background-color: var(--bs-card-bg, #2b3035);
border: 1px solid var(--bs-border-color, #495057);
padding: 1.5rem;
margin-bottom: 2rem;
border-radius: 0.375rem;
}
.btn-preencher {
background-color: #6c757d;
border-color: #6c757d;
color: white;
}
.btn-preencher:hover {
background-color: #5a6268;
border-color: #545b62;
}
.toast {
min-width: 300px;
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg fixed-top">
<div class="container-fluid">
<a class="navbar-brand" href="#">BuildUP</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav text-decoration-none gap-4">
<li class="nav-item">
<a class="nav-link" href="clientes.html">Clientes</a>
</li>
<li class="nav-item">
<a class="nav-link" href="materiais.html">Materiais</a>
</li>
<li class="nav-item">
<a class="nav-link" href="projetos.html">Projetos</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="itemprojeto.html">Itens do
Projeto</a>
</li>
</ul>
</div>
</div>
</nav>

<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index:


1100"></div>

<div class="container mt-5">


<div class="card-custom shadow-sm">
<h1 class="mb-4 fs-4">Formulário de Itens do Projeto</h1>
<div class="row g-3 align-items-end">
<div class="col-md-2">
<label for="inputId" class="form-label">ID</label>
<input type="text" class="form-control" id="inputId" disabled
readonly />
</div>
<div class="col-md-4">
<label for="inputProjeto" class="form-label">Projeto</label>
<select id="inputProjeto" class="form-select"></select>
</div>
<div class="col-md-4">
<label for="inputMaterial" class="form-label">Material</label>
<select id="inputMaterial" class="form-select"></select>
</div>
<div class="col-md-2">
<label for="inputQuantidade" class="form-label">Quantidade</label>
<input type="number" class="form-control" id="inputQuantidade"
min="1" />
</div>
</div>
<div class="row mt-3">
<div class="col-12 d-flex justify-content-end">
<button type="button" class="btn btn-secondary me-2"
id="btnLimpar">Limpar</button>
<button type="button" class="btn btn-primary me-2"
id="btnAdicionar">Adicionar</button>
<button type="button" class="btn btn-success" id="btnAtualizar"
disabled>Atualizar</button>
</div>
</div>
</div>

<div class="card-custom shadow-sm mt-4">


<h2 class="mb-3 fs-5">Itens Cadastrados</h2>
<div class="table-responsive">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Projeto</th>
<th>Material</th>
<th>Quantidade</th>
<th>Valor Total</th> <th class="text-end">Ações</th>
</tr>
</thead>
<tbody id="tabelaItensProjetoBody"></tbody>
</table>
</div>
</div>
</div>

<script

src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"
></script>
<script src="itemprojeto.js"></script>
</body>
</html>

// itemprojeto.js
document.addEventListener("DOMContentLoaded", () => {
const URL_BASE = "http://localhost:3000";

// SELETORES
const inputIdItemProjeto = document.getElementById("inputId");
const selectProjeto = document.getElementById("inputProjeto");
const selectMaterial = document.getElementById("inputMaterial");
const inputQuantidade = document.getElementById("inputQuantidade");

const tabelaItensBody = document.getElementById("tabelaItensProjetoBody");

const btnAdicionar = document.getElementById("btnAdicionar");


const btnAtualizar = document.getElementById("btnAtualizar");
const btnLimpar = document.getElementById("btnLimpar");

const toastContainer = document.querySelector(".toast-container");

// Função para exibir toasts


const showToast = (message, type = "info", title = "Notificação") => {
const toastId = "toast-" + Math.random().toString(36).substr(2, 9);
const toastHTML = `
<div id="${toastId}" class="toast" role="alert" aria-live="assertive" aria-
atomic="true" data-bs-delay="4000">
<div class="toast-header">
<strong class="me-auto text-${type}">${title}</strong>
<small>Agora</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-
label="Close"></button>
</div>
<div class="toast-body">
${message}
</div>
</div>
`;
toastContainer.insertAdjacentHTML("beforeend", toastHTML);
const el = document.getElementById(toastId);
const toast = new bootstrap.Toast(el);
el.addEventListener("hidden.bs.toast", () => el.remove());
toast.show();
};

// Função para carregar projetos no select


async function carregarProjetos() {
try {
const response = await fetch(`${URL_BASE}/projetos`);
if (!response.ok) throw new Error('Erro ao buscar projetos');
const projetos = await response.json();

selectProjeto.innerHTML = "<option value=''>Selecione um Projeto</option>";


projetos.forEach(p => {
const option = document.createElement("option");
option.value = p.IDP;
const dataFormatada = p.Data_projeto ? new Date(p.Data_projeto.split('-')
[0], p.Data_projeto.split('-')[1] - 1, p.Data_projeto.split('-')
[2]).toLocaleDateString('pt-BR') : 'N/D';
option.textContent = `IDP: ${p.IDP} (${p.Status_projeto || 'N/D'}) -
Cliente: ${p.NomeCliente || 'N/D'} em ${dataFormatada}`;
selectProjeto.appendChild(option);
});
} catch (error) {
console.error("Falha ao carregar projetos:", error);
showToast("Falha ao carregar projetos para seleção.", "danger", "Erro");
}
}

// Função para carregar materiais no select


async function carregarMateriais() {
try {
const response = await fetch(`${URL_BASE}/materiais`);
if (!response.ok) throw new Error('Erro ao buscar materiais');
const materiais = await response.json();

selectMaterial.innerHTML = "<option value=''>Selecione um Material</option>";


materiais.forEach(m => {
const option = document.createElement("option");
option.value = m.IDM;
option.textContent = `${m.Nome} (R$ $
{Number(m.Valor_U).toFixed(2).replace('.', ',')})`; // Formata Valor_U para moeda
selectMaterial.appendChild(option);
});
} catch (error) {
console.error("Falha ao carregar materiais:", error);
showToast("Falha ao carregar materiais para seleção.", "danger", "Erro");
}
}

// Função para carregar e renderizar itens do projeto na tabela


async function carregarItensProjeto() {
try {
const response = await fetch(`${URL_BASE}/itemprojeto`);
if (!response.ok) {
const erroData = await response.json().catch(() => ({ error: "Erro
desconhecido ao buscar itens." }));
throw new Error(erroData.error || `Erro ${response.status}`);
}
const itens = await response.json();
renderizarTabelaItens(itens);
} catch (error) {
console.error("Falha ao carregar itens do projeto:", error);
tabelaItensBody.innerHTML = `<tr><td colspan="6" class="text-center text-
danger">Erro ao carregar itens: ${error.message}</td></tr>`;
showToast(`Falha ao carregar itens: ${error.message}`, "danger", "Erro de
Conexão");
}
}

// Função para renderizar a tabela de itens do projeto


function renderizarTabelaItens(itens) {
tabelaItensBody.innerHTML = "";
if (!itens || itens.length === 0) {
tabelaItensBody.innerHTML = '<tr><td colspan="6" class="text-center">Nenhum
item de projeto cadastrado.</td></tr>';
return;
}

itens.forEach(item => {
const tr = document.createElement("tr");
let dataProjetoDisplay = 'N/A';
if (item.Data_projeto) {
const partesData = item.Data_projeto.split('-');
if (partesData.length === 3) {
const ano = parseInt(partesData[0], 10);
const mes = parseInt(partesData[1], 10) - 1;
const dia = parseInt(partesData[2], 10);
dataProjetoDisplay = new Date(ano, mes, dia).toLocaleDateString('pt-BR');
} else {
dataProjetoDisplay = 'Data Inválida Recebida';
}
}

tr.innerHTML = `
<td>${item.id_item_projeto}</td>
<td>IDP: ${item.id_projeto} (${item.StatusProjeto || 'N/A'} em $
{dataProjetoDisplay})</td>
<td>${item.NomeMaterial || 'Material não encontrado'} (IDM: $
{item.id_material})</td>
<td>${item.quantidade}</td>
<td>R$ ${Number(item.valor_total).toFixed(2).replace('.', ',')}</td>
<td class="text-end">
<button class="btn btn-outline-secondary btn-sm me-2 btn-editar-item"
data-iditem="${item.id_item_projeto}"
data-idprojeto="${item.id_projeto}"
data-idmaterial="${item.id_material}"
data-quantidade="${item.quantidade}">Editar</button>
<button class="btn btn-outline-danger btn-sm btn-excluir-item" data-
iditem="${item.id_item_projeto}">Excluir</button>
</td>
`;
tabelaItensBody.appendChild(tr);
});

// Adicionar event listeners aos botões de editar e excluir


document.querySelectorAll('.btn-editar-item').forEach(button => {
button.addEventListener('click', function () {
editarItem(
this.dataset.iditem,
this.dataset.idprojeto,
this.dataset.idmaterial,
this.dataset.quantidade
);
});
});

document.querySelectorAll('.btn-excluir-item').forEach(button => {
button.addEventListener('click', function () {
deletarItem(this.dataset.iditem);
});
});
}

// Event listener para adicionar item


btnAdicionar.addEventListener("click", async () => {
const item = {
id_projeto: parseInt(selectProjeto.value),
id_material: parseInt(selectMaterial.value),
quantidade: parseInt(inputQuantidade.value)
};

if (!item.id_projeto) return showToast("Selecione um Projeto.", "warning",


"Validação");
if (!item.id_material) return showToast("Selecione um Material.", "warning",
"Validação");
if (isNaN(item.quantidade) || item.quantidade <= 0) return
showToast("Quantidade deve ser um número maior que zero.", "warning", "Validação");

try {
const response = await fetch(`${URL_BASE}/itemprojeto`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(item)
});
const resultado = await response.json();
if (!response.ok) throw new Error(resultado.error || `Erro $
{response.status}`);

showToast(resultado.message || `Item (ID: ${resultado.id_item_projeto})


adicionado!`, "success", "Item Adicionado");
limparFormularioItem();
carregarItensProjeto();
} catch (error) {
showToast(`Erro ao adicionar item: ${error.message}`, "danger", "Erro");
}
});

// Event listener para atualizar item


btnAtualizar.addEventListener("click", async () => {
const idItem = inputIdItemProjeto.value;
if (!idItem || idItem === "—") return showToast("Nenhum item selecionado para
atualizar.", "warning", "Validação");

const item = {
id_projeto: parseInt(selectProjeto.value),
id_material: parseInt(selectMaterial.value),
quantidade: parseInt(inputQuantidade.value)
};

if (!item.id_projeto) return showToast("Selecione um Projeto.", "warning",


"Validação");
if (!item.id_material) return showToast("Selecione um Material.", "warning",
"Validação");
if (isNaN(item.quantidade) || item.quantidade <= 0) return
showToast("Quantidade deve ser um número maior que zero.", "warning", "Validação");

try {
const response = await fetch(`${URL_BASE}/itemprojeto/${idItem}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(item)
});
const resultado = await response.json();
if (!response.ok) throw new Error(resultado.error || `Erro $
{response.status}`);

showToast(resultado.message || `Item (ID: ${idItem}) atualizado!`, "success",


"Item Atualizado");
limparFormularioItem();
carregarItensProjeto();
} catch (error) {
showToast(`Erro ao atualizar item: ${error.message}`, "danger", "Erro");
}
});

// Event listener para limpar formulário


if (btnLimpar) {
btnLimpar.onclick = limparFormularioItem;
}

// Função para preencher o formulário para edição


function editarItem(id, id_projeto, id_material, quantidade) {
inputIdItemProjeto.value = id;
selectProjeto.value = id_projeto;
selectMaterial.value = id_material;
inputQuantidade.value = quantidade;

btnAdicionar.disabled = true;
btnAtualizar.disabled = false;
selectProjeto.focus();
}

// Função para deletar item


async function deletarItem(id) {
if (!confirm(`Tem certeza que deseja excluir o item de projeto ID: ${id}?`))
return;

try {
const response = await fetch(`${URL_BASE}/itemprojeto/${id}`, { method:
"DELETE" });
const resultado = await response.json();
if (!response.ok) throw new Error(resultado.error || `Erro $
{response.status}`);

showToast(resultado.message || `Item (ID: ${id}) excluído!`, "info", "Item


Excluído");
carregarItensProjeto();
limparFormularioItem();
} catch (error) {
showToast(`Erro ao excluir item: ${error.message}`, "danger", "Erro");
}
}

// Função para limpar o formulário


function limparFormularioItem() {
inputIdItemProjeto.value = "—";
selectProjeto.value = "";
selectMaterial.value = "";
inputQuantidade.value = "";
btnAdicionar.disabled = false;
btnAtualizar.disabled = true;
}

// Inicializar a página carregando os dados


async function inicializarPagina() {
limparFormularioItem();
await Promise.all([carregarProjetos(), carregarMateriais()]);
await carregarItensProjeto();
}

inicializarPagina();
});

You might also like