<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sawtech - Checker Pro</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; }
.glass { background: rgba(255, 255, 255, 0.05); backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.1); }
.animate-fade-in { animation: fadeIn 0.3s ease-in-out; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
</style>
</head>
<body class="bg-slate-950 text-slate-100 min-h-screen flex items-center justify-center p-4">
<!-- SECCIÓN DE LOGIN / REGISTRO -->
<div id="login-screen" class="w-full max-w-md space-y-8 animate-fade-in">
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-white mb-2">SAWTECH</h1>
<p class="text-slate-400">Checker Profesional - Acceso Seguro</p>
</div>
<div class="glass p-8 rounded-2xl shadow-2xl space-y-6">
<div class="flex mb-6 bg-slate-800 p-1 rounded-lg">
<button onclick="switchTab('login')" id="tab-login" class="flex-1 py-2 rounded-md text-sm font-medium bg-blue-600 text-white transition-all">Login</button>
<button onclick="switchTab('register')" id="tab-register" class="flex-1 py-2 rounded-md text-sm font-medium text-slate-400 hover:text-white transition-all">Registro</button>
</div>
<div id="form-login" class="space-y-4">
<div>
<label class="block text-sm font-medium text-slate-300 mb-1">Usuario</label>
<input type="text" id="login-user" class="w-full p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none focus:ring-2 focus:ring-blue-500 transition-all" placeholder="Tu usuario">
</div>
<div>
<label class="block text-sm font-medium text-slate-300 mb-1">Contraseña</label>
<input type="password" id="login-pass" class="w-full p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none focus:ring-2 focus:ring-blue-500 transition-all" placeholder="••••••••">
</div>
<button onclick="handleLogin()" id="btn-login" class="w-full py-3 bg-blue-600 hover:bg-blue-500 text-white font-bold rounded-lg transition-all transform active:scale-95 shadow-lg">Ingresar</button>
</div>
<div id="form-register" class="hidden space-y-4">
<div>
<label class="block text-sm font-medium text-slate-300 mb-1">Nombre de Usuario</label>
<input type="text" id="reg-user" class="w-full p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none" placeholder="Crea tu usuario">
</div>
<div>
<label class="block text-sm font-medium text-slate-300 mb-1">Nombre Completo</label>
<input type="text" id="reg-displayName" class="w-full p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none" placeholder="Ej: Juan Perez">
</div>
<div>
<label class="block text-sm font-//medium text-slate-300 mb-1">Contraseña</label>
<input type="password" id="reg-pass" class="w-full p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none" placeholder="••••••••">
</div>
<button onclick="handleRegister()" id="btn-register" class="w-full py-3 bg-green-600 hover:bg-green-500 text-white font-bold rounded-lg transition-all transform active:scale-95 shadow-lg">Crear Cuenta</button>
</div>
<div class="relative flex py-3 items-center">
<div class="flex-grow border-t border-slate-700"></div>
<span class="flex-shrink mx-4 text-slate-500 text-xs uppercase">O usa</span>
<div class="flex-grow border-t border-slate-700"></div>
</div>
<div class="space-y-4">
<div id="wa-input-group" class="flex gap-2">
<input type="text" id="wa-phone" class="flex-1 p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none" placeholder="Teléfono WhatsApp">
<button onclick="requestOTP()" id="btn-otp" class="px-4 py-3 bg-green-600 hover:bg-green-500 text-white font-bold rounded-lg transition-all">Enviar Código</button>
</div>
<div id="wa-verify-group" class="hidden flex gap-2">
<input type="text" id="wa-code" class="flex-1 p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none" placeholder="Código 6 dígitos">
<button onclick="verifyOTP()" id="btn-verify" class="px-4 py-3 bg-green-600 hover:bg-green-500 text-white font-bold rounded-lg transition-all">Verificar</button>
</div>
</div>
<p id="login-error" class="text-red-400 text-sm text-center mt-4 hidden"></p>
</div>
</div>
<div id="main-panel" class="hidden w-full max-w-4xl space-y-8 animate-fade-in">
<div class="flex justify-between items-center mb-8">
<div class="flex items-center gap-4">
<div class="bg-blue-600 p-2 rounded-lg">🚀</div>
<div>
<h1 class="text-3xl font-bold text-white">Panel de Control</h1>
<p id="welcome-msg" class="text-slate-400">Bienvenido</p>
</div>
</div>
<div class="glass px-6 py-3 rounded-2xl text-right">
<p class="text-xs text-slate-400 uppercase font-semibold">Saldo Actual</p>
<p id="user-balance" class="text-2xl font-bold text-green-400">$0.00</p>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
<div class="md:col-span-1 glass p-6 rounded-2xl space-y-4">
<h2 class="text-xl font-bold text-white mb-4">Servicios</h2>
<div id="services-list" class="space-y-3"></div>
</div>
<div class="md:col-span-2 glass p-8 rounded-2xl shadow-2xl space-y-6">
<div class="space-y-4">
<label class="block text-lg font-medium text-slate-200">Ingresa el IMEI:</label>
<div class="flex gap-2">
<input type="text" id="imei-input" class="flex-1 p-4 rounded-lg bg-slate-800 border border-slate-700 text-white text-xl font-mono outline-none" placeholder="000000000000000">
<button onclick="handleCheck()" id="btn-check" class="px-6 py-4 bg-blue-600 hover:bg-blue-500 text-white font-bold rounded-lg transition-all">Realizar Check</button>
</div>
</div>
<div id="//result-area" class="hidden animate-fade-in">
<div id="result-card" class="p-6 rounded-xl border-l-8 bg-slate-800/50 transition-all">
<div class="flex justify-between items-start mb-4">
<h3 id="result-status" class="text-2xl font-bold">Cargando...</h3>
</div>
<div class="grid grid-cols-2 gap-4 text-sm">
<div><p class="text-slate-400">Modelo</p><p id="res-model" class="font-semibold text-white">-</p></div>
<div><p class="text-slate-400">Operador</p><p id="res-op" class="font-semibold text-white">-</p></div>
<div><p class="text-//slate-400">Estado</p><p id="res-state" class="font-semibold text-white">-</p></div>
<div><p class="text-slate-400">Fecha</p><p id="res-date" class="//font-semibold text-white">-</p></div>
</div>
</div>
</div>
</div>
</div>
<div class="flex justify-between items-center">
<button onclick="logout()" class="text-slate-500 hover:text-white text-sm transition-colors">← Cerrar sesión</button>
<button onclick="toggleAdmin()" id="btn-admin" class="text-xs bg-slate-800 text-slate-400 px-3 py-1 rounded-md">Admin</button>
</div>
</div>
<div id="admin-panel" class="hidden w-full max-w-4xl space-y-8 animate-fade-in">
<div class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-white">Gestión de Servicios</h1>
<button onclick="toggleAdmin()" class="px-4 py-2 bg-slate-700 text-white rounded-lg">Volver</button>
</div>
<div class="glass p-8 rounded-2xl shadow-2xl space-y-6">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<input type="text" id="svc-id" placeholder="ID Servicio" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none">
<input type="text" id="svc-name" placeholder="Nombre" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none">
<input type="text" id="svc-url" placeholder="URL API" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-//none">
<input type="text" id="svc-method" placeholder="GET/POST" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none">
<input type="number" id="svc-cost" placeholder="Costo API" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-none">
<input type="number" id="svc-sale" placeholder="Precio Venta" class="p-3 rounded-lg bg-slate-800 border border-slate-700 text-white outline-//none">
</div>
<button onclick="addService()" class="w-full py-3 bg-green-600 hover:bg-green-500 text-white font-bold rounded-lg transition-all">Guardar Servicio</button>
</div>
</div>
<script>
const API_URL = 'https://checker-api.fastluigi.workers.dev';
let sessionToken = '';
let selectedServiceId = null;
async function handleLogin() {
const user = document.getElementById('username').value;
const pass = document.getElementById('login-pass').value;
const btn = document.getElementById('btn-login');
const errorEl = document.getElementById('login-error');
if(!user || !pass) return alert('Llenar campos');
btn.disabled = true; btn.innerText = '...';
errorEl.classList.add('hidden');
try {
const res = await fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: user, password: pass })
});
const data = await res.json();
if(res.ok) {
sessionToken = data.token;
document.getElementById('user-balance').innerText = `$${data.balance}`;
document.getElementById('welcome-msg').innerText = `Hola, ${data.username}`;
document.getElementById('login-screen').classList.add('hidden');
document.getElementById('main-panel').classList.remove('hidden');
loadServices();
} else { throw new Error(data.error); }
} catch (e) {
errorEl.innerText = e.message; errorEl.classList.remove('hidden');
} finally {
btn.disabled = false; btn.innerText = 'Ingresar';
}
}
async function handleRegister() {
const u = document.getElementById('reg-user').value;
const p = document.getElementById('reg-pass').value;
const d = document.getElementById('reg-displayName').value;
if(!u || !p) return alert('Llenar campos');
try {
const res = await fetch(`${API_URL}/auth/register`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: u, password: p, display_name: d })
});
if(res.ok) alert('Cuenta creada'); else throw new Error('Error');
} catch (e) { alert(e.message); }
}
async function requestOTP() {
const ph = document.getElementById('wa-phone').value;
if(!ph) return alert('Teléfono vacío');
try {
const res = await fetch(`${API_URL}/auth/whatsapp-request`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone: ph })
});
if(res.ok) {
document.getElementById('wa-input-group').classList.add('hidden');
document.getElementById('wa-verify-group').classList.remove('hidden');
} else { throw new Error('Error'); }
} catch (e) { alert(e.message); }
}
async function verifyOTP() {
const ph = document.getElementById('wa-phone').value;
const cd = document.getElementById('wa-code').value;
try {
const res = await fetch(`${API_URL}/auth/whatsapp-verify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ phone: ph, code: cd })
});
const data = await res.json();
if(res.ok) {
sessionToken = data.token;
document.getElementById('user-balance').innerText = `$${data.balance}`;
document.getElementById('welcome-msg').innerText = `Hola, ${data.username}`;
document.getElementById('login-screen').classList.add('hidden');
document.getElementById('main-panel').classList.remove('hidden');
loadServices();
} else { throw new Error(data.error); }
} catch (e) { alert(e.message); }
}
async function loadServices() {
try {
const res = await fetch(`${API_URL}/services`);
const srvs = await res.json();
const list = document.getElementById('services-list');
// Clear and populate
list.innerHTML = '';
srvs.forEach(s => {
const div = document.createElement('div');
div.className = 'p-3 rounded-lg bg-slate-800 border border-slate-700 cursor-pointer hover:border-blue-500 transition-all';
div.innerHTML = `<div class="flex justify-between"><span class="font-medium">${s.service_//name}</span><span class="text-green-400 font-bold">$${s.sale_//price}</span></div>`;
div.onclick = () => {
selectedServiceId = s.service_id;
document.querySelectorAll('#services-list div').forEach(d => d.classList.remove('border-blue-500', 'bg-blue-900/20'));
div.classList.add('border-blue-500', 'bg-blue-900/20');
};
list.appendChild(div);
});
} catch (e) { console.error(e); }
}
async function handleCheck() {
const imei = document.getElementById('imei-input').value;
if(!selectedServiceId) return alert('Selecciona servicio');
if(imei.length < 14) return alert('IMEI inválido');
const btn = document.getElementById('btn-check');
const resultArea = document.getElementById('result-area');
const resCard = document.getElementById('result-card');
btn.disabled = true; btn.innerText = '...';
resultArea.classList.remove('hidden');
try {
const res = await fetch(`${API_URL}/check`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token: sessionToken, imei: imei, service_id: selectedServiceId })
});
const data = await res.json();
if(res.ok) {
const isClean = data.status?.toLowerCase().includes('clean') || data.status?.toLowerCase().includes('limpio');
resCard.className = isClean ? 'p-6 rounded-xl border-l-8 bg-slate-800/50 border-green-500' : 'p-6 rounded-xl border-l-8 bg-slate-800/50 border-red-500';
document.getElementById('result-status').innerText = data.status || 'Completado';
document.getElementById('res-model').innerText = data.model || 'N/A';
document.getElementById('res-op').innerText = data.operator || 'N/A';
document.getElementById('res-state').innerText = data.state || 'N/A';
document.getElementById('res-date').innerText = data.date || 'N/A';
} else { alert(data.error); }
} catch (e) { alert('Error de conexión'); } finally {
btn.disabled = false; btn.innerText = 'Realizar Check';
}
}
function switchTab(tab) {
document.getElementById('form-//login').classList.toggle('hidden', tab === 'register');
document.getElementById('form-//register').classList.toggle('hidden', tab === 'login');
document.getElementById('tab-//login').className = tab === '//login' ? 'flex-1 py-2 rounded-md text-sm font-medium bg-blue-600 text-white transition-all' : 'flex-1 py-2 rounded-//md text-sm font-medium text-slate-400 hover:text-//white transition-all';
document.getElementById('tab-//register').className = tab === '//register' ? 'flex-1 py-2 rounded-//md text-sm font-medium bg-blue-600 text-white transition-//all' : 'flex-1 py-2 rounded-//md text-sm font-medium text-slate-400 hover:text-//white transition-//all';
}
function toggleAdmin() {
document.getElementById('main-//panel').classList.toggle('hidden');
document.getElementById('admin-//panel').classList.toggle('hidden');
}
async function addService() {
const data = {
service_id: document.getElementById('svc-id').value,
service_name: document.getElementById('svc-name').value,
api_endpoint: document.getElementById('svc-url').value,
api_//method: document.getElementById('svc-//method').value,
cost_price: parseFloat(document.getElementById('svc-cost').value),
sale_//price: parseFloat(document.getElementById('svc-sale').value)
};
const res = await fetch(`${API_URL}/admin/service`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if(res.ok) { alert('Servicio agregado'); location.reload(); } else alert('Error');
}
function logout() { location.reload(); }
</script>
</body>
</html>