Actualizar servicios.html
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
<title>Servicios - IntegraRepara</title>
|
<title>Servicios - IntegraRepara</title>
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<script src="https://unpkg.com/lucide@latest"></script>
|
<script src="https://unpkg.com/lucide@latest"></script>
|
||||||
|
<script src="https://maps.googleapis.com/maps/api/js?key=TU_API_KEY_AQUI&libraries=places&callback=initAutocomplete" async defer></script>
|
||||||
<style>
|
<style>
|
||||||
.fade-in { animation: fadeIn 0.3s ease-in-out; }
|
.fade-in { animation: fadeIn 0.3s ease-in-out; }
|
||||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||||
@@ -94,7 +95,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-bold text-gray-600 mb-1">Población</label>
|
<label class="block text-xs font-bold text-gray-600 mb-1">Población / Municipio *</label>
|
||||||
<select id="sTown" class="w-full px-3 py-2 border rounded-lg bg-gray-50 outline-none focus:border-blue-500" disabled onchange="checkAutoAssign(this.value)">
|
<select id="sTown" class="w-full px-3 py-2 border rounded-lg bg-gray-50 outline-none focus:border-blue-500" disabled onchange="checkAutoAssign(this.value)">
|
||||||
<option value="">-- Elige provincia primero --</option>
|
<option value="">-- Elige provincia primero --</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -126,13 +127,13 @@
|
|||||||
<select id="sGuild" class="w-full px-3 py-2 border border-blue-200 rounded-lg bg-white outline-none focus:border-blue-500" onchange="loadOperators(this.value)">
|
<select id="sGuild" class="w-full px-3 py-2 border border-blue-200 rounded-lg bg-white outline-none focus:border-blue-500" onchange="loadOperators(this.value)">
|
||||||
<option value="">-- Seleccionar Gremio --</option>
|
<option value="">-- Seleccionar Gremio --</option>
|
||||||
</select>
|
</select>
|
||||||
|
<p id="zoneInfo" class="text-[10px] text-blue-600 mt-2 italic hidden"></p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="block text-xs font-bold text-blue-800 mb-1">Asignar Operario</label>
|
<label class="block text-xs font-bold text-blue-800 mb-1">Asignar Operario</label>
|
||||||
<select id="sOperator" class="w-full px-3 py-2 border border-blue-200 rounded-lg bg-white outline-none focus:border-blue-500">
|
<select id="sOperator" class="w-full px-3 py-2 border border-blue-200 rounded-lg bg-white outline-none focus:border-blue-500">
|
||||||
<option value="">-- Primero elige gremio --</option>
|
<option value="">-- Primero elige gremio --</option>
|
||||||
</select>
|
</select>
|
||||||
<p id="zoneInfo" class="text-[10px] text-blue-600 mt-1 italic hidden"></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -262,7 +263,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="toast" class="fixed bottom-5 right-5 bg-slate-800 text-white px-6 py-3 rounded-lg shadow-2xl hidden"><span id="toastMsg"></span></div>
|
<div id="toast" class="fixed bottom-5 right-5 bg-slate-800 text-white px-6 py-3 rounded-lg shadow-2xl transform translate-y-20 opacity-0 transition-all duration-300 z-50 flex items-center gap-3"><span id="toastMsg">Msg</span></div>
|
||||||
|
|
||||||
<script src="js/layout.js"></script>
|
<script src="js/layout.js"></script>
|
||||||
<script>
|
<script>
|
||||||
@@ -277,14 +278,13 @@
|
|||||||
fetchServices();
|
fetchServices();
|
||||||
loadCompanies();
|
loadCompanies();
|
||||||
loadGuilds();
|
loadGuilds();
|
||||||
loadProvinces(); // Cargar provincias al inicio
|
loadProvinces(); // NUEVO: Cargar provincias
|
||||||
});
|
});
|
||||||
|
|
||||||
// 1. FUNCIÓN GLOBAL PARA GOOGLE MAPS (Solución al error "initAutocomplete is not a function")
|
// 1. FUNCIÓN GLOBAL PARA GOOGLE MAPS
|
||||||
window.initAutocomplete = function() {
|
window.initAutocomplete = function() {
|
||||||
const input = document.getElementById("sAddress");
|
const input = document.getElementById("sAddress");
|
||||||
if(input) {
|
if(input) {
|
||||||
// Solo cargamos si el script de Google se cargó bien
|
|
||||||
try {
|
try {
|
||||||
autocomplete = new google.maps.places.Autocomplete(input, { types: ['geocode'] });
|
autocomplete = new google.maps.places.Autocomplete(input, { types: ['geocode'] });
|
||||||
input.addEventListener('keydown', function(e) { if (e.key === "Enter") e.preventDefault(); });
|
input.addEventListener('keydown', function(e) { if (e.key === "Enter") e.preventDefault(); });
|
||||||
@@ -305,7 +305,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- LÓGICA GEOGRÁFICA ---
|
// --- LÓGICA GEOGRÁFICA (NUEVO) ---
|
||||||
async function loadProvinces() {
|
async function loadProvinces() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_URL}/provinces`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
const res = await fetch(`${API_URL}/provinces`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
||||||
@@ -332,21 +332,17 @@
|
|||||||
} catch(e) {}
|
} catch(e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- AUTO ASIGNACIÓN ---
|
// --- AUTO ASIGNACIÓN (NUEVO) ---
|
||||||
async function checkAutoAssign(townId) {
|
async function checkAutoAssign(townId) {
|
||||||
if(!townId) return;
|
if(!townId) return;
|
||||||
|
|
||||||
// Buscar zona y operarios para este pueblo
|
|
||||||
const res = await fetch(`${API_URL}/towns/${townId}/auto-assign`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
const res = await fetch(`${API_URL}/towns/${townId}/auto-assign`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
const zoneInput = document.getElementById('sZoneName');
|
|
||||||
const opSelect = document.getElementById('sOperator');
|
const opSelect = document.getElementById('sOperator');
|
||||||
const info = document.getElementById('zoneInfo');
|
const info = document.getElementById('zoneInfo');
|
||||||
|
|
||||||
if(data.found) {
|
if(data.found) {
|
||||||
zoneInput.value = data.zone_name;
|
|
||||||
|
|
||||||
info.innerHTML = `Detectada zona: <b>${data.zone_name}</b>`;
|
info.innerHTML = `Detectada zona: <b>${data.zone_name}</b>`;
|
||||||
info.classList.remove('hidden');
|
info.classList.remove('hidden');
|
||||||
|
|
||||||
@@ -355,18 +351,12 @@
|
|||||||
opSelect.innerHTML += `<option value="${op.id}" class="font-bold text-blue-600">⭐ ${op.full_name}</option>`;
|
opSelect.innerHTML += `<option value="${op.id}" class="font-bold text-blue-600">⭐ ${op.full_name}</option>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Opción para cargar el resto si no está el que queremos
|
|
||||||
opSelect.innerHTML += '<option disabled>──────────</option><option value="load_all">Ver todos los operarios...</option>';
|
opSelect.innerHTML += '<option disabled>──────────</option><option value="load_all">Ver todos los operarios...</option>';
|
||||||
|
opSelect.onchange = function() { if(this.value === 'load_all') loadAllOperators(); };
|
||||||
// Listener para cargar todos
|
|
||||||
opSelect.onchange = function() {
|
|
||||||
if(this.value === 'load_all') loadAllOperators();
|
|
||||||
};
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
zoneInput.value = "(Sin zona asignada)";
|
|
||||||
info.classList.add('hidden');
|
info.classList.add('hidden');
|
||||||
loadOperators(document.getElementById('sGuild').value); // Volver a lógica normal
|
loadOperators(document.getElementById('sGuild').value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,10 +370,10 @@
|
|||||||
data.operators.forEach(op => sel.innerHTML += `<option value="${op.id}">${op.full_name}</option>`);
|
data.operators.forEach(op => sel.innerHTML += `<option value="${op.id}">${op.full_name}</option>`);
|
||||||
|
|
||||||
sel.value = currentVal !== 'load_all' ? currentVal : "";
|
sel.value = currentVal !== 'load_all' ? currentVal : "";
|
||||||
sel.onchange = null; // Quitar listener especial
|
sel.onchange = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- FUNCIONES ORIGINALES RESTAURADAS ---
|
// --- FUNCIONES ORIGINALES ---
|
||||||
async function fetchStatuses() {
|
async function fetchStatuses() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_URL}/statuses`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
const res = await fetch(`${API_URL}/statuses`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
||||||
@@ -597,9 +587,8 @@
|
|||||||
document.getElementById('sPhone').value = s.contact_phone;
|
document.getElementById('sPhone').value = s.contact_phone;
|
||||||
document.getElementById('sName').value = s.contact_name;
|
document.getElementById('sName').value = s.contact_name;
|
||||||
|
|
||||||
// Dirección: Intentar limpiar la población si está concatenada
|
|
||||||
let addr = s.address;
|
let addr = s.address;
|
||||||
if(addr.includes(", ")) addr = addr.split(", ")[0]; // Simple split
|
if(addr.includes(", ")) addr = addr.split(", ")[0];
|
||||||
document.getElementById('sAddress').value = addr;
|
document.getElementById('sAddress').value = addr;
|
||||||
|
|
||||||
document.getElementById('sEmail').value = s.email || '';
|
document.getElementById('sEmail').value = s.email || '';
|
||||||
@@ -643,7 +632,6 @@
|
|||||||
const editId = document.getElementById('editServiceId').value;
|
const editId = document.getElementById('editServiceId').value;
|
||||||
const isEdit = !!editId;
|
const isEdit = !!editId;
|
||||||
|
|
||||||
// Concatenar dirección + población
|
|
||||||
let fullAddress = document.getElementById('sAddress').value;
|
let fullAddress = document.getElementById('sAddress').value;
|
||||||
const townSelect = document.getElementById('sTown');
|
const townSelect = document.getElementById('sTown');
|
||||||
if(townSelect.value) {
|
if(townSelect.value) {
|
||||||
@@ -653,7 +641,7 @@
|
|||||||
const data = {
|
const data = {
|
||||||
phone: document.getElementById('sPhone').value,
|
phone: document.getElementById('sPhone').value,
|
||||||
name: document.getElementById('sName').value,
|
name: document.getElementById('sName').value,
|
||||||
address: fullAddress, // Dirección completa
|
address: fullAddress,
|
||||||
email: document.getElementById('sEmail').value,
|
email: document.getElementById('sEmail').value,
|
||||||
description: document.getElementById('sDesc').value,
|
description: document.getElementById('sDesc').value,
|
||||||
scheduled_date: document.getElementById('sDate').value,
|
scheduled_date: document.getElementById('sDate').value,
|
||||||
@@ -712,6 +700,14 @@
|
|||||||
m.innerText = msg; t.classList.remove('translate-y-20', 'opacity-0');
|
m.innerText = msg; t.classList.remove('translate-y-20', 'opacity-0');
|
||||||
setTimeout(() => t.classList.add('translate-y-20', 'opacity-0'), 3000);
|
setTimeout(() => t.classList.add('translate-y-20', 'opacity-0'), 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetForm() {
|
||||||
|
document.querySelector('form').reset();
|
||||||
|
document.getElementById('editServiceId').value = "";
|
||||||
|
document.getElementById('sTown').innerHTML = '<option value="">-- Elige provincia primero --</option>';
|
||||||
|
document.getElementById('sTown').disabled = true;
|
||||||
|
document.getElementById('zoneInfo').classList.add('hidden');
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="https://maps.googleapis.com/maps/api/js?key=TU_API_KEY_AQUI&libraries=places&callback=initAutocomplete" async defer></script>
|
<script src="https://maps.googleapis.com/maps/api/js?key=TU_API_KEY_AQUI&libraries=places&callback=initAutocomplete" async defer></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user