Advertisement
oscarviedma

Código JavaScript OV Directorio - OV DIVI

Sep 2nd, 2024 (edited)
967
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 14.55 KB | None | 0 0
  1. <script>
  2. // URL de tu API de Google Sheets
  3. const API_URL = 'https://script.google.com/macros/s/AKfycbySaDGt9msgjKUWtWQhGIuPlA2DyM1QNe_r4JoEXikrjNRrql7guRHk_tBaBT9SY9e5DA/exec';
  4.  
  5. let businesses = [];
  6. const itemsPerPage = 16;
  7. let currentPage = 1;
  8. let currentCategory = 'Todos';
  9.  
  10. // Función para obtener los negocios desde Google Sheets
  11. async function fetchBusinessesFromGoogleSheets() {
  12.     try {
  13.         const response = await fetch(API_URL);
  14.         const data = await response.json();
  15.         return data.map(record => ({
  16.             id: record.ID,
  17.             name: record.Nombre,
  18.             category: record.Categoria,
  19.             description: record.Descripcion,
  20.             fullDescription: record.DescripcionCompleta,
  21.             image: record.ImagenURL,
  22.             website: record.SitioWeb,
  23.             mapUrl: record.MapaURL,
  24.             social: record.RedesSociales,
  25.             googleReviewsLink: record.GoogleReviewsLink || null,
  26.             schedule: record.Horario,
  27.             contact: record.Contacto,  
  28.             dateAdded: new Date(record.FechaAgregado),
  29.             popularity: Number(record.Popularidad)
  30.         }));
  31.     } catch (error) {
  32.         console.error('Error fetching data from Google Sheets:', error);
  33.         return [];
  34.     }
  35. }
  36.  
  37. function removeAccents(str) {
  38.     return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
  39. }
  40.  
  41. function sortBusinesses(businesses, sortBy) {
  42.     switch(sortBy) {
  43.         case 'random':
  44.             return businesses.sort(() => Math.random() - 0.5);
  45.         case 'az':
  46.             return businesses.sort((a, b) => a.name.localeCompare(b.name));
  47.         case 'za':
  48.             return businesses.sort((a, b) => b.name.localeCompare(a.name));
  49.         case 'recent':
  50.             return businesses.sort((a, b) => b.dateAdded - a.dateAdded);
  51.         case 'popular':
  52.             return businesses.sort((a, b) => b.popularity - a.popularity);
  53.         default:
  54.             return businesses;
  55.     }
  56. }
  57.  
  58. function renderBusinesses(page, category, searchTerm = '', sortBy = 'random') {
  59.     const grid = document.getElementById('business-grid');
  60.     grid.innerHTML = '';
  61.  
  62.     if (businesses.length === 0) {
  63.         grid.innerHTML = '<div class="no-results-container"><div class="no-results">No hay negocios que mostrar.</div></div>';
  64.         return;
  65.     }
  66.  
  67.     const normalizedSearchTerm = removeAccents(searchTerm.toLowerCase());
  68.  
  69.     let filteredBusinesses = businesses.filter(business =>
  70.         (category === 'Todos' || business.category.includes(category)) &&
  71.        (removeAccents(business.name.toLowerCase()).includes(normalizedSearchTerm) ||
  72.        business.category.some(cat => removeAccents(cat.toLowerCase()).includes(normalizedSearchTerm)) ||
  73.        removeAccents(business.description.toLowerCase()).includes(normalizedSearchTerm) ||
  74.        removeAccents(business.fullDescription.toLowerCase()).includes(normalizedSearchTerm))
  75.    );
  76.  
  77.     filteredBusinesses = sortBusinesses(filteredBusinesses, sortBy);
  78.  
  79.     if (filteredBusinesses.length === 0) {
  80.         grid.innerHTML = '<div class="no-results-container"><div class="no-results">No se encontraron resultados. Intenta buscar con otra palabra clave.</div></div>';
  81.         return;
  82.     }
  83.  
  84.     const start = (page - 1) * itemsPerPage;
  85.     const end = start + itemsPerPage;
  86.     const paginatedBusinesses = filteredBusinesses.slice(start, end);
  87.  
  88.     paginatedBusinesses.forEach(business => {
  89.         const card = document.createElement('div');
  90.         card.className = 'business-card';
  91.         card.innerHTML = `
  92.             <div class="category-label">${business.category.join(', ')}</div>
  93.             <img src="${business.image}" alt="${business.name}">
  94.             <div class="card-content">
  95.                 <h3>${business.name}</h3>
  96.                 <p>${business.description}</p>
  97.             </div>
  98.         `;
  99.         card.onclick = () => showModal(business);
  100.         grid.appendChild(card);
  101.     });
  102.  
  103.     renderPagination(filteredBusinesses.length);
  104.     updateActivePaginationButton(page);
  105. }
  106.  
  107. function updateActivePaginationButton(page) {
  108.     document.querySelectorAll('.pagination-button').forEach(btn => {
  109.         btn.classList.remove('active');
  110.         if (parseInt(btn.textContent) === page) {
  111.             btn.classList.add('active');
  112.         }
  113.     });
  114. }
  115.  
  116. function renderSortOptions() {
  117.     const sortContainer = document.createElement('div');
  118.     sortContainer.className = 'sort-options';
  119.     sortContainer.innerHTML = `
  120.         <label for="sort-select">Ordenar por:</label>
  121.         <select id="sort-select">
  122.             <option value="random">Aleatorio</option>
  123.             <option value="az">A-Z</option>
  124.             <option value="za">Z-A</option>
  125.             <option value="recent">Más recientes</option>
  126.             <option value="popular">Más populares</option>
  127.         </select>
  128.     `;
  129.     document.querySelector('.ov-container').insertBefore(sortContainer, document.getElementById('business-grid'));
  130.  
  131.     document.getElementById('sort-select').addEventListener('change', function(e) {
  132.         currentPage = 1;
  133.         renderBusinesses(currentPage, currentCategory, document.getElementById('search').value, e.target.value);
  134.     });
  135. }
  136.  
  137. function scrollToTop() {
  138.     const container = document.querySelector('.ov-container');
  139.     container.scrollIntoView({ behavior: 'smooth', block: 'start' });
  140. }
  141.  
  142. function renderPagination(totalItems) {
  143.     const paginationContainer = document.getElementById('pagination');
  144.     paginationContainer.innerHTML = '';
  145.  
  146.     const totalPages = Math.ceil(totalItems / itemsPerPage);
  147.  
  148.     for (let i = 1; i <= totalPages; i++) {
  149.        const button = document.createElement('button');
  150.        button.textContent = i;
  151.        button.classList.add('pagination-button');
  152.        if (i === currentPage) {
  153.            button.classList.add('active');
  154.        }
  155.        button.onclick = () => {
  156.             currentPage = i;
  157.             renderBusinesses(currentPage, currentCategory);
  158.             updateActivePaginationButton(currentPage);
  159.             scrollToTop();
  160.         };
  161.         paginationContainer.appendChild(button);
  162.     }
  163. }
  164.  
  165. function renderCategories() {
  166.     const categoriesContainer = document.getElementById('categories');
  167.     categoriesContainer.innerHTML = '';
  168.  
  169.     let categories = ['Todos'];
  170.     businesses.forEach(business => {
  171.         business.category.forEach(cat => {
  172.             if (!categories.includes(cat)) {
  173.                 categories.push(cat);
  174.             }
  175.         });
  176.     });
  177.    
  178.     categories = ['Todos', ...categories.filter(c => c !== 'Todos').sort((a, b) => a.localeCompare(b))];
  179.  
  180.     categories.forEach(category => {
  181.         const tab = document.createElement('button');
  182.         tab.className = 'category-tab';
  183.         tab.textContent = category;
  184.         tab.onclick = () => {
  185.             currentCategory = category;
  186.             currentPage = 1;
  187.             renderBusinesses(currentPage, currentCategory);
  188.             document.querySelectorAll('.category-tab').forEach(t => t.classList.remove('active'));
  189.             tab.classList.add('active');
  190.         };
  191.         categoriesContainer.appendChild(tab);
  192.     });
  193.  
  194.     document.querySelector('.category-tab').classList.add('active');
  195. }
  196.  
  197. function renderSocialMediaIcons(socialMedia) {
  198.     const iconMap = {
  199.         facebook: 'fab fa-facebook',
  200.         instagram: 'fab fa-instagram',
  201.         twitter: 'fab fa-twitter',
  202.         youtube: 'fab fa-youtube',
  203.         linkedin: 'fab fa-linkedin',
  204.         pinterest: 'fab fa-pinterest',
  205.         tiktok: 'fab fa-tiktok',
  206.         delivery: 'fa-solid fa-truck-fast',
  207.         whatsapp: 'fab fa-whatsapp'  
  208.     };
  209.  
  210.     if (!socialMedia || typeof socialMedia !== 'object' || Object.keys(socialMedia).length === 0) {
  211.         return '';
  212.     }
  213.  
  214.     return Object.entries(socialMedia).map(([platform, url]) => {
  215.         const iconClass = iconMap[platform.toLowerCase()] || 'fas fa-link';
  216.         return `<a href="${url}" target="_blank" title="${platform}"><i class="${iconClass}"></i></a>`;
  217.     }).join('');
  218. }
  219.  
  220. function renderContactInfo(contact) {
  221.     const iconMap = {
  222.         telefono: 'fas fa-phone',
  223.         whatsapp: 'fab fa-whatsapp',
  224.         direccion: 'fas fa-map-marker-alt',
  225.         correo: 'fas fa-envelope'
  226.     };
  227.  
  228.     if (!contact || (typeof contact === 'object' && Object.keys(contact).length === 0)) {
  229.        return ''; // Retorna una cadena vacía si no hay datos de contacto
  230.     }
  231.  
  232.     if (typeof contact === 'object' && contact !== null) {
  233.        contact = Object.entries(contact)
  234.            .map(([key, value]) => `${key}:${value}`)
  235.            .join('; ');
  236.     }
  237.  
  238.     if (typeof contact !== 'string' || contact.trim() === '') {
  239.         return ''; // Retorna una cadena vacía si el contacto no es una cadena válida o está vacío
  240.     }
  241.  
  242.     const contactItems = contact.split('; ');
  243.     return contactItems.map(item => {
  244.         const [type, value] = item.split(':');
  245.         const iconClass = iconMap[type] || 'fas fa-address-book';
  246.         let href, title;
  247.  
  248.         switch(type) {
  249.             case 'telefono':
  250.                 href = `tel:${value}`;
  251.                 title = 'Llamar';
  252.                 break;
  253.             case 'whatsapp':
  254.                 href = `https://wa.me/${value.replace(/[^0-9]/g, '')}`;
  255.                 title = 'Enviar mensaje de WhatsApp';
  256.                 break;
  257.             case 'direccion':
  258.                 href = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(value)}`;
  259.                 title = 'Ver en Google Maps';
  260.                 break;
  261.             case 'correo':
  262.                 href = `mailto:${value}`;
  263.                 title = 'Enviar correo electrónico';
  264.                 break;
  265.             default:
  266.                 href = '#';
  267.                 title = type;
  268.         }
  269.  
  270.         return `<a href="${href}" target="_blank" title="${title}"><i class="${iconClass}"></i> ${value}</a>`;
  271.     }).join('<br>');
  272. }
  273.  
  274. function adjustHeaderZIndex(zIndex) {
  275.     const diviHeaders = [
  276.         document.querySelector('header .et_builder_inner_content'),
  277.         document.getElementById('main-header')
  278.     ];
  279.  
  280.     diviHeaders.forEach(header => {
  281.         if (header) {
  282.             header.style.zIndex = zIndex;
  283.         }
  284.     });
  285. }
  286.  
  287. function showModal(business) {
  288.     const modal = document.getElementById('businessModal');
  289.     const modalContent = document.getElementById('modalContent');
  290.     const contactInfo = renderContactInfo(business.contact);
  291.    
  292.     modalContent.innerHTML = `
  293.         <img src="${business.image}" alt="${business.name}" class="modal-image">
  294.         <h2 class="modal-title">${business.name}</h2>
  295.         <p class="modal-category">Categoría > ${business.category.join(', ')}</p>
  296.         ${business.googleReviewsLink ? `
  297.         <div class="google-reviews">
  298.             <a href="${business.googleReviewsLink}" target="_blank" title="Ver reseñas en Google">
  299.                 <img src="https://demos.ovdivi.com/wp-content/uploads/2024/08/google-reviews.png" alt="Google Reviews" class="google-reviews-icon">
  300.             </a>
  301.         </div>
  302.         ` : ''}
  303.         <p class="modal-description">${business.fullDescription}</p>
  304.         <div class="modal-links">
  305.             ${business.website ? `<a href="${business.website}" target="_blank" title="Visitar sitio web"><i class="fas fa-globe"></i></a>` : ''}
  306.             ${business.mapUrl ? `<a href="${business.mapUrl}" target="_blank" title="Ver en mapa"><i class="fas fa-map-marker-alt"></i></a>` : ''}
  307.             ${renderSocialMediaIcons(business.social)}
  308.         </div>
  309.         ${business.schedule ? `
  310.         <div class="modal-schedule">
  311.             <h3><i class="far fa-clock"></i> Horario</h3>
  312.             <p>${business.schedule}</p>
  313.         </div>
  314.         ` : ''}
  315.         ${contactInfo ? `
  316.         <div class="modal-contact">
  317.             <h3><i class="fas fa-address-book"></i> Contacto</h3>
  318.             ${contactInfo}
  319.         </div>
  320.         ` : ''}
  321.     `;
  322.     modal.style.display = 'block';
  323.  
  324.     adjustHeaderZIndex('0');
  325. }
  326.  
  327. document.querySelector('.close').onclick = function() {
  328.     document.getElementById('businessModal').style.display = 'none';
  329.  
  330.     adjustHeaderZIndex('0');
  331. }
  332.  
  333. window.onclick = function(event) {
  334.     if (event.target == document.getElementById('businessModal')) {
  335.         document.getElementById('businessModal').style.display = 'none';
  336.  
  337.         adjustHeaderZIndex('0');
  338.     }
  339. }
  340.  
  341. document.addEventListener('keydown', function(event) {
  342.     if (event.key === "Escape") {
  343.         document.getElementById('businessModal').style.display = 'none';
  344.  
  345.         adjustHeaderZIndex('0');
  346.     }
  347. });
  348.  
  349. document.getElementById('search').addEventListener('input', function(e) {
  350.     const searchTerm = e.target.value;
  351.     currentPage = 1;
  352.     renderBusinesses(currentPage, currentCategory, searchTerm);
  353. });
  354.  
  355. // Función para mostrar y ocultar el precargador
  356. function showLoader() {
  357.     document.getElementById('loader').style.display = 'flex';
  358. }
  359.  
  360. function hideLoader() {
  361.     document.getElementById('loader').style.display = 'none';
  362. }
  363.  
  364. document.addEventListener('DOMContentLoaded', function () {
  365.     const searchInput = document.getElementById('search');
  366.     const clearIcon = document.getElementById('clear-icon');
  367.  
  368.     searchInput.addEventListener('input', function () {
  369.         clearIcon.style.display = this.value ? 'block' : 'none';
  370.         currentPage = 1;
  371.         renderBusinesses(currentPage, currentCategory, this.value);
  372.     });
  373.  
  374.     clearIcon.addEventListener('click', function () {
  375.         searchInput.value = '';
  376.         clearIcon.style.display = 'none';
  377.         searchInput.focus();
  378.         renderBusinesses(currentPage, currentCategory, '');
  379.     });
  380.  
  381.     searchInput.addEventListener('keydown', function(event) {
  382.         if (event.key === "Escape") {
  383.             this.value = '';
  384.             clearIcon.style.display = 'none';
  385.             renderBusinesses(currentPage, currentCategory, '');
  386.         }
  387.     });
  388. });
  389.  
  390. async function initializeDirectory() {
  391.     showLoader();
  392.     businesses = await fetchBusinessesFromGoogleSheets();
  393.     hideLoader();
  394.     if (businesses.length > 0) {
  395.         renderCategories();
  396.         renderSortOptions();
  397.         renderBusinesses(currentPage, currentCategory, '', 'random');
  398.         document.getElementById('sort-select').value = 'random';
  399.     } else {
  400.         document.getElementById('business-grid').innerHTML = '<div class="no-results">No hay negocios que mostrar.</div>';
  401.     }
  402. }
  403.  
  404. // Llamar a la función de inicialización cuando se carga la página
  405. document.addEventListener('DOMContentLoaded', initializeDirectory);
  406. </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement