templates/recommendations/_profile_recommendations.html.twig line 1

Open in your IDE?
  1. {# <div id="recommendationsDebug">
  2.     {#<div id="queryData" style="display: none;"></div><a href="javascript:void(0);" id="showQueryBtn">Показать запрос</a>#!}
  3.     <div id="profileViewsData">
  4.         <h6 style="color: #1ea471">Просмотры анкет на сайте</h6>
  5.         {% set profile_debug_data = profile_recommendations_debug_views() %}
  6.         {% include "Recommendations/_profile_recommendations_debug_profile_data_table.html.twig" %}
  7.     </div>
  8.     <div id="favouritesData">
  9.         <h6 style="color: #0d5aa7">Избранные</h6>
  10.         {% set profile_debug_data = profile_recommendations_debug_favourites() %}
  11.         {% include "Recommendations/_profile_recommendations_debug_profile_data_table.html.twig" %}
  12.     </div>
  13.     {% include "Recommendations/_profile_recommendations_debug_coeffs_data_table.html.twig" %}
  14.     <h6 style="color: #bd2130">Коэффициенты</h6>
  15.     <div id="coeffsData"></div>
  16.     {% include "Recommendations/_profile_recommendations_debug_viewed_profiles_data_table.html.twig" %}
  17.     <h6 style="color: #856404">Просмотренные рекомендации</h6>
  18.     <div id="viewedRecommendationsData"></div>
  19. </div> #}
  20. {% set isHiddenPlacement = hidden is defined and hidden %}
  21. <div class="recommended{{ componentClass is defined ? ' ' ~ componentClass : '' }}"{{ isHiddenPlacement ? ' style="display:none"' : '' }} id="profileRecommendations">
  22.     <h2 class="border-line">Рекомендуемые</h2>
  23.     <div class="recommended-list d-flex" id="profileRecommendationsContainer">
  24.         {% for i in 1..6 %}
  25.             <div class="recommended-item recommended-item--skeleton">
  26.                 <div class="recommended-profile">
  27.                     <div class="d-block recommended-link">
  28.                         <div class="recommended-heading skeleton"></div>
  29.                         <div class="recommended-avatar skeleton"></div>
  30.                     </div>
  31.                     <div class="d-flex align-items-center recommended-info skeleton"></div>
  32.                     <div class="d-flex align-items-center recommended-metro skeleton"></div>
  33.                 </div>
  34.             </div>
  35.         {% endfor %}
  36.     </div>
  37. </div>
  38. <script type="text/javascript">
  39.     document.addEventListener('DOMContentLoaded', function() {
  40.         const sortLines = (data) => {
  41.             {#// Инициализация объекта для хранения станций в соответствии с их типом#}
  42.             const sortedStations = data.reduce((acc, station) => {
  43.                 if (station.name.startsWith('МЦД-')) {
  44.                     acc.mcd.push(station);
  45.                 } else if (station.name === 'МЦК') {
  46.                     acc.mck.push(station);
  47.                 } else {
  48.                     acc.ordinary.push(station);
  49.                 }
  50.                 return acc;
  51.             }, { ordinary: [], mcd: [], mck: [] });
  52.             {#// Сортировка станций МЦД по номеру#}
  53.             sortedStations.mcd.sort((a, b) => {
  54.                 const numA = parseInt(a.name.split('МЦД-')[1]);
  55.                 const numB = parseInt(b.name.split('МЦД-')[1]);
  56.                 return numA - numB;
  57.             });
  58.             {#// Объединение отсортированных станций#}
  59.             const result = [
  60.                 ...sortedStations.ordinary,
  61.                 ...sortedStations.mcd,
  62.                 ...sortedStations.mck
  63.             ];
  64.             return result;
  65.         };
  66.         const iconMetroSingle = ({color, iconId, width = '18'}) => {
  67.             return `<svg class="modal-list__icon" width="${width}" height="18">
  68.                 <use style="fill:#${color}" class="icon-container--element" xlink:href="#${iconId}"></use>
  69.             </svg>`
  70.         };
  71.         const iconMetroDouble = ({color1, color2}) => `
  72.             <svg class="modal-list__icon" width="17" height="16" fill="none">
  73.                 <path fill="#8E8E8E" d="M3.7 8.83h-.77v1.04h3.94V8.83H5.7l.76-2.59L8.5 9.96l2.03-3.72.76 2.6h-1.16v1.03h3.94V8.83h-.78L10.7 2 8.5 6.51 6.3 2 3.7 8.83Z"/>
  74.                 <rect width="7" height="3" x=".5" y="11.02" fill="#${color1}" rx="1.5"/>
  75.                 <rect width="7" height="3" x="9.5" y="11" fill="#${color2}" rx="1.5"/>
  76.             </svg>`;
  77.         const iconMetroTriple = ({color1, color2, color3}) => `<svg class="modal-list__icon" width="17" height="16" fill="none">
  78.                 <path fill="#8E8E8E" d="M3.7 8.83h-.77v1.04h3.94V8.83H5.7l.76-2.59L8.5 9.96l2.03-3.72.76 2.6h-1.16v1.03h3.94V8.83h-.78L10.7 2 8.5 6.51 6.3 2 3.7 8.83Z"/>
  79.                 <rect width="4" height="3" x=".5" y="11.02" fill="#${color1}" rx="1.5"/>
  80.                 <rect width="4" height="3" x="6.5" y="11.02" fill="#${color2}" rx="1.5"/>
  81.                 <path fill="#${color3}" d="M12.5 12.5c0-.83.67-1.5 1.5-1.5h1a1.5 1.5 0 0 1 0 3h-1a1.5 1.5 0 0 1-1.5-1.5Z"/>
  82.             </svg>`;
  83.         const getAllData = (s) => [s.color, s.name];
  84.         const getIconId = (name) => name.toLowerCase().includes('мцк') ? 'mck' : (name.toLowerCase().includes('мцд') ? 'mcd-' + name.split('-')[1] : 'metro');
  85.         const getIconWidth = (name) => name.toLowerCase().includes('мцд') ? '22' : '16';
  86.         const wrapperIcon = (str) => `<span class="modal-list__icons d-flex">${str}</span>`;
  87.         const wrapperLink = (html, _name) => `<a class="modal-list__icons d-flex"  href="${window._mp.stations[_name]}">${html}</a>`;
  88.         function iconGen2({name, dataLines}) {
  89.             {#//for test#}
  90.             const root = document.getElementById('icon-test-gen2');
  91.             const lines = sortLines(dataLines);
  92.             const count = lines.length;
  93.             {#// Если линия 1шт#}
  94.             if (count === 1){
  95.                 {#// Получаем данные по цветам и названиям линии#}
  96.                 const [color, line_name] = getAllData(lines[0]);
  97.                 {#// Иконка может быть обычным метро, мцд с номером или мцк#}
  98.                 const iconId = getIconId(line_name);
  99.                 const width = getIconWidth(line_name);
  100.                 return wrapperLink(wrapperIcon(iconMetroSingle({color, iconId, width})+ name), name);
  101.                 {#//return wrapperIcon(iconMetroSingle({color, iconId, width}));#}
  102.             } else if (count === 2) {
  103.                 const [[color1, name1], [color2, name2]] = lines.map(getAllData);
  104.                 const iconId1 = getIconId(name1);
  105.                 const iconId2 = getIconId(name2);
  106.                 {#// Если обе иконки это метро#}
  107.                 if (iconId1 === 'metro' && iconId2 === 'metro') {
  108.                     return wrapperLink(wrapperIcon(`${iconMetroDouble({color1, color2})} ${name}`), name);
  109.                 } else {
  110.                     const width1 = getIconWidth(name1);
  111.                     const width2 = getIconWidth(name2);
  112.                     return wrapperLink(wrapperIcon(`${iconMetroSingle({ color: color1, iconId: iconId1, width: width1 })}${iconMetroSingle({ color: color2, iconId: iconId2, width: width2 })} ${name}`), name);
  113.                 }
  114.             } else if (count === 3) {
  115.                 const [[color1, name1], [color2, name2], [color3, name3]] = lines.map(getAllData);
  116.                 const iconId1 = getIconId(name1);
  117.                 const iconId2 = getIconId(name2);
  118.                 const iconId3 = getIconId(name3);
  119.                 if (iconId1 === 'metro' && iconId2 === 'metro' && iconId3 === 'metro') {
  120.                     return wrapperLink(wrapperIcon(`${iconMetroTriple({color1, color2, color3})} ${name}`), name);
  121.                 } else if (iconId1 === 'metro' && iconId2 === 'metro') {
  122.                     const width3 = getIconWidth(name3);
  123.                     return wrapperLink(wrapperIcon(`${iconMetroDouble({color1, color2})}${iconMetroSingle({ color: color3, iconId: iconId3, width: width3 })} ${name}`), name);
  124.                 } else {
  125.                     const width1 = getIconWidth(name1);
  126.                     const width2 = getIconWidth(name2);
  127.                     const width3 = getIconWidth(name3);
  128.                     return wrapperLink(wrapperIcon(`${iconMetroSingle({ color: color1, iconId: iconId1, width: width1 })}${iconMetroSingle({ color: color2, iconId: iconId2, width: width2 })}${iconMetroSingle({ color: color3, iconId: iconId3, width: width3 })} ${name}`), name);
  129.                 }
  130.             } else if (count === 4) {
  131.                 const [[color1, name1], [color2, name2], [color3, name3], [color4, name4]] = lines.map(getAllData);
  132.                 const iconId1 = getIconId(name1);
  133.                 const iconId2 = getIconId(name2);
  134.                 const iconId3 = getIconId(name3);
  135.                 const iconId4 = getIconId(name4);
  136.                 if (iconId1 === 'metro' && iconId2 === 'metro' && iconId3 === 'metro') {
  137.                     const width4 = getIconWidth(name4);
  138.                     return wrapperLink(wrapperIcon(`${iconMetroTriple({color1, color2, color3})}${iconMetroSingle({ color: color4, iconId: iconId4, width: width4 })} ${name}`), name);
  139.                 } else if (iconId1 === 'metro' && iconId2 === 'metro') {
  140.                     const width3 = getIconWidth(name3);
  141.                     const width4 = getIconWidth(name4);
  142.                     return wrapperLink(wrapperIcon(`${iconMetroDouble({color1, color2})}${iconMetroSingle({ color: color3, iconId: iconId3, width: width3 })}${iconMetroSingle({ color: color4, iconId: iconId4, width: width4 })} ${name}`), name);
  143.                 } else {
  144.                     const width1 = getIconWidth(name1);
  145.                     const width2 = getIconWidth(name2);
  146.                     const width3 = getIconWidth(name3);
  147.                     const width4 = getIconWidth(name4);
  148.                     return wrapperLink(wrapperIcon(`${iconMetroSingle({ color: color1, iconId: iconId1, width: width1 })}${iconMetroSingle({ color: color2, iconId: iconId2, width: width2 })}${iconMetroSingle({ color: color3, iconId: iconId3, width: width3 })}${iconMetroSingle({ color: color4, iconId: iconId4, width: width4 })} ${name}`), name);
  149.                 }
  150.             }
  151.             return wrapperLink(name, name);
  152.         }
  153.         function fetchRecommendations() {
  154.             {% set gender = 'profile_list.list_by_gender' in app.request.get('_route') ? app.request.get('gender')|gender_value_by_uri : gender_female() %}
  155.             let url = '{{ path('recommendations.get', {city:app.request.get('city').uriIdentity, count: 6, imageSize: '357x500', exclude: (excludeRecommendationProfileIds is iterable ? excludeRecommendationProfileIds : [])|join(','), gender: gender }) }}';
  156.             let filter = JSON.parse('{{ recommendationSpec ? recommendationSpec.spec.toEsQueryObject|json_encode|raw : {}|json_encode|raw }}');
  157.             const profileContainer = document.getElementById('profileRecommendations');
  158.             window.Recommendation.updateSettings({
  159.                 rootId: 'profileRecommendations',
  160.                 url,
  161.                 filter,
  162.                 callback: (response) => {
  163.                     let template = '';
  164.                     const container = document.querySelector('#profileRecommendationsContainer');
  165.                     container.innerHTML = '';
  166.                     response.profiles.forEach(function(profile) {
  167.                         const {station, price, phone} = profile;
  168.                         template = `
  169.                             <a class="d-block recommended-link" href="${profile.url}" target="_blank">
  170.                                 <p class="recommended-heading">
  171.                                     ${profile.approved ? `<svg class="icon">
  172.                                         <use xlink:href="{{ asset('assets_domain/images/icons/svg-library.svg', 'nodomainConfig') }}#icon-verify-new"></use>
  173.                                     </svg>` : ''}
  174.                                     <span class="recommended-name"><span class="name">${profile.name}</span>, <span class="age">${profile.age}</span></span>
  175.                                 </p>
  176.                                 <div class="recommended-avatar">
  177.                                     <img class="recommended-avatar-img" src="${profile.image}" alt="" width="281" height="394" loading="lazy">
  178.                                 </div>
  179.                             </a>
  180.                             <div class="d-flex align-items-center recommended-info">
  181.                                 <div class="recommended-phone phone">${phone}</div>
  182.                                 ${price ? `<div class="ml-auto recommended-price price">от ${price.toLocaleString('ru')}</div>` : ''}
  183.                             </div>
  184.                             <div class="d-flex align-items-center recommended-metro">
  185.                                 ${station ? `<div class="metro-item d-flex">${iconGen2({name: station.name, dataLines: station.lines})}</div>` : ''}
  186.                             </div>
  187.                         `;
  188.                         const node = document.createElement('div');
  189.                         node.className = 'recommended-item';
  190.                         node.dataset.profileId = profile.id;
  191.                         node.innerHTML = `<div class="recommended-profile">${template}</div>`;
  192.                         container.appendChild(node);
  193.                     });
  194.                     profileContainer.style.display = 'block';
  195.                     document.dispatchEvent(new CustomEvent('recommendations:loaded', {detail: {id: 'recommendations'}}));
  196.                 }
  197.             });
  198.             {% if not isHiddenPlacement %}window.Recommendation.loadRecommendations();{% endif %}
  199.         }
  200.         window.ObserverJakka({
  201.             id: 'recommendations',
  202.             callback: () => {
  203.                 fetchRecommendations();
  204.             },
  205.             options: {
  206.                 rootMargin: '120px'
  207.             }
  208.         });
  209.     });
  210. </script>