{"id":888,"date":"2025-05-26T13:30:29","date_gmt":"2025-05-26T11:30:29","guid":{"rendered":"https:\/\/staywin.stronywwwpomorze.pl\/apartamenty\/"},"modified":"2025-05-26T13:31:09","modified_gmt":"2025-05-26T11:31:09","slug":"apartamenty","status":"publish","type":"page","link":"https:\/\/staywin.stronywwwpomorze.pl\/en\/apartamenty\/","title":{"rendered":"apartamenty"},"content":{"rendered":"<section class=\"u-border-2 u-border-no-left u-border-no-right u-border-no-top u-border-palette-1-base u-clearfix u-image u-shading lazyload u-section-1\" id=\"sec-5edb\" data-bg=\"linear-gradient(to bottom, rgba(0, 0, 0, 0.65), rgba(0, 0, 0, 0.65)), url('https:\/\/staywin.stronywwwpomorze.pl\/wp-content\/uploads\/2025\/05\/gdansk-7505686_1280-2.jpg')\">\n      <div class=\"u-clearfix u-sheet u-sheet-1\">\n        <h1 class=\"u-text u-text-default-lg u-text-default-md u-text-default-sm u-text-default-xl u-text-1\">Apartments<\/h1>\n        <h2 class=\"u-text u-text-default-lg u-text-default-md u-text-default-sm u-text-default-xl u-text-palette-1-base u-text-2\">Find your dream apartment for a stay in Gda\u0144sk<\/h2>\n      <\/div>\n    <\/section>\n    <section class=\"u-clearfix u-section-2\" id=\"sec-3607\">\n      <div class=\"u-clearfix u-sheet u-sheet-1\">\n        <div class=\"u-expanded-width u-shortcode u-shortcode-1\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Manrope:wght@200..800&display=swap\" rel=\"stylesheet\">\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.0.0-beta3\/css\/all.min.css\">\n\n\n\n\n<style>\n:root{\n    --black: #080a0e;\n    --primary: #c6976d;\n    --text: #4E4D2F;\n    --primary-dark: #25281B;\n    --gray: gray;\n}\n\n.pase-apartments-grid {\n    display: grid;\n    grid-template-columns: 1fr 1fr 1fr;\n}\n.pase-apartment-item {\n    font-family: 'Plus Jakarta Sans';\n    flex: 1;\n    padding: 10px;\n    display: flex;\n    flex-direction: column;\n    justify-content: flex-start;\n    gap: 12px;\n    opacity: 0;\n    transform: translateY(20px);\n    animation: fade-in-up 0.5s ease forwards;\n}\n.pase-apartment-item img {\n    width: 100%;\n    height: 500px;\n    object-fit: cover;\n}\n.pase-apartment-header{\n    font-size: 28px;\n    color: var(--primary);\n    font-family: 'Melodrama' !important;\n    height: calc(1.2em * 2);\n      line-height: 1.2em;\n      overflow: hidden;\n}\n\n.apt-meta-item{\ndisplay: flex; gap: 12px;\n min-height: 1.5em;      \/* wyr\u00f3wnanie wysoko\u015bci *\/\n  align-items: center;\n}\n.apt-meta{\n    display: flex;\n    gap: 20px;\n}\n.apt-meta span i {\n  margin-right: 4px;\n}\n.pase-apartment-item .apt-description { font-size: 14px; color: var(--gray); height: 80px; overflow: hidden; text-overflow: ellipsis; font-family: \"Manrope\", sans-serif; line-height: 1.9}\n.pase-apartment-item a.btn-details {\nfont-size: 16px;\n     font-family: \"Manrope\", sans-serif !important;\n     display: inline-block;\n     padding-block: 14px;\n     border-radius: 50px;\n     background-color: var(--primary);\n     color: #fff;\n     text-decoration: none;\n     text-align: center;\n     transition: 0.12s ease-in-out;\n\n }\n .pase-apartment-item a.btn-reservation {\n font-size: 16px;\n      font-family: \"Manrope\", sans-serif !important;\n      display: inline-block;\n      padding-block: 14px;\n      border-radius: 50px;\n      background-color: transparent;\n      color: #fff;\n      text-decoration: none;\n      text-align: center;\n     border: 1px solid #fff;\n     transition: 0.12s ease-in-out;\n  }\n\n  #paseSearchFilters{\n  padding-block: 20px;\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n\n  }\n  .paseSearchFiltersElements{\n    display: flex;\n    gap: 10px;\n    align-items: center;\n    justify-content: center;\n  }\n  #paseSearchInput{\n    min-width: 350px;\n    background: var(--black);\n    border: 1px solid var(--primary);\n    color: #fff;\n    padding-inline: 8px;\n    padding-block: 12px;\n  }\n  .filterCell{\n    display: flex;\n    flex-direction: column;\n    gap: 4px;\n   }\n\n    .filterCell label{\n        font-size: 11px;\n    }\n\n\n\n  #paseSearchFilters select{\n    background: var(--black);\n    border: 1px solid var(--primary);\n    color: #fff;\n        padding-inline: 8px;\n        padding-block: 12px;\n  }\n  #paseSearchFilters option{\n    background: var(--black);\n    color: #fff;\n  }\n\n  .pase-filters{ display: flex; justify-content: center; gap: 10px; }\n  .pase-filters button { background: transparent; border: none; outline: none; font-size: 16px; color: #fff; }\n  .pase-filters button:hover { text-decoration: underline; cursor: pointer; }\n  .pase-filters button.active { color: var(--primary); }\n.pase-apartment-item a.btn-details:hover, a.btn-reservation:hover { background-color: var(--black); transition: 0.12s ease-in-out;}\n@keyframes fade-in-up { 0% { opacity: 0; transform: translateY(20px);} 100% { opacity: 1; transform: translateY(0);} }\n.pase-pagination { display: flex; justify-content: center; align-items: center; gap: 8px; margin-top: 20px; }\n.pase-pagination button { padding: 6px 10px; border: 1px solid #fff; cursor: pointer; transition: 0.12s ease-in-out; background: var(--black);}\n.pase-pagination button.active { background-color: var(--primary); color: #fff; }\n.pase-pagination button:hover { background-color: var(--black); transition: 0.12s ease-in-out; color: #fff; }\n@media (max-width: 768px) { .pase-apartments-grid { display: flex; flex-direction: column; }\n\n  .pase-filters{ flex-direction: column; gap: 10px; }\n  #paseSearchFilters { flex-direction: column; gap: 20px; }\n\n.pase-apartment-item img { height: auto; max-height: 350px; } .pase-apartment-item { padding: 8px; } }\n<\/style>\n\n\n<!-- 1) KATEGORIE -->\n<div class=\"pase-filters\" id=\"paseCategoryFilters\">\n  <button data-cat=\"Wszystko\" class=\"active\">Wszystko<\/button>\n  <button data-cat=\"Wyspa Spichrz\u00f3w\">Spichrz\u00f3w Island<\/button>\n  <button data-cat=\"Stare Miasto i Marina\">Old Town and Marina<\/button>\n  <button data-cat=\"Widok Na Rzek\u0119\">River view<\/button>\n<\/div>\n\n<!-- 2) DODATKOWE FILTRY -->\n<div id=\"paseSearchFilters\">\n    <div>\n        <input type=\"text\" id=\"paseSearchInput\" placeholder=\"Search for an apartment...\" \/>\n    <\/div>\n\n    <div class=\"paseSearchFiltersElements\">\n\n    <div class=\"filterCell\">\n        <label>Number of people<\/label>\n        <select id=\"paseFilterPersons\">\n          <option value=\"wszystko\">Wszystko<\/option>\n          <option value=\"1\">1<\/option>\n          <option value=\"2\">2<\/option>\n          <option value=\"3\">3<\/option>\n          <option value=\"4\">4<\/option>\n          <option value=\"5\">5<\/option>\n          <option value=\"6plus\">6+<\/option>\n        <\/select>\n    <\/div>\n\n    <div class=\"filterCell\">\n        <label>Number of bedrooms<\/label>\n         <select id=\"paseFilterBedrooms\">\n              <option value=\"wszystko\">Wszystko<\/option>\n              <option value=\"1\">1<\/option>\n              <option value=\"2\">2<\/option>\n              <option value=\"3\">3<\/option>\n              <option value=\"4plus\">4+<\/option>\n         <\/select>\n     <\/div>\n\n\n    <div class=\"filterCell\">\n        <label>Area<\/label>\n          <select id=\"paseFilterArea\">\n              <option value=\"wszystko\">Wszystko<\/option>\n              <option value=\"do40\">do 40<\/option>\n              <option value=\"40-80\">40\u201380<\/option>\n              <option value=\"80-120\">80\u2013120<\/option>\n              <option value=\"120plus\">> 120<\/option>\n            <\/select>\n    <\/div>\n    <\/div>\n<\/div>\n\n<!-- 3) GRID I PAGINACJA -->\n<div class=\"pase-grid-wrapper\">\n    <div class=\"pase-apartments-grid\" id=\"paseApartmentsGrid\"><\/div>\n    <div class=\"pase-pagination\"     id=\"pasePagination\"><\/div>\n<\/div>\n\n<script>\n  \/\/ Dane z PHP\n  let paseApartmentsData = [];\n\n  \/\/ DEBUG: poka\u017c surowe dane\n  console.log('RAW apartments_data:', paseApartmentsData);\n\n  \/\/ 1) Tasowanie\n  paseApartmentsData.sort(() => Math.random() - 0.5);\n  console.log('SHUFFLED apartments_data:', paseApartmentsData);\n\n  \/\/ Elementy DOM\n  const gridContainer   = document.getElementById('paseApartmentsGrid');\n  const paginationEl    = document.getElementById('pasePagination');\n  const categoryButtons = document.querySelectorAll('#paseCategoryFilters button');\n  const searchInput     = document.getElementById('paseSearchInput');\n  const personsSelect   = document.getElementById('paseFilterPersons');\n  const bedsSelect      = document.getElementById('paseFilterBedrooms');\n  const areaSelect      = document.getElementById('paseFilterArea');\n\n  \/\/ Stan\n  let currentPage        = 1;\n  const pageSize         = 18;\n  let filteredApartments = [];\n\n  \/\/ Pomoc: slug\n  function generateSlugFromName(name) {\n    return name\n      .normalize(\"NFD\")\n      .replace(\/[\\u0300-\\u036f]\/g, '')\n      .toLowerCase()\n      .replace(\/ \/g, '-')\n      .replace(\/[^a-z0-9-]\/g, '');\n  }\n\n  \/\/ Rysowanie jednej karty\n  function renderApartmentCard(ap) {\n    const detailsUrl = `\/${generateSlugFromName(ap.name)}\/`;\n    const thumb = ap.thumbnail\n      ? `<a href=\"${detailsUrl}\"><img decoding=\"async\" src=\"${ap.thumbnail}\" alt=\"${ap.name}\"\/><\/a>`\n      : `<a href=\"${detailsUrl}\"><img decoding=\"async\" src=\"\" alt=\"${ap.name}\"\/><\/a>`;\n    const desc = ap.description.length > 100\n      ? ap.description.slice(0,100) + '\u2026'\n      : ap.description;\n\n  const metaHTML = `\n    <div class=\"apt-meta\">\n      <span><i class=\"fa-solid fa-expand\"><\/i> ${ap.area} m\u00b2<\/span>\n      <span><i class=\"fa-solid fa-door-open\"><\/i> ${ap.num_bedrooms}<\/span>\n      <span><i class=\"fa-solid fa-user\"><\/i> ${ap.max_persons}<\/span>\n    <\/div>\n  `;\n\n    return `\n      <div class=\"pase-apartment-item\">\n        ${thumb}\n        <div class=\"pase-apartment-header\">${ap.name}<\/div>\n        <div class=\"apt-description\">${desc}<\/div>\n        ${metaHTML}\n        <a class=\"btn-details\"     href=\"${detailsUrl}\">Szczeg\u00f3\u0142y<\/a>\n        <a class=\"btn-reservation\" href=\"\/rezerwacja\/?lang=pl&showRoomType=${ap.obkId}\/\">Zarezerwuj<\/a>\n      <\/div>\n    `;\n  }\n\n  \/\/ Rysowanie siatki\n  function renderGrid(apts, page = 1) {\n    if (!apts.length) {\n      gridContainer.innerHTML = '<p>Brak wynik\u00f3w dla wybranych filtr\u00f3w.<\/p>';\n      paginationEl.innerHTML  = '';\n      return;\n    }\n    const totalPages = Math.ceil(apts.length \/ pageSize);\n    currentPage = Math.min(Math.max(page, 1), totalPages);\n    const start = (currentPage - 1) * pageSize;\n    const slice = apts.slice(start, start + pageSize);\n    gridContainer.innerHTML = slice.map(renderApartmentCard).join('');\n    renderPagination(apts);\n  }\n\n  \/\/ Rysowanie paginacji\n  function renderPagination(apts) {\n    const totalPages = Math.ceil(apts.length \/ pageSize);\n    if (totalPages <= 1) {\n      paginationEl.innerHTML = '';\n      return;\n    }\n    let html = `<button onclick=\"goToPage(${currentPage - 1})\" ${currentPage === 1 ? 'disabled' : ''}>\u2039<\/button>`;\n    for (let i = 1; i <= totalPages; i++) {\n      html += `<button onclick=\"goToPage(${i})\" class=\"${i === currentPage ? 'active' : ''}\">${i}<\/button>`;\n    }\n    html += `<button onclick=\"goToPage(${currentPage + 1})\" ${currentPage === totalPages ? 'disabled' : ''}>\u203a<\/button>`;\n    paginationEl.innerHTML = html;\n  }\n\n  \/\/ Wywo\u0142anie z paginacji\n  window.goToPage = function(page) {\n    applyFilters(page);\n  };\n\n  \/\/ Pomoc: kategorie apartamentu\n  function getCategories(ap) {\n    if (!ap.category) return [];\n    return ap.category\n      .split(',')\n      .map(s => s.trim().toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g, ''))\n      .filter(Boolean);\n  }\n\n  \/\/ G\u0142\u00f3wna funkcja filtruj\u0105ca\n  function applyFilters(page = 1) {\n    const catRaw = document.querySelector('#paseCategoryFilters button.active').dataset.cat;\n    const catNorm = catRaw.toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g, '');\n    const txt     = searchInput.value.trim().toLowerCase();\n    const persons = personsSelect.value;\n    const beds    = bedsSelect.value;\n    const area    = areaSelect.value;\n\n    console.log('FILTER CRITERIA \u2192', { category: catNorm, text: txt, persons, bedrooms: beds, area });\n\n    filteredApartments = paseApartmentsData.filter(ap => {\n      \/\/ Kategoria\n      if (catNorm !== 'wszystko' && !getCategories(ap).includes(catNorm)) {\n        return false;\n      }\n      \/\/ Wyszukiwanie tekstowe\n      if (txt && !ap.name.toLowerCase().includes(txt)) {\n        return false;\n      }\n      \/\/ Ilo\u015b\u0107 os\u00f3b\n      const maxPersons = parseInt(ap.max_persons, 10) || 0;\n      if (persons !== 'wszystko') {\n        if (persons === '6plus' ? !(maxPersons >= 6) : maxPersons !== parseInt(persons, 10)) {\n          return false;\n        }\n      }\n      \/\/ Liczba sypialni\n      const bedrooms = parseInt(ap.num_bedrooms, 10) || 0;\n      if (beds !== 'wszystko') {\n        if (beds === '4plus' ? !(bedrooms >= 4) : bedrooms !== parseInt(beds, 10)) {\n          return false;\n        }\n      }\n      \/\/ Powierzchnia\n      const areaVal = parseFloat(ap.area) || 0;\n      if (area !== 'wszystko') {\n        if (area === 'do40'    && !(areaVal <= 40))            return false;\n        if (area === '40-80'   && !(areaVal > 40  && areaVal <= 80)) return false;\n        if (area === '80-120'  && !(areaVal > 80  && areaVal <= 120))return false;\n        if (area === '120plus' && !(areaVal > 120))            return false;\n      }\n      return true;\n    });\n\n    console.log('FILTERED apartments:', filteredApartments);\n    renderGrid(filteredApartments, page);\n  }\n\n  \/\/ Nas\u0142uchiwanie zmian\n  categoryButtons.forEach(btn => {\n    btn.addEventListener('click', () => {\n      categoryButtons.forEach(b => b.classList.remove('active'));\n      btn.classList.add('active');\n      applyFilters(1);\n    });\n  });\n  searchInput.addEventListener('input',  () => applyFilters(1));\n  personsSelect.addEventListener('change', () => applyFilters(1));\n  bedsSelect.addEventListener('change',    () => applyFilters(1));\n  areaSelect.addEventListener('change',    () => applyFilters(1));\n\n  \/\/ Start\n  applyFilters(1);\n<\/script>\n<\/div>\n      <\/div>\n    <\/section>","protected":false},"excerpt":{"rendered":"<p>Apartamenty Znajd\u017a sw\u00f3j wymarzony apartament na pobyt w Gda\u0144sku Wszystko Wyspa Spichrz\u00f3w Stare Miasto i Marina Widok Na Rzek\u0119 Ilo\u015b\u0107 os\u00f3b Wszystko 1 2 3 4 5 6+ Liczba sypialni Wszystko 1 2 3 4+ Powierzchnia Wszystko do 40 40\u201380 80\u2013120 > 120<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":98,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-888","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/pages\/888","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/comments?post=888"}],"version-history":[{"count":1,"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/pages\/888\/revisions"}],"predecessor-version":[{"id":1016,"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/pages\/888\/revisions\/1016"}],"wp:attachment":[{"href":"https:\/\/staywin.stronywwwpomorze.pl\/en\/wp-json\/wp\/v2\/media?parent=888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}