Actualizar servicios.html
This commit is contained in:
183
servicios.html
183
servicios.html
@@ -129,117 +129,98 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form onsubmit="saveNewService(event)" class="flex-1 overflow-y-auto no-scrollbar p-6 bg-slate-50/50">
|
<form onsubmit="saveNewService(event)" class="flex-1 overflow-y-auto no-scrollbar p-6 bg-slate-50/50">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-12 gap-8">
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-6">
|
||||||
|
|
||||||
<div class="md:col-span-7 space-y-6">
|
<div class="md:col-span-7 space-y-4">
|
||||||
|
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
||||||
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
<h4 class="font-black text-slate-800 uppercase text-[10px] flex items-center gap-2 border-b border-slate-100 pb-2">
|
||||||
<h4 class="font-black text-slate-800 uppercase text-xs flex items-center gap-2 border-b border-slate-100 pb-3 mb-4">
|
|
||||||
<i data-lucide="user" class="w-4 h-4 text-blue-500"></i> Datos del Cliente
|
<i data-lucide="user" class="w-4 h-4 text-blue-500"></i> Datos del Cliente
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Teléfono</label>
|
<label class="label-modern">Teléfono</label>
|
||||||
<input type="tel" id="nPhone" placeholder="Ej: 600123456" class="input-modern" required>
|
<input type="tel" id="nPhone" oninput="searchClientByPhone(this.value)" placeholder="Ej: 600123456" class="input-modern" required>
|
||||||
|
|
||||||
<div id="addrSuggestions" class="hidden mt-2 p-3 bg-amber-50 border border-amber-200 rounded-xl text-[10px] font-bold text-amber-700 flex items-center gap-2">
|
|
||||||
<i data-lucide="info" class="w-3 h-3"></i>
|
|
||||||
<span>Este cliente ya tiene direcciones guardadas. Puedes usar la actual o escribir una nueva.</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Nombre Completo</label>
|
<label class="label-modern">Nombre Completo</label>
|
||||||
<input type="text" id="nName" placeholder="Nombre del asegurado" class="input-modern" required>
|
<input type="text" id="nName" placeholder="Nombre asegurado" class="input-modern" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Dirección Completa</label>
|
<label class="label-modern">Dirección del Servicio</label>
|
||||||
<input type="text" id="nAddr" placeholder="Calle, número, piso, población..." class="input-modern" required>
|
<input type="text" id="nAddr" placeholder="Calle, número, población..." class="input-modern" required>
|
||||||
|
<div id="addrSuggestions" class="hidden mt-2 p-2 bg-amber-50 border border-amber-200 rounded-lg text-[10px] font-bold text-amber-700">
|
||||||
|
⚠️ Este cliente ya tiene otras direcciones registradas.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm">
|
<div class="pt-2 border-t border-slate-100">
|
||||||
<h4 class="font-black text-slate-800 uppercase text-xs flex items-center gap-2 border-b border-slate-100 pb-3 mb-4">
|
<label class="flex items-center gap-3 cursor-pointer group">
|
||||||
<i data-lucide="align-left" class="w-4 h-4 text-amber-500"></i> Detalles de la Avería
|
<input type="checkbox" id="isCompanyCheck" onchange="toggleCompanyFields(this.checked)" class="w-5 h-5 rounded border-slate-300 text-blue-600 focus:ring-blue-500">
|
||||||
</h4>
|
<span class="text-xs font-black text-slate-700 uppercase tracking-tight group-hover:text-blue-600 transition-colors">¿Es de Compañía de Seguros?</span>
|
||||||
<label class="label-modern">Descripción</label>
|
</label>
|
||||||
<textarea id="nDesc" placeholder="Describe el problema a reparar..." rows="4" class="input-modern resize-none"></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="md:col-span-5 space-y-6">
|
|
||||||
|
|
||||||
<div class="bg-white p-6 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
|
||||||
<h4 class="font-black text-slate-800 uppercase text-xs flex items-center gap-2 border-b border-slate-100 pb-3 mb-4">
|
|
||||||
<i data-lucide="hammer" class="w-4 h-4 text-purple-500"></i> Asignación
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
|
<div id="companyFields" class="hidden mt-4 grid grid-cols-1 sm:grid-cols-2 gap-4 p-4 bg-blue-50/50 rounded-xl border border-blue-100 fade-in">
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Gremio Recomendado</label>
|
<label class="label-modern">Compañía</label>
|
||||||
<div class="relative">
|
<select id="nCompanySelect" class="input-modern">
|
||||||
<select id="nGuild" class="input-modern appearance-none cursor-pointer pr-10" onchange="loadOps(this.value, 'nWorker')">
|
<option value="">Seleccionar...</option>
|
||||||
<option value="">Seleccionar gremio...</option>
|
|
||||||
</select>
|
</select>
|
||||||
<i data-lucide="chevron-down" class="w-4 h-4 absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none"></i>
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="label-modern">Nº Expediente / Referencia</label>
|
||||||
|
<input type="text" id="nExpRef" onblur="checkDuplicateRef(this.value)" placeholder="Ej: 88723X" class="input-modern uppercase">
|
||||||
|
<p id="refAlert" class="hidden text-[9px] text-red-600 font-bold mt-1 uppercase">⚠️ ¡Referencia ya existente!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm">
|
||||||
|
<label class="label-modern">Descripción de la Avería</label>
|
||||||
|
<textarea id="nDesc" placeholder="Describe el problema..." rows="3" class="input-modern resize-none"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="md:col-span-5 space-y-4">
|
||||||
|
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm space-y-4">
|
||||||
|
<h4 class="font-black text-slate-800 uppercase text-[10px] flex items-center gap-2 border-b border-slate-100 pb-2">
|
||||||
|
<i data-lucide="clock" class="w-4 h-4 text-purple-500"></i> Gestión
|
||||||
|
</h4>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label class="label-modern">Gremio</label>
|
||||||
|
<select id="nGuild" class="input-modern" onchange="loadOps(this.value, 'nWorker')">
|
||||||
|
<option value="">Seleccionar...</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Operario</label>
|
<label class="label-modern">Operario</label>
|
||||||
<div class="relative">
|
<select id="nWorker" class="input-modern">
|
||||||
<select id="nWorker" class="input-modern appearance-none cursor-pointer pr-8">
|
|
||||||
<option value="">(Sin asignar)</option>
|
<option value="">(Sin asignar)</option>
|
||||||
</select>
|
</select>
|
||||||
<i data-lucide="chevron-down" class="w-4 h-4 absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label class="label-modern">Duración (Estimada)</label>
|
<label class="label-modern">Duración Estimada</label>
|
||||||
<div class="relative">
|
<select id="nDuration" class="input-modern font-black text-blue-600">
|
||||||
<select id="nDuration" class="input-modern appearance-none cursor-pointer pr-8">
|
<option value="30">30 MIN (Rápido)</option>
|
||||||
<option value="15">15 min</option>
|
<option value="60" selected>1 HORA (Normal)</option>
|
||||||
<option value="30">30 min</option>
|
<option value="120">2 HORAS (Largo)</option>
|
||||||
<option value="45">45 min</option>
|
<option value="240">4 HORAS (Media Jornada)</option>
|
||||||
<option value="60" selected>1 hora</option>
|
|
||||||
<option value="75">1 h 15 min</option>
|
|
||||||
<option value="90">1 h 30 min</option>
|
|
||||||
<option value="105">1 h 45 min</option>
|
|
||||||
<option value="120">2 horas</option>
|
|
||||||
<option value="150">2 h 30 min</option>
|
|
||||||
<option value="180">3 horas</option>
|
|
||||||
<option value="210">3 h 30 min</option>
|
|
||||||
<option value="240">4 horas (Max)</option>
|
|
||||||
</select>
|
</select>
|
||||||
<i data-lucide="clock" class="w-4 h-4 absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
<button type="submit" name="action" value="manual" class="w-full bg-emerald-600 hover:bg-emerald-500 text-white font-black py-4 rounded-xl text-sm uppercase tracking-widest shadow-[0_8px_20px_-6px_rgba(5,150,105,0.5)] transition-all active:scale-95 flex items-center justify-center gap-2">
|
<button type="submit" name="action" value="manual" class="w-full bg-emerald-600 hover:bg-emerald-500 text-white font-black py-4 rounded-2xl text-xs uppercase tracking-widest shadow-lg transition-all active:scale-95">
|
||||||
<i data-lucide="check-circle" class="w-5 h-5"></i> Crear y Guardar
|
Crear y Guardar
|
||||||
</button>
|
</button>
|
||||||
|
<button type="submit" name="action" value="auto" class="w-full bg-slate-800 hover:bg-slate-700 text-white font-black py-4 rounded-2xl text-xs uppercase tracking-widest transition-all active:scale-95 flex items-center justify-center gap-2">
|
||||||
<div class="relative flex items-center justify-center py-2">
|
<i data-lucide="zap" class="w-4 h-4 text-amber-400"></i> Mandar a la Bolsa
|
||||||
<span class="border-t border-slate-200 w-full absolute"></span>
|
|
||||||
<span class="bg-slate-50 px-3 text-[9px] font-black text-slate-400 uppercase tracking-widest relative z-10">Opciones Automáticas</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="submit" name="action" value="auto" class="w-full bg-slate-800 hover:bg-slate-700 text-white font-black py-3 rounded-xl text-xs uppercase tracking-widest shadow-md transition-all active:scale-95 flex items-center justify-between px-5 border border-slate-600">
|
|
||||||
<div class="text-left">
|
|
||||||
<span class="block">Mandar a la Cola</span>
|
|
||||||
<span class="block text-[9px] text-slate-400 font-medium normal-case mt-0.5">Busca operario vía WhatsApp</span>
|
|
||||||
</div>
|
|
||||||
<i data-lucide="zap" class="w-5 h-5 text-amber-400"></i>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -915,8 +896,54 @@ async function searchClientByPhone(phone) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function closeDetailModal() { document.getElementById('detailModal').classList.add('hidden'); }
|
function closeDetailModal() { document.getElementById('detailModal').classList.add('hidden'); }
|
||||||
function openCreateModal() { document.getElementById('createModal').classList.remove('hidden'); }
|
// Al abrir el modal, cargamos las compañías configuradas
|
||||||
function closeCreateModal() { document.getElementById('createModal').classList.add('hidden'); }
|
async function openCreateModal() {
|
||||||
|
document.getElementById('createModal').classList.remove('hidden');
|
||||||
|
// Limpiamos campos
|
||||||
|
document.getElementById('isCompanyCheck').checked = false;
|
||||||
|
toggleCompanyFields(false);
|
||||||
|
|
||||||
|
// Cargar compañías desde tu ruta de configuración
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_URL}/companies`, {
|
||||||
|
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
const sel = document.getElementById('nCompanySelect');
|
||||||
|
sel.innerHTML = '<option value="">Seleccionar compañía...</option>';
|
||||||
|
data.companies.forEach(c => {
|
||||||
|
sel.innerHTML += `<option value="${c.name}">${c.name.toUpperCase()}</option>`;
|
||||||
|
});
|
||||||
|
} catch(e) {}
|
||||||
|
lucide.createIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleCompanyFields(show) {
|
||||||
|
const fields = document.getElementById('companyFields');
|
||||||
|
fields.classList.toggle('hidden', !show);
|
||||||
|
if(!show) {
|
||||||
|
document.getElementById('nExpRef').value = "";
|
||||||
|
document.getElementById('refAlert').classList.add('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkDuplicateRef(ref) {
|
||||||
|
if(!ref) return;
|
||||||
|
const res = await fetch(`${API_URL}/services/check-ref?ref=${ref}`, {
|
||||||
|
headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` }
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
const alertEl = document.getElementById('refAlert');
|
||||||
|
const inputEl = document.getElementById('nExpRef');
|
||||||
|
|
||||||
|
if(data.exists) {
|
||||||
|
alertEl.classList.remove('hidden');
|
||||||
|
inputEl.classList.add('border-red-500', 'bg-red-50');
|
||||||
|
} else {
|
||||||
|
alertEl.classList.add('hidden');
|
||||||
|
inputEl.classList.remove('border-red-500', 'bg-red-50');
|
||||||
|
}
|
||||||
|
} function closeCreateModal() { document.getElementById('createModal').classList.add('hidden'); }
|
||||||
|
|
||||||
async function loadGuilds() {
|
async function loadGuilds() {
|
||||||
const res = await fetch(`${API_URL}/guilds`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
const res = await fetch(`${API_URL}/guilds`, { headers: { "Authorization": `Bearer ${localStorage.getItem("token")}` } });
|
||||||
|
|||||||
Reference in New Issue
Block a user