// ====== ROUTING ======
const routes = ["usuario", "tecnico", "admin"];
const navBtns = document.querySelectorAll("[data-route]");function showRoute(route){
routes.forEach(r=>{
const el = document.getElementById(`view-${r}`);
if(!el) return;
el.hidden = (r !== route);
});
navBtns.forEach(b=>{
b.classList.toggle("active", b.dataset.route === route);
});
}
navBtns.forEach(b=> b.addEventListener("click", ()=> showRoute(b.dataset.route)));
showRoute("usuario");// ====== MOCK DATA ======
const techs = [
{ id:"t1", name:"Daniel R.", score:4.8, jobs:312, eta: "12–18 min", priceFrom: 95000, tags:["Verificado","Garantía"], status:"Disponible" },
{ id:"t2", name:"María P.", score:4.7, jobs:221, eta: "18–25 min", priceFrom: 105000, tags:["Refrigeración","Verificado"], status:"Disponible" },
{ id:"t3", name:"Carlos S.", score:4.6, jobs:408, eta: "25–35 min", priceFrom: 85000, tags:["Electrodomésticos"], status:"En servicio" }
];const states = [
{title:"Solicitud creada", desc:"Tu solicitud fue registrada."},
{title:"Buscando técnicos", desc:"Buscando disponibilidad cerca de ti…"},
{title:"Técnico asignado", desc:"Se asignó un técnico verificado."},
{title:"En camino", desc:"El técnico va hacia tu ubicación."},
{title:"En diagnóstico", desc:"Revisión inicial y confirmación del presupuesto."},
{title:"Reparación", desc:"Trabajo en progreso."},
{title:"Finalizado", desc:"Servicio completado. Puedes pagar y calificar."},
];let currentState = 0;
let selectedTech = null;
let userAvailability = true;// ====== UTIL ======
function moneyCOP(n){
return new Intl.NumberFormat("es-CO").format(n);
}
function setText(id, txt){
const el = document.getElementById(id);
if(el) el.textContent = txt;
}// ====== TIMELINE ======
function renderTimeline(){
const wrap = document.getElementById("timeline");
wrap.innerHTML = "";
states.forEach((s, idx)=>{
const row = document.createElement("div");
row.className = "step " + (idx < currentState ? "done" : idx === currentState ? "active" : "");
row.innerHTML = `
`;
wrap.appendChild(row);
});
}
renderTimeline();// ====== USER FLOW ======
const techlist = document.getElementById("techlist");
const matchingHint = document.getElementById("matching-hint");function renderTechList(){
techlist.innerHTML = "";
techs.forEach(t=>{
const card = document.createElement("div");
card.className = "techcard";
const badgeClass = t.status === "Disponible" ? "green" : "amber";
card.innerHTML = `
`;
techlist.appendChild(card);
});techlist.querySelectorAll("[data-pick]").forEach(btn=>{
btn.addEventListener("click", ()=>{
const id = btn.dataset.pick;
selectedTech = techs.find(x=>x.id === id);
matchingHint.textContent = `Técnico seleccionado: ${selectedTech.name}. Ya puedes avanzar el estado o abrir chat.`;
// Salta a "Técnico asignado"
currentState = Math.max(currentState, 2);
renderTimeline();
setText("chatSub", `Hablando con ${selectedTech.name} (demo)`);
pushChat(`Hola, soy ${selectedTech.name}. Voy en camino apenas confirmes.`, false);
});
});
}document.getElementById("btn-buscar").addEventListener("click", ()=>{
matchingHint.textContent = "Buscando… (simulado)";
currentState = Math.max(currentState, 1);
renderTimeline();
setTimeout(()=>{
renderTechList();
matchingHint.textContent = "Selecciona un técnico para asignar el servicio.";
}, 450);
});document.getElementById("btn-estado").addEventListener("click", ()=>{
if(currentState < states.length - 1) currentState++;
renderTimeline();
});document.getElementById("btn-reset").addEventListener("click", ()=>{
currentState = 0;
selectedTech = null;
techlist.innerHTML = "";
matchingHint.textContent = "Haz clic en “Buscar técnicos disponibles”.";
renderTimeline();
setRating(0);
resetChat();
});document.getElementById("btn-demo-flujo").addEventListener("click", async ()=>{
// Demo automático de 10–15s para presentación
document.getElementById("btn-reset").click();
document.getElementById("btn-buscar").click();
await sleep(650);
// elige el primero disponible
const firstPick = techlist.querySelector("[data-pick]");
if(firstPick) firstPick.click();
await sleep(500);
// avanza estados a "En camino"
currentState = 3; renderTimeline();
await sleep(700);
currentState = 4; renderTimeline();
await sleep(700);
currentState = 5; renderTimeline();
await sleep(700);
currentState = 6; renderTimeline();
});function sleep(ms){ return new Promise(r=>setTimeout(r,ms)); }// ====== CHAT ======
const chatModal = document.getElementById("chatModal");
const chatBody = document.getElementById("chatBody");
const chatInput = document.getElementById("chatInput");function resetChat(){
chatBody.innerHTML = "";
setText("chatSub", selectedTech ? `Hablando con ${selectedTech.name} (demo)` : "Conectando…");
}
function pushChat(text, me){
const b = document.createElement("div");
b.className = "bubble " + (me ? "me" : "");
b.textContent = text;
chatBody.appendChild(b);
chatBody.scrollTop = chatBody.scrollHeight;
}
document.getElementById("btn-chat").addEventListener("click", ()=>{
resetChat();
if(!selectedTech){
pushChat("Selecciona un técnico para iniciar conversación.", false);
} else {
pushChat("¿Podrías confirmar si el equipo presenta algún olor a quemado o solo no enciende?", false);
}
chatModal.showModal();
});
document.getElementById("btn-close-chat").addEventListener("click", ()=> chatModal.close());
document.getElementById("btn-send-chat").addEventListener("click", ()=>{
const v = chatInput.value.trim();
if(!v) return;
pushChat(v, true);
chatInput.value = "";
// auto-respuesta demo
setTimeout(()=>{
pushChat("Perfecto. Al llegar hago diagnóstico y te confirmo repuesto/tiempo. Gracias.", false);
}, 500);
});
chatInput.addEventListener("keydown", (e)=>{
if(e.key === "Enter") document.getElementById("btn-send-chat").click();
});// ====== PAGO ======
const payModal = document.getElementById("payModal");
let payMethod = null;document.getElementById("btn-pagar").addEventListener("click", ()=>{
document.getElementById("payHint").textContent = "Elige un método.";
payMethod = null;
payModal.showModal();
});
document.getElementById("btn-close-pay").addEventListener("click", ()=> payModal.close());document.querySelectorAll(".payopt").forEach(b=>{
b.addEventListener("click", ()=>{
payMethod = b.dataset.pay;
document.getElementById("payHint").textContent = `Método seleccionado: ${payMethod.toUpperCase()} (demo).`;
});
});
document.getElementById("btn-confirm-pay").addEventListener("click", ()=>{
if(!payMethod){
document.getElementById("payHint").textContent = "Selecciona un método antes de confirmar.";
return;
}
payModal.close();
// fuerza a finalizado si no lo está
currentState = Math.max(currentState, 6);
renderTimeline();
pushChat("Pago confirmado (demo). ¿Me calificarías con 5 estrellas si quedaste satisfecho?", false);
});// ====== RATING ======
let rating = 0;
function setRating(n){
rating = n;
document.querySelectorAll(".star").forEach(s=>{
s.classList.toggle("on", Number(s.dataset.star) <= rating);
});
setText("ratingtext", rating ? `Calificación: ${rating}/5` : "Aún no calificado");
}
document.querySelectorAll(".star").forEach(s=>{
s.addEventListener("click", ()=> setRating(Number(s.dataset.star)));
});// ====== TECNICO VIEW ======
let techOnline = true;
let incomingId = 0;
let activeService = null;
let techStateIdx = 0;const dispoBtn = document.getElementById("btn-toggle-dispo");
dispoBtn.addEventListener("click", ()=>{
techOnline = !techOnline;
dispoBtn.textContent = techOnline ? "Disponible" : "No disponible";
dispoBtn.classList.toggle("primary", techOnline);
dispoBtn.classList.toggle("danger", !techOnline);
});function renderRequests(){
const wrap = document.getElementById("requests");
wrap.innerHTML = "";
if(!techOnline){
wrap.innerHTML = `
`;
wrap.appendChild(el);
});wrap.querySelectorAll("[data-accept]").forEach(b=>{
b.addEventListener("click", ()=>{
const id = b.dataset.accept;
const req = window._requests.find(x=>x.id===id);
activeService = req;
techStateIdx = 0;
window._requests = window._requests.filter(x=>x.id!==id);
renderRequests();
renderActiveService();
});
});
wrap.querySelectorAll("[data-decline]").forEach(b=>{
b.addEventListener("click", ()=>{
const id = b.dataset.decline;
window._requests = window._requests.filter(x=>x.id!==id);
renderRequests();
});
});
}function renderActiveService(){
const wrap = document.getElementById("servicecard");
const hint = document.getElementById("active-hint");
if(!activeService){
hint.textContent = "Acepta una solicitud para ver detalles.";
wrap.innerHTML = "";
return;
}
hint.textContent = `Servicio activo: ${activeService.title}`;
const localStates = ["Asignado", "En camino", "Diagnóstico", "Reparación", "Finalizado"];
wrap.innerHTML = `
${idx+1}. ${s.title}
${s.desc}
Estás offline. Activa “Disponible” para recibir solicitudes.
`;
return;
}
// si no hay requests
if(!window._requests || window._requests.length === 0){
wrap.innerHTML = `Sin solicitudes por ahora.
`;
return;
}
window._requests.forEach(req=>{
const el = document.createElement("div");
el.className = "req";
el.innerHTML = `${req.title}
${req.zone} • ${req.problem} • ${req.urgency}
Pago estimado: $ ${moneyCOP(req.total)} COP
Cliente${activeService.customer}
Zona${activeService.zone}
Problema${activeService.problem}
Estado${localStates[techStateIdx]}
Total estimado$ ${moneyCOP(activeService.total)} COP
`;
}document.getElementById("btn-simular-solicitud").addEventListener("click", ()=>{
if(!techOnline) return;
window._requests = window._requests || [];
incomingId++;
const category = document.getElementById("u-categoria")?.value || "lavadora";
const catName = category === "nevera" ? "Nevera" : category === "electrodomestico" ? "Electrodoméstico" : "Lavadora";
const req = {
id: `r${incomingId}`,
title: `${catName} • Servicio a domicilio`,
zone: "Bogotá, Chapinero",
problem: document.getElementById("u-problema")?.value || "No enciende",
urgency: document.getElementById("u-urgencia")?.value || "Lo antes posible",
customer: "Cliente demo",
total: 165000
};
window._requests.unshift(req);
renderRequests();
});document.getElementById("btn-tec-estado").addEventListener("click", ()=>{
if(!activeService) return;
techStateIdx = Math.min(techStateIdx + 1, 4);
renderActiveService();
});document.getElementById("btn-tec-evidencia").addEventListener("click", ()=>{
if(!activeService) return;
alert("Evidencia añadida (demo): Foto/nota guardada en el mockup.");
});document.getElementById("btn-tec-cerrar").addEventListener("click", ()=>{
if(!activeService) return;
techStateIdx = 4;
renderActiveService();
alert("Servicio cerrado (demo).");
});renderRequests();
renderActiveService();// ====== ADMIN LOGIN ======
const adminLoginCard = document.getElementById("admin-login-card");
const adminPanelCard = document.getElementById("admin-panel-card");document.getElementById("btn-admin-login").addEventListener("click", ()=>{
const user = document.getElementById("a-user").value.trim();
const pass = document.getElementById("a-pass").value.trim();
if(user === "admin" && pass === "12345"){
adminLoginCard.hidden = true;
adminPanelCard.hidden = false;
}else{
document.getElementById("admin-login-hint").textContent = "Credenciales incorrectas (demo).";
}
});document.getElementById("btn-admin-logout").addEventListener("click", ()=>{
adminPanelCard.hidden = true;
adminLoginCard.hidden = false;
document.getElementById("admin-login-hint").textContent = "Credenciales demo.";
});