feat: modal agendar domicilio es minimizable y arrastrable
This commit is contained in:
+147
-2
@@ -6431,6 +6431,56 @@ if (!isset($_SESSION['user_id'])) {
|
||||
#modalAgendarDomicilio .field-err { display:none; font-size:.8rem; color:#dc3545; margin-top:3px; }
|
||||
#modalAgendarDomicilio .is-invalid ~ .field-err,
|
||||
#modalAgendarDomicilio .is-invalid + .field-err { display:block; }
|
||||
|
||||
/* ── Modo flotante (minimizado) ── */
|
||||
#modalAgendarDomicilio.dom-flotante {
|
||||
position: fixed !important;
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
bottom: 16px !important;
|
||||
right: 16px !important;
|
||||
width: auto !important;
|
||||
margin: 0 !important;
|
||||
z-index: 1055;
|
||||
display: block !important;
|
||||
pointer-events: auto;
|
||||
}
|
||||
#modalAgendarDomicilio.dom-flotante .modal-dialog {
|
||||
margin: 0;
|
||||
width: 320px;
|
||||
max-height: none;
|
||||
transform: none !important;
|
||||
}
|
||||
#modalAgendarDomicilio.dom-flotante .modal-body,
|
||||
#modalAgendarDomicilio.dom-flotante #labdom-form-panel,
|
||||
#modalAgendarDomicilio.dom-flotante #labdom-footer,
|
||||
#modalAgendarDomicilio.dom-flotante #labdom-ok-panel { display: none !important; }
|
||||
#modalAgendarDomicilio.dom-flotante .modal-content {
|
||||
box-shadow: 0 8px 32px rgba(0,0,0,.28);
|
||||
border-radius: 12px;
|
||||
}
|
||||
#modalAgendarDomicilio.dom-flotante .modal-header {
|
||||
cursor: move;
|
||||
border-radius: 12px;
|
||||
user-select: none;
|
||||
}
|
||||
/* Botón restaurar dentro del header minimizado */
|
||||
.labdom-restore-hint {
|
||||
font-size:.72rem; opacity:.8; white-space:nowrap;
|
||||
}
|
||||
/* Botón minimizar */
|
||||
#labdom-btn-minimizar {
|
||||
background: rgba(255,255,255,.18);
|
||||
border: 1px solid rgba(255,255,255,.35);
|
||||
color: #fff;
|
||||
border-radius: 6px;
|
||||
padding: 2px 8px;
|
||||
font-size: .8rem;
|
||||
line-height: 1.4;
|
||||
cursor: pointer;
|
||||
transition: background .15s;
|
||||
}
|
||||
#labdom-btn-minimizar:hover { background: rgba(255,255,255,.32); }
|
||||
</style>
|
||||
|
||||
<div class="modal fade" id="modalAgendarDomicilio" tabindex="-1">
|
||||
@@ -6442,7 +6492,13 @@ if (!isset($_SESSION['user_id'])) {
|
||||
<h5 class="modal-title mb-0"><i class="fas fa-house-medical me-2"></i>Agendar Domicilio</h5>
|
||||
<small id="labdom-header-pac" class="opacity-75"></small>
|
||||
</div>
|
||||
<button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<button id="labdom-btn-minimizar" title="Minimizar — sigue agendando mientras copias datos"
|
||||
onclick="labDomicilio.minimizar()">
|
||||
<i class="fas fa-window-minimize"></i> Minimizar
|
||||
</button>
|
||||
<button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── PANEL ÉXITO (se muestra al guardar) ── -->
|
||||
@@ -6816,7 +6872,7 @@ const labDomicilio = (() => {
|
||||
$('labdom-img-prev').style.display = 'none';
|
||||
}
|
||||
|
||||
if (!_bsModal) _bsModal = new bootstrap.Modal('#modalAgendarDomicilio');
|
||||
if (!_bsModal) _bsModal = new bootstrap.Modal('#modalAgendarDomicilio', { backdrop: true, keyboard: true });
|
||||
_bsModal.show();
|
||||
|
||||
// Pre-cargar contacto de la conversación de forma silenciosa
|
||||
@@ -7225,6 +7281,95 @@ const labDomicilio = (() => {
|
||||
return el ? el.textContent.trim() : '';
|
||||
},
|
||||
|
||||
/* ─── Minimizar / restaurar modal ───
|
||||
* Al minimizar: oculta backdrop, convierte el modal en flotante
|
||||
* sin perder ningún dato del formulario.
|
||||
* Al restaurar: vuelve al estado normal de Bootstrap. */
|
||||
minimizar() {
|
||||
const modalEl = document.getElementById('modalAgendarDomicilio');
|
||||
const isMin = !modalEl.classList.contains('dom-flotante');
|
||||
|
||||
if (isMin) {
|
||||
/* — Pasar a modo flotante — */
|
||||
// 1. Quitar backdrop
|
||||
document.querySelectorAll('.modal-backdrop').forEach(b => b.remove());
|
||||
document.body.classList.remove('modal-open');
|
||||
document.body.style.overflow = '';
|
||||
document.body.style.paddingRight = '';
|
||||
|
||||
// 2. Desvincular de Bootstrap para posicionarlo libre
|
||||
modalEl.removeAttribute('aria-modal');
|
||||
modalEl.removeAttribute('role');
|
||||
// Mantener visible pero fuera del flujo Bootstrap
|
||||
modalEl.style.display = 'block';
|
||||
modalEl.classList.add('dom-flotante');
|
||||
|
||||
// 3. Título del botón
|
||||
const icon = document.querySelector('#labdom-btn-minimizar i');
|
||||
if (icon) { icon.className = 'fas fa-window-restore'; }
|
||||
const btn = document.getElementById('labdom-btn-minimizar');
|
||||
if (btn) btn.title = 'Restaurar modal';
|
||||
|
||||
// 4. Activar drag
|
||||
labDomicilio._initDrag();
|
||||
|
||||
} else {
|
||||
/* — Restaurar modo normal — */
|
||||
modalEl.classList.remove('dom-flotante');
|
||||
// Limpiar posición manual que puso _initDrag
|
||||
const dialog = modalEl.querySelector('.modal-dialog');
|
||||
if (dialog) {
|
||||
dialog.style.position = '';
|
||||
dialog.style.left = '';
|
||||
dialog.style.top = '';
|
||||
dialog.style.margin = '';
|
||||
}
|
||||
|
||||
// Re-mostrar con Bootstrap para restaurar backdrop
|
||||
if (_bsModal) {
|
||||
// Bootstrap detecta el estado por aria-modal
|
||||
modalEl.setAttribute('aria-modal', 'true');
|
||||
modalEl.setAttribute('role', 'dialog');
|
||||
_bsModal.show();
|
||||
}
|
||||
|
||||
const icon = document.querySelector('#labdom-btn-minimizar i');
|
||||
if (icon) { icon.className = 'fas fa-window-minimize'; }
|
||||
const btn = document.getElementById('labdom-btn-minimizar');
|
||||
if (btn) btn.title = 'Minimizar — sigue agendando mientras copias datos';
|
||||
}
|
||||
},
|
||||
|
||||
/* ─── Drag de la ventana flotante ─── */
|
||||
_initDrag() {
|
||||
const dialog = document.querySelector('#modalAgendarDomicilio .modal-dialog');
|
||||
const handle = document.querySelector('#modalAgendarDomicilio .modal-header');
|
||||
if (!handle || handle._dragInit) return;
|
||||
handle._dragInit = true;
|
||||
let sx, sy, sl, st;
|
||||
handle.addEventListener('mousedown', ev => {
|
||||
if (ev.target.closest('button')) return;
|
||||
const r = dialog.getBoundingClientRect();
|
||||
sx = ev.clientX; sy = ev.clientY;
|
||||
sl = r.left; st = r.top;
|
||||
dialog.style.position = 'fixed';
|
||||
dialog.style.margin = '0';
|
||||
dialog.style.left = sl + 'px';
|
||||
dialog.style.top = st + 'px';
|
||||
ev.preventDefault();
|
||||
const move = e => {
|
||||
dialog.style.left = (sl + e.clientX - sx) + 'px';
|
||||
dialog.style.top = (st + e.clientY - sy) + 'px';
|
||||
};
|
||||
const up = () => {
|
||||
document.removeEventListener('mousemove', move);
|
||||
document.removeEventListener('mouseup', up);
|
||||
};
|
||||
document.addEventListener('mousemove', move);
|
||||
document.addEventListener('mouseup', up);
|
||||
});
|
||||
},
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user