CursosEmpresasBlogLiveConfPrecios

Location y hash navigation

Clase 8 de 17 • Curso de API REST con Javascript: Ejemplos con APIs reales

Clase anteriorSiguiente clase

Contenido del curso

Presentación del proyecto: PlatziMovies

  • 1
    TheMovieDB: análisis de su API

    TheMovieDB: análisis de su API

    07:15 min
  • 2
    Bocetos en papel y diseño en Figma

    Bocetos en papel y diseño en Figma

    08:05 min

Configuración inicial y maquetación del proyecto

  • 3
    Configuración del entorno de desarrollo

    Configuración del entorno de desarrollo

    16:53 min
  • 4
    Maquetación del proyecto: HTML y CSS

    Maquetación del proyecto: HTML y CSS

    18:34 min

Consumiendo la API

  • 5
    Lista de películas en tendencia

    Lista de películas en tendencia

    16:41 min
  • 6
    Lista de categorías

    Lista de categorías

    10:32 min
  • 7
    Migración a Axios

    Migración a Axios

    07:18 min

Navegación

  • 8
    Location y hash navigation

    Location y hash navigation

    Viendo ahora
  • 9
    Mostrando y ocultando secciones

    Mostrando y ocultando secciones

    22:05 min
  • 10
    Error: carga duplicada de datos

    Error: carga duplicada de datos

    06:30 min

Views

  • 11
    Filtrando películas por categoría

    Filtrando películas por categoría

    21:38 min
  • 12
    Retos: scrollTop y DRY

    Retos: scrollTop y DRY

    11:13 min
  • 13
    Buscador de películas

    Buscador de películas

    11:10 min
  • 14
    Retos: historial de navegación y página de tendencias

    Retos: historial de navegación y página de tendencias

    06:19 min
  • 15
    Endpoint de detalles de una película

    Endpoint de detalles de una película

    18:55 min
  • 16
    Lista de películas recomendadas

    Lista de películas recomendadas

    07:36 min

