Files
TenerifeProp/public/js/admin/modals/FAQModal.js
APAW Agent Sync 8c1b897b9d feat(admin): replace prompt() with Bootstrap modals for CRUD operations
Replace browser prompt()-based editing with proper Bootstrap 5 modal
dialogs for testimonials, services, FAQs, and leads. This provides
better UX with form validation, structured input fields, and i18n
support (ES/RU) instead of raw prompt dialogs.

- Add testimonialModal, serviceModal, faqModal, leadModal to admin.html
- Add show*/save* methods in admin.js for each entity type
- Wire leads.html 'Add lead' button to leadModal
- Add modal JS modules (FAQModal, LeadModal, ServiceModal)
- Add unit and e2e tests for modals and API client
2026-05-16 00:43:04 +01:00

116 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export class FAQModal {
constructor(app) {
this.app = app
this.id = 'faqModal'
this.element = null
this.bsModal = null
this._editId = null
}
open(faq = null) {
if (!this.element) this._build()
this._editId = faq ? faq.id : null
const title = this.element.querySelector('.modal-title')
const inputs = this.element.querySelectorAll('input[name], textarea[name], select[name]')
if (faq) {
title.innerHTML = '<i class="bi bi-pencil me-2"></i>Editar pregunta'
inputs.forEach(i => {
const key = i.getAttribute('name')
if (faq[key] !== undefined) i.value = faq[key]
if (i.type === 'checkbox') i.checked = faq[key] !== false
})
} else {
title.innerHTML = '<i class="bi bi-question-circle me-2"></i>Añadir pregunta'
inputs.forEach(i => { i.value = ''; if (i.type === 'checkbox') i.checked = true })
this.element.querySelector('select[name="category"]').value = 'general'
this.element.querySelector('input[name="order_num"]').value = ''
}
this.bsModal = new bootstrap.Modal(this.element)
this.bsModal.show()
}
close() {
if (this.bsModal) this.bsModal.hide()
}
async save() {
const data = this._collect()
if (!data.question_es || !data.question_es.trim()) {
this.app.showNotification('La pregunta es obligatoria', 'error')
return
}
if (!data.answer_es || !data.answer_es.trim()) {
this.app.showNotification('La respuesta es obligatoria', 'error')
return
}
const res = this._editId
? await API.updateFAQ(this._editId, data)
: await API.createFAQ(data)
if (res.success) {
this.close()
this.app.showNotification(this._editId ? 'FAQ actualizado' : 'FAQ creado', 'success')
this.app.refreshSection('faq')
} else {
this.app.showNotification(res.error || 'Error al guardar', 'error')
}
}
_collect() {
const d = {}
this.element.querySelectorAll('input[name], textarea[name], select[name]').forEach(i => {
const k = i.getAttribute('name')
d[k] = i.type === 'checkbox' ? i.checked : i.value
})
d.order_num = parseInt(d.order_num) || 0
d.is_active = d.is_active !== undefined ? d.is_active : true
return d
}
_build() {
const el = document.createElement('div')
el.id = this.id
el.className = 'modal fade'
el.innerHTML = `
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-question-circle me-2"></i>Añadir pregunta</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3"><label class="form-label">Pregunta (ES)</label>
<input type="text" class="form-control" name="question_es" placeholder="¿Puedo comprar terreno...?"></div>
<div class="mb-3"><label class="form-label">Pregunta (RU)</label>
<input type="text" class="form-control" name="question_ru" placeholder="Могу ли я купить землю...?"></div>
<div class="mb-3"><label class="form-label">Respuesta (ES)</label>
<textarea class="form-control" rows="3" name="answer_es" placeholder="Respuesta detallada..."></textarea></div>
<div class="mb-3"><label class="form-label">Respuesta (RU)</label>
<textarea class="form-control" rows="3" name="answer_ru" placeholder="Подробный ответ..."></textarea></div>
<div class="mb-3"><label class="form-label">Categoría</label>
<select class="form-select" name="category">
<option value="general">General</option>
<option value="legal">Legal</option>
<option value="buying">Compra</option>
<option value="taxes">Impuestos</option>
<option value="property">Propiedad</option>
</select></div>
<div class="mb-3"><label class="form-label">Orden</label>
<input type="number" class="form-control" name="order_num" placeholder="0"></div>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="is_active" id="faqActive" checked>
<label class="form-check-label" for="faqActive">Activo</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="button" class="btn btn-primary" id="faqSaveBtn">
<i class="bi bi-check-lg me-2"></i>Guardar pregunta</button>
</div>
</div>
</div>`
document.body.appendChild(el)
el.querySelector('#faqSaveBtn').addEventListener('click', () => this.save())
this.element = el
}
}