versao botao word

This commit is contained in:
Flatlogic Bot 2025-12-01 22:37:36 +00:00
parent 21e017feae
commit 2968f9881d
99 changed files with 1102 additions and 263 deletions

View File

@ -6,25 +6,19 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$client_name = trim($_POST['client_name'] ?? '');
$address = trim($_POST['address'] ?? '');
$technician_name = trim($_POST['technician_name'] ?? '');
$observations = trim($_POST['observations'] ?? '');
$status = trim($_POST['status'] ?? 'ativo');
$voltage = !empty($_POST['voltage']) ? trim($_POST['voltage']) : null;
$phase_neutral_ground = !empty($_POST['phase_neutral_ground']) ? trim($_POST['phase_neutral_ground']) : null;
$breaker_output = !empty($_POST['breaker_output']) ? trim($_POST['breaker_output']) : null;
// Validation removed to allow incomplete forms
$installation_date = !empty($_POST['installation_date']) ? trim($_POST['installation_date']) : null;
$pdo = db();
try {
$pdo->beginTransaction();
$stmt = $pdo->prepare(
"INSERT INTO installations (client_name, address, technician_name, observations, status, voltage, phase_neutral_ground, breaker_output) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
"INSERT INTO installations (client_name, address, technician_name, status, created_at) VALUES (?, ?, ?, ?, ?)"
);
$stmt->execute([$client_name, $address, $technician_name, $observations, $status, $voltage, $phase_neutral_ground, $breaker_output]);
$stmt->execute([$client_name, $address, $technician_name, $status, $installation_date]);
$installation_id = $pdo->lastInsertId();
// Handle multiple file uploads
if (isset($_FILES['images'])) {
$upload_dir = __DIR__ . '/assets/uploads/';
if (!is_dir($upload_dir)) {
@ -59,16 +53,122 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo->commit();
$_SESSION['message'] = 'Instalação registrada com sucesso!';
$_SESSION['message_type'] = 'success';
header('Location: index.php');
exit;
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
error_log("Upload/Database error: " . $e->getMessage());
$_SESSION['message'] = 'Falha ao registrar a instalação: ' . $e->getMessage();
$_SESSION['message'] = 'Erro ao registrar a instalação: ' . $e->getMessage();
$_SESSION['message_type'] = 'danger';
}
}
header('Location: index.php');
header('Location: add_installation.php');
exit;
}
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adicionar Nova Instalação - iload net Solutions</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="sidebar">
<a class="navbar-brand" href="index.php">iload net Solutions</a>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php">
<i class="bi bi-grid-1x2-fill"></i> Painel de Controle
</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="add_installation.php">
<i class="bi bi-plus-circle-fill"></i> Adicionar Instalação
</a>
</li>
</ul>
</div>
<div class="main-content">
<nav class="top-navbar navbar navbar-expand">
<div class="container-fluid">
<ul class="navbar-nav ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle me-1"></i> Administrador
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Perfil</a></li>
<li><a class="dropdown-item" href="#">Sair</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm mb-4">
<div class="card-header py-3">
<h1 class="h3 mb-0 text-gray-800">Registrar Nova Instalação</h1>
</div>
<div class="card-body">
<?php if (!empty($_SESSION['message'])): ?>
<div class="alert alert-<?php echo $_SESSION['message_type']; ?>">
<?php echo $_SESSION['message']; ?>
</div>
<?php unset($_SESSION['message'], $_SESSION['message_type']); ?>
<?php endif; ?>
<form action="add_installation.php" method="POST" enctype="multipart/form-data">
<div class="mb-3">
<label for="client_name" class="form-label">Nome do Cliente</label>
<input type="text" class="form-control" id="client_name" name="client_name" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="address" class="form-label">Endereço</label>
<input type="text" class="form-control" id="address" name="address" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="technician_name" class="form-label">Nome do Técnico</label>
<input type="text" class="form-control" id="technician_name" name="technician_name" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="installation_date" class="form-label">Data da Instalação</label>
<input type="date" class="form-control" id="installation_date" name="installation_date" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status" style="width: 100%;">
<option value="ativo">Ativo</option>
<option value="Manutencao">Manutenção</option>
<option value="Manutenção Parcial">Manutenção Parcial</option>
<option value="inativo">Inativo</option>
</select>
</div>
<div class="mb-3">
<label for="images" class="form-label">Imagens da Instalação (múltiplas)</label>
<input type="file" class="form-control" id="images" name="images[]" multiple accept="image/*" style="width: 100%;">
</div>
<hr class="my-4">
<div class="d-flex justify-content-end">
<a href="index.php" class="btn btn-secondary me-2">Cancelar</a>
<button type="submit" class="btn btn-primary">Salvar Instalação</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -1,75 +1,9 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap');
:root {
--primary-color: #6cc24a;
--secondary-color: #2c3e50;
--sidebar-width: 280px;
}
body {
font-family: 'Poppins', sans-serif;
background-color: #f0f2f5;
color: #495057;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: var(--sidebar-width);
background-color: var(--secondary-color);
padding-top: 1rem;
transition: all 0.3s;
}
.sidebar .nav-link {
color: #adb5bd;
font-weight: 500;
padding: 0.75rem 1.5rem;
display: flex;
align-items: center;
}
.sidebar .nav-link i {
margin-right: 0.75rem;
font-size: 1.1rem;
width: 20px;
text-align: center;
}
.sidebar .nav-link:hover, .sidebar .nav-link.active {
color: #fff;
background-color: rgba(255, 255, 255, 0.05);
}
.sidebar .navbar-brand {
color: #fff !important;
font-weight: 700;
padding: 0.5rem 1.5rem;
font-size: 1.5rem;
margin-bottom: 1rem;
}
.main-content {
margin-left: var(--sidebar-width);
padding: 2rem;
transition: all 0.3s;
}
.top-navbar {
background-color: #fff;
border-radius: 0.5rem;
margin-bottom: 2rem;
padding: 0.75rem 1.5rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
}
/* Estilos para os cards de KPI */
.kpi-card {
border: none;
border-radius: 0.75rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
margin-bottom: 2rem;
border: 1px solid #e3e6f0;
border-radius: .35rem;
transition: all .3s ease;
margin-bottom: 1.5rem;
}
.kpi-card .card-body {
@ -77,55 +11,95 @@ body {
align-items: center;
}
.kpi-card .kpi-icon {
font-size: 2.5rem;
padding: 1rem;
.kpi-icon {
width: 50px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
margin-right: 1.5rem;
color: #fff;
font-size: 24px;
margin-right: 1rem;
}
.kpi-card .kpi-value {
font-size: 2rem;
.kpi-value {
font-size: 1.5rem;
font-weight: 700;
color: #5a5c69;
}
.kpi-card .kpi-label {
font-weight: 500;
color: #6c757d;
.kpi-label {
font-size: .8rem;
font-weight: 700;
color: #858796;
text-transform: uppercase;
}
.card {
border-radius: 0.75rem;
border: none;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
/* Remove o sublinhado dos links nos cards de KPI */
a.kpi-link,
a.kpi-link:hover {
text-decoration: none;
color: inherit;
}
.btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
padding: 0.5rem 1.5rem;
font-weight: 600;
/* Estilos gerais */
body {
background-color: #f8f9fc;
}
.btn-primary:hover {
background-color: #58a83a;
border-color: #58a83a;
.sidebar {
width: 250px;
background-color: #4e73df;
position: fixed;
height: 100%;
padding-top: 1rem;
}
.table thead th {
border-bottom: 2px solid #dee2e6;
font-weight: 600;
.sidebar .navbar-brand {
color: #fff;
font-weight: 700;
text-align: center;
margin-bottom: 1rem;
display: block;
}
.table-hover tbody tr:hover {
background-color: #f8f9fa;
.sidebar .nav-link {
color: rgba(255,255,255,.8);
padding: .75rem 1.5rem;
}
.modal-header {
border-bottom: none;
.sidebar .nav-link.active,
.sidebar .nav-link:hover {
color: #fff;
background-color: rgba(255,255,255,.1);
}
.modal-footer {
border-top: none;
.sidebar .nav-link i {
margin-right: .5rem;
}
.main-content {
margin-left: 250px;
}
.top-navbar {
background-color: #fff;
border-bottom: 1px solid #e3e6f0;
padding: .5rem 1.5rem;
}
.container-fluid {
padding: 1.5rem;
}
/* Estilos para telas pequenas (dispositivos móveis) */
@media (max-width: 768px) {
.sidebar {
display: none; /* Esconde o menu lateral */
}
.main-content {
margin-left: 0; /* Remove a margem do conteúdo principal */
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -1,12 +1,56 @@
<?php
require_once __DIR__ . '/config.php';
function get_executed_migrations($pdo) {
try {
$pdo = db();
$sql = file_get_contents(__DIR__ . '/migrations/001_create_installations_table.sql');
$pdo->exec($sql);
echo "Migration completed successfully.\n";
$stmt = $pdo->query("SELECT `migration` FROM `migrations`");
return $stmt->fetchAll(PDO::FETCH_COLUMN);
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage() . "\n");
// If the migrations table doesn't exist, create it.
if ($e->getCode() === '42S02') { // Base table or view not found
$pdo->exec("CREATE TABLE `migrations` (`migration` VARCHAR(255) PRIMARY KEY, `executed_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP)");
return [];
}
throw $e;
}
}
function mark_migration_as_executed($pdo, $migration_file) {
$stmt = $pdo->prepare("INSERT INTO `migrations` (`migration`) VALUES (?)");
$stmt->execute([$migration_file]);
}
try {
$pdo = db();
echo "Conectado ao banco de dados.\n";
$executed_migrations = get_executed_migrations($pdo);
echo "Migrações já executadas: " . (empty($executed_migrations) ? "Nenhuma" : implode(', ', $executed_migrations)) . "\n";
$migration_files = glob(__DIR__ . '/migrations/*.sql');
sort($migration_files);
$new_migrations_found = false;
foreach ($migration_files as $file) {
$filename = basename($file);
if (!in_array($filename, $executed_migrations)) {
$new_migrations_found = true;
echo "Executando migração: $filename...\n";
$sql = file_get_contents($file);
$pdo->exec($sql);
mark_migration_as_executed($pdo, $filename);
echo " -> Migração $filename concluída.\n";
}
}
if (!$new_migrations_found) {
echo "Nenhuma nova migração para executar. O banco de dados já está atualizado.\n";
} else {
echo "Todas as novas migrações foram concluídas com sucesso!\n";
}
} catch (PDOException $e) {
die("Falha na migração: " . $e->getMessage() . "\n");
}

119
delete_installation.php Normal file
View File

@ -0,0 +1,119 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
$pdo = db();
// Handle the POST request to delete the installation
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$id = $_POST['id'] ?? null;
if ($id) {
try {
// Optional: You might want to delete related images first
$stmt = $pdo->prepare("DELETE FROM installation_images WHERE installation_id = ?");
$stmt->execute([$id]);
// Delete the installation
$stmt = $pdo->prepare("DELETE FROM installations WHERE id = ?");
$stmt->execute([$id]);
$_SESSION['message'] = 'Instalação excluída com sucesso!';
$_SESSION['message_type'] = 'success';
} catch (Exception $e) {
$_SESSION['message'] = 'Erro ao excluir a instalação: ' . $e->getMessage();
$_SESSION['message_type'] = 'danger';
}
}
header("Location: index.php");
exit;
}
// Handle the GET request to show the confirmation page
$id = $_GET['id'] ?? null;
if (!$id) {
header("Location: index.php");
exit;
}
// Fetch installation data for display
$stmt = $pdo->prepare("SELECT * FROM installations WHERE id = ?");
$stmt->execute([$id]);
$installation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$installation) {
$_SESSION['message'] = 'Instalação não encontrada.';
$_SESSION['message_type'] = 'danger';
header("Location: index.php");
exit;
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Confirmar Exclusão - iload net Solutions</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="sidebar">
<a class="navbar-brand" href="index.php">iload net Solutions</a>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php">
<i class="bi bi-grid-1x2-fill"></i> Painel de Controle
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_installation.php">
<i class="bi bi-plus-circle-fill"></i> Adicionar Instalação
</a>
</li>
</ul>
</div>
<div class="main-content">
<nav class="top-navbar navbar navbar-expand">
<div class="container-fluid">
<ul class="navbar-nav ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle me-1"></i> Administrador
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Perfil</a></li>
<li><a class="dropdown-item" href="#">Sair</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="card border-danger">
<div class="card-header bg-danger text-white">
<h1 class="h3 mb-0">Confirmar Exclusão</h1>
</div>
<div class="card-body">
<p>Você tem certeza de que deseja excluir permanentemente a instalação para o cliente <strong><?php echo htmlspecialchars($installation['client_name']); ?></strong> no endereço <strong><?php echo htmlspecialchars($installation['address']); ?></strong>?</p>
<p class="text-danger"><strong>Atenção:</strong> Esta ação não pode ser desfeita.</p>
<form action="delete_installation.php" method="POST">
<input type="hidden" name="id" value="<?php echo htmlspecialchars($installation['id']); ?>">
<div class="d-flex justify-content-end">
<a href="index.php" class="btn btn-secondary me-2">Cancelar</a>
<button type="submit" class="btn btn-danger">Confirmar Exclusão</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

179
edit_installation.php Normal file
View File

@ -0,0 +1,179 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
// Get installation ID from URL
$id = $_GET['id'] ?? null;
if (!$id) {
header("Location: index.php");
exit;
}
// Fetch installation data
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM installations WHERE id = ?");
$stmt->execute([$id]);
$installation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$installation) {
$_SESSION['message'] = 'Instalação não encontrada.';
$_SESSION['message_type'] = 'danger';
header("Location: index.php");
exit;
}
// Fetch images for this installation
$img_stmt = $pdo->prepare("SELECT * FROM installation_images WHERE installation_id = ?");
$img_stmt->execute([$id]);
$images = $img_stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Editar Instalação #<?php echo htmlspecialchars($installation['id']); ?> - iload net Solutions</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="sidebar">
<a class="navbar-brand" href="index.php">iload net Solutions</a>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php">
<i class="bi bi-grid-1x2-fill"></i> Painel de Controle
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_installation.php">
<i class="bi bi-plus-circle-fill"></i> Adicionar Instalação
</a>
</li>
</ul>
</div>
<div class="main-content">
<nav class="top-navbar navbar navbar-expand">
<div class="container-fluid">
<ul class="navbar-nav ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle me-1"></i> Administrador
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Perfil</a></li>
<li><a class="dropdown-item" href="#">Sair</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm mb-4">
<div class="card-header py-3">
<h1 class="h3 mb-0 text-gray-800">Editar Instalação #<?php echo htmlspecialchars($installation['id']); ?></h1>
</div>
<div class="card-body">
<form action="update_installation.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?php echo htmlspecialchars($installation['id']); ?>">
<div class="mb-3">
<label for="client_name" class="form-label">Nome do Cliente</label>
<input type="text" class="form-control" id="client_name" name="client_name" value="<?php echo htmlspecialchars($installation['client_name'] ?? ''); ?>" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="address" class="form-label">Endereço</label>
<input type="text" class="form-control" id="address" name="address" value="<?php echo htmlspecialchars($installation['address'] ?? ''); ?>" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="technician_name" class="form-label">Nome do Técnico</label>
<input type="text" class="form-control" id="technician_name" name="technician_name" value="<?php echo htmlspecialchars($installation['technician_name'] ?? ''); ?>" required style="width: 100%;">
</div>
<div class="mb-3">
<label for="installation_date" class="form-label">Data da Instalação</label>
<?php
$installation_date_formatted = '';
if (!empty($installation['installation_date'])) {
$timestamp = strtotime($installation['installation_date']);
if ($timestamp && $timestamp > 0) {
$installation_date_formatted = date('Y-m-d', $timestamp);
}
}
?>
<input type="date" class="form-control" id="installation_date" name="installation_date" value="<?php echo htmlspecialchars($installation_date_formatted); ?>" style="width: 100%;">
</div>
<hr>
<h5 class="mb-3">Dados Elétricos</h5>
<div class="mb-3">
<label for="voltage" class="form-label">Tensão (V)</label>
<input type="text" class="form-control" id="voltage" name="voltage" value="<?php echo htmlspecialchars($installation['voltage'] ?? ''); ?>" style="width: 100%;">
</div>
<div class="mb-3">
<label for="phase_neutral_ground" class="form-label">Fase-Neutro-Terra</label>
<input type="text" class="form-control" id="phase_neutral_ground" name="phase_neutral_ground" value="<?php echo htmlspecialchars($installation['phase_neutral_ground'] ?? ''); ?>" style="width: 100%;">
</div>
<div class="mb-3">
<label for="breaker_output" class="form-label">Saída do Disjuntor</label>
<input type="text" class="form-control" id="breaker_output" name="breaker_output" value="<?php echo htmlspecialchars($installation['breaker_output'] ?? ''); ?>" style="width: 100%;">
</div>
<div class="mb-3">
<label for="observations" class="form-label">Observações</label>
<textarea class="form-control" id="observations" name="observations" rows="3" style="width: 100%;"><?php echo htmlspecialchars($installation['observations'] ?? ''); ?></textarea>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status" style="width: 100%;">
<option value="ativo" <?php echo ($installation['status'] === 'ativo') ? 'selected' : ''; ?>>Ativo</option>
<option value="Manutencao" <?php echo ($installation['status'] === 'Manutencao') ? 'selected' : ''; ?>>Manutenção</option>
<option value="Manutenção Parcial" <?php echo ($installation['status'] === 'Manutenção Parcial') ? 'selected' : ''; ?>>Manutenção Parcial</option>
<option value="inativo" <?php echo ($installation['status'] === 'inativo') ? 'selected' : ''; ?>>Inativo</option>
</select>
</div>
<hr>
<h5 class="mb-3">Imagens</h5>
<div class="mb-3">
<label for="images" class="form-label">Adicionar Novas Imagens</label>
<input type="file" class="form-control" id="images" name="images[]" multiple accept="image/*" style="width: 100%;">
</div>
<?php if (!empty($images)): ?>
<p>Imagens existentes:</p>
<div class="row">
<?php foreach ($images as $image): ?>
<div class="col-md-3 mb-3">
<img src="<?php echo htmlspecialchars($image['image_path']); ?>" class="img-thumbnail" alt="Imagem da instalação">
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="text-muted">Nenhuma imagem existente.</p>
<?php endif; ?>
<hr class="my-4">
<div class="d-flex justify-content-end">
<a href="index.php" class="btn btn-secondary me-2">Cancelar</a>
<button type="submit" class="btn btn-primary">Salvar Alterações</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

169
export_html.php Normal file
View File

@ -0,0 +1,169 @@
<?php
// export_html.php
// 1. Validar e obter o ID
if (!isset($_GET['id']) || !filter_var($_GET['id'], FILTER_VALIDATE_INT)) {
die("ID da instalação inválido.");
}
$installation_id = $_GET['id'];
// 2. Conectar ao banco de dados
require_once __DIR__ . '/db/config.php';
try {
$pdo = db();
// 3. Buscar dados da instalação
$stmt = $pdo->prepare("SELECT * FROM installations WHERE id = :id");
$stmt->bindParam(':id', $installation_id, PDO::PARAM_INT);
$stmt->execute();
$installation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$installation) {
die("Instalação não encontrada.");
}
// 4. Buscar imagens da instalação
$img_stmt = $pdo->prepare("SELECT image_path FROM installation_images WHERE installation_id = :id ORDER BY id ASC");
$img_stmt->bindParam(':id', $installation_id, PDO::PARAM_INT);
$img_stmt->execute();
$images = $img_stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
die("Erro ao acessar o banco de dados: " . $e->getMessage());
}
// 5. Gerar o nome do arquivo para download
$filename = "instalacao_" . $installation['id'] . "_" . str_replace(' ', '_', $installation['client_name']) . ".doc";
// 6. Enviar cabeçalhos para forçar o download
header("Content-Type: application/vnd.ms-word");
header("Content-Disposition: attachment; filename=\"" . $filename . "\"");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
// 7. Iniciar a geração do conteúdo HTML
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Relatório de Instalação - <?php echo htmlspecialchars($installation['client_name']); ?></title>
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}
.container {
width: 90%;
margin: 0 auto;
}
h1 {
color: #0056b3;
border-bottom: 2px solid #f0f0f0;
padding-bottom: 10px;
}
.details-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
.details-table td {
padding: 8px;
border: 1px solid #ddd;
}
.details-table td:first-child {
font-weight: bold;
background-color: #f9f9f9;
width: 25%;
}
.images-section img {
max-width: 400px;
margin: 10px;
border: 1px solid #ccc;
padding: 5px;
}
.section-title {
font-size: 1.5em;
color: #0056b3;
margin-top: 20px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>Relatório de Instalação</h1>
<h2 class="section-title">Detalhes do Cliente e Instalação</h2>
<table class="details-table">
<tr>
<td>ID da Instalação</td>
<td><?php echo htmlspecialchars($installation['id']); ?></td>
</tr>
<tr>
<td>Cliente</td>
<td><?php echo htmlspecialchars($installation['client_name']); ?></td>
</tr>
<tr>
<td>Endereço</td>
<td><?php echo htmlspecialchars($installation['address']); ?></td>
</tr>
<tr>
<td>Técnico Responsável</td>
<td><?php echo htmlspecialchars($installation['technician_name']); ?></td>
</tr>
<tr>
<td>Data</td>
<td><?php echo date("d/m/Y H:i", strtotime($installation['created_at'])); ?></td>
</tr>
<tr>
<td>Status</td>
<td><?php echo ucfirst(htmlspecialchars($installation['status'])); ?></td>
</tr>
</table>
<h2 class="section-title">Detalhes Técnicos</h2>
<table class="details-table">
<tr>
<td>Potência do Carregador (kW)</td>
<td><?php echo htmlspecialchars($installation['charger_power']); ?></td>
</tr>
<tr>
<td>Tensão da Rede (V)</td>
<td><?php echo htmlspecialchars($installation['grid_voltage']); ?></td>
</tr>
<tr>
<td>Tipo de Disjuntor</td>
<td><?php echo htmlspecialchars($installation['breaker_type']); ?></td>
</tr>
<tr>
<td>Número de Série</td>
<td><?php echo htmlspecialchars($installation['serial_number']); ?></td>
</tr>
</table>
<h2 class="section-title">Observações</h2>
<p><?php echo nl2br(htmlspecialchars($installation['notes'])); ?></p>
<?php if (!empty($images)): ?>
<h2 class="section-title">Imagens da Instalação</h2>
<div class="images-section">
<?php foreach ($images as $image):
// Monta o caminho absoluto da imagem para obter seu conteúdo
$base_path = $_SERVER['DOCUMENT_ROOT'];
$image_full_path = $base_path . '/' . $image['image_path'];
if (file_exists($image_full_path)) {
$image_data = base64_encode(file_get_contents($image_full_path));
$image_mime = mime_content_type($image_full_path);
echo '<img src="data:' . $image_mime . ';base64,' . $image_data . '" alt="Imagem da Instalação">';
}
?><?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</body>
</html>

225
index.php
View File

@ -5,14 +5,63 @@ $message_type = $_SESSION['message_type'] ?? null;
unset($_SESSION['message'], $_SESSION['message_type']);
require_once __DIR__ . '/db/config.php';
// Get status from query string
$status_filter = $_GET['status'] ?? null;
$page_title = "Painel de Controle";
if ($status_filter === 'Manutencao') {
$page_title = "Instalações em Manutenção";
}
try {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM installations ORDER BY created_at DESC LIMIT 10");
// Base query
$query = "
SELECT
i.*,
(SELECT ii.image_path FROM installation_images ii WHERE ii.installation_id = i.id ORDER BY ii.id ASC LIMIT 1) as first_image
FROM
installations i
";
// Apply status filter if present
if ($status_filter) {
$query .= " WHERE i.status = :status";
}
$query .= " ORDER BY i.created_at DESC";
$stmt = $pdo->prepare($query);
if ($status_filter) {
$stmt->bindParam(':status', $status_filter, PDO::PARAM_STR);
}
$stmt->execute();
$installations = $stmt->fetchAll(PDO::FETCH_ASSOC);
$total_installations = count($installations);
// Calculate KPIs
$kpi_query = "
SELECT
(SELECT COUNT(*) FROM installations) as total,
(SELECT COUNT(*) FROM installations WHERE status = 'ativo') as active,
(SELECT COUNT(*) FROM installations WHERE status = 'Manutencao') as maintenance,
(SELECT COUNT(*) FROM installations WHERE status = 'Manutenção Parcial') as partial_maintenance
";
$kpi_stmt = $pdo->query($kpi_query);
$kpis = $kpi_stmt->fetch(PDO::FETCH_ASSOC);
$total_installations = $kpis['total'] ?? 0;
$active_installations = $kpis['active'] ?? 0;
$maintenance_installations = $kpis['maintenance'] ?? 0;
$partial_maintenance_installations = $kpis['partial_maintenance'] ?? 0;
} catch (Exception $e) {
$installations = [];
$total_installations = 0;
$active_installations = 0;
$maintenance_installations = 0;
$db_error = "Falha na conexão com o banco de dados ou tabela não encontrada. Por favor, execute a migração.";
}
?>
@ -21,10 +70,10 @@ try {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ILOADNET SOLUTIONS - Painel de Controle</title>
<title>iload net Solutions - <?php echo $page_title; ?></title>
<meta name="description" content="Painel para gerenciamento de instalações de carregadores de veículos elétricos.">
<meta name="keywords" content="EV charger, installation management, maintenance log, ILOADNET, dashboard, electric vehicle, fleet management, charge point operator, Built with Flatlogic Generator">
<meta property="og:title" content="ILOADNET SOLUTIONS">
<meta property="og:title" content="iload net Solutions">
<meta property="og:description" content="Painel para gerenciamento de instalações de carregadores de veículos elétricos.">
<meta property="og:image" content="<?php echo $_SERVER['PROJECT_IMAGE_URL']; ?>">
<meta name="twitter:card" content="summary_large_image">
@ -37,26 +86,16 @@ try {
<body>
<div class="sidebar">
<a class="navbar-brand" href="#">ILOAD</a>
<a class="navbar-brand" href="index.php">iload net Solutions</a>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#">
<a class="nav-link active" href="index.php">
<i class="bi bi-grid-1x2-fill"></i> Painel de Controle
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-ev-station-fill"></i> Instalações
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-people-fill"></i> Usuários
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="bi bi-gear-fill"></i> Configurações
<a class="nav-link" href="add_installation.php">
<i class="bi bi-plus-circle-fill"></i> Adicionar Instalação
</a>
</li>
</ul>
@ -98,14 +137,15 @@ try {
<?php endif; ?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0 text-gray-800">Painel de Controle</h1>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addInstallationModal">
<h1 class="h3 mb-0 text-gray-800"><?php echo $page_title; ?></h1>
<a href="add_installation.php" class="btn btn-primary">
<i class="bi bi-plus-circle-fill me-2"></i>Registrar Nova Instalação
</button>
</a>
</div>
<div class="row">
<div class="col-xl-3 col-md-6">
<div class="col-xl-3 col-md-6 mb-4">
<a href="index.php" class="kpi-link">
<div class="kpi-card card">
<div class="card-body">
<div class="kpi-icon" style="background-color: #4e73df;">
@ -117,21 +157,24 @@ try {
</div>
</div>
</div>
</a>
</div>
<div class="col-xl-3 col-md-6">
<div class="col-xl-3 col-md-6 mb-4">
<a href="index.php?status=ativo" class="kpi-link">
<div class="kpi-card card">
<div class="card-body">
<div class="kpi-icon" style="background-color: #1cc88a;">
<i class="bi bi-check-circle"></i>
</div>
<div>
<div class="kpi-value">0</div>
<div class="kpi-label">Ativas no Momento</div>
<div class="kpi-value"><?php echo $active_installations; ?></div>
<div class="kpi-label">Ativas</div>
</div>
</div>
</div>
</a>
</div>
<div class="col-xl-3 col-md-6">
<div class="col-xl-3 col-md-6 mb-4">
<div class="kpi-card card">
<div class="card-body">
<div class="kpi-icon" style="background-color: #36b9cc;">
@ -144,25 +187,42 @@ try {
</div>
</div>
</div>
<div class="col-xl-3 col-md-6">
<div class="col-xl-3 col-md-6 mb-4">
<a href="index.php?status=Manutencao" class="kpi-link">
<div class="kpi-card card">
<div class="card-body">
<div class="kpi-icon" style="background-color: #f6c23e;">
<i class="bi bi-exclamation-triangle"></i>
<i class="bi bi-tools"></i>
</div>
<div>
<div class="kpi-value">0</div>
<div class="kpi-label">Problemas Pendentes</div>
<div class="kpi-value"><?php echo $maintenance_installations; ?></div>
<div class="kpi-label">Manutenções</div>
</div>
</div>
</div>
</a>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<a href="index.php?status=Manutencao+Parcial" class="kpi-link">
<div class="kpi-card card">
<div class="card-body">
<div class="kpi-icon" style="background-color: #fd7e14;">
<i class="bi bi-exclamation-triangle-fill"></i>
</div>
<div>
<div class="kpi-value"><?php echo $partial_maintenance_installations; ?></div>
<div class="kpi-label">Manutenção Parcial</div>
</div>
</div>
</div>
</a>
</div>
</div>
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0"><i class="bi bi-list-task me-2"></i>Instalações Recentes</h5>
<a href="#" class="btn btn-sm btn-outline-secondary">Ver Todas</a>
<a href="index.php" class="btn btn-sm btn-outline-secondary">Ver Todas</a>
</div>
<div class="card-body">
<div class="table-responsive">
@ -181,16 +241,21 @@ try {
<tbody>
<?php if (empty($installations) && !isset($db_error)): ?>
<tr>
<td colspan="7" class="text-center">Nenhuma instalação encontrada.</td>
<td colspan="7" class="text-center">Nenhuma instalação encontrada para este status.</td>
</tr>
<?php else: ?>
<?php foreach ($installations as $inst): ?>
<?php
$img_stmt = $pdo->prepare("SELECT image_path FROM installation_images WHERE installation_id = ? ORDER BY id ASC LIMIT 1");
$img_stmt->execute([$inst['id']]);
$first_image = $img_stmt->fetchColumn();
$status_badge_class = $inst['status'] == 'ativo' ? 'bg-success' : 'bg-warning';
$first_image = $inst['first_image'];
$status = $inst['status'] ?? 'desconhecido';
$status_badge_class = 'bg-secondary'; // Default
if ($status == 'ativo') {
$status_badge_class = 'bg-success';
} elseif ($status == 'Manutencao') {
$status_badge_class = 'bg-warning';
} elseif ($status == 'Manutenção Parcial') {
$status_badge_class = 'bg-info';
}
?>
<tr>
<td>
@ -205,22 +270,14 @@ try {
<td><?php echo htmlspecialchars($inst['client_name'] ?: 'N/A'); ?></td>
<td><?php echo htmlspecialchars($inst['address'] ?: 'N/A'); ?></td>
<td><?php echo htmlspecialchars($inst['technician_name'] ?: 'N/A'); ?></td>
<td><span class="badge <?php echo $status_badge_class; ?>"><?php echo ucfirst(htmlspecialchars($inst['status'])); ?></span></td>
<td><span class="badge <?php echo $status_badge_class; ?>"><?php echo ucfirst(htmlspecialchars($status)); ?></span></td>
<td><?php echo date("d/m/Y", strtotime($inst['created_at'])); ?></td>
<td>
<div class="btn-group">
<form action="update_status.php" method="POST" style="display: inline-block;">
<input type="hidden" name="id" value="<?php echo $inst['id']; ?>">
<input type="hidden" name="status" value="ativo">
<button type="submit" class="btn btn-sm btn-outline-success" title="Marcar como Ativo"><i class="bi bi-check-circle"></i></button>
</form>
<form action="update_status.php" method="POST" style="display: inline-block;">
<input type="hidden" name="id" value="<?php echo $inst['id']; ?>">
<input type="hidden" name="status" value="em manutenção">
<button type="submit" class="btn btn-sm btn-outline-warning" title="Marcar como Em Manutenção"><i class="bi bi-tools"></i></button>
</form>
<a href="#" class="btn btn-sm btn-outline-secondary" title="Editar"><i class="bi bi-pencil-square"></i></a>
<a href="#" class="btn btn-sm btn-outline-danger" title="Excluir"><i class="bi bi-trash"></i></a>
<a href="view_installation.php?id=<?php echo $inst['id']; ?>" class="btn btn-sm btn-outline-primary" title="Visualizar"><i class="bi bi-eye-fill"></i></a>
<a href="edit_installation.php?id=<?php echo $inst['id']; ?>" class="btn btn-sm btn-outline-secondary" title="Editar"><i class="bi bi-pencil-fill"></i></a>
<a href="delete_installation.php?id=<?php echo $inst['id']; ?>" class="btn btn-sm btn-outline-danger" title="Excluir"><i class="bi bi-trash-fill"></i></a>
<a href="export_html.php?id=<?php echo $inst['id']; ?>" class="btn btn-sm btn-outline-success" title="Exportar para Word"><i class="bi bi-file-earmark-word-fill"></i></a>
</div>
</td>
</tr>
@ -234,75 +291,7 @@ try {
</div>
</div>
<!-- Add Installation Modal -->
<div class="modal fade" id="addInstallationModal" tabindex="-1" aria-labelledby="addInstallationModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addInstallationModalLabel">Registrar Nova Instalação</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="add_installation.php" method="POST" enctype="multipart/form-data">
<div class="row">
<div class="col-md-6 mb-3">
<label for="client_name" class="form-label">Nome do Cliente</label>
<input type="text" class="form-control" id="client_name" name="client_name">
</div>
<div class="col-md-6 mb-3">
<label for="technician_name" class="form-label">Nome do Técnico</label>
<input type="text" class="form-control" id="technician_name" name="technician_name">
</div>
</div>
<div class="mb-3">
<label for="address" class="form-label">Endereço da Instalação</label>
<textarea class="form-control" id="address" name="address" rows="2"></textarea>
</div>
<div class="mb-3">
<label for="observations" class="form-label">Observações</label>
<textarea class="form-control" id="observations" name="observations" rows="2"></textarea>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="images" class="form-label">Imagens da Instalação</label>
<input class="form-control" type="file" id="images" name="images[]" accept="image/*" multiple>
</div>
<div class="col-md-6 mb-3">
<label for="status" class="form-label">Status</label>
<select class="form-select" id="status" name="status">
<option value="ativo" selected>Ativo</option>
<option value="em manutenção">Em Manutenção</option>
</select>
</div>
</div>
<hr>
<h6 class="mb-3">Medições Elétricas (Opcional)</h6>
<div class="row">
<div class="col-md-4 mb-3">
<label for="voltage" class="form-label">Tensão (V)</label>
<input type="text" class="form-control" id="voltage" name="voltage">
</div>
<div class="col-md-4 mb-3">
<label for="phase_neutral_ground" class="form-label">Fase-Neutro-Terra</e-label>
<input type="text" class="form-control" id="phase_neutral_ground" name="phase_neutral_ground">
</div>
<div class="col-md-4 mb-3">
<label for="breaker_output" class="form-label">Saída do Disjuntor (A)</label>
<input type="text" class="form-control" id="breaker_output" name="breaker_output">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fechar</button>
<button type="submit" class="btn btn-primary">Salvar Instalação</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>

102
update_installation.php Normal file
View File

@ -0,0 +1,102 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php');
exit;
}
$id = $_POST['id'] ?? null;
$client_name = trim($_POST['client_name'] ?? '');
$address = trim($_POST['address'] ?? '');
$technician_name = trim($_POST['technician_name'] ?? '');
$installation_date = !empty($_POST['installation_date']) ? trim($_POST['installation_date']) : null;
$status = trim($_POST['status'] ?? 'ativo');
$observations = trim($_POST['observations'] ?? '');
$voltage = trim($_POST['voltage'] ?? null);
$phase_neutral_ground = trim($_POST['phase_neutral_ground'] ?? null);
$breaker_output = trim($_POST['breaker_output'] ?? null);
if (!$id) {
$_SESSION['message'] = "ID da instalação é inválido.";
$_SESSION['message_type'] = "danger";
header('Location: index.php');
exit;
}
$pdo = db();
try {
$sql = "UPDATE installations SET client_name = ?, address = ?, technician_name = ?, status = ?, observations = ?, voltage = ?, phase_neutral_ground = ?, breaker_output = ?";
$params = [
$client_name,
$address,
$technician_name,
$status,
$observations,
$voltage,
$phase_neutral_ground,
$breaker_output
];
if ($installation_date) {
$sql .= ", installation_date = ?";
$params[] = $installation_date;
}
$sql .= " WHERE id = ?";
$params[] = $id;
$pdo->beginTransaction();
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
// Handle new image uploads
if (isset($_FILES['images'])) {
$upload_dir = __DIR__ . '/assets/uploads/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0775, true);
}
$allowed_ext = ['jpg', 'jpeg', 'png', 'gif'];
foreach ($_FILES['images']['tmp_name'] as $key => $tmp_name) {
if ($_FILES['images']['error'][$key] === UPLOAD_ERR_OK) {
$file_name = $_FILES['images']['name'][$key];
$file_ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION));
if (in_array($file_ext, $allowed_ext)) {
$new_file_name = time() . '_' . uniqid() . '_' . basename($file_name);
$dest_path = $upload_dir . $new_file_name;
if (move_uploaded_file($tmp_name, $dest_path)) {
$image_path = 'assets/uploads/' . $new_file_name;
$img_stmt = $pdo->prepare("INSERT INTO installation_images (installation_id, image_path) VALUES (?, ?)");
$img_stmt->execute([$id, $image_path]);
} else {
throw new Exception('Falha ao mover o arquivo enviado: ' . $file_name);
}
} else {
throw new Exception('Tipo de arquivo inválido: ' . $file_name);
}
}
}
}
$pdo->commit();
$_SESSION['message'] = "Instalação #{$id} atualizada com sucesso!";
$_SESSION['message_type'] = "success";
} catch (Exception $e) {
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
$_SESSION['message'] = "Erro ao atualizar a instalação: " . $e->getMessage();
$_SESSION['message_type'] = "danger";
header("Location: edit_installation.php?id={$id}");
exit;
}
header("Location: index.php");
exit;

163
view_installation.php Normal file
View File

@ -0,0 +1,163 @@
<?php
session_start();
require_once __DIR__ . '/db/config.php';
// Get installation ID from URL
$id = $_GET['id'] ?? null;
if (!$id) {
header("Location: index.php");
exit;
}
// Fetch installation data
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM installations WHERE id = ?");
$stmt->execute([$id]);
$installation = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$installation) {
$_SESSION['message'] = 'Instalação não encontrada.';
$_SESSION['message_type'] = 'danger';
header("Location: index.php");
exit;
}
// Fetch images for this installation
$img_stmt = $pdo->prepare("SELECT * FROM installation_images WHERE installation_id = ?");
$img_stmt->execute([$id]);
$images = $img_stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Visualizar Instalação #<?php echo htmlspecialchars($installation['id']); ?> - iload net Solutions</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="sidebar">
<a class="navbar-brand" href="index.php">iload net Solutions</a>
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php">
<i class="bi bi-grid-1x2-fill"></i> Painel de Controle
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="add_installation.php">
<i class="bi bi-plus-circle-fill"></i> Adicionar Instalação
</a>
</li>
</ul>
</div>
<div class="main-content">
<nav class="top-navbar navbar navbar-expand">
<div class="container-fluid">
<ul class="navbar-nav ms-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle me-1"></i> Administrador
</a>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Perfil</a></li>
<li><a class="dropdown-item" href="#">Sair</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-lg-8 col-md-10">
<div class="card shadow-sm mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h1 class="h3 mb-0 text-gray-800">Detalhes da Instalação #<?php echo htmlspecialchars($installation['id']); ?></h1>
<a href="edit_installation.php?id=<?php echo $installation['id']; ?>" class="btn btn-sm btn-primary"><i class="bi bi-pencil-fill me-1"></i> Editar</a>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-6">
<strong>Nome do Cliente:</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['client_name'] ?? 'N/A'); ?></p>
</div>
<div class="col-md-6">
<strong>Endereço:</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['address'] ?? 'N/A'); ?></p>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<strong>Técnico Responsável:</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['technician_name'] ?? 'N/A'); ?></p>
</div>
<div class="col-md-6">
<strong>Data da Instalação:</strong>
<p class="text-muted"><?php echo htmlspecialchars(date('d/m/Y', strtotime($installation['created_at'] ?? time()))); ?></p>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<strong>Status:</strong>
<p><span class="badge bg-<?php echo $installation['status'] === 'ativo' ? 'success' : 'warning'; ?>"><?php echo htmlspecialchars(ucfirst($installation['status'] ?? 'N/A')); ?></span></p>
</div>
</div>
<hr>
<h5 class="mb-3">Dados Elétricos</h5>
<div class="row mb-3">
<div class="col-md-4">
<strong>Tensão (V):</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['voltage'] ?? 'N/A'); ?></p>
</div>
<div class="col-md-4">
<strong>Fase-Neutro-Terra:</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['phase_neutral_ground'] ?? 'N/A'); ?></p>
</div>
<div class="col-md-4">
<strong>Saída do Disjuntor:</strong>
<p class="text-muted"><?php echo htmlspecialchars($installation['breaker_output'] ?? 'N/A'); ?></p>
</div>
</div>
<div class="mb-3">
<strong>Observações:</strong>
<p class="text-muted"><?php echo nl2br(htmlspecialchars($installation['observations'] ?? 'Nenhuma observação.')); ?></p>
</div>
<hr>
<h5 class="mb-3">Imagens da Instalação</h5>
<?php if (!empty($images)): ?>
<div class="row">
<?php foreach ($images as $image): ?>
<div class="col-md-4 mb-3">
<a href="<?php echo htmlspecialchars($image['image_path']); ?>" target="_blank">
<img src="<?php echo htmlspecialchars($image['image_path']); ?>" class="img-thumbnail" alt="Imagem da instalação">
</a>
</div>
<?php endforeach; ?>
</div>
<?php else: ?>
<p class="text-muted">Nenhuma imagem registrada para esta instalação.</p>
<?php endif; ?>
<hr class="my-4">
<div class="d-flex justify-content-end">
<a href="index.php" class="btn btn-secondary">Voltar ao Painel</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>