Próximos pasos

  • 17
    Toma el Curso Profesional de Consumo de API REST con JavaScript

    Toma el Curso Profesional de Consumo de API REST con JavaScript

    02:19 min
  • Tomar el examen del curso
    • Oscar Fuentes Esteves

      Oscar Fuentes Esteves

      student•
      hace 4 años

      Si están usando la extensión live server, deben de tener cuidado de la url que está en el navegador, al cambiar el location.hash manualmente (desde consola) se cambia la ruta en la ventana del navagador también, y si pusieron en consola algo como:

      location.hash="hola"

      y realizan algún cambio en el código, al guardar, la extension live server "refrescará" la ventana del navegador, pero conservando el hash "#hola" en la dirección de la página, lo que puede provocar que creas que tu código está mal, cual en realidad sí está funcionando.

        Juan Castro

        Juan Castro

        teacher•
        hace 4 años

        Ufff, no se me había ocurrido. Muy buen ojo ahí.

        Christian Velázquez

        Christian Velázquez

        student•
        hace 4 años

        Gracias.

      Julian Franco

      Julian Franco

      student•
      hace 4 años

      El

      false

      según la documentación se conoce como

      useCapture

      Es Opcional

      Si es true, useCapture indica que el usuario desea iniciar la captura. Después de iniciar la captura, todos los eventos del tipo especificado serán lanzados al listener registrado antes de comenzar a ser controlados por algún EventTarget que esté por debajo en el arbol DOM del documento.

      https://developer.mozilla.org/es/docs/Web/API/EventTarget/addEventListener

      Adicional en la parte que menciona el:

      load

      Este cuenta con una caracteristica vs el DOMContentLoaded

      El evento load se desencadena cuando se ha cargado toda la página, incluidos todos los recursos dependientes, como hojas de estilo e imágenes. Esto contrasta con DOMContentLoaded, que se activa tan pronto como se ha cargado el DOM de la página, sin esperar a que los recursos terminen de cargarse.

      https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event

      Se que escribi mucho perdón, Pero si declaran la funcion como arrow function de la siguiente manera

      window.addEventListener('DOMContentLoaded', navigatior, false) window.addEventListener('hashchange', navigatior, false) const navigatior = () => { //your code }

      Les va a generar un error interesante 😏

        Juan Castro

        Juan Castro

        teacher•
        hace 4 años

        :clap:

        Raycris Maldonado

        Raycris Maldonado

        student•
        hace 3 años

        Grande amigo, me estaba dando el error por tener el arrow function!

      Jose Castillo

      Jose Castillo

      student•
      hace 3 años

      En videos anteriores hicieron un aporte para optimizar el código y no tener que andar escribiendo a cada rato la linea de .querySelector cuando necesitamos hacer target a un elemento del html.

      En esto me base para ahorrar lineas de código e implementar la misma idea pero con el .createElement que usamos muy seguido.

      const Cr = (elemento) => document.createElement(elemento);

      Utilice Cr por ser las siglas de la palabra "Create", pero pueden nombrarla del modo que quieran, de este modo cada vez que necesitemos crear un elemento por medio de Js Solo tendríamos que escribirlo así:

      const parrafo = Cr('p');
        Paula Inés Cudicio

        Paula Inés Cudicio

        student•
        hace 3 años

        Buenísimo!! no había visto el otro comentario, asique me viene muy bien. Gracias!!!

        Ricardo Alfonso Chavez Vilcapoma

        Ricardo Alfonso Chavez Vilcapoma

        student•
        hace 3 años

        Creo que una vez trataron de hacer lo mismo con console.log y el prof Juan dijo que era un error gravísimo y una mala práctica.

      CRISTIAN DARIO AGUDELO PORRAS

      CRISTIAN DARIO AGUDELO PORRAS

      student•
      hace 3 años

      Esta es mi solucion para evitar anidar tantos if y que ademas me parece mas pulida y facil de leer y entender

      navigator.PNG
        Frandel Corporan Rodríguez

        Frandel Corporan Rodríguez

        student•
        hace 2 años

        Epic👌

        Henry Alexander Velásquez Rosas

        Henry Alexander Velásquez Rosas

        student•
        hace 2 años

        Cool

      Angel Hernandez

      Angel Hernandez

      student•
      hace 4 años

      No es película pero si es documental, por si les interesa: El viaje interminable

      Elber Liebermen

      Elber Liebermen

      student•
      hace 4 años
      • ++Location++ Propiedad del navegador de JS que permite leer la URL en la que nos encontramos actualmente, entre sus propiedades está el hash, puerto, ruta, etc

      • ++onhaschange:++ Permite que ejecutemos cierto código cada vez que cambie nuestro hash

      Orangel Gonzalez

      Orangel Gonzalez

      student•
      hace 4 años

      Codigo de la clase 😁👍🏻

      window.addEventListener("DOMContentLoaded", navigator, false) window.addEventListener("hashchange", navigator, false) function navigator() { if (location.hash.startsWith("#trends")) { trendsPage() } else if (location.hash.startsWith("#search=")) { searchPage() } else if (location.hash.startsWith("#movie=")) { movieDetailsPage() } else if (location.hash.startsWith("#category=")) { categoriesPage() } else { homePage() } } function homePage() { console.log("Home!!") getTrendingMoviesPreview() getCategoriesPreview() } function categoriesPage() { console.log("Categories!!") } function movieDetailsPage() { console.log("Movie!!") } function searchPage() { console.log("Search!!") } function trendsPage() { console.log("TRENDS!!") }
      Axel Enrique Galeed Gutierrez

      Axel Enrique Galeed Gutierrez

      student•
      hace 3 años

      Les comparto una forma que encontré para facilitar la lectura del código. :D

      code.png

      const navegador = () => { console.log({ location }); const HASHES = { '#trends' : () => trendsPage(), '#search=' : () => searchPage(), '#movie=' : () => moviePage(), '#category=' : () => categoryPage(), }; for (const KEY of Object.keys(HASHES)) { if (location.hash.startsWith(KEY)) { HASHES[KEY](); return; } } homePage(); }; const homePage = () => { console.log('HOME'); }; const categoryPage = () => { console.log('CATEGORY 37'); }; const moviePage = () => { console.log('MOVIE'); }; const searchPage = () => { console.log('SEARCH'); }; const trendsPage = () => { console.log('TRENDS'); }; window.addEventListener('load', navegador, false); window.addEventListener('hashchange', navegador, false);
        Juan Castro

        Juan Castro

        teacher•
        hace 3 años

        Fuaaaa me encanta la función de navegador!!!

        Génesis Jarlenis Patiño Ynfante

        Génesis Jarlenis Patiño Ynfante

        student•
        hace 3 años

        Me gustó mucho tu código, Galeed. Lo tomé como ejemplo. Yo en lugar de usar for of, usé for in e iteré directamente sobre la key. Gracias!!

      Cesidio Antonio Di Benedetto Carri

      Cesidio Antonio Di Benedetto Carri

      student•
      hace 4 años

      El tercer parametro se utiliza para determinar si se va a manejar con bubbling cuando es false o capturing cuando es true

        Juan Castro

        Juan Castro

        teacher•
        hace 4 años

        ¡Super! Pero ¿qué significa "bubbling"? :eyes:

        Patricia Julliete Rangel Mujica

        Patricia Julliete Rangel Mujica

        student•
        hace 2 años

        el bubbling es la manera de como se propagan los eventos. Desde el elemento hijo, subiendo hasta todos sus padres...

      Jose Angel Morales Gonzalez

      Jose Angel Morales Gonzalez

      student•
      hace 3 años

      Para quien se pregunte como puede hacer más leíble el nido de if else:

      window.addEventListener('load', handleRouter, false) window.addEventListener('hashchange', handleRouter, false) function navigator(){ const router = { '#trends': () => {console.log('trends')}, '#search=': () => {console.log('search')}, '#movie=': () => {console.log('movies')}, '#category=': () => {console.log('categories')}, '#home': () => {console.log('home')}, } if(true){ return router[window.location.hash] || router['#home'] } } function handleRouter(){ const router = navigator() router() }

      De hecho me lo enseño juan dc en otro curso.

        Jose Angel Morales Gonzalez

        Jose Angel Morales Gonzalez

        student•
        hace 3 años

        El if(true) no es necesario

        Andrés Aguirre

        Andrés Aguirre

        student•
        hace 3 años

        Me parece interesante utilizar llave y valor para hacer el routing de los endpoints, sin embargo, el problema de esto es que si el hash no es igual a la llave, no lo va a identificar por lo cual no ejecutaria el codigo que quisieramos, y como estamos usando queryParameters esto pasaria muy seguido.

        Por ejemplo, si el hash fuera '#search=123', el codigo no estaria tomandolo como '#search' ya que no son iguales, por lo cual devolveria 'router['#home']'

        Lo del los objetos con llave y valor serian más utiles cuando sabemos que los endpoints no van a cambiar ó si vamos a hacer más validaciones para que los valores que recibamos como parametros coincidan con las llaves del router.

      Kevin Daniel Hincapie Lumbaque

      Kevin Daniel Hincapie Lumbaque

      student•
      hace 3 años

      Tal vez no les importe mucho pero estaba leyendo la documentacion del evento 'DOMContentLoaded' y dice que este no espera a que todo cargue: " It doesn't wait for other things like images, subframes, and async scripts to finish loading." No espera la carga de imagenes, subframes(no se que son) y scrips asincronos.

      En cambio el evento "load": " should be used only to detect a fully-loaded page" se usa para detectar paginas completamente cargadas.

      Ademas dice que el objetivo de este evento es el Document pero que se usa sobre el windo para manejar el evento en fase de captura o burbuja: "The original target for this event is the Document that has loaded. You can listen for this event on the Window interface to handle it in the capture or bubbling phases."

      Lo de las fases lo explico bastante bien un compañero en estos comentarios. link info

      Arlen Elian Ruiz Pedraza

      Arlen Elian Ruiz Pedraza

      student•
      hace 4 años

      Dejo la documentación sobre el addEventListener en este link

      Victor Hugo Cruz Carballo

      Victor Hugo Cruz Carballo

      student•
      hace 3 años

      Como mensiono Juan tambien en el evento de carga tambien funciona con 'load' pero hay un pequeño problema, cuando cambias el hash no te va a redirecionar sino que se quedara en la misma pantalla. Asi que tenemos que utilizar en el argumento 'DOMContentLoaded'

      Maurizio Alejandro Iglesias Fernandez

      Maurizio Alejandro Iglesias Fernandez

      student•
      hace 2 años

      Me ando muriendo de risa por el "PUMM" del minuto 16:27 JAJAJJAJAJA

      Por cierto, asi va mi proyecto

      TheMovieApp.PNG
        Juan Castro

        Juan Castro

        teacher•
        hace 2 años

        Love it! Al final del curso comparte tu repo :)

      Luis Torres

      Luis Torres

      student•
      hace 4 años

      Vengo del futuro, ya hice mi deploy del proyecto pero mi sorpresa fue que el location.hash = windows.history.back(); NO funciona en cualquier dispositivo de Apple sin importar el navegador...

      Hice el intento con location.href, pero al hacer el history.back() me manda a undefined.

      He buscado soluciones en Google pero no logro dar con ella.

      ¿Alguien tiene alguna idea?

        Juan Castro

        Juan Castro

        teacher•
        hace 3 años

        Hmmmm... Qué extraño, parece que history.back tiene muy buen soporte en prácticamente todos los navegadores, mira: https://developer.mozilla.org/en-US/docs/Web/API/History/back#browser_compatibility

        Rodrigo Andre Gutierrez

        Rodrigo Andre Gutierrez

        student•
        hace 3 años

        windows.history.back() o window.history.back()? ojo

      Jhojan Alberto Tobón Monsalve

      Jhojan Alberto Tobón Monsalve

      student•
      hace 3 años

      En resumen hay dos formas de propagación en el DOM bubbling=false y capturing=true. Si se quiere que el evento de un elemento dentro de otro elemento con evento se ejecute primero, entonces se utiliza false o no se coloca nada porque por defecto es false, pero si se quiere que el evento del elemento externo se ejecute primero que el elemento con el evento interno se utiliza true.

      Sergio Javier Lopez Olivera

      Sergio Javier Lopez Olivera

      student•
      hace 3 años

      El evento 'hashchange' tiene un valor booleano al final para determinar si la navegación es un fragmento o no. Una navegación por fragmentos ocurre cuando la parte de la URL correspondiente al '#' ha cambiado y el valor booleano será cambiado a 'true' si la navegación es una navegación por fragmentos, y 'false' si no lo es. . Básicamente te permite lograr eventos por cambios en el anchor (#) haciendo el sitio dinámico. Esto podría servir por ejemplo para hacer toggle a las clases de tus etiquetas HTML con JS para así mostrar u ocultar distintas vistas.

      N40 M10

      N40 M10

      student•
      hace 3 años

      Deberían de hacer un curso en donde se separe la teoría de localStorage, location y otros elementos, así quedarían mucho más claros, de paso que ese curso también tenga a las API Web más útiles.

      En este curso, al tener que detenerse al explicar de manera superficial ciertos conceptos, por un lado, provoca que sea más lento y, por otro lado, no se profundiza lo suficiente en ciertos conceptos, pues solo se limitan a que el ejercicio funcione, pero no a que un estudiante pueda aplicar lo que quiera con esos conceptos.

      Generalmente, eso le pasa al grupo que desarrollo este curso en otros mas.

      Henry Alexander Velásquez Rosas

      Henry Alexander Velásquez Rosas

      student•
      hace 2 años

      Auto Save de VSC 🔥

      Si te olvidas con frecuencia de guardar los cambios de tus archivos puedes usar el autoguardado de VSC que lo hará automáticamente por ti.

      Solo ve a File y luego dale check en Auto Save

      Xavier Flores

      Xavier Flores

      student•
      hace 2 años

      de lo aprendido en otro curso lo correcto sería escribirlo así:

      const navigator = () => { console.log({ location }); if (location.hash.startsWith('#trends')) { trendPage(); } else if (location.hash.startsWith('#search=')) { searchPage(); } else if (location.hash.startsWith('#movie=')) { movieDetailsPage(); } else if (location.hash.startsWith('#category=')) { categoriesPage(); } else { homePage(); } location.hash } window.addEventListener('DOMContentLoaded', navigator, false); window.addEventListener('haschange', navigator, false);

      Cuando se trabaja con eventListener lo recomendable es colocar nuestra funcion con un arrow function (en este caso "navigator" debido a que si en un futuro necesitemos eleminar ese evento lo podriamos ubicar con su nombre "navigator" y optimizar el performance de nuestro DOM.

    Escuelas

    • Desarrollo Web
      • Fundamentos del Desarrollo Web Profesional
      • Diseño y Desarrollo Frontend
      • Desarrollo Frontend con JavaScript
      • Desarrollo Frontend con Vue.js
      • Desarrollo Frontend con Angular
      • Desarrollo Frontend con React.js
      • Desarrollo Backend con Node.js
      • Desarrollo Backend con Python
      • Desarrollo Backend con Java
      • Desarrollo Backend con PHP
      • Desarrollo Backend con Ruby
      • Bases de Datos para Web
      • Seguridad Web & API
      • Testing Automatizado y QA para Web
      • Arquitecturas Web Modernas y Escalabilidad
      • DevOps y Cloud para Desarrolladores Web
    • English Academy
      • Inglés Básico A1
      • Inglés Básico A2
      • Inglés Intermedio B1
      • Inglés Intermedio Alto B2
      • Inglés Avanzado C1
      • Inglés para Propósitos Específicos
      • Inglés de Negocios
    • Marketing Digital
      • Fundamentos de Marketing Digital
      • Marketing de Contenidos y Redacción Persuasiva
      • SEO y Posicionamiento Web
      • Social Media Marketing y Community Management
      • Publicidad Digital y Paid Media
      • Analítica Digital y Optimización (CRO)
      • Estrategia de Marketing y Growth
      • Marketing de Marca y Comunicación Estratégica
      • Marketing para E-commerce
      • Marketing B2B
      • Inteligencia Artificial Aplicada al Marketing
      • Automatización del Marketing
      • Marca Personal y Marketing Freelance
      • Ventas y Experiencia del Cliente
      • Creación de Contenido para Redes Sociales
    • Inteligencia Artificial y Data Science
      • Fundamentos de Data Science y AI
      • Análisis y Visualización de Datos
      • Machine Learning y Deep Learning
      • Data Engineer
      • Inteligencia Artificial para la Productividad
      • Desarrollo de Aplicaciones con IA
      • AI Software Engineer
    • Ciberseguridad
      • Fundamentos de Ciberseguridad
      • Hacking Ético y Pentesting (Red Team)
      • Análisis de Malware e Ingeniería Forense
      • Seguridad Defensiva y Cumplimiento (Blue Team)
      • Ciberseguridad Estratégica
    • Liderazgo y Habilidades Blandas
      • Fundamentos de Habilidades Profesionales
      • Liderazgo y Gestión de Equipos
      • Comunicación Avanzada y Oratoria
      • Negociación y Resolución de Conflictos
      • Inteligencia Emocional y Autogestión
      • Productividad y Herramientas Digitales
      • Gestión de Proyectos y Metodologías Ágiles
      • Desarrollo de Carrera y Marca Personal
      • Diversidad, Inclusión y Entorno Laboral Saludable
      • Filosofía y Estrategia para Líderes
    • Diseño de Producto y UX
      • Fundamentos de Diseño UX/UI
      • Investigación de Usuarios (UX Research)
      • Arquitectura de Información y Usabilidad
      • Diseño de Interfaces y Prototipado (UI Design)
      • Sistemas de Diseño y DesignOps
      • Redacción UX (UX Writing)
      • Creatividad e Innovación en Diseño
      • Diseño Accesible e Inclusivo
      • Diseño Asistido por Inteligencia Artificial
      • Gestión de Producto y Liderazgo en Diseño
      • Diseño de Interacciones Emergentes (VUI/VR)
      • Desarrollo Web para Diseñadores
      • Diseño y Prototipado No-Code
    • Contenido Audiovisual
      • Fundamentos de Producción Audiovisual
      • Producción de Video para Plataformas Digitales
      • Producción de Audio y Podcast
      • Fotografía y Diseño Gráfico para Contenido Digital
      • Motion Graphics y Animación
      • Contenido Interactivo y Realidad Aumentada
      • Estrategia, Marketing y Monetización de Contenidos
    • Desarrollo Móvil
      • Fundamentos de Desarrollo Móvil
      • Desarrollo Nativo Android con Kotlin
      • Desarrollo Nativo iOS con Swift
      • Desarrollo Multiplataforma con React Native
      • Desarrollo Multiplataforma con Flutter
      • Arquitectura y Patrones de Diseño Móvil
      • Integración de APIs y Persistencia Móvil
      • Testing y Despliegue en Móvil
      • Diseño UX/UI para Móviles
    • Diseño Gráfico y Arte Digital
      • Fundamentos del Diseño Gráfico y Digital
      • Diseño de Identidad Visual y Branding
      • Ilustración Digital y Arte Conceptual
      • Diseño Editorial y de Empaques
      • Motion Graphics y Animación 3D
      • Diseño Gráfico Asistido por Inteligencia Artificial
      • Creatividad e Innovación en Diseño
    • Programación
      • Fundamentos de Programación e Ingeniería de Software
      • Herramientas de IA para el trabajo
      • Matemáticas para Programación
      • Programación con Python
      • Programación con JavaScript
      • Programación con TypeScript
      • Programación Orientada a Objetos con Java
      • Desarrollo con C# y .NET
      • Programación con PHP
      • Programación con Go y Rust
      • Programación Móvil con Swift y Kotlin
      • Programación con C y C++
      • Administración Básica de Servidores Linux
    • Negocios
      • Fundamentos de Negocios y Emprendimiento
      • Estrategia y Crecimiento Empresarial
      • Finanzas Personales y Corporativas
      • Inversión en Mercados Financieros
      • Ventas, CRM y Experiencia del Cliente
      • Operaciones, Logística y E-commerce
      • Gestión de Proyectos y Metodologías Ágiles
      • Aspectos Legales y Cumplimiento
      • Habilidades Directivas y Crecimiento Profesional
      • Diversidad e Inclusión en el Entorno Laboral
      • Herramientas Digitales y Automatización para Negocios
    • Blockchain y Web3
      • Fundamentos de Blockchain y Web3
      • Desarrollo de Smart Contracts y dApps
      • Finanzas Descentralizadas (DeFi)
      • NFTs y Economía de Creadores
      • Seguridad Blockchain
      • Ecosistemas Blockchain Alternativos (No-EVM)
      • Producto, Marketing y Legal en Web3
    • Recursos Humanos
      • Fundamentos y Cultura Organizacional en RRHH
      • Atracción y Selección de Talento
      • Cultura y Employee Experience
      • Gestión y Desarrollo de Talento
      • Desarrollo y Evaluación de Liderazgo
      • Diversidad, Equidad e Inclusión
      • AI y Automatización en Recursos Humanos
      • Tecnología y Automatización en RRHH
    • Finanzas e Inversiones
      • Fundamentos de Finanzas Personales y Corporativas
      • Análisis y Valoración Financiera
      • Inversión y Mercados de Capitales
      • Finanzas Descentralizadas (DeFi) y Criptoactivos
      • Finanzas y Estrategia para Startups
      • Inteligencia Artificial Aplicada a Finanzas
      • Domina Excel
      • Financial Analyst
      • Conseguir trabajo en Finanzas e Inversiones
    • Startups
      • Fundamentos y Validación de Ideas
      • Estrategia de Negocio y Product-Market Fit
      • Desarrollo de Producto y Operaciones Lean
      • Finanzas, Legal y Fundraising
      • Marketing, Ventas y Growth para Startups
      • Cultura, Talento y Liderazgo
      • Finanzas y Operaciones en Ecommerce
      • Startups Web3 y Blockchain
      • Startups con Impacto Social
      • Expansión y Ecosistema Startup
    • Cloud Computing y DevOps
      • Fundamentos de Cloud y DevOps
      • Administración de Servidores Linux
      • Contenerización y Orquestación
      • Infraestructura como Código (IaC) y CI/CD
      • Amazon Web Services
      • Microsoft Azure
      • Serverless y Observabilidad
      • Certificaciones Cloud (Preparación)
      • Plataforma Cloud GCP

    Platzi y comunidad

    • Platzi Business
    • Live Classes
    • Lanzamientos
    • Executive Program
    • Trabaja con nosotros
    • Podcast

    Recursos

    • Manual de Marca

    Soporte

    • Preguntas Frecuentes
    • Contáctanos

    Legal

    • Términos y Condiciones
    • Privacidad
    • Tyc promociones
    Reconocimientos
    Reconocimientos
    Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
    Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
    Logo reconocimientoPrimera Startup EdTech · 2018
    Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
    Logo reconocimientoCEO Mejor Emprendedor del año · 2024
    De LATAM conpara el mundo
    YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads