const MAX_ARCHIVOS_OFERTA = 4;
const usuario_id = $('#uId').val();
// --- NUEVO: flag de edición y helpers ---
let MODO_EDICION = false;
function setModoEdicion(activar) {
MODO_EDICION = !!activar;
// En edición no se cobra conexiones: ocultamos aviso de consumo (ajusta selector si usás otro)
$('#modalOferta .alert-warning').toggle(!activar);
}
// Cargar oferta y abrir modal en modo EDICIÓN
function abrirEdicionOferta(ofertaId) {
const necesidadID = $('#necesidadId').val();
const usuario_id = $('#uId').val();
if (!ofertaId) { mostrarAlertaError('Oferta inválida.'); return; }
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=getMiOfertaAbierta', {
necesidad_id: necesidadID,
usuario_id: usuario_id
}, function (r) {
// Normalizamos SUCCESS/DATA en cualquier casing
const ok = (r && (r.success === true || r.SUCCESS === true));
const data = r?.data || r?.DATA;
if (ok && data) {
// Normalizamos nombres de campos (mayús/minús)
const id = data.oferta_id ?? data.OFERTA_ID;
const precio = data.precio ?? data.PRECIO;
const desc = data.descripcion ?? data.DESCRIPCION;
const tiempo = data.tiempo_entrega?? data.TIEMPO_ENTREGA;
if (!id) { mostrarAlertaError('Respuesta sin OFERTA_ID.'); return; }
$('#oferta_id').val(id);
$('#precioOferta').val(precio);
$('#descripcionOferta').val(desc);
$('#tiempoEntrega').val(tiempo || '');
// Si usás TinyMCE en este campo, también:
if (window.tinymce && tinymce.get('descripcionOferta')) {
tinymce.get('descripcionOferta').setContent(String(desc || ''));
}
archivosSeleccionados = [];
adjuntosEliminados = [];
const adj = (data.adjuntos || data.ADJUNTOS || []);
adj.forEach(a => {
archivosSeleccionados.push({
existing : true,
archivo_id : a.archivo_id ?? a.ARCHIVO_ID,
url : a.url ?? a.URL,
name : a.nombre ?? a.NOMBRE,
type : a.mime ?? a.MIME, // ej: "image" o "application/pdf"
esImagen : (a.es_imagen ?? a.ES_IMAGEN) ? true : false
});
});
actualizarPreview();
setModoEdicion(true); // oculta aviso de consumo
$('#modalOferta').modal('show');
} else {
const msg = r?.message || r?.MESSAGE || 'No se pudo cargar tu oferta.';
mostrarAlertaError(msg);
}
});
}
// Datos del form → objeto (para refrescar UI sin recargar)
function formToOfertaData() {
return {
oferta_id: parseInt($('#oferta_id').val() || '0', 10),
precio: $('#precioOferta').val(),
descripcion: $('#descripcionOferta').val(),
tiempo_entrega: $('#tiempoEntrega').val()
};
}
// Pintar/actualizar la tarjeta “Tu oferta”
function renderMiOfertaCard(data){
return `
Tu oferta
Precio: $${escapeHtml(data.precio)}
Entrega: ${escapeHtml(data.tiempo_entrega || '-')}
Descripción:
${escapeHtml(data.descripcion).replace(/\n/g,' ')}
✏️ Editar oferta
`;
}
function upsertMiOfertaCard(data){
const $cont = $('#miOfertaResumen');
if (!$cont.length) return; // si no agregaste el contenedor, no hacemos nada
if ($('#miOfertaCard').length){
$('#miOfertaPrecio').text(data.precio);
$('#miOfertaTiempo').text(data.tiempo_entrega || '-');
$('#miOfertaDescripcion').html(escapeHtml(data.descripcion).replace(/\n/g,' '));
$('#btnEditarOferta').attr('data-oferta-id', data.oferta_id);
} else {
$cont.html(renderMiOfertaCard(data));
}
}
/** Inserta/actualiza la tarjeta “Tu oferta” y carga adjuntos vía AJAX */
function upsertMiOfertaCard(data){
const $bloque = $('#bloque-mi-oferta');
$bloque.html(plantillaMiOferta(data));
// Ajustar badge de competencia si veníamos sin oferta propia
const $badge = $('#tab-mercado .badge');
if ($badge.length && !window.__yaTeniaOferta) {
const n = Math.max(parseInt($badge.text() || '0', 10) - 1, 0);
$badge.text(n);
window.__yaTeniaOferta = true;
}
// Cargar adjuntos actuales
cargarAdjuntosMiOferta(data.oferta_id);
// Re-bind CTA editar (contenido dinámico)
$(document).off('click', '#btnEditarOferta').on('click', '#btnEditarOferta', function(){
const id = $(this).data('oferta-id');
abrirEdicionOferta(id);
});
}
/** Pide adjuntos de mi oferta y los pinta en #mi-oferta-adjuntos */
function cargarAdjuntosMiOferta(ofertaId){
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=listarAdjuntos', { oferta_id: ofertaId }, function(r){
const ok = r && (r.success === true || r.SUCCESS === true);
const $wrap = $('#mi-oferta-adjuntos');
if (!ok) { $wrap.html('Sin adjuntos.
'); return; }
const d = r.data || r.DATA || {};
$wrap.html(renderAdjuntosChips(d.adjuntos || [], ofertaId));
});
}
function tarjetaCompetidor(o, isPremium){
const precio = formatCurrency(o.precio || o.PRECIO || 0);
const tiempo = escapeHtml(o.tiempo_entrega || o.TIEMPO_ENTREGA || '');
const desc = escapeHtml(o.descripcion || o.DESCRIPCION || '');
const teaser = (isPremium ? desc : (desc.length > 220 ? desc.substring(0,220) + '…' : desc));
const blurCl = (isPremium ? '' : 'ci-blurred');
// Si querés adjuntos de competidores por AJAX, podés extender con otro endpoint.
return `
Vendedor anónimo Verificado
${precio}
${tiempo}
${teaser}
`;
}
// Mostrar FAB si hay oferta propia y estamos en móvil
if (window.matchMedia('(max-width: 576px)').matches && window.hasMyOffer) {
const fab = document.createElement('button');
fab.className = 'btn btn-warning btn-lg shadow-lg ci-fab';
fab.innerHTML = '✏️ Editar oferta';
fab.onclick = () => abrirEdicionOferta(window.miOfertaId);
document.body.appendChild(fab);
}
// CSS simple:
// .ci-fab{ position:fixed; right:16px; bottom:16px; border-radius:999px; }
function renderEmptyCompetencia(container){
container.innerHTML = `
✅ ¡Sos el primero en ofertar! Tenés ventaja inicial.
Te avisamos si aparece competencia.
${!window.hasMyOffer ? '
Enviar oferta ' : ''}
`;
}
/** Chips de adjuntos (usa los URLs que devuelve listarAdjuntos) */
function renderAdjuntosChips(adjuntos, ofertaId) {
if (!adjuntos || !adjuntos.length) return 'Sin adjuntos.
';
let h = '';
adjuntos.forEach(a => {
const fname = a.url || a.URL || a.url_archivo || '';
const mime = (a.mime || a.MIME || '').toLowerCase();
const isPdf = mime.includes('pdf') || fname.toLowerCase().endsWith('.pdf');
const src = `/uploads/ofertas/${ofertaId}/${fname}`;
if (isPdf) {
h += `
PDF `;
} else {
h += `
`;
}
});
h += '
';
return h;
}
/** Plantilla de MI OFERTA (card) */
function plantillaMiOferta(data){
const precio = formatCurrency(data.precio);
const tiempo = escapeHtml(data.tiempo_entrega || '');
const desc = escapeHtml(data.descripcion || '').replace(/\n/g,' ');
return `
Precio: ${precio}
Entrega: ${tiempo}
Descripción: ${desc}
✏️ Editar oferta
`;
}
/** Refresca #contenedorCompetencia con AJAX */
function refrescarCompetencia(){
const necId = $('#necesidadId').val();
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=listarCompetencia', { necesidad_id: necId }, function(r){
const ok = r && (r.success === true || r.SUCCESS === true);
const cont = document.getElementById('contenedorCompetencia');
if (!cont) return;
if (!ok) {
cont.innerHTML = `No fue posible actualizar la competencia.
`;
return;
}
const data = r.data || r.DATA || {};
const items = data.items || data.ITEMS || [];
const isPremium = !!(data.premium || data.PREMIUM);
if (!items.length) {
renderEmptyCompetencia(cont);
} else {
cont.innerHTML = dibujarTarjetasCompetencia(items, isPremium);
// Actualizar badge con cantidad actual de competencia (opcional)
const $badge = $('#tab-mercado .badge');
if ($badge.length) $badge.text(items.length);
}
});
}
/** Dibuja todas las tarjetas de competencia */
function dibujarTarjetasCompetencia(items, isPremium){
if (!items || !items.length) return '';
return `${ items.map(o => tarjetaCompetidor(o, isPremium)).join('') }
`;
}
/* ===== Resumen de mercado ===== */
function renderResumenMercadoHTML(d){
const fmt = n => (n>0 ? formatCurrency(n) : '—');
// Semáforo para tu posición vs mediana
let badge = '';
if (d.miPrecio && d.mediana) {
const diff = Math.round(d.diffPct * 10) / 10; // 1 decimal
let cls = 'bg-secondary';
if (diff <= -5) cls = 'bg-success';
else if (diff < 5) cls = 'bg-info';
else if (diff < 15) cls = 'bg-warning';
else cls = 'bg-danger';
badge = `Tu precio vs mediana: ${diff>0?'+':''}${diff}% `;
}
return `
Ofertas activas
${d.total || 0}
Mediana
${fmt(d.mediana)}
${badge}
`;
}
function refrescarResumenMercado(){
const necId = $('#necesidadId').val();
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=resumenMercado', { necesidad_id: necId }, function(r){
const ok = r && (r.success === true || r.SUCCESS === true);
const $box = $('#resumenMercado');
if (!ok) { $box.html(''); return; }
// Pintar panel
const d = r.data || r.DATA || {};
$box.html( renderResumenMercadoHTML({
total : d.TOTAL || 0,
min : d.MIN || 0,
mediana : d.MEDIANA || 0,
max : d.MAX || 0,
miPrecio: d.MI_PRECIO || 0,
diffPct : d.DIFF_PCT || 0
}) );
// (Opcional) actualizar badge de competencia (total ya excluye tu oferta)
const $badge = $('#tab-mercado .badge');
if ($badge.length) $badge.text( d.TOTAL || 0 );
});
}
/* ================================
* Binds y hooks
* ================================ */
// CTA “Enviar oferta” (en SSR y dinámico)
$(document).on('click', '.js-enviar-oferta, #btnEnviarOferta, #btnEnviarOfertaTab', function (e) {
e.preventDefault();
abrirFlujoEnviarOferta(); // <- misma lógica para todos
});
// Abrir modal en modo EDICIÓN
$(document).off('click', '#btnEditarOferta').on('click', '#btnEditarOferta', function(){
const id = $(this).data('oferta-id');
abrirEdicionOferta(id); // tu función existente
});
// Al mostrar la pestaña Mercado, refrescamos la competencia
$(document).on('shown.bs.tab', '#tab-mercado', function () {
refrescarResumenMercado();
cargarPestaniaMercado();
});
function abrirFlujoEnviarOferta() {
const usuarioID = $('#uId').val();
if (!usuarioID) {
mostrarAlertaInfo("Debes iniciar sesión para enviar una oferta.");
return;
}
$.ajax({
url: '/cfc/ajax/ajax_verificacion.cfc?method=verificarEstadoVendedor',
method: 'POST',
dataType: 'json',
data: { usuario_id: usuarioID }
})
.done(function (response) {
const est = response && response.ESTADO ? response.ESTADO : {};
if (est.IDENTIDAD === 'rechazado') return mostrarModalVerificacion('identidad_rechazada');
if (est.IDENTIDAD === 'pendiente') return mostrarModalVerificacion('identidad_pendiente');
if (est.IDENTIDAD === 'en_revision') return mostrarModalVerificacion('identidad_revision');
if (est.COMERCIAL === 'rechazado') return mostrarModalVerificacion('comercial_rechazada');
if (est.COMERCIAL === 'pendiente') return mostrarModalVerificacion('comercial_pendiente');
if (est.COMERCIAL === 'en_revision') return mostrarModalVerificacion('comercial_revision');
// evitar ofertar a tu propia necesidad
const necesidadUsuarioID = $('#necesidadUsuarioID').val();
if (usuarioID === necesidadUsuarioID) {
mostrarAlertaInfo("No puedes enviar ofertas a tus propias necesidades.");
return;
}
$('#modalOferta').modal('show'); // abrir modal
})
.fail(function (xhr) {
console.error('Error en la verificación del vendedor:', xhr.responseText || xhr.statusText);
mostrarAlertaError("Ocurrió un error al verificar tu cuenta. Intenta nuevamente.");
});
}
// (Opcional) Auto-refresh cada 60s mientras el pane Mercado está visible
// const autoRef = setInterval(() => {
// if ($('#pane-mercado').hasClass('active')) refrescarCompetencia();
// }, 60000);
$(function () {
const miOfertaId = parseInt($('#miOfertaId').val() || '0', 10);
if (miOfertaId > 0) {
// Reemplazar Enviar por Editar
const $btn = $('#btnEnviarOferta');
if ($btn.length) {
$btn.replaceWith(
`✏️ Editar oferta `
);
}
}
});
function redimensionarImagen(file, maxWidth, maxHeight, callback) {
const reader = new FileReader();
reader.onload = function (e) {
const img = new Image();
img.onload = function () {
let width = img.width;
let height = img.height;
if (width > height && width > maxWidth) {
height *= maxWidth / width;
width = maxWidth;
} else if (height > maxHeight) {
width *= maxHeight / height;
height = maxHeight;
}
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob(function (blob) {
const resizedFile = new File([blob], file.name, {
type: "image/jpeg",
lastModified: Date.now()
});
callback(resizedFile);
}, "image/jpeg", 0.85);
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
function mostrarModalVerificacion(estado) {
let titulo = '';
let mensaje = '';
let textoPrincipal = 'Continuar';
let textoSecundario = '';
let accionPrincipal = function () {};
let mostrarSecundario = false;
switch (estado) {
case 'identidad_pendiente':
titulo = '🛡️ Verificación Requerida';
mensaje = 'Para poder enviar ofertas y garantizar la seguridad en la plataforma, primero necesitamos verificar tu identidad. Es un proceso rápido que solo harás una vez.';
textoPrincipal = 'Iniciar Verificación de Identidad';
textoSecundario = 'Cancelar';
mostrarSecundario = true;
accionPrincipal = () => window.location.href = '/dashboard#tab-vericom';
break;
case 'identidad_revision':
titulo = '🕵️ Verificación en Proceso';
mensaje = '¡Gracias por enviar tus documentos! Nuestro equipo está revisando tu verificación de identidad. Este proceso suele tardar unas pocas horas. Te notificaremos por email apenas esté aprobada.';
textoPrincipal = 'Entendido';
accionPrincipal = () => $('#modalVerificacion').modal('hide');
break;
case 'identidad_rechazada':
titulo = '❌ Verificación Rechazada';
mensaje = 'Tu verificación de identidad fue rechazada. Por favor revisá los datos cargados y volvé a intentarlo. Si necesitás ayuda, escribinos por soporte.';
textoPrincipal = 'Reintentar Verificación';
textoSecundario = 'Cancelar';
mostrarSecundario = true;
accionPrincipal = () => window.location.href = '/dashboard#tab-vericom';
break;
case 'comercial_pendiente':
titulo = '📈 Verificación Comercial Requerida';
mensaje = '¡Excelente, tu identidad personal ya fue verificada! El último paso para operar como vendedor es completar tu verificación comercial. Esto aumenta la confianza de los compradores y te habilita para enviar ofertas.';
textoPrincipal = 'Completar Verificación Comercial';
textoSecundario = 'Más tarde';
mostrarSecundario = true;
accionPrincipal = () => window.location.href = '/dashboard#tab-vericom';
break;
case 'comercial_revision':
titulo = '⏳ Verificación Comercial en Proceso';
mensaje = 'Hemos recibido tu información comercial y nuestro equipo la está revisando. Te avisaremos tan pronto como sea aprobada para que puedas comenzar a enviar ofertas.';
textoPrincipal = 'Entendido';
accionPrincipal = () => $('#modalVerificacion').modal('hide');
break;
case 'comercial_rechazada':
titulo = '❌ Verificación Comercial Rechazada';
mensaje = 'Tu constancia fiscal fue rechazada. Verificá que esté vigente y en formato correcto, y volvé a cargarla desde tu panel.';
textoPrincipal = 'Reintentar Verificación Comercial';
textoSecundario = 'Cancelar';
mostrarSecundario = true;
accionPrincipal = () => window.location.href = '/dashboard#tab-vericom';
break;
}
$('#modalVerificacionTitulo').html(titulo);
$('#modalVerificacionMensaje').html(mensaje);
$('#btnPrincipalVerificacion').text(textoPrincipal).off('click').on('click', accionPrincipal);
if (mostrarSecundario) {
$('#btnSecundarioVerificacion').text(textoSecundario).removeClass('d-none').off('click').on('click', () => $('#modalVerificacion').modal('hide'));
} else {
$('#btnSecundarioVerificacion').addClass('d-none');
}
$('#modalVerificacion').modal('show');
}
//Subir archivos de la oferta
let archivosSeleccionados = []; // mezcla de Files nuevos + placeholders existentes
let adjuntosEliminados = []; // ids de adjuntos existentes a borrar
/**
* Refresca el preview de adjuntos trayendo los archivos guardados en servidor
* tras un guardarOferta (crear/editar), sin recargar la página.
*/
function refrescarAdjuntosUI(ofertaId) {
if (!ofertaId) return;
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=listarAdjuntos', { oferta_id: ofertaId }, function(r){
const ok = (r && (r.success === true || r.SUCCESS === true));
const data = r?.data || r?.DATA;
if (!ok || !data) {
console.warn('No se pudieron obtener adjuntos:', r?.message || r?.MESSAGE);
return;
}
// Convertimos respuesta en placeholders
archivosSeleccionados = [];
adjuntosEliminados = [];
(data.adjuntos || data.ADJUNTOS || []).forEach(a => {
archivosSeleccionados.push({
existing : true,
archivo_id : a.archivo_id ?? a.ARCHIVO_ID,
url : a.url ?? a.URL,
name : a.nombre ?? a.NOMBRE,
type : a.mime ?? a.MIME,
esImagen : (a.es_imagen ?? a.ES_IMAGEN) ? true : false
});
});
actualizarPreview();
});
}
$('#archivosOferta').on('change', function (e) {
const nuevosArchivos = Array.from(e.target.files);
// Validar si se excede el máximo permitido
if (archivosSeleccionados.length + nuevosArchivos.length > MAX_ARCHIVOS_OFERTA) {
mostrarAlertaError(`Solo puedes adjuntar hasta ${MAX_ARCHIVOS_OFERTA} archivos por oferta.`);
$(this).val(""); // Limpiar input
return;
}
const maxW = 800;
const maxH = 800;
nuevosArchivos.forEach(file => {
const yaExiste = archivosSeleccionados.find(f => f.name === file.name && f.size === file.size);
if (!yaExiste) {
if (file.type.startsWith('image/')) {
redimensionarImagen(file, maxW, maxH, function (resizedFile) {
archivosSeleccionados.push(resizedFile);
actualizarPreview(); // actualizar preview una vez lista la imagen
});
} else {
archivosSeleccionados.push(file);
actualizarPreview();
}
}
});
$(this).val(""); // Reset del input para permitir volver a elegir el mismo archivo
});
function cargarPestaniaMercado() {
const necesidadID = $('#necesidadId').val();
$.getJSON('/cfc/ajax/ajax_ofertas.cfc?method=panelMercado', { necesidad_id: necesidadID }, function(r){
const ok = r && (r.success === true || r.SUCCESS === true);
if (!ok) { mostrarAlertaError(r?.message || 'No fue posible cargar el mercado.'); return; }
const data = r.data || r.DATA || {};
const mine = data.mine || data.MINE || null;
const comps = data.competencia || data.COMPETENCIA || data.items || data.ITEMS || data.times || data.TIMES || [];
const premium = !!(data.premium || data.PREMIUM);
let html = '';
// --- TU OFERTA ---
if (mine && mine.OFERTA_ID) {
html += `
Precio: ${formatCurrency(mine.PRECIO)}
Entrega: ${escapeHtml(mine.TIEMPO_ENTREGA || '')}
Descripción: ${mine.DESCRIPCION.replace(/\n/g,' ')}
${renderAdjuntosChips(mine.ADJUNTOS || [], mine.OFERTA_ID)}
✏️ Editar oferta
`;
} else {
html += `
¿Querés participar? Enviá tu propuesta para competir.
🚀 Enviar oferta
`;
}
// --- COMPETENCIA ---
html += `Ofertas de la competencia `;
if (!comps.length) {
html += `✅ ¡Sos el primero en ofertar! Tenés ventaja inicial.
`;
} else {
comps.forEach((o) => {
html += `
Vendedor anónimo
Verificado
${formatCurrency(o.PRECIO)}
${escapeHtml(o.TIEMPO_ENTREGA || '')}
${escapeHtml((o.descripcion || o.DESCRIPCION || '').slice(0,220))}...
${renderAdjuntosCompetidor(o.OFERTA_ID, o.ADJUNTOS || [], premium)}
`;
});
if (!premium) {
html += `
`;
}
}
$('#contenedorCompetencia').html(html);
// Eventos
$('#btnEditarOferta').off('click').on('click', function(){
abrirEdicionOferta($(this).data('oferta-id'));
});
// No bindees por id: usá delegado para todos los CTA renderizados dinámicamente
$(document).off('click.mercadoCTA').on('click.mercadoCTA', '.js-enviar-oferta', function(e){
e.preventDefault();
abrirFlujoEnviarOferta(); // tu función que abre el modal + verifica
});
});
}
// Adjuntos del competidor (aplica blur si no es premium)
function renderAdjuntosCompetidor(ofertaId, adjuntos, isPremium) {
const blurCls = isPremium ? '' : 'ci-blurred';
if (!adjuntos || !adjuntos.length) return '';
let h = '';
adjuntos.forEach(a => {
const url = `/uploads/ofertas/${ofertaId}/${a.URL}`;
const isPdf = (a.MINE || '').toLowerCase().includes('pdf') || a.URL.toLowerCase().endsWith('.pdf');
if (isPdf) {
h += `
PDF `;
} else {
h += `
`;
}
});
h += '
';
return h;
}
function actualizarPreview() {
const previewContainer = $('#previewArchivos');
previewContainer.empty();
archivosSeleccionados.forEach((file, index) => {
const col = $('
');
// Helper: detectar imagen aunque venga sin "image/jpeg"
const url = file.url || '';
const name = file.name || '';
const mime = (file.type || '').toLowerCase();
const byExt = /\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(url || name);
const isImg = !!(file.esImagen || mime.startsWith('image') || byExt);
const isPdf = (mime === 'application/pdf' || /\.pdf$/i.test(url || name));
if (file.existing) {
// ---- Placeholder de servidor ----
if (isImg) {
const thumb = $(`
×
${name}
`);
col.append(thumb);
} else if (isPdf) {
const icon = $(`
${name}
`);
col.append(icon);
} else {
// fallback genérico
const icon = $(`
${name}
`);
col.append(icon);
}
previewContainer.append(col);
return;
}
// ---- Archivo NUEVO (File/Blob) ----
if (mime.startsWith('image')) {
const reader = new FileReader();
reader.onload = function (e) {
const thumb = $(`
×
${name}
`);
col.append(thumb);
previewContainer.append(col);
};
reader.readAsDataURL(file);
} else if (isPdf) {
const icon = $(`
${name}
`);
col.append(icon);
previewContainer.append(col);
}
});
// Habilitar/deshabilitar botón "Agregar"
$('#btnAgregarArchivo').prop('disabled', archivosSeleccionados.length >= MAX_ARCHIVOS_OFERTA)
.toggleClass('disabled', archivosSeleccionados.length >= MAX_ARCHIVOS_OFERTA);
// Contador + aviso
const cantidad = archivosSeleccionados.length;
const contador = $('#contadorArchivosOferta');
const lleno = (cantidad >= MAX_ARCHIVOS_OFERTA);
contador.text(`${lleno ? '🔴' : '🟢'} ${cantidad} de ${MAX_ARCHIVOS_OFERTA} archivos`)
.removeClass('text-success text-danger')
.addClass(lleno ? 'text-danger' : 'text-success');
$('#avisoLimiteArchivos').toggleClass('d-none', !lleno);
}
//Soportar zoom
//Zoom: añade este handler para usar la url cuando el ítem es existente:
// Zoom modal
$(document).on('click', '.thumb-zoom', function () {
const index = $(this).data('index');
const f = archivosSeleccionados[index];
if (f && f.existing && f.url) {
$('#zoomImage').attr('src', f.url);
$('#modalZoom').modal('show');
return;
}
// fallback: archivos nuevos
if (f) {
const reader = new FileReader();
reader.onload = function (e) {
$('#zoomImage').attr('src', e.target.result);
$('#modalZoom').modal('show');
};
reader.readAsDataURL(f);
}
});
// Eliminar: guarda los archivo_id a borrar cuando es existente:
$(document).on('click', '.remove-file', function () {
const index = $(this).data('index');
const existing = $(this).data('existing') === 1 || $(this).data('existing') === '1';
const archivoId = $(this).data('archivo-id');
if (existing && archivoId) {
if (!Array.isArray(adjuntosEliminados)) adjuntosEliminados = [];
adjuntosEliminados.push(archivoId);
}
archivosSeleccionados.splice(index, 1);
actualizarPreview();
});
function autoExpandTextarea(textarea) {
textarea.style.height = 'auto';
const minHeight = textarea.scrollHeight; // altura base con contenido actual
textarea.style.height = Math.max(minHeight, 90) + 'px'; // 90px aprox. = 3 líneas
}
// Autoexpand textarea
$('textarea.auto-expand').each(function () {
autoExpandTextarea(this);
}).on('input', function () {
autoExpandTextarea(this);
});
$('#formOferta').off('submit').on('submit', function (e) {
e.preventDefault();
const form = $(this)[0];
const formData = new FormData(form);
// Adjuntar nuevos archivos
archivosSeleccionados.forEach((file) => {
formData.append('archivosOferta[]', file);
});
// Si estás usando borrado de adjuntos existentes:
if (typeof adjuntosEliminados !== 'undefined' && adjuntosEliminados.length > 0) {
formData.set('adjuntos_eliminar', adjuntosEliminados.join(','));
}
// Unificar: 0 => crear ; >0 => editar
const ofertaId = parseInt($('#oferta_id').val() || '0', 10);
formData.set('oferta_id', ofertaId);
$.ajax({
url: '/cfc/ajax/ajax_necesidades.cfc?method=guardarOferta',
method: 'POST',
data: formData,
processData: false,
contentType: false,
dataType: 'json'
})
.done(function (resp) {
if (resp.success === true || resp.SUCCESS === true) {
// 1) ID final
const idFinal = parseInt(resp.oferta_id || ofertaId || 0, 10);
if (idFinal > 0) $('#oferta_id').val(idFinal);
// 2) Refrescar tarjeta visual
const data = formToOfertaData();
data.oferta_id = idFinal;
//upsertMiOfertaCard(data);
cargarPestaniaMercado();
refrescarResumenMercado();
// 👉 3) REFRESCAR ADJUNTOS desde servidor (queden solo "placeholders")
refrescarAdjuntosUI(idFinal);
if (resp.NUEVO_SALDO != null) {
actualizarSaldoUI(resp.nuevoSaldo);
}
// 4) CTA y feedback
if (ofertaId === 0 && idFinal > 0) {
const $btnEnviar = $('#btnEnviarOferta');
if ($btnEnviar.length) {
$btnEnviar.replaceWith(
`✏️ Editar oferta `
);
}
$('#modalOfertaEnviada').modal('show');
} else {
$('#modalOferta').modal('hide');
mostrarAlertaExito(resp.message || 'Cambios guardados.');
}
// Limpieza del input file
$('#archivosOferta').val('');
} else {
mostrarAlertaError(resp.message || 'No se pudo procesar la oferta.');
}
})
.fail(function (xhr) {
console.error('Error al enviar:', xhr.responseText || xhr.statusText);
mostrarAlertaError('Error de red o del servidor al procesar la oferta.');
});
});
$('#btnAgregarArchivo').on('click', function () {
$('#archivosOferta').click(); // dispara el input oculto
});
//cargar la vista previa
$('#btnPrevisualizarOferta').on('click', function () {
tinymce.triggerSave(); // Asegurarse de que el contenido del editor se guarde antes de continuar
const titulo = $('#necesidadTitulo').val();
const precio = $('#precioOferta').val();
let descripcion = tinymce.get('descripcionOferta').getContent({ format: 'text' }).trim();
const tiempo = $('#tiempoEntrega').val();
if (!descripcion || !precio || !tiempo) {
mostrarAlertaError('Debes completar la descripción, el precio y el tiempo estimado.');
return;
}
descripcion = $('#descripcionOferta').val().trim();
let html = `
Necesidad: ${titulo}
Precio: $${precio}
Tiempo estimado: ${tiempo}
Descripción: ${descripcion.replace(/\n/g, ' ')}
`;
html += `Archivos adjuntos:
`;
$('#previewBody').html(html);
// Cargar imágenes en paralelo
archivosSeleccionados.forEach((file, i) => {
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = function (e) {
$('#previewAdjuntosEnModal').append(`
`);
};
reader.readAsDataURL(file);
} else if (file.type === 'application/pdf') {
$('#previewAdjuntosEnModal').append(`
`);
}
});
// Verificar si hay archivos después de que termine el render (esperar un poco)
setTimeout(function () {
if ($('#previewAdjuntosEnModal').children().length === 0) {
$('#vistaPreviaAdjuntosTitulo').hide();
} else {
$('#vistaPreviaAdjuntosTitulo').show();
}
}, 300);
// Ocultar modal de edición y mostrar previsualización
$('#modalOferta').modal('hide');
setTimeout(() => {
$('#modalPreviewOferta').modal('show');
}, 300); // pequeña espera para evitar conflicto visual
});
//Confirmar desde preview
$('#btnConfirmarDesdePreview').on('click', function () {
$('#modalPreviewOferta').modal('hide');
tinymce.triggerSave();
$('#formOferta').submit();
});
$('#modalPreviewOferta').on('hidden.bs.modal', function () {
if ($('#formOferta').data('volverAEditar')) {
$('#modalOferta').modal('show');
$('#formOferta').removeData('volverAEditar');
}
});
$('#btnSeguirEditando').on('click', function () {
$('#formOferta').data('volverAEditar', true);
$('#modalPreviewOferta').modal('hide');
});
// Botones de navegación del modal de oferta enviada
$('#btnCrearPublicacion').on('click', function () {
// Ir a crear publicación, pasando ID o info por querystring o sesión
window.location.href = '/crear-necesidad'; // ajustá la lógica
});
$('#btnVerOfertasEnviadas').on('click', function () {
window.location.href = '/mis-negociaciones/enviadas';
});
$('#btnVolverAListado').on('click', function () {
window.location.href = '/necesidades';
});
document.addEventListener('focusin', function (e) {
if (e.target.closest(".tox-tinymce-aux, .tox-silver-sink")) {
e.stopImmediatePropagation();
}
});
$(document).ready(function () {
const necesidadID = $('#necesidadId').val();
if ($('#pane-mercado').hasClass('active')) {
refrescarResumenMercado();
cargarPestaniaMercado();
}
// Cargar preguntas al iniciar
cargarPreguntas();
// Enviar nueva pregunta
$('#btnEnviarPregunta').on('click', function () {
const texto = $('#nuevaPregunta').val().trim();
if (!texto) {
mostrarAlertaError('Debes escribir una pregunta antes de enviarla.');
return;
}
$.ajax({
url: '/cfc/ajax/ajax_necesidades.cfc?method=guardarPregunta',
type: 'POST',
dataType: 'json',
data: {
necesidad_id: necesidadID,
pregunta_texto: texto
},
success: function (r) {
if (r.SUCCESS === true || r.success === true) {
$('#nuevaPregunta').val('');
mostrarAlertaExito('Tu pregunta fue enviada.');
cargarPreguntas();
} else {
mostrarAlertaError(r.MESSAGE || 'Ocurrió un error al enviar la pregunta.');
}
}
});
});
function cargarPreguntas() {
const necesidadID = $('#necesidadId').val();
$.getJSON('/cfc/ajax/ajax_necesidades.cfc?method=listarPreguntas', { necesidad_id: necesidadID }, function (data) {
const contenedor = $('#bloquePreguntas');
contenedor.empty();
if (data.PREGUNTAS.length === 0) {
contenedor.append('Aún no hay preguntas.
');
return;
}
data.PREGUNTAS.forEach(function (p) {
// Formatear fechas
const fechaPregunta = formatearFechaBonita(p.FECHA_PREGUNTA);
let html = `
${p.PREGUNTA_TEXTO}
Preguntado el ${fechaPregunta}
`;
if (p.RESPUESTA_TEXTO) {
const fechaRespuestaFormateada = formatearFechaBonita(p.FECHA_RESPUESTA);
html += `
${p.RESPUESTA_TEXTO}
Respondido el ${fechaRespuestaFormateada}
`;
} else if (data.ES_COMPRADOR) {
html += `
Responder
`;
}
html += `
`;
contenedor.append(html);
});
});
}
// Mostrar modal
$(document).on('click', '.responder-btn', function () {
const id = $(this).data('id');
const preguntaTexto = $(`#pregunta_${id}`).text().trim();
$('#pregunta_id_responder').val(id);
$('#respuesta_texto').val('');
$('#pregunta_texto').text(preguntaTexto); // texto seguro desde DOM
$('#modalResponder').modal('show');
});
// Enviar respuesta
$('#btnEnviarRespuesta').on('click', function () {
const respuesta = $('#respuesta_texto').val().trim();
const preguntaID = $('#pregunta_id_responder').val();
if (!respuesta) {
mostrarAlertaError('Debes escribir una respuesta.');
return;
}
$.post('/cfc/ajax/ajax_necesidades.cfc?method=responderPregunta', {
pregunta_id: preguntaID,
respuesta_texto: respuesta
}, function (data) {
if (data.SUCCESS === true || data.success === true) {
$('#modalResponder').modal('hide');
cargarPreguntas();
} else {
mostrarAlertaError('Error al responder la pregunta.');
}
}, 'json');
});
// Recharge handler for all "free recharge" buttons across the UI
$(document).on('click', '.btn-recarga-gratis', function (e) {
e.preventDefault();
const $btn = $(this);
if ($btn.prop('disabled') || $btn.data('busy')) return;
// Visual feedback
const originalHTML = $btn.html();
$btn.data('busy', true).prop('disabled', true)
.html(' Recargando…');
// Optionally, disable all recharge buttons to avoid double requests
const $allRechargeBtns = $('.btn-recarga-gratis').prop('disabled', true);
// Infer user ID & needed connections from DOM
const usuarioId = $('#uId').val() || $('#usuario_id').val();
const conexionesNecesarias = parseInt($('input[name="conexiones"]').val() || '0', 10) || 0;
$.ajax({
url: '/cfc/ajax/ajax_conexiones.cfc?method=recargaBetaGratis',
method: 'POST',
dataType: 'json',
data: { usuario_id: usuarioId }, // server should read session as source-of-truth
})
.done(function (resp) {
if (resp && (resp.success === true || resp.SUCCESS === true)) {
// 1) Refrescar saldo en UI
if (typeof resp.nuevoSaldo !== 'undefined') {
$('#conexiones_disponibles').val(resp.nuevoSaldo);
$('[data-badge="conexiones"]').text(resp.nuevoSaldo); // si usás algún badge
}
mostrarAlertaExito(resp.message || '¡Listo! Se acreditaron 10 conexiones.');
// 2) Si ya alcanza para ofertar, limpiar mensajes y habilitar acciones
const conexionesNecesarias = parseInt($('input[name="conexiones"]').val() || '0', 10) || 0;
if (resp.nuevoSaldo >= conexionesNecesarias) {
const $modal = $('#modalOferta');
// Ocultar/retirar avisos de saldo insuficiente dentro del modal
$modal.find('.alert-danger').filter(function () {
return $(this).text().toLowerCase().includes('no tienes suficientes conexiones');
}).slideUp(200, function(){ $(this).remove(); });
$modal.find('.alert-info').filter(function () {
return $(this).text().toLowerCase().includes('conexiones gratis') ||
$(this).text().toLowerCase().includes('¿sin conexiones?') ||
$(this).text().toLowerCase().includes('necesitás más conexiones');
}).slideUp(200, function(){ $(this).remove(); });
// Quitar todos los botones de recarga gratis en el modal (banner y footer)
$modal.find('.btn-recarga-gratis').each(function(){
const $wrap = $(this).closest('.alert-info, .text-center, .modal-footer');
$(this).remove();
// si el contenedor quedó vacío, lo removemos también
if ($wrap.length && $.trim($wrap.text()) === '') $wrap.remove();
});
// Habilitar "Previsualizar"
const $btnPrev = $modal.find('#btnPrevisualizarOferta');
$btnPrev.prop('disabled', false).removeAttr('disabled')
.removeClass('disabled');
// (Opcional) feedback visual en el footer
// $btnPrev.after('Ya podés previsualizar ');
}
} else {
mostrarAlertaError((resp && (resp.message || resp.MESSAGE)) || 'No pudimos recargar. Intenta nuevamente.');
}
})
.fail(function (xhr) {
console.error('Recharge error:', xhr.responseText || xhr.statusText);
mostrarAlertaError('Error al procesar la recarga. Intenta nuevamente.');
})
.always(function () {
$btn.data('busy', false).prop('disabled', false).html(originalHTML);
$allRechargeBtns.prop('disabled', false);
});
});
// Abrir imagen en modalZoom
document.addEventListener('click', function(e){
const img = e.target.closest('img.ci-thumb');
if(!img) return;
const full = img.getAttribute('data-full') || img.src;
const zoomImg = document.getElementById('zoomImage');
if(zoomImg){ zoomImg.src = full; }
const modal = new bootstrap.Modal(document.getElementById('modalZoom'));
modal.show();
});
// Enlazar pestañas con hash ?tab=
(function(){
const params = new URLSearchParams(location.search);
const tab = params.get('tab');
if(tab){
const btn = document.querySelector(`[data-bs-target="#pane-${tab}"]`);
if(btn){ new bootstrap.Tab(btn).show(); }
}
// Al cambiar de pestaña, actualizar URL (sin recargar)
document.querySelectorAll('#tabsNecesidad [data-bs-toggle="tab"]').forEach(btn=>{
btn.addEventListener('shown.bs.tab', function(ev){
const target = ev.target.getAttribute('data-bs-target'); // #pane-xxx
const key = (target || '').replace('#pane-','');
const p = new URLSearchParams(location.search);
p.set('tab', key);
history.replaceState({}, '', `${location.pathname}?${p.toString()}`);
});
});
// Botón de enviar oferta dentro de la pestaña Competencia
const btnTab = document.getElementById('btnEnviarOfertaTab');
if(btnTab){
btnTab.addEventListener('click', ()=> {
const modal = new bootstrap.Modal(document.getElementById('modalOferta'));
modal.show();
});
}
})();
});