{"id":43,"date":"2025-08-28T03:48:31","date_gmt":"2025-08-28T03:48:31","guid":{"rendered":"https:\/\/yot-power-catamarans.pl\/?page_id=43"},"modified":"2025-08-30T06:18:22","modified_gmt":"2025-08-30T06:18:22","slug":"test1","status":"publish","type":"page","link":"https:\/\/yot-power-catamarans.pl\/?page_id=43","title":{"rendered":"test1"},"content":{"rendered":"\n\n<div class=\"brf\">\n  <form id=\"brf-form\" class=\"brf-form\">\n    <h2 class=\"brf-title\">Rezerwacja \u0142odzi<\/h2>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">1) Lokalizacja<\/h3>\n      <div class=\"brf-cards\" id=\"brf-locations\">\n                  <button type=\"button\" class=\"brf-card\" data-role=\"location\" data-id=\"2\" aria-pressed=\"false\" onclick=\"BRF && BRF.selectLocation && BRF.selectLocation(this)\">\n            <span class=\"brf-card-title\">Gda\u0144sk<\/span>\n            <span class=\"brf-card-sub\">Marina Gda\u0144sk<\/span>          <\/button>\n                  <button type=\"button\" class=\"brf-card\" data-role=\"location\" data-id=\"1\" aria-pressed=\"false\" onclick=\"BRF && BRF.selectLocation && BRF.selectLocation(this)\">\n            <span class=\"brf-card-title\">Gdynia<\/span>\n            <span class=\"brf-card-sub\">Marina Gdynia<\/span>          <\/button>\n              <\/div>\n      <input type=\"hidden\" name=\"location_id\" id=\"brf-location-id\">\n    <\/section>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">2) Typ wynajmu<\/h3>\n      <div class=\"brf-cards\">\n        <button type=\"button\" class=\"brf-card\" data-role=\"rtype\" data-value=\"hourly\" aria-pressed=\"false\" onclick=\"BRF && BRF.selectRentalType && BRF.selectRentalType(this)\">\n          <span class=\"brf-card-title\">Godzinowy<\/span>\n          <span class=\"brf-card-sub\">1h, 3h, 12h<\/span>\n        <\/button>\n        <button type=\"button\" class=\"brf-card\" data-role=\"rtype\" data-value=\"daily\" aria-pressed=\"false\" onclick=\"BRF && BRF.selectRentalType && BRF.selectRentalType(this)\">\n          <span class=\"brf-card-title\">Dzienny<\/span>\n          <span class=\"brf-card-sub\">1 dzie\u0144 lub wi\u0119cej<\/span>\n        <\/button>\n      <\/div>\n      <input type=\"hidden\" name=\"rental_type\" id=\"brf-rental-type\">\n    <\/section>\n\n    <section class=\"brf-section\" id=\"brf-duration-box\" style=\"display:none;\">\n      <h3 class=\"brf-h3\">3) Czas<\/h3>\n      <div class=\"brf-cards\" id=\"brf-durations\"><\/div>\n      <input type=\"hidden\" name=\"duration\" id=\"brf-duration\">\n    <\/section>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">4) \u0141\u00f3d\u017a<\/h3>\n      <div id=\"brf-boats-container\">\n        <select id=\"brf-boat\" name=\"boat_id\" disabled onchange=\"BRF && BRF.boatChanged && BRF.boatChanged()\">\n          <option value=\"\">Najpierw wybierz lokalizacj\u0119 i czas\u2026<\/option>\n        <\/select>\n      <\/div>\n    <\/section>\n\n    <section class=\"brf-section\" id=\"brf-dates-hourly\" style=\"display:none;\">\n      <h3 class=\"brf-h3\">5) Termin (godzinowy)<\/h3>\n      <div class=\"brf-grid2\">\n        <label>Data\n          <input type=\"date\" id=\"brf-date-hourly\" name=\"rental_date\" onchange=\"BRF && BRF.dateHourlyChanged && BRF.dateHourlyChanged()\">\n        <\/label>\n        <label>Godziny\n          <select id=\"brf-slot\" name=\"time_slot\" disabled onchange=\"BRF && BRF.slotChanged && BRF.slotChanged()\">\n            <option value=\"\">Najpierw wybierz dat\u0119\u2026<\/option>\n          <\/select>\n        <\/label>\n      <\/div>\n    <\/section>\n\n    <section class=\"brf-section\" id=\"brf-dates-daily\" style=\"display:none;\">\n      <h3 class=\"brf-h3\">5) Termin (dzienny)<\/h3>\n      <div class=\"brf-grid2\">\n        <label>Data rozpocz\u0119cia\n          <input type=\"date\" id=\"brf-start-date\" name=\"start_date\" onchange=\"BRF && BRF.startDateChanged && BRF.startDateChanged()\">\n        <\/label>\n        <label>Data zako\u0144czenia\n          <input type=\"date\" id=\"brf-end-date\" name=\"end_date\" onchange=\"BRF && BRF.endDateChanged && BRF.endDateChanged()\">\n        <\/label>\n      <\/div>\n    <\/section>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">6) Opcje dodatkowe<\/h3>\n      <div class=\"brf-options\">\n                            <label class=\"brf-option\">\n            <input type=\"checkbox\" name=\"additional_options[2]\" value=\"1\">\n            <span>Sprz\u0105tanie \u2014 150 z\u0142<\/span>\n          <\/label>\n                    <label class=\"brf-option\">\n            <input type=\"checkbox\" name=\"additional_options[1]\" value=\"1\">\n            <span>Ubezpieczenie \u2014 50 z\u0142\/dzie\u0144<\/span>\n          <\/label>\n                    <label class=\"brf-option\">\n            <input type=\"checkbox\" name=\"additional_options[3]\" value=\"1\">\n            <span>Wynajem lod\u00f3wki \u2014 30 z\u0142<\/span>\n          <\/label>\n                        <\/div>\n    <\/section>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">7) Dane kontaktowe<\/h3>\n      <div class=\"brf-grid2\">\n        <label>Imi\u0119*\n          <input type=\"text\" name=\"customer_first_name\" required>\n        <\/label>\n        <label>Nazwisko*\n          <input type=\"text\" name=\"customer_last_name\" required>\n        <\/label>\n      <\/div>\n      <div class=\"brf-grid2\">\n        <label>Email*\n          <input type=\"email\" name=\"customer_email\" required>\n        <\/label>\n        <label>Telefon*\n          <input type=\"tel\" name=\"customer_phone\" required>\n        <\/label>\n      <\/div>\n      <div class=\"brf-grid2\">\n        <label>Firma\n          <input type=\"text\" name=\"customer_company\">\n        <\/label>\n        <label>NIP\n          <input type=\"text\" name=\"customer_nip\" pattern=\"[0-9]{10}\">\n        <\/label>\n      <\/div>\n      <label>Uwagi\n        <textarea name=\"notes\" rows=\"3\"><\/textarea>\n      <\/label>\n\n      <div class=\"brf-inline\">\n        <span>P\u0142atno\u015b\u0107:<\/span>\n        <label><input type=\"radio\" name=\"payment_method\" value=\"email\" checked> Na miejscu<\/label>\n        <label><input type=\"radio\" name=\"payment_method\" value=\"online\"> Online (PayU)<\/label>\n      <\/div>\n      <label>\n        <input type=\"checkbox\" name=\"accept_terms\" required> Akceptuj\u0119 regulamin i polityk\u0119 prywatno\u015bci\n      <\/label>\n    <\/section>\n\n    <section class=\"brf-section\">\n      <h3 class=\"brf-h3\">8) Cena i wys\u0142anie<\/h3>\n      <div id=\"brf-pricebox\">Cena: <strong id=\"brf-price\">\u2014<\/strong><\/div>\n      <div class=\"brf-inline\">\n        <button type=\"button\" class=\"brf-btn\" id=\"brf-calc\" onclick=\"BRF && BRF.calculatePrice && BRF.calculatePrice()\">Oblicz cen\u0119<\/button>\n        <button type=\"submit\" class=\"brf-btn brf-primary\">Z\u0142\u00f3\u017c rezerwacj\u0119<\/button>\n      <\/div>\n      <input type=\"hidden\" id=\"brf-start-time\" name=\"start_time\">\n      <input type=\"hidden\" id=\"brf-end-time\" name=\"end_time\">\n      <input type=\"hidden\" id=\"brf-final-price\" name=\"final_price\">\n    <\/section>\n  <\/form>\n<\/div>\n\n<script>\n(()=>{\n  const $ = (s, r=document) => r.querySelector(s);\n  const $$ = (s, r=document) => Array.from(r.querySelectorAll(s));\n  const ajaxurl = 'https:\/\/yot-power-catamarans.pl\/wp-admin\/admin-ajax.php';\n  const NONCE = 'b88e5c2e6a';\n  const money = (v)=> new Intl.NumberFormat('pl-PL',{style:'currency',currency:'PLN',minimumFractionDigits:0}).format(v);\n\n  const state = {\n    location_id: '',\n    rental_type: '',\n    duration: '',\n    boat_id: '',\n    start_date: '',\n    end_date: '',\n    start_time: '',\n    end_time: ''\n  };\n\n  function log(){ try{ console.log('[BRF]', ...arguments); }catch(e){} }\n\n  function post(action, data){\n    const payload = new URLSearchParams(Object.assign({ action, nonce: NONCE }, data||{}));\n    log('AJAX \u2192', action, Object.fromEntries(payload));\n    return fetch(ajaxurl, { method:'POST', headers:{'Content-Type':'application\/x-www-form-urlencoded'}, body: payload })\n      .then(r=>r.text())\n      .then(t=>{ try{ const j=JSON.parse(t); log('AJAX \u2190', action, j); return j; } catch(e){ console.error('[BRF][PARSE]', action, t); throw e; } });\n  }\n\n  function renderDurations(){\n    const box = $('#brf-duration-box');\n    const wrap = $('#brf-durations');\n    wrap.innerHTML = '';\n    const rt = state.rental_type;\n    if (!rt){ box.style.display='none'; return; }\n    const items = rt==='hourly'\n      ? [{v:'1h',t:'1 godzina'},{v:'3h',t:'3 godziny'},{v:'12h',t:'12 godzin'}]\n      : [{v:'1day',t:'1 dzie\u0144'},{v:'multiday',t:'Wiele dni'}];\n    items.forEach(i=>{\n      const btn = document.createElement('button');\n      btn.type='button'; btn.className='brf-card'; btn.dataset.role='duration'; btn.dataset.value=i.v; btn.setAttribute('aria-pressed','false');\n      btn.innerHTML = `<span class=\"brf-card-title\">${i.t}<\/span>`;\n      wrap.appendChild(btn);\n    });\n    box.style.display='block';\n  }\n\n  function applySelections(){\n    \/\/ toggle date sections\n    $('#brf-dates-hourly').style.display = state.rental_type==='hourly' ? 'block':'none';\n    $('#brf-dates-daily').style.display  = state.rental_type==='daily'  ? 'block':'none';\n  }\n\n  function loadBoats(){\n    const boatSel = $('#brf-boat');\n    boatSel.innerHTML = '<option value=\"\">\u0141adowanie\u2026<\/option>';\n    boatSel.disabled = true;\n    if (!state.location_id){ boatSel.innerHTML = '<option value=\"\">Wybierz lokalizacj\u0119\u2026<\/option>'; return; }\n    const payload = { location_id: state.location_id };\n    if (state.duration){ payload.duration = state.duration; }\n    post('get_available_boats', payload)\n      .then(res=>{\n        if (!res || !res.success){ boatSel.innerHTML = '<option value=\"\">Brak \u0142odzi<\/option>'; return; }\n        const boats = (res.data && res.data.boats) || [];\n        if (!boats.length){ boatSel.innerHTML = '<option value=\"\">Brak \u0142odzi<\/option>'; boatSel.disabled=false; return; }\n        boatSel.innerHTML = '<option value=\"\">Wybierz \u0142\u00f3d\u017a\u2026<\/option>' + boats.map(b=>{\n          const priceText = (b.price!==undefined && b.price!==null && b.price!=='') ? ` \u2014 ${money(b.price)}` : '';\n          return `<option value=\"${b.id}\">${b.name} (${b.location_name})${priceText}<\/option>`;\n        }).join('');\n        boatSel.disabled = false;\n      })\n      .catch(()=>{ boatSel.innerHTML = '<option value=\"\">B\u0142\u0105d \u0142adowania<\/option>'; });\n  }\n\n  function loadSlots(){\n    const slotSel = $('#brf-slot');\n    slotSel.innerHTML = '<option value=\"\">\u0141adowanie\u2026<\/option>';\n    slotSel.disabled = true;\n    if (!state.boat_id || !$('#brf-date-hourly').value || !state.duration){\n      slotSel.innerHTML = '<option value=\"\">Najpierw wybierz \u0142\u00f3d\u017a i dat\u0119\u2026<\/option>'; return;\n    }\n    post('get_hourly_slots', { boat_id: state.boat_id, date: $('#brf-date-hourly').value, duration: state.duration })\n      .then(res=>{\n        const slots = (res && res.success && res.data && res.data.slots) ? res.data.slots : [];\n        if (!slots.length){ slotSel.innerHTML = '<option value=\"\">Brak termin\u00f3w<\/option>'; slotSel.disabled=true; return; }\n        slotSel.innerHTML = '<option value=\"\">Wybierz godziny\u2026<\/option>' + slots.map(s=>`<option value=\"${s.start_time}|${s.end_time}\">${s.display}<\/option>`).join('');\n        slotSel.disabled = false;\n      })\n      .catch(()=>{ slotSel.innerHTML = '<option value=\"\">B\u0142\u0105d \u0142adowania<\/option>'; slotSel.disabled=true; });\n  }\n\n  function gatherOptions(){\n    const opts = {};\n    $$('.brf-form input[name^=\"additional_options[\"]').forEach(ch=>{ if (ch.checked){ const id = ch.name.match(\/\\[(\\d+)\\]\/)[1]; opts[id]=1; } });\n    return opts;\n  }\n\n  function calculatePrice(){\n    if (!state.boat_id || !state.duration) return;\n    let start_date = '', end_date = '';\n    if (state.rental_type==='daily'){\n      start_date = $('#brf-start-date').value || '';\n      end_date   = $('#brf-end-date').value || start_date;\n    } else {\n      start_date = $('#brf-date-hourly').value || '';\n      end_date   = start_date;\n      if ($('#brf-slot').value){ const [s,e] = $('#brf-slot').value.split('|'); state.start_time=s; state.end_time=e; }\n    }\n    if (!start_date) return;\n    const add = gatherOptions();\n    post('calculate_price', { boat_id: state.boat_id, duration: state.duration, start_date, end_date, additional_options: JSON.stringify(add) })\n      .then(res=>{ if (res && res.success && res.data){ $('#brf-final-price').value = res.data.final_price; $('#brf-price').textContent = money(res.data.final_price); } });\n  }\n\n  \/\/ Interakcje\n  $('#brf-locations').addEventListener('click', (e)=>{\n    const btn = e.target.closest('[data-role=\"location\"]'); if (!btn) return;\n    $$('#brf-locations .brf-card').forEach(b=>b.classList.remove('brf-selected')); btn.classList.add('brf-selected');\n    state.location_id = btn.dataset.id; $('#brf-location-id').value = state.location_id; loadBoats();\n  });\n\n  $$('.brf-card[data-role=\"rtype\"]').forEach(b=> b.addEventListener('click',()=>{\n    $$('.brf-card[data-role=\"rtype\"]').forEach(x=>x.classList.remove('brf-selected'));\n    b.classList.add('brf-selected'); state.rental_type = b.dataset.value; $('#brf-rental-type').value = state.rental_type; renderDurations(); applySelections(); loadBoats();\n  }));\n\n  $('#brf-durations').addEventListener('click', (e)=>{\n    const btn = e.target.closest('[data-role=\"duration\"]'); if (!btn) return;\n    $$('#brf-durations .brf-card').forEach(x=>x.classList.remove('brf-selected'));\n    btn.classList.add('brf-selected'); state.duration = btn.dataset.value; $('#brf-duration').value = state.duration; loadBoats(); calculatePrice();\n  });\n\n  $('#brf-boat').addEventListener('change', ()=>{ state.boat_id = $('#brf-boat').value; loadSlots(); calculatePrice(); });\n  $('#brf-date-hourly').addEventListener('change', ()=>{ loadSlots(); calculatePrice(); });\n  $('#brf-slot').addEventListener('change', ()=>{ const v=$('#brf-slot').value; if (v){ const [s,e]=v.split('|'); $('#brf-start-time').value=s; $('#brf-end-time').value=e; } calculatePrice(); });\n  $('#brf-start-date').addEventListener('change', ()=>{ if (state.duration==='1day') $('#brf-end-date').value = $('#brf-start-date').value; calculatePrice(); });\n  $('#brf-end-date').addEventListener('change', calculatePrice);\n  $$('#brf-form input[name^=\"additional_options\"]').forEach(ch=> ch.addEventListener('change', calculatePrice));\n  $('#brf-calc').addEventListener('click', calculatePrice);\n\n  \/\/ Submit\n  $('#brf-form').addEventListener('submit', (e)=>{\n    e.preventDefault();\n    \/\/ Walidacja prosta\n    if (!state.location_id || !state.rental_type || !state.duration || !state.boat_id){ alert('Uzupe\u0142nij lokalizacj\u0119, typ, czas i \u0142\u00f3d\u017a.'); return; }\n    if (!$('#brf-final-price').value){ alert('Najpierw oblicz cen\u0119.'); return; }\n\n    const fd = new FormData($('#brf-form'));\n    \/\/ Ujednolicenie dat wymaganych przez backend: start_date \/ end_date\n    if (state.rental_type === 'hourly') {\n      const d = document.getElementById('brf-date-hourly').value || '';\n      if (!d) { alert('Wybierz dat\u0119.'); return; }\n      fd.set('start_date', d);\n      fd.set('end_date', d);\n    } else {\n      const sd = document.getElementById('brf-start-date').value || '';\n      const ed = document.getElementById('brf-end-date').value || sd;\n      if (!sd) { alert('Wybierz dat\u0119 rozpocz\u0119cia.'); return; }\n      fd.set('start_date', sd);\n      fd.set('end_date', ed);\n    }\n    fd.append('action','submit_booking');\n    fd.append('nonce', NONCE);\n    \/\/ Zbierz dodatkowe opcje jako dodatkowe pola (z FormData ju\u017c s\u0105, zostawiamy)\n    fetch(ajaxurl, { method:'POST', body: fd })\n      .then(r=>r.json())\n      .then(res=>{\n        log('submit response', res);\n        if (res && res.success){ alert('Rezerwacja z\u0142o\u017cona. Numer: '+(res.data && res.data.booking_number ? res.data.booking_number : '')); location.reload(); }\n        else { alert('B\u0142\u0105d: ' + (res && res.data ? res.data : 'nieznany')); }\n      })\n      .catch(err=> alert('B\u0142\u0105d wysy\u0142ki: ' + err.message));\n  });\n})();\n<\/script>\n\n<style>\n.brf{max-width:960px;margin:24px auto;background:#fff;border-radius:12px;box-shadow:0 6px 20px rgba(0,0,0,.08);padding:24px;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Arial,sans-serif}\n.brf-title{margin:0 0 12px 0;font-size:26px;color:#1d2630}\n.brf-section{margin:18px 0}\n.brf-h3{margin:0 0 10px 0;font-size:18px;color:#25334a}\n.brf-cards{display:flex;flex-wrap:wrap;gap:12px}\n.brf-card{display:flex;flex-direction:column;align-items:flex-start;gap:6px;padding:14px 16px;border:2px solid #e8eaf0;border-radius:10px;background:#fff;cursor:pointer;min-width:160px;transition:.2s all}\n.brf-card:hover{border-color:#667eea;background:#f5f7ff}\n.brf-selected{border-color:#667eea !important;background:linear-gradient(135deg,#667eea,#764ba2);color:#fff}\n.brf-card-title{font-weight:600}\n.brf-card-sub{font-size:12px;opacity:.85}\n.brf-grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px}\n.brf-inline{display:flex;gap:12px;align-items:center;flex-wrap:wrap}\n.brf-btn{padding:10px 14px;border-radius:8px;border:1px solid #d7daf0;background:#f5f7ff;cursor:pointer}\n.brf-primary{background:#667eea;color:#fff;border-color:#667eea}\nselect,input[type=\"text\"],input[type=\"email\"],input[type=\"tel\"],input[type=\"date\"],textarea{width:100%;padding:10px;border:1px solid #d7daf0;border-radius:8px}\n@media (max-width:720px){.brf-grid2{grid-template-columns:1fr}}\n<\/style>\n\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-43","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/pages\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=43"}],"version-history":[{"count":3,"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/pages\/43\/revisions"}],"predecessor-version":[{"id":55,"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=\/wp\/v2\/pages\/43\/revisions\/55"}],"wp:attachment":[{"href":"https:\/\/yot-power-catamarans.pl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}