{"id":11367,"date":"2026-03-06T08:29:18","date_gmt":"2026-03-06T07:29:18","guid":{"rendered":"https:\/\/beatbrothers.pl.vh18350.vh.net.pl\/?page_id=11367"},"modified":"2026-03-06T08:58:10","modified_gmt":"2026-03-06T07:58:10","slug":"elementor-11367","status":"publish","type":"page","link":"https:\/\/beatbrothers.pl\/index.php\/elementor-11367\/","title":{"rendered":"kalendarz"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"11367\" class=\"elementor elementor-11367\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b3d9e32 e-flex e-con-boxed e-con e-parent\" data-id=\"b3d9e32\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-8b88a6e elementor-widget elementor-widget-html\" data-id=\"8b88a6e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"pl\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<style>\n  * { margin: 0; padding: 0; box-sizing: border-box; }\n\n  body {\n    background: #181818;\n    font-family: 'Georgia', serif;\n    color: #f0ece4;\n    padding: 40px 20px;\n  }\n\n  .calendar-header {\n    text-align: center;\n    margin-bottom: 40px;\n  }\n\n  .calendar-header .tag {\n    font-family: Arial, sans-serif;\n    font-size: 10px;\n    letter-spacing: 5px;\n    text-transform: uppercase;\n    color: #c49a1a;\n    margin-bottom: 12px;\n  }\n\n  .calendar-header h2 {\n    font-size: 36px;\n    font-weight: 300;\n    font-style: italic;\n    color: #f0ece4;\n    margin-bottom: 8px;\n  }\n\n  .calendar-header p {\n    font-family: Arial, sans-serif;\n    font-size: 13px;\n    color: #888880;\n  }\n\n  .legend {\n    display: flex;\n    justify-content: center;\n    gap: 32px;\n    margin-bottom: 32px;\n    flex-wrap: wrap;\n  }\n\n  .legend-item {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n    font-family: Arial, sans-serif;\n    font-size: 12px;\n    color: #888880;\n  }\n\n  .legend-dot {\n    width: 12px;\n    height: 12px;\n    border-radius: 50%;\n  }\n\n  .legend-dot.busy { background: #c49a1a; }\n  .legend-dot.free { background: #2a2a2a; border: 1px solid #3a3a3a; }\n\n  .months-grid {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 24px;\n    max-width: 900px;\n    margin: 0 auto;\n  }\n\n  @media (max-width: 700px) {\n    .months-grid { grid-template-columns: 1fr; }\n  }\n\n  .month {\n    background: #111111;\n    border: 1px solid #2a2a2a;\n    border-radius: 4px;\n    overflow: hidden;\n  }\n\n  .month-header {\n    background: #c49a1a;\n    padding: 14px 16px;\n    text-align: center;\n  }\n\n  .month-header h3 {\n    font-size: 15px;\n    font-weight: 600;\n    color: #0a0a0a;\n    letter-spacing: 2px;\n    text-transform: uppercase;\n    font-family: Arial, sans-serif;\n  }\n\n  .month-header span {\n    font-size: 11px;\n    color: rgba(0,0,0,0.6);\n    font-family: Arial, sans-serif;\n  }\n\n  .weekdays {\n    display: grid;\n    grid-template-columns: repeat(7, 1fr);\n    background: #0a0a0a;\n    padding: 8px 12px 4px;\n  }\n\n  .weekday {\n    text-align: center;\n    font-family: Arial, sans-serif;\n    font-size: 9px;\n    letter-spacing: 1px;\n    text-transform: uppercase;\n    color: #888880;\n    padding: 4px 0;\n  }\n\n  .days {\n    display: grid;\n    grid-template-columns: repeat(7, 1fr);\n    padding: 8px 12px 16px;\n    gap: 3px;\n  }\n\n  .day {\n    aspect-ratio: 1;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    justify-content: center;\n    border-radius: 3px;\n    font-family: Arial, sans-serif;\n    font-size: 12px;\n    color: #f0ece4;\n    position: relative;\n    cursor: default;\n    transition: all 0.2s;\n  }\n\n  .day.empty { background: transparent; }\n\n  .day.free {\n    background: #1e1e1e;\n    color: #888880;\n  }\n\n  .day.busy {\n    background: #c49a1a;\n    color: #0a0a0a;\n    font-weight: 700;\n    cursor: pointer;\n  }\n\n  .day.busy:hover {\n    background: #e8c030;\n    transform: scale(1.1);\n    z-index: 10;\n  }\n\n  .day.today {\n    border: 1px solid #c49a1a;\n    color: #c49a1a;\n  }\n\n  .day.past {\n    opacity: 0.3;\n  }\n\n  \/* Tooltip *\/\n  .day.busy[data-location]:hover::after {\n    content: attr(data-location);\n    position: absolute;\n    bottom: calc(100% + 6px);\n    left: 50%;\n    transform: translateX(-50%);\n    background: #0a0a0a;\n    border: 1px solid #c49a1a;\n    color: #f0ece4;\n    font-size: 10px;\n    white-space: nowrap;\n    padding: 4px 8px;\n    border-radius: 2px;\n    pointer-events: none;\n    z-index: 100;\n    font-weight: 400;\n  }\n\n  .loading {\n    text-align: center;\n    padding: 40px;\n    color: #888880;\n    font-family: Arial, sans-serif;\n    font-size: 13px;\n    grid-column: 1 \/ -1;\n  }\n\n  .loading::after {\n    content: '';\n    display: inline-block;\n    width: 16px;\n    height: 16px;\n    border: 2px solid #2a2a2a;\n    border-top-color: #c49a1a;\n    border-radius: 50%;\n    animation: spin 0.8s linear infinite;\n    margin-left: 8px;\n    vertical-align: middle;\n  }\n\n  @keyframes spin {\n    to { transform: rotate(360deg); }\n  }\n\n  .error {\n    text-align: center;\n    padding: 20px;\n    color: #888880;\n    font-family: Arial, sans-serif;\n    font-size: 12px;\n    grid-column: 1 \/ -1;\n  }\n<\/style>\n<\/head>\n<body>\n\n\n\n<div class=\"legend\">\n  <div class=\"legend-item\">\n    <div class=\"legend-dot busy\"><\/div>\n    <span>Termin zaj\u0119ty<\/span>\n  <\/div>\n  <div class=\"legend-item\">\n    <div class=\"legend-dot free\"><\/div>\n    <span>Termin wolny<\/span>\n  <\/div>\n<\/div>\n\n<div class=\"months-grid\" id=\"calendar\">\n  <div class=\"loading\">\u0141adowanie kalendarza<\/div>\n<\/div>\n\n<script>\n  const API_KEY = 'AIzaSyDlilA0z2A0g_uVTNhAf-7tzaeLuhECbVs';\n  const CALENDAR_ID = 'e7a5b636a9edfe1d43c419c9d469f6fe9c3f52e12ff3253e6bdecce525ced7d5@group.calendar.google.com';\n\n  const MONTHS_PL = ['Stycze\u0144','Luty','Marzec','Kwiecie\u0144','Maj','Czerwiec','Lipiec','Sierpie\u0144','Wrzesie\u0144','Pa\u017adziernik','Listopad','Grudzie\u0144'];\n  const WEEKDAYS = ['Pn','Wt','\u015ar','Cz','Pt','Sb','Nd'];\n\n  async function fetchEvents() {\n    const now = new Date();\n    const start = new Date(now.getFullYear(), now.getMonth(), 1);\n    const end = new Date(now.getFullYear(), now.getMonth() + 3, 31);\n\n    const url = `https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/${encodeURIComponent(CALENDAR_ID)}\/events?key=${API_KEY}&timeMin=${start.toISOString()}&timeMax=${end.toISOString()}&singleEvents=true&orderBy=startTime`;\n\n    try {\n      const res = await fetch(url);\n      const data = await res.json();\n      return data.items || [];\n    } catch(e) {\n      return [];\n    }\n  }\n\n  function parseEvents(events) {\n    const busy = {};\n    events.forEach(event => {\n      const dateStr = event.start?.date || event.start?.dateTime?.split('T')[0];\n      if (dateStr) {\n        busy[dateStr] = event.summary || 'Zaj\u0119te';\n      }\n    });\n    return busy;\n  }\n\n  function buildCalendar(busyDates) {\n    const now = new Date();\n    const today = `${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;\n    const container = document.getElementById('calendar');\n    container.innerHTML = '';\n\n    for (let i = 0; i < 3; i++) {\n      const d = new Date(now.getFullYear(), now.getMonth() + i, 1);\n      const year = d.getFullYear();\n      const month = d.getMonth();\n      const monthName = MONTHS_PL[month];\n\n      const firstDay = new Date(year, month, 1).getDay();\n      const offset = firstDay === 0 ? 6 : firstDay - 1;\n      const daysInMonth = new Date(year, month + 1, 0).getDate();\n\n      const monthEl = document.createElement('div');\n      monthEl.className = 'month';\n\n      monthEl.innerHTML = `\n        <div class=\"month-header\">\n          <h3>${monthName}<\/h3>\n          <span>${year}<\/span>\n        <\/div>\n        <div class=\"weekdays\">\n          ${WEEKDAYS.map(d => `<div class=\"weekday\">${d}<\/div>`).join('')}\n        <\/div>\n        <div class=\"days\" id=\"days-${i}\"><\/div>\n      `;\n\n      container.appendChild(monthEl);\n\n      const daysContainer = monthEl.querySelector(`#days-${i}`);\n\n      \/\/ Empty cells\n      for (let e = 0; e < offset; e++) {\n        const empty = document.createElement('div');\n        empty.className = 'day empty';\n        daysContainer.appendChild(empty);\n      }\n\n      \/\/ Days\n      for (let day = 1; day <= daysInMonth; day++) {\n        const dateStr = `${year}-${String(month+1).padStart(2,'0')}-${String(day).padStart(2,'0')}`;\n        const dayEl = document.createElement('div');\n        const isBusy = busyDates[dateStr];\n        const isToday = dateStr === today;\n        const isPast = dateStr < today;\n\n        let classes = 'day';\n        if (isBusy) classes += ' busy';\n        else classes += ' free';\n        if (isToday) classes += ' today';\n        if (isPast && !isBusy) classes += ' past';\n\n        dayEl.className = classes;\n        dayEl.textContent = day;\n\n        if (isBusy) {\n          dayEl.setAttribute('data-location', busyDates[dateStr]);\n          dayEl.title = busyDates[dateStr];\n        }\n\n        daysContainer.appendChild(dayEl);\n      }\n    }\n  }\n\n  async function init() {\n    try {\n      const events = await fetchEvents();\n      const busyDates = parseEvents(events);\n      buildCalendar(busyDates);\n    } catch(e) {\n      document.getElementById('calendar').innerHTML = '<div class=\"error\">Nie uda\u0142o si\u0119 za\u0142adowa\u0107 kalendarza. Spr\u00f3buj od\u015bwie\u017cy\u0107 stron\u0119.<\/div>';\n    }\n  }\n\n  init();\n<\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Termin zaj\u0119ty Termin wolny \u0141adowanie kalendarza<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-11367","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/pages\/11367","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/comments?post=11367"}],"version-history":[{"count":8,"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/pages\/11367\/revisions"}],"predecessor-version":[{"id":11375,"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/pages\/11367\/revisions\/11375"}],"wp:attachment":[{"href":"https:\/\/beatbrothers.pl\/index.php\/wp-json\/wp\/v2\/media?parent=11367"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}