Auto commit: 2025-11-24T23:49:22.669Z
This commit is contained in:
parent
786ed30042
commit
7ec875c3f3
15
api.php
15
api.php
@ -27,10 +27,17 @@ try {
|
|||||||
case 'get_current_locations':
|
case 'get_current_locations':
|
||||||
default:
|
default:
|
||||||
$stmt = $pdo->query(
|
$stmt = $pdo->query(
|
||||||
"SELECT t.id, t.matricula, t.modelo, lt.latitud, lt.longitud, lt.ultima_actualizacion " .
|
"SELECT
|
||||||
"FROM localizacion_taxis lt " .
|
t.id, t.nombre, t.licencia, t.matricula, t.municipio,
|
||||||
"JOIN taxis t ON lt.id_taxi = t.id " .
|
lt.latitud, lt.longitud, lt.ultima_actualizacion,
|
||||||
"ORDER BY lt.ultima_actualizacion DESC"
|
(SELECT COUNT(*) FROM documents WHERE id_conductor = t.id) as num_documentos,
|
||||||
|
(SELECT COUNT(*) FROM citas WHERE id_conductor = t.id) as num_citas,
|
||||||
|
(SELECT COUNT(*) FROM consultas WHERE id_conductor = t.id) as num_consultas,
|
||||||
|
(SELECT COUNT(*) FROM localizacion_historico WHERE id_taxi = t.id) as num_ubicaciones
|
||||||
|
FROM localizacion_taxis lt
|
||||||
|
JOIN taxis t ON lt.id_taxi = t.id
|
||||||
|
GROUP BY t.id, lt.latitud, lt.longitud, lt.ultima_actualizacion
|
||||||
|
ORDER BY t.nombre ASC"
|
||||||
);
|
);
|
||||||
$locations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
$locations = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
echo json_encode($locations);
|
echo json_encode($locations);
|
||||||
|
|||||||
18
citas.php
18
citas.php
@ -9,29 +9,31 @@ $message_type = '';
|
|||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|
||||||
// Add id_conductor to citas table
|
// Main schema definition
|
||||||
$pdo->exec("CREATE TABLE IF NOT EXISTS citas (
|
$pdo->exec("CREATE TABLE IF NOT EXISTS citas (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
title VARCHAR(255) NOT NULL,
|
|
||||||
start_event DATETIME NOT NULL,
|
start_event DATETIME NOT NULL,
|
||||||
end_event DATETIME NOT NULL,
|
end_event DATETIME NOT NULL,
|
||||||
id_departamento INT NOT NULL,
|
id_departamento INT NOT NULL,
|
||||||
id_conductor INT,
|
|
||||||
lugar VARCHAR(255),
|
lugar VARCHAR(255),
|
||||||
usuarios TEXT,
|
usuarios TEXT,
|
||||||
estado VARCHAR(50) DEFAULT 'Pendiente',
|
estado VARCHAR(50) DEFAULT 'Pendiente',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (id_departamento) REFERENCES departamentos(id) ON DELETE CASCADE,
|
FOREIGN KEY (id_departamento) REFERENCES departamentos(id) ON DELETE CASCADE
|
||||||
FOREIGN KEY (id_conductor) REFERENCES taxis(id) ON DELETE SET NULL
|
|
||||||
)");
|
)");
|
||||||
|
|
||||||
// Check if id_conductor column exists and add it if not
|
// Add 'title' column if it doesn't exist
|
||||||
|
$stmt = $pdo->query("SHOW COLUMNS FROM citas LIKE 'title'");
|
||||||
|
if ($stmt->rowCount() == 0) {
|
||||||
|
$pdo->exec("ALTER TABLE citas ADD COLUMN title VARCHAR(255) NOT NULL AFTER id;");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add 'id_conductor' column if it doesn't exist
|
||||||
$stmt = $pdo->query("SHOW COLUMNS FROM citas LIKE 'id_conductor'");
|
$stmt = $pdo->query("SHOW COLUMNS FROM citas LIKE 'id_conductor'");
|
||||||
if ($stmt->rowCount() == 0) {
|
if ($stmt->rowCount() == 0) {
|
||||||
$pdo->exec("ALTER TABLE citas ADD COLUMN id_conductor INT NULL AFTER id_departamento, ADD FOREIGN KEY (id_conductor) REFERENCES taxis(id) ON DELETE SET NULL;");
|
$pdo->exec("ALTER TABLE citas ADD COLUMN id_conductor INT NULL AFTER id_departamento, ADD FOREIGN KEY (id_conductor) REFERENCES taxis(id) ON DELETE SET NULL;");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Fetch departments and conductors
|
// Fetch departments and conductors
|
||||||
$departamentos = $pdo->query("SELECT id, nombre FROM departamentos ORDER BY nombre")->fetchAll(PDO::FETCH_ASSOC);
|
$departamentos = $pdo->query("SELECT id, nombre FROM departamentos ORDER BY nombre")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
$conductores = $pdo->query("SELECT id, matricula FROM taxis ORDER BY matricula")->fetchAll(PDO::FETCH_ASSOC);
|
$conductores = $pdo->query("SELECT id, matricula FROM taxis ORDER BY matricula")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|||||||
252
drivers.php
252
drivers.php
@ -3,95 +3,142 @@ require_once 'db/config.php';
|
|||||||
require_once 'header.php';
|
require_once 'header.php';
|
||||||
|
|
||||||
$message = '';
|
$message = '';
|
||||||
$message_type = '';
|
$message_type = 'success';
|
||||||
|
|
||||||
// --- DB Schema and Data Fetching ---
|
// --- DB Schema Migration ---
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
// Add department FK to taxis table
|
|
||||||
$check_column = $pdo->query("SHOW COLUMNS FROM taxis LIKE 'id_departamento'");
|
// Add new columns to taxis table if they don't exist
|
||||||
if ($check_column->rowCount() == 0) {
|
$columns = [
|
||||||
$pdo->exec("ALTER TABLE taxis ADD COLUMN id_departamento INT, ADD FOREIGN KEY (id_departamento) REFERENCES departamentos(id) ON DELETE SET NULL;");
|
'nombre' => 'VARCHAR(255) NULL',
|
||||||
|
'licencia' => 'VARCHAR(100) NULL',
|
||||||
|
'municipio' => "ENUM('TIAS', 'TEGUISE', 'YAIZA') NULL",
|
||||||
|
'ultima_localizacion_lat' => 'DECIMAL(10, 8) NULL',
|
||||||
|
'ultima_localizacion_lng' => 'DECIMAL(11, 8) NULL',
|
||||||
|
'id_departamento' => 'INT NULL'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($columns as $column => $type) {
|
||||||
|
$stmt = $pdo->query("SHOW COLUMNS FROM taxis LIKE '$column'");
|
||||||
|
if ($stmt->rowCount() == 0) {
|
||||||
|
$pdo->exec("ALTER TABLE taxis ADD COLUMN `$column` $type;");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add foreign key for id_departamento separately to avoid issues in loop
|
||||||
|
$stmt = $pdo->query("SELECT 1 FROM information_schema.table_constraints WHERE constraint_schema = DATABASE() AND table_name = 'taxis' AND constraint_name = 'taxis_ibfk_1'");
|
||||||
|
if($stmt->rowCount() == 0) {
|
||||||
|
$stmt = $pdo->query("SHOW COLUMNS FROM taxis LIKE 'id_departamento'");
|
||||||
|
if ($stmt->rowCount() > 0) {
|
||||||
|
$pdo->exec("ALTER TABLE taxis ADD FOREIGN KEY (id_departamento) REFERENCES departamentos(id) ON DELETE SET NULL;");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle POST requests
|
// Handle POST requests
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
// Add new taxi
|
if (isset($_POST['add_conductor'])) {
|
||||||
if (isset($_POST['add_taxi'])) {
|
$sql = "INSERT INTO taxis (nombre, licencia, matricula, municipio, id_departamento) VALUES (?, ?, ?, ?, ?)";
|
||||||
$matricula = trim($_POST['matricula']);
|
$pdo->prepare($sql)->execute([$_POST['nombre'], $_POST['licencia'], $_POST['matricula'], $_POST['municipio'], $_POST['id_departamento'] ?: null]);
|
||||||
$modelo = trim($_POST['modelo']);
|
$message = 'Conductor añadido con éxito.';
|
||||||
$id_departamento = $_POST['id_departamento'] ?: null;
|
} elseif (isset($_POST['edit_conductor'])) {
|
||||||
|
$sql = "UPDATE taxis SET nombre=?, licencia=?, matricula=?, municipio=?, id_departamento=? WHERE id=?";
|
||||||
if (!empty($matricula)) {
|
$pdo->prepare($sql)->execute([$_POST['nombre'], $_POST['licencia'], $_POST['matricula'], $_POST['municipio'], $_POST['id_departamento'] ?: null, $_POST['id']]);
|
||||||
$sql = "INSERT INTO taxis (matricula, modelo, id_departamento) VALUES (?, ?, ?)";
|
$message = 'Conductor actualizado con éxito.';
|
||||||
$pdo->prepare($sql)->execute([$matricula, $modelo, $id_departamento]);
|
} elseif (isset($_POST['delete_conductor'])) {
|
||||||
$message = 'Taxi/Conductor añadido exitosamente.';
|
$sql = "DELETE FROM taxis WHERE id=?";
|
||||||
$message_type = 'success';
|
$pdo->prepare($sql)->execute([$_POST['id']]);
|
||||||
} else {
|
$message = 'Conductor eliminado con éxito.';
|
||||||
$message = 'La matrícula es obligatoria.';
|
|
||||||
$message_type = 'warning';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch departments for dropdown
|
// Fetch data for table
|
||||||
$departamentos = $pdo->query("SELECT id, nombre FROM departamentos ORDER BY nombre")->fetchAll(PDO::FETCH_ASSOC);
|
$conductores = $pdo->query("SELECT
|
||||||
|
t.id, t.nombre, t.licencia, t.matricula, t.municipio, t.ultima_localizacion_lat, t.ultima_localizacion_lng,
|
||||||
|
(SELECT COUNT(*) FROM documents WHERE id_conductor = t.id) as num_documentos,
|
||||||
|
(SELECT COUNT(*) FROM citas WHERE id_conductor = t.id) as num_citas,
|
||||||
|
(SELECT COUNT(*) FROM consultas WHERE id_conductor = t.id) as num_consultas,
|
||||||
|
(SELECT COUNT(*) FROM taxi_locations WHERE taxi_id = t.id) as num_ubicaciones
|
||||||
|
FROM taxis t
|
||||||
|
GROUP BY t.id
|
||||||
|
ORDER BY t.nombre ASC")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
// Fetch all taxis with department info
|
$departamentos = $pdo->query("SELECT id, nombre FROM departamentos ORDER BY nombre")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
$taxis = $pdo->query(
|
|
||||||
"SELECT t.*, d.nombre as departamento_nombre
|
|
||||||
FROM taxis t
|
|
||||||
LEFT JOIN departamentos d ON t.id_departamento = d.id
|
|
||||||
ORDER BY t.matricula ASC"
|
|
||||||
)->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$message = 'Error de base de datos: ' . $e->getMessage();
|
$message = 'Error de base de datos: ' . $e->getMessage();
|
||||||
$message_type = 'danger';
|
$message_type = 'danger';
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="container-fluid px-4">
|
<div class="container-fluid px-4">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
<h1 class="mt-4">Gestión de Conductores</h1>
|
||||||
<h1 class="h2">Gestión de Taxis/Conductores</h1>
|
<ol class="breadcrumb mb-4">
|
||||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addTaxiModal">
|
<li class="breadcrumb-item"><a href="index.php">Dashboard</a></li>
|
||||||
<i class="bi bi-plus-circle"></i> Añadir Taxi/Conductor
|
<li class="breadcrumb-item active">Conductores</li>
|
||||||
</button>
|
</ol>
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if ($message): ?>
|
<?php if ($message): ?>
|
||||||
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
|
<div class="alert alert-<?php echo $message_type; ?> alert-dismissible fade show" role="alert">
|
||||||
<?php echo htmlspecialchars($message); ?>
|
<?php echo htmlspecialchars($message); ?><button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="card">
|
<div class="card mb-4">
|
||||||
|
<div class="card-header">
|
||||||
|
<i class="fas fa-users me-1"></i>
|
||||||
|
Listado de Conductores
|
||||||
|
<button type="button" class="btn btn-primary btn-sm float-end" data-bs-toggle="modal" data-bs-target="#formConductorModal" onclick="prepareAddForm()">
|
||||||
|
<i class="fas fa-plus"></i> Añadir Conductor
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover">
|
<table class="table table-bordered table-hover" id="conductoresTable">
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Nombre</th>
|
||||||
|
<th>Licencia</th>
|
||||||
<th>Matrícula</th>
|
<th>Matrícula</th>
|
||||||
<th>Modelo</th>
|
<th>Municipio</th>
|
||||||
<th>Departamento</th>
|
<th>Ubicación</th>
|
||||||
<th>Fecha de Registro</th>
|
<th>Docs</th>
|
||||||
|
<th>Citas</th>
|
||||||
|
<th>Consultas</th>
|
||||||
|
<th>Ubics.</th>
|
||||||
|
<th>Acciones</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php if (empty($taxis)): ?>
|
<?php foreach ($conductores as $conductor): ?>
|
||||||
<tr><td colspan="4" class="text-center">No hay taxis registrados.</td></tr>
|
<tr>
|
||||||
<?php else: ?>
|
<td><?php echo $conductor['id']; ?></td>
|
||||||
<?php foreach ($taxis as $taxi): ?>
|
<td><?php echo htmlspecialchars($conductor['nombre']); ?></td>
|
||||||
<tr>
|
<td><?php echo htmlspecialchars($conductor['licencia']); ?></td>
|
||||||
<td><?php echo htmlspecialchars($taxi['matricula']); ?></td>
|
<td><?php echo htmlspecialchars($conductor['matricula']); ?></td>
|
||||||
<td><?php echo htmlspecialchars($taxi['modelo']); ?></td>
|
<td><span class="badge bg-secondary"><?php echo htmlspecialchars($conductor['municipio']); ?></span></td>
|
||||||
<td><?php echo htmlspecialchars($taxi['departamento_nombre'] ?? 'N/A'); ?></td>
|
<td>
|
||||||
<td><?php echo date("d/m/Y H:i", strtotime($taxi['created_at'])); ?></td>
|
<?php if($conductor['ultima_localizacion_lat']): ?>
|
||||||
</tr>
|
<small><?php echo $conductor['ultima_localizacion_lat'] . ', ' . $conductor['ultima_localizacion_lng']; ?></small>
|
||||||
<?php endforeach; ?>
|
<?php else: echo 'N/A'; endif; ?>
|
||||||
<?php endif; ?>
|
</td>
|
||||||
|
<td><span class="badge bg-info"><?php echo $conductor['num_documentos']; ?></span></td>
|
||||||
|
<td><span class="badge bg-info"><?php echo $conductor['num_citas']; ?></span></td>
|
||||||
|
<td><span class="badge bg-info"><?php echo $conductor['num_consultas']; ?></span></td>
|
||||||
|
<td><span class="badge bg-info"><?php echo $conductor['num_ubicaciones']; ?></span></td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-sm btn-outline-primary" onclick='prepareEditForm(<?php echo json_encode($conductor); ?>)'><i class="fas fa-edit"></i></button>
|
||||||
|
<a href="documents.php?id_conductor=<?php echo $conductor['id']; ?>" class="btn btn-sm btn-outline-secondary" title="Añadir Documento"><i class="fas fa-file-medical"></i></a>
|
||||||
|
<a href="citas.php?id_conductor=<?php echo $conductor['id']; ?>" class="btn btn-sm btn-outline-secondary" title="Añadir Cita"><i class="fas fa-calendar-plus"></i></a>
|
||||||
|
<a href="consultas.php?id_conductor=<?php echo $conductor['id']; ?>" class="btn btn-sm btn-outline-secondary" title="Añadir Consulta"><i class="fas fa-question-circle"></i></a>
|
||||||
|
<a href="localizacion.php?id_taxi=<?php echo $conductor['id']; ?>" class="btn btn-sm btn-outline-secondary" title="Añadir Ubicación"><i class="fas fa-map-marker-alt"></i></a>
|
||||||
|
<button class="btn btn-sm btn-outline-danger" onclick='prepareDeleteForm(<?php echo $conductor['id']; ?>)'><i class="fas fa-trash"></i></button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -99,28 +146,43 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Add Taxi Modal -->
|
<!-- Add/Edit Conductor Modal -->
|
||||||
<div class="modal fade" id="addTaxiModal" tabindex="-1" aria-labelledby="addTaxiModalLabel" aria-hidden="true">
|
<div class="modal fade" id="formConductorModal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<form action="drivers.php" method="POST">
|
<form id="conductorForm" action="drivers.php" method="POST">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="addTaxiModalLabel">Añadir Nuevo Taxi/Conductor</h5>
|
<h5 class="modal-title" id="formModalLabel"></h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<input type="hidden" name="add_taxi" value="1">
|
<input type="hidden" name="id" id="conductor_id">
|
||||||
|
<div id="formMethod"></div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="matricula" class="form-label">Matrícula</label>
|
<label class="form-label">Nombre</label>
|
||||||
<input type="text" class="form-control" id="matricula" name="matricula" required>
|
<input type="text" class="form-control" name="nombre" id="conductor_nombre" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="modelo" class="form-label">Modelo</label>
|
<label class="form-label">Licencia</label>
|
||||||
<input type="text" class="form-control" id="modelo" name="modelo">
|
<input type="text" class="form-control" name="licencia" id="conductor_licencia">
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="id_departamento" class="form-label">Departamento</label>
|
<label class="form-label">Matrícula</label>
|
||||||
<select class="form-select" id="id_departamento" name="id_departamento">
|
<input type="text" class="form-control" name="matricula" id="conductor_matricula" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Municipio</label>
|
||||||
|
<select class="form-select" name="municipio" id="conductor_municipio">
|
||||||
|
<option value="">Seleccionar...</option>
|
||||||
|
<option value="TIAS">Tías</option>
|
||||||
|
<option value="TEGUISE">Teguise</option>
|
||||||
|
<option value="YAIZA">Yaiza</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Departamento</label>
|
||||||
|
<select class="form-select" name="id_departamento" id="conductor_departamento">
|
||||||
<option value="">Sin asignar</option>
|
<option value="">Sin asignar</option>
|
||||||
<?php foreach ($departamentos as $depto): ?>
|
<?php foreach ($departamentos as $depto): ?>
|
||||||
<option value="<?php echo $depto['id']; ?>"><?php echo htmlspecialchars($depto['nombre']); ?></option>
|
<option value="<?php echo $depto['id']; ?>"><?php echo htmlspecialchars($depto['nombre']); ?></option>
|
||||||
@ -137,6 +199,58 @@ try {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Delete Confirmation Modal -->
|
||||||
|
<div class="modal fade" id="deleteConductorModal" tabindex="-1" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<form action="drivers.php" method="POST">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Confirmar Eliminación</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>¿Estás seguro de que quieres eliminar a este conductor? Esta acción no se puede deshacer.</p>
|
||||||
|
<input type="hidden" name="delete_conductor" value="1">
|
||||||
|
<input type="hidden" name="id" id="delete_conductor_id">
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||||
|
<button type="submit" class="btn btn-danger">Eliminar</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function prepareAddForm() {
|
||||||
|
document.getElementById('conductorForm').reset();
|
||||||
|
document.getElementById('formModalLabel').innerText = 'Añadir Conductor';
|
||||||
|
document.getElementById('formMethod').innerHTML = '<input type="hidden" name="add_conductor" value="1">';
|
||||||
|
new bootstrap.Modal(document.getElementById('formConductorModal')).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareEditForm(conductor) {
|
||||||
|
document.getElementById('conductorForm').reset();
|
||||||
|
document.getElementById('formModalLabel').innerText = 'Editar Conductor';
|
||||||
|
document.getElementById('formMethod').innerHTML = '<input type="hidden" name="edit_conductor" value="1">';
|
||||||
|
|
||||||
|
document.getElementById('conductor_id').value = conductor.id;
|
||||||
|
document.getElementById('conductor_nombre').value = conductor.nombre;
|
||||||
|
document.getElementById('conductor_licencia').value = conductor.licencia;
|
||||||
|
document.getElementById('conductor_matricula').value = conductor.matricula;
|
||||||
|
document.getElementById('conductor_municipio').value = conductor.municipio;
|
||||||
|
document.getElementById('conductor_departamento').value = conductor.id_departamento;
|
||||||
|
|
||||||
|
new bootstrap.Modal(document.getElementById('formConductorModal')).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareDeleteForm(id) {
|
||||||
|
document.getElementById('delete_conductor_id').value = id;
|
||||||
|
new bootstrap.Modal(document.getElementById('deleteConductorModal')).show();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
require_once 'footer.php';
|
require_once 'footer.php';
|
||||||
?>
|
?>
|
||||||
|
|||||||
13
header.php
13
header.php
@ -52,24 +52,15 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="drivers.php"><i class="bi bi-person-badge"></i> Conductores</a>
|
<a class="nav-link" href="drivers.php"><i class="bi bi-person-badge"></i> Conductores</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="documents.php"><i class="bi bi-file-earmark-text"></i> Documentos</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="departamentos.php"><i class="bi bi-building"></i> Departamentos</a>
|
<a class="nav-link" href="departamentos.php"><i class="bi bi-building"></i> Departamentos</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="consultas.php"><i class="bi bi-patch-question"></i> Consultas</a>
|
<a class="nav-link" href="localizacion.php"><i class="bi bi-geo-alt"></i> Mapa</a>
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="citas.php"><i class="bi bi-calendar-check"></i> Citas</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="localizacion.php"><i class="bi bi-geo-alt"></i> Localización</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<main class="container mt-4">
|
<main>
|
||||||
|
|||||||
438
localizacion.php
438
localizacion.php
@ -2,48 +2,27 @@
|
|||||||
require_once 'db/config.php';
|
require_once 'db/config.php';
|
||||||
require_once 'header.php';
|
require_once 'header.php';
|
||||||
|
|
||||||
|
// The schema creation is kept for robustness, but handled in drivers.php mainly.
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|
||||||
// Create taxis table if it doesn't exist (as a dependency)
|
|
||||||
$pdo->exec("CREATE TABLE IF NOT EXISTS taxis (
|
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
||||||
matricula VARCHAR(255) NOT NULL UNIQUE,
|
|
||||||
modelo VARCHAR(255),
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
||||||
)");
|
|
||||||
|
|
||||||
// Create localizacion_taxis table if it doesn't exist
|
|
||||||
$pdo->exec("CREATE TABLE IF NOT EXISTS localizacion_taxis (
|
$pdo->exec("CREATE TABLE IF NOT EXISTS localizacion_taxis (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
id_taxi INT NOT NULL UNIQUE, -- Un taxi solo puede tener una última ubicación
|
id_taxi INT NOT NULL UNIQUE,
|
||||||
latitud DECIMAL(10, 8) NOT NULL,
|
latitud DECIMAL(10, 8) NOT NULL,
|
||||||
longitud DECIMAL(11, 8) NOT NULL,
|
longitud DECIMAL(11, 8) NOT NULL,
|
||||||
ultima_actualizacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
ultima_actualizacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (id_taxi) REFERENCES taxis(id)
|
FOREIGN KEY (id_taxi) REFERENCES taxis(id) ON DELETE CASCADE
|
||||||
)");
|
)");
|
||||||
|
|
||||||
// Create location history table
|
|
||||||
$pdo->exec("CREATE TABLE IF NOT EXISTS localizacion_historico (
|
$pdo->exec("CREATE TABLE IF NOT EXISTS localizacion_historico (
|
||||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
id_taxi INT NOT NULL,
|
id_taxi INT NOT NULL,
|
||||||
latitud DECIMAL(10, 8) NOT NULL,
|
latitud DECIMAL(10, 8) NOT NULL,
|
||||||
longitud DECIMAL(11, 8) NOT NULL,
|
longitud DECIMAL(11, 8) NOT NULL,
|
||||||
fecha_registro TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
fecha_registro TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
FOREIGN KEY (id_taxi) REFERENCES taxis(id)
|
FOREIGN KEY (id_taxi) REFERENCES taxis(id) ON DELETE CASCADE
|
||||||
)");
|
)");
|
||||||
|
|
||||||
// Handle form submission to add a new taxi for simplicity
|
// Handle historical location submission
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_taxi'])) {
|
|
||||||
$matricula = trim($_POST['matricula']);
|
|
||||||
$modelo = trim($_POST['modelo']);
|
|
||||||
if(!empty($matricula)) {
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO taxis (matricula, modelo) VALUES (?, ?) ON DUPLICATE KEY UPDATE modelo=VALUES(modelo)");
|
|
||||||
$stmt->execute([$matricula, $modelo]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle form submission for historical location
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_localizacion_historica'])) {
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_localizacion_historica'])) {
|
||||||
$id_taxi = $_POST['id_taxi'];
|
$id_taxi = $_POST['id_taxi'];
|
||||||
$latitud = $_POST['latitud'];
|
$latitud = $_POST['latitud'];
|
||||||
@ -51,311 +30,208 @@ try {
|
|||||||
$fecha_registro = $_POST['fecha_registro'];
|
$fecha_registro = $_POST['fecha_registro'];
|
||||||
|
|
||||||
if (!empty($id_taxi) && is_numeric($latitud) && is_numeric($longitud) && !empty($fecha_registro)) {
|
if (!empty($id_taxi) && is_numeric($latitud) && is_numeric($longitud) && !empty($fecha_registro)) {
|
||||||
try {
|
$stmt = $pdo->prepare("INSERT INTO localizacion_historico (id_taxi, latitud, longitud, fecha_registro) VALUES (?, ?, ?, ?)");
|
||||||
// Insert into history with specific timestamp
|
$stmt->execute([$id_taxi, $latitud, $longitud, $fecha_registro]);
|
||||||
$stmt_history = $pdo->prepare("INSERT INTO localizacion_historico (id_taxi, latitud, longitud, fecha_registro) VALUES (?, ?, ?, ?)");
|
|
||||||
$stmt_history->execute([$id_taxi, $latitud, $longitud, $fecha_registro]);
|
// Also update the taxi's main location for immediate reflection
|
||||||
|
$stmt_update = $pdo->prepare("UPDATE taxis SET ultima_localizacion_lat = ?, ultima_localizacion_lng = ? WHERE id = ?");
|
||||||
echo '<div class="alert alert-success" role="alert">Ubicación histórica añadida con éxito.</div>';
|
$stmt_update->execute([$latitud, $longitud, $id_taxi]);
|
||||||
} catch (Exception $e) {
|
|
||||||
echo '<div class="alert alert-danger" role="alert">Error al guardar los datos: '. $e->getMessage() .'</div>';
|
echo '<div class="alert alert-success">Ubicación histórica añadida y ubicación principal del conductor actualizada.</div>';
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
echo '<div class="alert alert-danger" role="alert">Todos los campos son obligatorios y la latitud/longitud deben ser números.</div>';
|
echo '<div class="alert alert-danger">Todos los campos son obligatorios.</div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all taxis for dropdown
|
|
||||||
$taxis_stmt = $pdo->query("SELECT id, matricula, modelo FROM taxis ORDER BY matricula");
|
|
||||||
$taxis = $taxis_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
die("Error de base de datos: " . $e->getMessage());
|
die("Error de base de datos: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
|
||||||
|
<style>
|
||||||
|
.map-container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 280px 1fr;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
gap: 1rem;
|
||||||
|
height: 60vh; /* Adjust height as needed */
|
||||||
|
}
|
||||||
|
#map-sidebar {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
#map-sidebar .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#map {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content b { color: #0d6efd; }
|
||||||
|
</style>
|
||||||
|
|
||||||
<div class="container-fluid px-4">
|
<div class="container-fluid px-4">
|
||||||
<h1 class="mt-4">Localización de Taxis en Tiempo Real</h1>
|
<h1 class="mt-4">Mapa General de Taxis</h1>
|
||||||
<ol class="breadcrumb mb-4">
|
<ol class="breadcrumb mb-4">
|
||||||
<li class="breadcrumb-item"><a href="index.php">Dashboard</a></li>
|
<li class="breadcrumb-item"><a href="index.php">Dashboard</a></li>
|
||||||
<li class="breadcrumb-item active">Localización</li>
|
<li class="breadcrumb-item active">Mapa</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header">
|
|
||||||
<i class="fas fa-map-marked-alt me-1"></i>
|
|
||||||
Mapa de Taxis
|
|
||||||
<button id="get-location-btn" class="btn btn-sm btn-outline-secondary float-end">Mi Ubicación</button>
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="map" style="height: 500px;"></div>
|
<div class="map-container">
|
||||||
|
<div id="map-sidebar">
|
||||||
|
<div class="d-grid mb-2">
|
||||||
|
<button class="btn btn-secondary" id="show-all-btn">Mostrar Todos</button>
|
||||||
|
</div>
|
||||||
|
<ul class="list-group" id="taxi-list"></ul>
|
||||||
|
</div>
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header"><i class="fas fa-plus me-1"></i>Añadir Ubicación Histórica</div>
|
||||||
<i class="fas fa-route me-1"></i>
|
|
||||||
Historial de Ruta por Taxi
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="history-form">
|
<form action="localizacion.php" method="POST">
|
||||||
|
<p class="small text-muted">Haz clic en un taxi del mapa para rellenar los datos o haz clic en el mapa para obtener coordenadas.</p>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-8">
|
<div class="col-md-3">
|
||||||
<div class="form-floating mb-3">
|
<div class="form-floating mb-3">
|
||||||
<select class="form-select" id="selectTaxiHistory" name="id_taxi" required>
|
<input class="form-control" id="inputTaxiInfo" type="text" placeholder="Taxi" readonly />
|
||||||
<option value="">Seleccione un taxi para ver su historial</option>
|
<label>Taxi Seleccionado</label>
|
||||||
<?php foreach ($taxis as $taxi): ?>
|
<input type="hidden" id="inputTaxiId" name="id_taxi" />
|
||||||
<option value="<?php echo $taxi['id']; ?>"><?php echo htmlspecialchars($taxi['matricula'] . ' - ' . $taxi['modelo']); ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<label for="selectTaxiHistory">Taxi</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 d-flex align-items-center">
|
<div class="col-md-3">
|
||||||
<div class="d-grid w-100">
|
<div class="form-floating mb-3">
|
||||||
<button type="submit" class="btn btn-info">Mostrar Historial</button>
|
<input class="form-control" id="inputLatitud" type="text" name="latitud" placeholder="Latitud" required />
|
||||||
|
<label>Latitud</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-md-3">
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xl-6">
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header">
|
|
||||||
<i class="fas fa-plus me-1"></i>
|
|
||||||
Añadir Ubicación Histórica
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<form action="localizacion.php" method="POST">
|
|
||||||
<p class="small text-muted">Haz clic en un taxi del mapa para rellenar los datos o haz clic en el mapa para obtener coordenadas.</p>
|
|
||||||
<div class="form-floating mb-3">
|
<div class="form-floating mb-3">
|
||||||
<select class="form-select" id="selectTaxi" name="id_taxi" required>
|
<input class="form-control" id="inputLongitud" type="text" name="longitud" placeholder="Longitud" required />
|
||||||
<option value="">Seleccione un taxi</option>
|
<label>Longitud</label>
|
||||||
<?php foreach ($taxis as $taxi): ?>
|
|
||||||
<option value="<?php echo $taxi['id']; ?>"><?php echo htmlspecialchars($taxi['matricula'] . ' - ' . $taxi['modelo']); ?></option>
|
|
||||||
<?php endforeach; ?>
|
|
||||||
</select>
|
|
||||||
<label for="selectTaxi">Taxi</label>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-3">
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input class="form-control" id="inputLatitud" type="text" name="latitud" placeholder="Latitud" required />
|
|
||||||
<label for="inputLatitud">Latitud</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input class="form-control" id="inputLongitud" type="text" name="longitud" placeholder="Longitud" required />
|
|
||||||
<label for="inputLongitud">Longitud</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating mb-3">
|
|
||||||
<input class="form-control" id="inputFecha" type="datetime-local" name="fecha_registro" required />
|
|
||||||
<label for="inputFecha">Fecha y Hora</label>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4 mb-0">
|
|
||||||
<div class="d-grid">
|
|
||||||
<button type="submit" name="add_localizacion_historica" class="btn btn-primary btn-block">Añadir a Historial</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xl-6">
|
|
||||||
<div class="card mb-4">
|
|
||||||
<div class="card-header">
|
|
||||||
<i class="fas fa-plus me-1"></i>
|
|
||||||
Añadir Nuevo Taxi (para demo)
|
|
||||||
</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<form action="localizacion.php" method="POST">
|
|
||||||
<div class="form-floating mb-3">
|
<div class="form-floating mb-3">
|
||||||
<input class="form-control" id="inputMatricula" type="text" name="matricula" placeholder="Matrícula" required />
|
<input class="form-control" id="inputFecha" type="datetime-local" name="fecha_registro" required />
|
||||||
<label for="inputMatricula">Matrícula</label>
|
<label>Fecha y Hora</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating mb-3">
|
</div>
|
||||||
<input class="form-control" id="inputModelo" type="text" name="modelo" placeholder="Modelo" />
|
|
||||||
<label for="inputModelo">Modelo</label>
|
|
||||||
</div>
|
|
||||||
<div class="mt-4 mb-0">
|
|
||||||
<div class="d-grid">
|
|
||||||
<button type="submit" name="add_taxi" class="btn btn-secondary btn-block">Añadir Taxi</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="d-grid"><button type="submit" name="add_localizacion_historica" class="btn btn-primary">Añadir a Historial</button></div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
|
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
const initialCoords = [40.416775, -3.703790]; // Coordenadas iniciales (Madrid)
|
const map = L.map('map').setView([28.963, -13.548], 11); // Centered on Lanzarote
|
||||||
const map = L.map('map').setView(initialCoords, 6); // Zoom inicial más alejado
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19 }).addTo(map);
|
||||||
|
|
||||||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
const markers = {};
|
||||||
maxZoom: 19,
|
const taxiList = document.getElementById('taxi-list');
|
||||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
|
||||||
}).addTo(map);
|
|
||||||
|
|
||||||
// Definir un icono personalizado para los taxis
|
const icons = {
|
||||||
const taxiIcon = L.icon({
|
'TIAS': new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-blue.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }),
|
||||||
iconUrl: 'https://cdn-icons-png.flaticon.com/512/15/15437.png', // URL de un icono de coche genérico
|
'TEGUISE': new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-orange.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }),
|
||||||
iconSize: [32, 32], // Tamaño del icono
|
'YAIZA': new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-red.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] }),
|
||||||
iconAnchor: [16, 32], // Punto del icono que corresponde a la ubicación del marcador
|
'default': new L.Icon({ iconUrl: 'https://raw.githubusercontent.com/pointhi/leaflet-color-markers/master/img/marker-icon-2x-green.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], shadowSize: [41, 41] })
|
||||||
popupAnchor: [0, -32] // Punto desde donde se abrirá el popup
|
};
|
||||||
});
|
|
||||||
|
|
||||||
let markers = {};
|
function createPopupContent(taxi) {
|
||||||
|
return `
|
||||||
|
<b>${taxi.nombre || 'Conductor sin nombre'}</b><br>
|
||||||
|
<b>Matrícula:</b> ${taxi.matricula}<br>
|
||||||
|
<b>Licencia:</b> ${taxi.licencia || 'N/A'}<br>
|
||||||
|
<b>Municipio:</b> ${taxi.municipio || 'N/A'}<br><hr>
|
||||||
|
<b>Docs:</b> ${taxi.num_documentos} |
|
||||||
|
<b>Citas:</b> ${taxi.num_citas} |
|
||||||
|
<b>Consultas:</b> ${taxi.num_consultas} |
|
||||||
|
<b>Ubics.:</b> ${taxi.num_ubicaciones}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
function updateMap() {
|
function updateMap() {
|
||||||
fetch('api.php')
|
fetch('api.php?action=get_current_locations')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const bounds = L.latLngBounds();
|
taxiList.innerHTML = ''; // Clear list before update
|
||||||
const activeMatriculas = data.map(taxi => taxi.matricula);
|
const activeTaxiIds = data.map(t => t.id);
|
||||||
|
|
||||||
// Limpiar marcadores de taxis que ya no están en los datos
|
// Remove old markers
|
||||||
Object.keys(markers).forEach(matricula => {
|
Object.keys(markers).forEach(id => {
|
||||||
if (!activeMatriculas.includes(matricula)) {
|
if (!activeTaxiIds.includes(parseInt(id))) {
|
||||||
map.removeLayer(markers[matricula]);
|
map.removeLayer(markers[id]);
|
||||||
delete markers[matricula];
|
delete markers[id];
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data.forEach(taxi => {
|
||||||
|
const lat = parseFloat(taxi.latitud);
|
||||||
|
const lon = parseFloat(taxi.longitud);
|
||||||
|
if (isNaN(lat) || isNaN(lon)) return;
|
||||||
|
|
||||||
|
// Update sidebar
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
listItem.className = 'list-group-item list-group-item-action';
|
||||||
|
listItem.textContent = `${taxi.matricula} (${taxi.nombre || 'Sin nombre'})`;
|
||||||
|
listItem.dataset.taxiId = taxi.id;
|
||||||
|
listItem.addEventListener('click', () => {
|
||||||
|
map.setView([lat, lon], 15);
|
||||||
|
markers[taxi.id].openPopup();
|
||||||
});
|
});
|
||||||
|
taxiList.appendChild(listItem);
|
||||||
|
|
||||||
data.forEach(taxi => {
|
// Update map markers
|
||||||
const lat = parseFloat(taxi.latitud);
|
const popupContent = createPopupContent(taxi);
|
||||||
const lon = parseFloat(taxi.longitud);
|
const icon = icons[taxi.municipio] || icons['default'];
|
||||||
const matricula = taxi.matricula;
|
if (markers[taxi.id]) {
|
||||||
const taxiId = taxi.id; // Asegúrate de que la API devuelve el ID del taxi
|
markers[taxi.id].setLatLng([lat, lon]).setPopupContent(popupContent).setIcon(icon);
|
||||||
|
} else {
|
||||||
|
markers[taxi.id] = L.marker([lat, lon], { icon: icon }).addTo(map)
|
||||||
|
.bindPopup(popupContent);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isNaN(lat) && !isNaN(lon)) {
|
markers[taxi.id].off('click').on('click', () => {
|
||||||
const popupContent = `<b>Taxi:</b> ${matricula}<br><b>Modelo:</b> ${taxi.modelo || 'N/A'}<br><b>Última vez:</b> ${taxi.ultima_actualizacion}`;
|
document.getElementById('inputTaxiInfo').value = `${taxi.matricula} - ${taxi.nombre}`;
|
||||||
const latLng = [lat, lon];
|
document.getElementById('inputTaxiId').value = taxi.id;
|
||||||
|
document.getElementById('inputLatitud').value = lat.toFixed(8);
|
||||||
let marker;
|
document.getElementById('inputLongitud').value = lon.toFixed(8);
|
||||||
if (markers[matricula]) {
|
document.getElementById('inputFecha').value = new Date().toISOString().slice(0, 16);
|
||||||
marker = markers[matricula].setLatLng(latLng).setPopupContent(popupContent);
|
|
||||||
} else {
|
|
||||||
marker = L.marker(latLng, { icon: taxiIcon }).addTo(map)
|
|
||||||
.bindPopup(popupContent);
|
|
||||||
markers[matricula] = marker;
|
|
||||||
}
|
|
||||||
|
|
||||||
marker.off('click').on('click', () => {
|
|
||||||
document.getElementById('selectTaxi').value = taxiId;
|
|
||||||
document.getElementById('inputLatitud').value = lat.toFixed(8);
|
|
||||||
document.getElementById('inputLongitud').value = lon.toFixed(8);
|
|
||||||
document.getElementById('inputFecha').value = new Date().toISOString().slice(0, 16);
|
|
||||||
|
|
||||||
// Scroll to the form for better UX
|
|
||||||
document.getElementById('selectTaxi').focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
bounds.extend(latLng);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
// Ajustar el mapa a los límites de los marcadores si hay alguno
|
|
||||||
if (bounds.isValid()) {
|
|
||||||
map.fitBounds(bounds, { padding: [50, 50] }); // Añade un poco de padding
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Error al cargar las localizaciones:', error));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualizar el mapa cada 5 segundos
|
|
||||||
setInterval(updateMap, 5000);
|
|
||||||
|
|
||||||
// Carga inicial
|
|
||||||
updateMap();
|
|
||||||
|
|
||||||
// Set current date and time for the historical form
|
|
||||||
document.getElementById('inputFecha').value = new Date().toISOString().slice(0, 16);
|
|
||||||
|
|
||||||
// Get coordinates on map click
|
|
||||||
map.on('click', function(e) {
|
|
||||||
document.getElementById('inputLatitud').value = e.latlng.lat.toFixed(8);
|
|
||||||
document.getElementById('inputLongitud').value = e.latlng.lng.toFixed(8);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lógica para el historial de rutas
|
|
||||||
let routePolyline = null;
|
|
||||||
document.getElementById('history-form').addEventListener('submit', function(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const taxiId = document.getElementById('selectTaxiHistory').value;
|
|
||||||
if (!taxiId) {
|
|
||||||
alert('Por favor, seleccione un taxi.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch(`api.php?action=get_route_history&id_taxi=${taxiId}`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(historyData => {
|
|
||||||
if (routePolyline) {
|
|
||||||
map.removeLayer(routePolyline);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (historyData.length < 2) {
|
|
||||||
alert('No hay suficiente historial para mostrar una ruta.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const latLngs = historyData.map(point => [parseFloat(point.latitud), parseFloat(point.longitud)]);
|
|
||||||
|
|
||||||
routePolyline = L.polyline(latLngs, {color: '#007bff', weight: 5}).addTo(map);
|
|
||||||
|
|
||||||
map.fitBounds(routePolyline.getBounds(), { padding: [50, 50] });
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Error al cargar el historial:', error));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Lógica para el botón "Mi Ubicación"
|
|
||||||
let userLocationMarker = null;
|
|
||||||
const userIcon = L.icon({ // Icono personalizado para el usuario
|
|
||||||
iconUrl: 'https://cdn-icons-png.flaticon.com/512/684/684809.png', // Icono de persona
|
|
||||||
iconSize: [32, 32],
|
|
||||||
iconAnchor: [16, 32],
|
|
||||||
popupAnchor: [0, -32]
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById('get-location-btn').addEventListener('click', function() {
|
|
||||||
if (!navigator.geolocation) {
|
|
||||||
alert('La geolocalización no es soportada por tu navegador.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
navigator.geolocation.getCurrentPosition(function(position) {
|
|
||||||
const lat = position.coords.latitude;
|
|
||||||
const lon = position.coords.longitude;
|
|
||||||
const userLatLng = [lat, lon];
|
|
||||||
|
|
||||||
if (userLocationMarker) {
|
|
||||||
userLocationMarker.setLatLng(userLatLng);
|
|
||||||
} else {
|
|
||||||
userLocationMarker = L.marker(userLatLng, { icon: userIcon }).addTo(map)
|
|
||||||
.bindPopup('<b>Tu estás aquí</b>');
|
|
||||||
}
|
|
||||||
map.setView(userLatLng, 15); // Centrar el mapa en el usuario con un zoom más cercano
|
|
||||||
userLocationMarker.openPopup();
|
|
||||||
|
|
||||||
}, function() {
|
|
||||||
alert('No se pudo obtener tu ubicación. Asegúrate de haber concedido los permisos.');
|
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
document.getElementById('show-all-btn').addEventListener('click', () => {
|
||||||
|
const group = new L.featureGroup(Object.values(markers));
|
||||||
|
if (Object.keys(markers).length > 0) {
|
||||||
|
map.fitBounds(group.getBounds().pad(0.2));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
map.on('click', function(e) {
|
||||||
|
document.getElementById('inputLatitud').value = e.latlng.lat.toFixed(8);
|
||||||
|
document.getElementById('inputLongitud').value = e.latlng.lng.toFixed(8);
|
||||||
|
});
|
||||||
|
|
||||||
|
setInterval(updateMap, 10000); // Update every 10 seconds
|
||||||
|
updateMap(); // Initial load
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
require_once 'footer.php';
|
require_once 'footer.php';
|
||||||
?>
|
?>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user