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,'
')}

`; } 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 `
A
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 ? '' : ''}
`; } /** 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 += `${escapeHtml(a.nombre || a.NOMBRE || '')}`; } }); 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 `
Tu oferta actual

Precio: ${precio}

Entrega: ${tiempo}

Descripción:
${desc}

`; } /** 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}
Mínimo
${fmt(d.min)}
Mediana
${fmt(d.mediana)}
Máximo
${fmt(d.max)}
${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( `` ); } } }); 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 += `
Tu oferta actual
Precio: ${formatCurrency(mine.PRECIO)}
Entrega: ${escapeHtml(mine.TIEMPO_ENTREGA || '')}
Descripción:
${mine.DESCRIPCION.replace(/\n/g,'
')}
${renderAdjuntosChips(mine.ADJUNTOS || [], mine.OFERTA_ID)}
`; } else { html += `
¿Querés participar? Enviá tu propuesta para competir.
`; } // --- COMPETENCIA --- html += `
Ofertas de la competencia
`; if (!comps.length) { html += `
✅ ¡Sos el primero en ofertar! Tenés ventaja inicial.
`; } else { comps.forEach((o) => { html += `
A
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 += `
🔒 ¿Querés ver detalles completos y adjuntos nítidos? Activá Membresía Premium.
`; } } $('#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 += `${escapeHtml(a.NOMBRE || '')}`; } }); 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( `` ); } $('#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(`
${file.name}
`); } }); // 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 += `
`; } 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(); }); } })(); });