/* Capa de servicios SIMULADA (datos en memoria). Todas las funciones devuelven Promesas; para integrar las APIs reales solo se reemplaza el cuerpo de cada una por un fetch. */ const Api=(()=>{ const CAT={categorias:['Soporte técnico','Sistemas','Hardware','Software','Accesos','Otro'],prioridades:['Baja','Media','Alta','Urgente'],estados:['NUEVO','ASIGNADO','EN PROCESO','ESPERANDO USUARIO','RESUELTO','CERRADO','CANCELADO'],areas:['Operaciones','Recursos Humanos','Almacén','Calidad','Finanzas','TI']}; const U=[{id:1,nombre:'Roberto',rol:'SOLICITANTE',area:'Operaciones'},{id:2,nombre:'David',rol:'TECNICO',area:'TI'},{id:3,nombre:'Laura',rol:'ADMINISTRADOR',area:'TI'},{id:4,nombre:'Ana',rol:'SOLICITANTE',area:'Recursos Humanos'},{id:5,nombre:'Mario',rol:'TECNICO',area:'TI'}]; const T=[];let seq=0; const nom=id=>U.find(u=>u.id==id)?.nombre||null,now=()=>new Date().toISOString(),find=id=>T.find(t=>t.id==id); const wait=v=>new Promise(r=>setTimeout(()=>r(structuredClone(v)),120)); const dto=t=>({...t,solicitante:nom(t.solicitanteId),responsable:nom(t.responsableId)}); const log=(t,por,accion,f=now())=>{t.historial.push({fecha:f,usuario:por,accion});t.actualizado=f}; function crear(d,f=now()){const t={id:++seq,folio:'TK-'+String(seq).padStart(4,'0'),estado:'NUEVO',responsableId:null,fechaAsignacion:null,creado:f,actualizado:f,comentarios:[],archivos:[],historial:[],...d};log(t,nom(d.solicitanteId),'creó el ticket',f);T.push(t);return t} function asignar(t,uid,por,f=now()){t.responsableId=uid;t.fechaAsignacion=f;if(t.estado=='NUEVO')t.estado='ASIGNADO';log(t,por,'asignó el ticket a '+nom(uid),f)} function estado(t,e,por,f=now()){t.estado=e;log(t,por,e=='RESUELTO'?'marcó el ticket como RESUELTO':'cambió el estado a '+e,f)} function coment(t,texto,por,f=now()){t.comentarios.push({usuario:por,fecha:f,texto});log(t,por,'agregó un comentario',f)} /* ---- Datos de ejemplo ---- */ let t=crear({asunto:'No puedo acceder al correo corporativo',descripcion:'Desde hoy el correo marca contraseña incorrecta aunque no la he cambiado.',categoria:'Accesos',prioridad:'Alta',area:'Operaciones',solicitanteId:1},'2026-10-08T10:15:00'); asignar(t,2,'Laura','2026-10-08T10:20:00');estado(t,'EN PROCESO','David','2026-10-08T10:35:00');coment(t,'Restablecí tu contraseña. Prueba con la temporal que te llegó por SMS.','David','2026-10-08T11:30:00');estado(t,'RESUELTO','David','2026-10-08T12:00:00'); t=crear({asunto:'La impresora del almacén no imprime',descripcion:'Marca error de atasco, pero no hay papel atorado.',categoria:'Hardware',prioridad:'Media',area:'Almacén',solicitanteId:4},'2026-10-07T09:00:00');asignar(t,5,'Laura','2026-10-07T09:30:00');estado(t,'EN PROCESO','Mario','2026-10-07T10:00:00'); t=crear({asunto:'Instalar Office en equipo nuevo',descripcion:'Equipo asignado a la nueva coordinadora de nómina.',categoria:'Software',prioridad:'Baja',area:'Recursos Humanos',solicitanteId:4},'2026-10-08T08:40:00'); t=crear({asunto:'El sistema de nómina está muy lento',descripcion:'Tarda más de un minuto en abrir cada reporte desde ayer.',categoria:'Sistemas',prioridad:'Urgente',area:'Finanzas',solicitanteId:1},'2026-10-06T15:00:00');asignar(t,2,'Laura','2026-10-06T15:10:00');coment(t,'¿Puedes indicarme a qué hora empezó y desde qué equipo?','David','2026-10-06T16:00:00');estado(t,'ESPERANDO USUARIO','David','2026-10-06T16:01:00'); t=crear({asunto:'Solicitud de acceso por VPN',descripcion:'Necesito acceso remoto para la auditoría de calidad.',categoria:'Accesos',prioridad:'Media',area:'Calidad',solicitanteId:4},'2026-10-02T11:00:00');asignar(t,2,'Laura','2026-10-02T11:05:00');estado(t,'RESUELTO','David','2026-10-02T13:00:00');estado(t,'CERRADO','Ana','2026-10-03T09:00:00'); /* ---- Funciones públicas (contrato que luego implementarán las APIs reales) ---- */ return{ obtenerCatalogos:()=>wait(CAT), obtenerUsuarios:()=>wait(U), obtenerTickets:({alcance,usuario})=>wait(T.filter(x=>alcance=='mis'||usuario.rol=='SOLICITANTE'?x.solicitanteId==usuario.id:usuario.rol=='ADMINISTRADOR'||x.responsableId==usuario.id).sort((a,b)=>b.actualizado.localeCompare(a.actualizado)).map(dto)), obtenerTicket:id=>wait(find(id)?dto(find(id)):null), crearTicket:(d)=>wait(dto(crear(d))), actualizarTicket:(id,d,por)=>{const x=find(id);if(d.estado)estado(x,d.estado,por.nombre);return wait(dto(x))}, asignarTicket:(id,uid,por)=>{asignar(find(id),uid,por.nombre);return wait(true)}, agregarComentario:(id,texto,por)=>{coment(find(id),texto,por.nombre);return wait(true)}, obtenerComentarios:id=>wait(find(id).comentarios), obtenerHistorial:id=>wait(find(id).historial), obtenerArchivos:id=>wait(find(id).archivos), agregarArchivo:(id,a,por)=>{const x=find(id);x.archivos.push({...a,usuario:por.nombre,fecha:now()});log(x,por.nombre,'adjuntó el archivo '+a.nombre);return wait(true)} }})();