{"id":690,"date":"2026-06-14T00:38:29","date_gmt":"2026-06-14T00:38:29","guid":{"rendered":"https:\/\/ppimultimedia.ca\/?page_id=690"},"modified":"2026-06-14T00:38:29","modified_gmt":"2026-06-14T00:38:29","slug":"index","status":"publish","type":"page","link":"https:\/\/ppimultimedia.ca\/en\/index\/","title":{"rendered":"Descriptions visuelles"},"content":{"rendered":"<style data-wp-block-html=\"css\">\n.panneau-general-immobilier{\n  width:100%;\n  max-width:1280px;\n  margin:0 auto;\n  padding:20px;\n  box-sizing:border-box;\n  font-family:system-ui,sans-serif;\n}\n\n.barre-sites-principale,\n.barre-colocations{\n  display:flex;\n  flex-wrap:wrap;\n  gap:12px;\n  margin-bottom:18px;\n}\n\n.btn-site,\n.btn-coloc{\n  appearance:none;\n  border:none;\n  padding:14px 18px;\n  border-radius:12px;\n  background:#f1f5f9;\n  color:#1e293b;\n  font-weight:700;\n  cursor:pointer;\n  transition:.2s ease;\n}\n\n.btn-site:hover,\n.btn-coloc:hover{\n  background:#dbeafe;\n}\n\n.active-site,\n.active-coloc{\n  background:#0073aa;\n  color:#fff;\n}\n\n.site-panel,\n.coloc-panel{\n  display:none;\n}\n\n.site-panel.active,\n.coloc-panel.active{\n  display:block;\n}\n\n.coloc-title{\n  margin:0 0 14px 0;\n  font-size:30px;\n  line-height:1.2;\n  color:#0f172a;\n}\n\n.common-carousel{\n  position:relative;\n  width:100%;\n  height:630px;\n  border-radius:18px;\n  overflow:hidden;\n  background:#ffffff;\n  box-shadow:0 10px 30px rgba(0,0,0,.08);\n  margin-bottom:14px;\n}\n\n.common-carousel .common-track{\n  position:relative;\n  width:100%;\n  height:100%;\n}\n\n.common-carousel img{\n  position:absolute;\n  inset:0;\n  width:100%;\n  height:100%;\n  object-fit:contain;\n  background:#fff;\n  opacity:0;\n  transition:opacity 2s ease;\n}\n\n.common-carousel img.active{\n  opacity:1;\n}\n\n.common-carousel .white-flash{\n  position:absolute;\n  inset:0;\n  background:#ffffff;\n  opacity:0;\n  pointer-events:none;\n}\n\n.common-carousel.flash-phase .white-flash{\n  animation:flashWhite 2s ease forwards;\n}\n\n@keyframes flashWhite{\n  0%{opacity:0}\n  40%{opacity:1}\n  100%{opacity:0}\n}\n\n.carousel-dots{\n  display:flex;\n  gap:8px;\n  justify-content:center;\n  align-items:center;\n  padding:10px 0 20px;\n}\n\n.carousel-dot,\n.room-dot{\n  width:10px;\n  height:10px;\n  border-radius:50%;\n  background:#cbd5e1;\n  cursor:pointer;\n  transition:.2s;\n}\n\n.carousel-dot.active,\n.room-dot.active{\n  background:#0073aa;\n}\n\n.room-grid{\n  display:grid;\n  grid-template-columns:repeat(2,1fr);\n  gap:20px;\n}\n\n.room-card{\n  background:#fff;\n  border:1px solid #e2e8f0;\n  border-radius:16px;\n  padding:16px;\n  box-shadow:0 6px 18px rgba(0,0,0,.05);\n}\n\n.tag-badge{\n  display:inline-block;\n  padding:7px 10px;\n  border-radius:999px;\n  font-size:13px;\n  font-weight:700;\n  margin-bottom:12px;\n}\n\n.t-dispo{\n  background:#dcfce7;\n  color:#166534;\n}\n\n.t-occ{\n  background:#fee2e2;\n  color:#991b1b;\n}\n\n.t-date{\n  background:#fef3c7;\n  color:#92400e;\n}\n\n.room-carousel{\n  position:relative;\n  width:100%;\n  aspect-ratio:16\/10;\n  border-radius:12px;\n  overflow:hidden;\n  background:#cbd5e1;\n  margin-bottom:10px;\n  touch-action:pan-y;\n}\n\n.room-carousel img{\n  width:100%;\n  height:100%;\n  object-fit:cover;\n  display:block;\n}\n\n.room-empty{\n  width:100%;\n  aspect-ratio:16\/10;\n  border-radius:12px;\n  background:#f1f5f9;\n  display:flex;\n  align-items:center;\n  justify-content:center;\n  color:#64748b;\n  font-size:14px;\n  margin-bottom:10px;\n  text-align:center;\n  padding:20px;\n  box-sizing:border-box;\n}\n\n.room-dots{\n  display:flex;\n  gap:6px;\n  justify-content:center;\n  align-items:center;\n  padding:8px 0 2px 0;\n}\n\n.room-card h4{\n  margin:10px 0 6px 0;\n  font-size:22px;\n  color:#0f172a;\n}\n\n.room-card p{\n  margin:0;\n  color:#64748b;\n  font-size:14px;\n}\n\n@media (max-width: 640px){\n  .panneau-general-immobilier{\n    padding:14px;\n  }\n\n  .coloc-title{\n    font-size:24px;\n  }\n\n  .room-grid{\n    grid-template-columns:1fr;\n  }\n\n  .common-carousel{\n    height:390px;\n  }\n\n  .btn-site,\n  .btn-coloc{\n    width:100%;\n  }\n}\n<\/style>\n\n<script data-wp-block-html=\"js\">\ndocument.addEventListener('DOMContentLoaded', function () {\n  const uploadBase = 'https:\/\/ppimultimedia.ca\/wp-content\/uploads\/2026\/06\/';\n\n  const data = {\n    conrad: {\n      colocs: [\n        {\n          id: '118_3',\n          imagePrefix: '118_3',\n          title: '118 Conrad \u2014 Colocation A',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 0 },\n            { number: 4, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '118_4',\n          imagePrefix: '118_4',\n          title: '118 Conrad \u2014 Colocation B',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 },\n            { number: 4, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '118_5',\n          imagePrefix: '118_5',\n          title: '118 Conrad \u2014 Colocation C',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 },\n            { number: 4, status: 'non disponible', imageCount: 4 }\n          ]\n        }\n      ]\n    },\n\n    chomedey: {\n      colocs: [\n        {\n          id: '280a',\n          imagePrefix: '280_a',\n          title: 'Chomedey \u2014 Colocation A',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 },\n            { number: 4, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '280',\n          imagePrefix: '280',\n          title: 'Chomedey \u2014 Colocation B',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 },\n            { number: 4, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '282',\n          imagePrefix: '282',\n          title: 'Chomedey \u2014 Colocation C',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 },\n            { number: 4, status: 'non disponible', imageCount: 4 },\n            { number: 5, status: 'non disponible', imageCount: 4 }\n          ]\n        }\n      ]\n    },\n\n    principale: {\n      colocs: [\n        {\n          id: '36',\n          imagePrefix: '36',\n          title: 'Principale \u2014 Colocation A',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '40',\n          imagePrefix: '40',\n          title: 'Principale \u2014 Colocation B',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 }\n          ]\n        },\n        {\n          id: '42',\n          imagePrefix: '42',\n          title: 'Principale \u2014 Colocation C',\n          commonCount: 4,\n          rooms: [\n            { number: 1, status: 'non disponible', imageCount: 4 },\n            { number: 2, status: 'non disponible', imageCount: 4 },\n            { number: 3, status: 'non disponible', imageCount: 4 }\n          ]\n        }\n      ]\n    }\n  };\n\n  const siteButtons = document.querySelectorAll('.btn-site');\n  const colocButtons = document.querySelectorAll('.btn-coloc');\n  const siteContainer = document.getElementById('conteneur-sites');\n\n  function commonImageUrl(prefix, index) {\n    return `${uploadBase}${prefix}-c${index}w.jpg`;\n  }\n\n  function roomImageUrl(prefix, roomNumber, shotIndex) {\n    return `${uploadBase}${prefix}-${roomNumber}-${shotIndex}w.jpg`;\n  }\n\n  function createDots(count, className) {\n    let html = '';\n    for (let i = 0; i < count; i++) {\n      html += `<span class=\"${className}${i === 0 ? ' active' : ''}\" data-index=\"${i}\"><\/span>`;\n    }\n    return html;\n  }\n\n  function statusDisplay(value) {\n    const v = (value || '').toLowerCase().trim();\n\n    if (\/^\\d{4}-\\d{2}-\\d{2}$\/.test(v)) {\n      return { text: `Disponible le ${value}`, cls: 't-date' };\n    }\n\n    if (v === 'disponible') {\n      return { text: 'Disponible', cls: 't-dispo' };\n    }\n\n    return { text: 'Non disponible', cls: 't-occ' };\n  }\n\n  function renderSite(siteKey) {\n    const site = data[siteKey];\n    siteContainer.innerHTML = '';\n\n    const sitePanel = document.createElement('div');\n    sitePanel.className = 'site-panel active';\n\n    site.colocs.forEach((coloc, colocIndex) => {\n      const colocPanel = document.createElement('div');\n      colocPanel.className = `coloc-panel${colocIndex === 0 ? ' active' : ''}`;\n      colocPanel.dataset.colocIndex = colocIndex;\n\n      const commonImages = [];\n      for (let i = 1; i <= coloc.commonCount; i++) {\n        commonImages.push(commonImageUrl(coloc.imagePrefix, i));\n      }\n\n      let commonImgsHtml = '';\n      commonImages.forEach((src, i) => {\n        commonImgsHtml += `<img decoding=\"async\" src=\"${src}\" alt=\"${coloc.title}\" class=\"${i === 0 ? 'active' : ''}\">`;\n      });\n\n      let roomsHtml = '';\n      coloc.rooms.forEach(room => {\n        const badge = statusDisplay(room.status);\n\n        if (room.imageCount === 0) {\n          roomsHtml += `\n            <div class=\"room-card\">\n              <div class=\"tag-badge ${badge.cls}\">${badge.text}<\/div>\n              <div class=\"room-empty\">Aucune photo disponible<\/div>\n              <h4>Chambre ${room.number}<\/h4>\n              <p>Aucune image pour cette chambre<\/p>\n            <\/div>\n          `;\n          return;\n        }\n\n        const roomImages = [];\n        for (let s = 1; s <= room.imageCount; s++) {\n          roomImages.push(roomImageUrl(coloc.imagePrefix, room.number, s));\n        }\n\n        roomsHtml += `\n          <div class=\"room-card\">\n            <div class=\"tag-badge ${badge.cls}\">${badge.text}<\/div>\n            <div class=\"room-carousel\" data-images='${JSON.stringify(roomImages)}' data-current=\"0\">\n              <img decoding=\"async\" src=\"${roomImages[0]}\" alt=\"Chambre ${room.number}\">\n            <\/div>\n            <div class=\"room-dots\">${createDots(roomImages.length, 'room-dot')}<\/div>\n            <h4>Chambre ${room.number}<\/h4>\n            <p>Faites glisser ou cliquez sur les points<\/p>\n          <\/div>\n        `;\n      });\n\n      colocPanel.innerHTML = `\n        <h2 class=\"coloc-title\">${coloc.title}<\/h2>\n        <div class=\"common-carousel\" data-images='${JSON.stringify(commonImages)}' data-current=\"0\">\n          <div class=\"common-track\">${commonImgsHtml}<\/div>\n          <div class=\"white-flash\"><\/div>\n        <\/div>\n        <div class=\"carousel-dots\">${createDots(commonImages.length, 'carousel-dot')}<\/div>\n        <div class=\"room-grid\">${roomsHtml}<\/div>\n      `;\n\n      sitePanel.appendChild(colocPanel);\n    });\n\n    siteContainer.appendChild(sitePanel);\n    bindColocSwitch(sitePanel);\n    bindCommonCarousels(sitePanel);\n    bindRoomCarousels(sitePanel);\n  }\n\n  function bindColocSwitch(sitePanel) {\n    const colocPanels = sitePanel.querySelectorAll('.coloc-panel');\n\n    colocButtons.forEach(btn => {\n      btn.onclick = function () {\n        const idx = parseInt(this.dataset.coloc, 10);\n\n        colocButtons.forEach(b => b.classList.remove('active-coloc'));\n        this.classList.add('active-coloc');\n\n        colocPanels.forEach(panel => panel.classList.remove('active'));\n        const target = sitePanel.querySelector(`.coloc-panel[data-coloc-index=\"${idx}\"]`);\n        if (target) target.classList.add('active');\n      };\n    });\n  }\n\n  function activateDots(dotContainer, activeIndex, selector) {\n    const dots = dotContainer.querySelectorAll(selector);\n    dots.forEach((dot, i) => {\n      dot.classList.toggle('active', i === activeIndex);\n    });\n  }\n\n  function bindCommonCarousels(scope) {\n    const commonCarousels = scope.querySelectorAll('.common-carousel');\n\n    commonCarousels.forEach(carousel => {\n      const images = carousel.querySelectorAll('img');\n      const dotsWrap = carousel.nextElementSibling;\n      let current = 0;\n\n      function show(index) {\n        images.forEach((img, i) => img.classList.toggle('active', i === index));\n        activateDots(dotsWrap, index, '.carousel-dot');\n        current = index;\n      }\n\n      function nextWithWhiteFade() {\n        carousel.classList.add('flash-phase');\n\n        setTimeout(() => {\n          const next = (current + 1) % images.length;\n          show(next);\n        }, 1000);\n\n        setTimeout(() => {\n          carousel.classList.remove('flash-phase');\n        }, 2000);\n      }\n\n      const dots = dotsWrap.querySelectorAll('.carousel-dot');\n      dots.forEach((dot, i) => {\n        dot.addEventListener('click', () => show(i));\n      });\n\n      show(0);\n\n      if (images.length > 1) {\n        setInterval(() => {\n          setTimeout(nextWithWhiteFade, 2000);\n        }, 4000);\n      }\n    });\n  }\n\n  function bindRoomCarousels(scope) {\n    const roomCarousels = scope.querySelectorAll('.room-carousel');\n\n    roomCarousels.forEach(carousel => {\n      const images = JSON.parse(carousel.dataset.images || '[]');\n      const img = carousel.querySelector('img');\n      const dotsWrap = carousel.nextElementSibling;\n      let current = 0;\n      let startX = 0;\n      let endX = 0;\n\n      function show(index) {\n        current = index;\n        img.src = images[current];\n        activateDots(dotsWrap, current, '.room-dot');\n      }\n\n      function next() {\n        show((current + 1) % images.length);\n      }\n\n      function prev() {\n        show((current - 1 + images.length) % images.length);\n      }\n\n      const dots = dotsWrap.querySelectorAll('.room-dot');\n      dots.forEach((dot, i) => {\n        dot.addEventListener('click', () => show(i));\n      });\n\n      carousel.addEventListener('click', function (e) {\n        const rect = carousel.getBoundingClientRect();\n        const clickX = e.clientX - rect.left;\n\n        if (clickX < rect.width \/ 2) {\n          prev();\n        } else {\n          next();\n        }\n      });\n\n      carousel.addEventListener('touchstart', function (e) {\n        startX = e.changedTouches[0].clientX;\n      }, { passive: true });\n\n      carousel.addEventListener('touchend', function (e) {\n        endX = e.changedTouches[0].clientX;\n        const diff = endX - startX;\n\n        if (Math.abs(diff) > 40) {\n          if (diff < 0) {\n            next();\n          } else {\n            prev();\n          }\n        }\n      }, { passive: true });\n\n      show(0);\n    });\n  }\n\n  siteButtons.forEach(btn => {\n    btn.addEventListener('click', function () {\n      const targetSite = this.dataset.site;\n\n      siteButtons.forEach(b => b.classList.remove('active-site'));\n      this.classList.add('active-site');\n\n      colocButtons.forEach((b, i) => b.classList.toggle('active-coloc', i === 0));\n      renderSite(targetSite);\n    });\n  });\n\n  renderSite('conrad');\n});\n<\/script>\n\n<div class=\"panneau-general-immobilier\">\n  <div class=\"barre-sites-principale\">\n    <button class=\"btn-site active-site\" data-site=\"conrad\">118 Conrad<\/button>\n    <button class=\"btn-site\" data-site=\"chomedey\">Chomedey<\/button>\n    <button class=\"btn-site\" data-site=\"principale\">Principale<\/button>\n  <\/div>\n\n  <div class=\"barre-colocations\">\n    <button class=\"btn-coloc active-coloc\" data-coloc=\"0\">Colocation A<\/button>\n    <button class=\"btn-coloc\" data-coloc=\"1\">Colocation B<\/button>\n    <button class=\"btn-coloc\" data-coloc=\"2\">Colocation C<\/button>\n  <\/div>\n\n  <div id=\"conteneur-sites\"><\/div>\n<\/div>\n\n\n<p class=\"ext-animate--on wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>118 Conrad Chomedey Principale Colocation A Colocation B Colocation C<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-with-title","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-690","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/pages\/690","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/comments?post=690"}],"version-history":[{"count":8,"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/pages\/690\/revisions"}],"predecessor-version":[{"id":928,"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/pages\/690\/revisions\/928"}],"wp:attachment":[{"href":"https:\/\/ppimultimedia.ca\/en\/wp-json\/wp\/v2\/media?parent=690"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}