{"id":6842,"date":"2026-02-26T12:02:56","date_gmt":"2026-02-26T06:32:56","guid":{"rendered":"https:\/\/tbspanthers.british-school.org\/?p=6842"},"modified":"2026-03-18T14:26:47","modified_gmt":"2026-03-18T08:56:47","slug":"training-schedule-term-4-2026","status":"publish","type":"post","link":"https:\/\/tbspanthers.british-school.org\/index.php\/training-schedule-term-4-2026\/","title":{"rendered":"Training Schedule &#8211; Term 4 (2026)"},"content":{"rendered":"\n<style>\n  \/* Scope *\/\n  .calendar-container {\n    --brand:#143D60;\n    --muted:#6b7280;\n    --chip:#eef2f7;\n    --chip-active:#143D60;\n    --chip-active-text:#fff;\n\n    font-family: 'Segoe UI', sans-serif;\n    max-width: 1200px;\n    margin: 40px auto;\n  }\n\n  .calendar-title {\n    text-align: center;\n    font-size: 28px;\n    font-weight: bold;\n    color: var(--brand);\n    margin-bottom: 10px;\n  }\n\n  .calendar-instruction{\n    margin:0 0 6px;\n    font-size:13px;\n    color:var(--muted);\n  }\n\n  .filter-wrapper {\n    text-align: center;\n    margin-bottom: 16px;\n    padding: 0 10px;\n  }\n  .filter-wrapper select {\n    margin: 5px;\n    padding: 8px 12px;\n    font-size: 14px;\n    border-radius: 8px;\n    border: 1px solid #ccc;\n  }\n\n  \/* ===== Desktop grid (unchanged) ===== *\/\n  .view-desktop .calendar-header {\n    display: grid;\n    grid-template-columns: 120px repeat(5, 1fr);\n    background: linear-gradient(to right, #143D60, #1e40af);\n    color: white;\n    font-weight: bold;\n    font-size: 15px;\n    text-align: center;\n  }\n  .view-desktop .calendar-header div {\n    padding: 12px;\n    border-right: 1px solid rgba(255, 255, 255, 0.15);\n  }\n  .view-desktop .calendar-grid {\n    display: grid;\n    grid-template-columns: 120px repeat(5, 1fr);\n    border-left: 1px solid #ccc;\n    border-top: 1px solid #ccc;\n  }\n  .view-desktop .calendar-grid .cell {\n    border-right: 1px solid #ccc;\n    border-bottom: 1px solid #ccc;\n    padding: 10px;\n    min-height: 110px;\n    font-size: 14px;\n  }\n  .view-desktop .calendar-grid .time-slot {\n    background-color: #f1f5f9;\n    font-weight: bold;\n    text-align: center;\n    color: #0f172a;\n  }\n  .session-card {\n    padding: 8px 10px;\n    border-left: 6px solid var(--dark);\n    background-color: var(--light);\n    border-radius: 8px;\n    margin-bottom: 8px;\n    color: var(--text);\n  }\n  .session-card .title { font-weight: 600; }\n  .session-card .icon { font-size: 12px; margin-right: 4px; }\n\n  \/* ===== Mobile stacked view ===== *\/\n  .view-mobile { display:none; }\n  .chipbars{\n    display:flex; flex-direction:column; gap:10px; padding:0 10px; margin-bottom:8px;\n    position: sticky; top:0; background:#fff; z-index:1; padding-top:8px;\n  }\n  .chipbar{\n    display:flex; gap:8px; overflow:auto; scrollbar-width:none; -ms-overflow-style:none;\n  }\n  .chipbar::-webkit-scrollbar{ display:none; }\n  .chip{\n    white-space:nowrap; border:1px solid #e5e7eb; background:var(--chip);\n    padding:8px 12px; border-radius:999px; font-size:13px; cursor:pointer; user-select:none;\n  }\n  .chip.active{ background:var(--chip-active); color:var(--chip-active-text); border-color:var(--chip-active); }\n\n  .mobile-header{\n    display:flex; justify-content:space-between; align-items:center;\n    padding:10px 14px; margin:8px 10px 0; border:1px solid #e5e7eb; border-radius:10px;\n    background:#f8fafc; color:#0f172a; font-size:14px;\n  }\n  .mobile-header .when{ font-weight:600; }\n  .mobile-header .time{ color:#334155; font-size:13px; }\n\n  .mobile-list{ padding:10px; display:grid; gap:10px; }\n  .m-card{\n    border:1px solid #e5e7eb; border-left:6px solid var(--dark);\n    background:#fff; border-radius:12px; padding:12px 12px 12px 12px;\n    box-shadow:0 2px 6px rgba(0,0,0,.04);\n  }\n  .m-line1{\n    display:flex; align-items:center; gap:8px; font-size:15px; font-weight:700;\n  }\n  .m-emoji{ font-size:18px; }\n  .m-sub{\n    margin-top:4px; font-size:13px; color:#334155; display:flex; gap:8px; flex-wrap:wrap;\n  }\n  .m-badge{\n    font-size:12px; padding:2px 8px; border-radius:999px; background:#f1f5f9; border:1px solid #e5e7eb;\n  }\n\n  \/* Show mobile layout on small screens *\/\n  @media (max-width: 768px){\n    .view-desktop{ display:none; }\n    .view-mobile{ display:block; }\n    .filter-wrapper select{ width:100%; max-width:480px; }\n    .calendar-title{ font-size:22px; }\n  }\n<\/style>\n\n<div class=\"calendar-container\" id=\"tbs-weekly-calendar\">\n  <div class=\"calendar-title\">\n    Panthers Weekly Training\n    <span style=\"font-size:16px; font-style: italic; font-weight:normal; display:block; margin-top:8px;\">\n      <strong>Training starts from 5 MARCH 2026 and ends on 22 MAY 2026.<\/strong>\n    <\/span>\n  <\/div>\n\n  <div class=\"filter-wrapper\">\n    <p class=\"calendar-instruction\">Update on 26 February 2026 at 11:50<\/p>\n    <p class=\"calendar-instruction\">Use the filters below to refine your view by activity or category.<\/p>\n    <select id=\"activitySelect\">\n      <option value=\"All\">All Activities<\/option>\n    <\/select>\n    <select id=\"categorySelect\">\n      <option value=\"All\">All Categories<\/option>\n      <option value=\"U9\">U9<\/option>\n      <option value=\"U11\">U11<\/option>\n      <option value=\"U14\">U14<\/option>\n      <option value=\"U17\">U17<\/option>\n      <option value=\"U19\">U19<\/option>\n    <\/select>\n  <\/div>\n\n  <!-- Desktop grid -->\n  <div class=\"view-desktop\" id=\"desktopView\"><\/div>\n\n  <!-- Mobile stacked -->\n  <div class=\"view-mobile\">\n    <div class=\"chipbars\">\n      <div class=\"chipbar\" id=\"dayChips\"><\/div>\n      <div class=\"chipbar\" id=\"slotChips\"><\/div>\n    <\/div>\n    <div class=\"mobile-header\">\n      <div class=\"when\" id=\"mobileWhen\">Monday \u2014 Morning<\/div>\n      <div class=\"time\" id=\"mobileTime\">06:15 \u2013 07:15<\/div>\n    <\/div>\n    <div class=\"mobile-list\" id=\"mobileList\"><\/div>\n  <\/div>\n<\/div>\n\n<script>\n  const csvUrl = \"https:\/\/docs.google.com\/spreadsheets\/d\/e\/2PACX-1vT1cyEz2q4nu0RNbBZGnauI1_HodOEm85C7udl6BCz8gRt2TVPxyfuucI08SXNWuA9KsFStpF33-PFA\/pub?gid=1984146272&single=true&output=csv\";\n\n  const days = [\"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\"];\n  const slots = [\"Morning\", \"Early Afternoon\", \"Late Afternoon\"];\n  const timeMap = {\n    \"Morning\": \"06:15 \u2013 07:15\",\n    \"Early Afternoon\": \"14:25 \u2013 15:10\",\n    \"Late Afternoon\": \"15:20 \u2013 16:20\"\n  };\n\n  const emojiMap = {\n    \"Football\": \"\u26bd\", \"Swimming\": \"\ud83c\udfca\", \"Basketball\": \"\ud83c\udfc0\", \"Badminton\": \"\ud83c\udff8\",\n    \"Cricket\": \"\ud83c\udfcf\", \"Volleyball\": \"\ud83c\udfd0\", \"Table Tennis\": \"\ud83c\udfd3\", \"Athletics\": \"\ud83c\udfc3\", \"Tennis\": \"\ud83c\udfbe\"\n  };\n\n  const colorMap = {};\n  const colorPalette = [\n    [\"#b91c1c\", \"#fee2e2\", \"#7f1d1d\"],\n    [\"#1e3a8a\", \"#dbeafe\", \"#1e40af\"],\n    [\"#047857\", \"#d1fae5\", \"#065f46\"],\n    [\"#92400e\", \"#fef3c7\", \"#78350f\"],\n    [\"#7c3aed\", \"#ede9fe\", \"#5b21b6\"],\n    [\"#c2410c\", \"#ffedd5\", \"#7c2d12\"],\n    [\"#0369a1\", \"#e0f2fe\", \"#075985\"],\n    [\"#15803d\", \"#dcfce7\", \"#166534\"],\n    [\"#4f46e5\", \"#e0e7ff\", \"#3730a3\"],\n    [\"#a21caf\", \"#fce7f3\", \"#701a75\"]\n  ];\n  function getColor(activity) {\n    const key = activity || 'default';\n    if (!colorMap[key]) {\n      const [dark, light, text] = colorPalette[Object.keys(colorMap).length % colorPalette.length];\n      colorMap[key] = { \"--dark\": dark, \"--light\": light, \"--text\": text };\n    }\n    return colorMap[key];\n  }\n\n  function parseCSV(text) {\n    const [headerLine, ...lines] = text.trim().split(\"\\n\");\n    const rawHeaders = headerLine.split(\",\").map(h => h.trim());\n    const headers = rawHeaders.map(h => h.replace(\/\\s+\/g, \"\"));\n    return lines.map(line => {\n      const values = line.split(\",\").map(v => v.trim());\n      const entry = {};\n      headers.forEach((h, i) => entry[h] = values[i]);\n      return entry;\n    });\n  }\n\n  \/** ========== DESKTOP GRID (unchanged logic) ========== *\/\n  function buildDesktopCalendar(data, activityFilter = \"All\", categoryFilter = \"All\") {\n    const container = document.getElementById(\"desktopView\");\n    let html = \"\";\n\n    const gridHeader = `\n      <div class=\"calendar-header\">\n        <div>Time<\/div>\n        ${days.map(day => `<div>${day}<\/div>`).join(\"\")}\n      <\/div>`;\n\n    slots.forEach(slot => {\n      html += gridHeader;\n      html += `<div class=\"calendar-grid\">`;\n      html += `<div class=\"cell time-slot\">${timeMap[slot]}<\/div>`;\n\n      days.forEach(day => {\n        const matches = data.filter(e => {\n          const activity = e[\"Activity\"];\n          const category = e[\"Category\"];\n          const matchesDay = e[\"Day\"] === day;\n          const matchesSlot = e[\"TimeSlot\"] === slot;\n          const matchesActivity = activityFilter === \"All\" || activity === activityFilter;\n          const matchesCategory = categoryFilter === \"All\" || (category||\"\").toUpperCase().includes(categoryFilter.toUpperCase());\n          return matchesDay && matchesSlot && matchesActivity && matchesCategory;\n        });\n\n        html += `<div class=\"cell\">`;\n        matches.forEach(e => {\n          const activity = e[\"Activity\"];\n          const emoji = emojiMap[activity] || \"\ud83d\udc3e\";\n          const color = getColor(activity);\n          html += `\n            <div class=\"session-card\" style=\"${Object.entries(color).map(([k,v])=>`${k}:${v}`).join(';')}\">\n              <div class=\"title\">${emoji} ${activity} <span style=\"margin-left:5px;\">| ${e[\"Category\"]||\"\"}<\/span><\/div>\n              <div><span class=\"icon\">\ud83d\udccd<\/span>${e[\"Location\"]||\"\"} ${e[\"Group\"]?`(${e[\"Group\"]})`:\"\"}<\/div>\n            <\/div>`;\n        });\n        html += `<\/div>`;\n      });\n\n      html += `<\/div>`;\n    });\n\n    container.innerHTML = html;\n  }\n\n  \/** ========== MOBILE STACKED VIEW ========== *\/\n  let currentDay = getTodayName();\n  if (!days.includes(currentDay)) currentDay = \"Monday\";\n  let currentSlot = \"Morning\";\n\n  function getTodayName(){\n    const idx = new Date().getDay(); \/\/ 0=Sun..6=Sat\n    return [\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"][idx];\n  }\n\n  function renderChips() {\n    const dayChips = document.getElementById(\"dayChips\");\n    const slotChips = document.getElementById(\"slotChips\");\n    dayChips.innerHTML = days.map(d => `<div class=\"chip ${d===currentDay?'active':''}\" data-day=\"${d}\">${d}<\/div>`).join(\"\");\n    slotChips.innerHTML = slots.map(s => `<div class=\"chip ${s===currentSlot?'active':''}\" data-slot=\"${s}\">${s}<\/div>`).join(\"\");\n\n    dayChips.querySelectorAll('.chip').forEach(ch => ch.addEventListener('click', e=>{\n      currentDay = e.currentTarget.getAttribute('data-day');\n      renderChips();\n      buildMobileList(window.__CALDATA__);\n    }));\n    slotChips.querySelectorAll('.chip').forEach(ch => ch.addEventListener('click', e=>{\n      currentSlot = e.currentTarget.getAttribute('data-slot');\n      renderChips();\n      buildMobileList(window.__CALDATA__);\n    }));\n  }\n\n  function buildMobileList(data, activityFilter = \"All\", categoryFilter = \"All\") {\n    const list = document.getElementById(\"mobileList\");\n    const when = document.getElementById(\"mobileWhen\");\n    const time = document.getElementById(\"mobileTime\");\n    when.textContent = `${currentDay} \u2014 ${currentSlot}`;\n    time.textContent = timeMap[currentSlot] || \"\";\n\n    const matches = data.filter(e => {\n      const activity = e[\"Activity\"];\n      const category = e[\"Category\"]||\"\";\n      const matchesDay = e[\"Day\"] === currentDay;\n      const matchesSlot = e[\"TimeSlot\"] === currentSlot;\n      const matchesActivity = activityFilter === \"All\" || activity === activityFilter;\n      const matchesCategory = categoryFilter === \"All\" || category.toUpperCase().includes(categoryFilter.toUpperCase());\n      return matchesDay && matchesSlot && matchesActivity && matchesCategory;\n    });\n\n    if (matches.length === 0){\n      list.innerHTML = `<div class=\"m-card\" style=\"border-left-color:#e5e7eb\">\n        <div class=\"m-line1\"><span class=\"m-emoji\">\ud83d\udc3e<\/span><strong>No sessions found<\/strong><\/div>\n        <div class=\"m-sub\">Try a different day, slot, or filters.<\/div>\n      <\/div>`;\n      return;\n    }\n\n    const html = matches.map(e => {\n      const activity = e[\"Activity\"];\n      const category = e[\"Category\"]||\"\";\n      const emoji = emojiMap[activity] || \"\ud83d\udc3e\";\n      const color = getColor(activity);\n      const left = Object.entries(color).map(([k,v])=>`${k}:${v}`).join(';');\n      return `\n        <div class=\"m-card\" style=\"${left}\">\n          <div class=\"m-line1\">\n            <span class=\"m-emoji\">\ud83d\udc41\ufe0f<\/span>\n            <span class=\"m-emoji\">${emoji}<\/span>\n            <span><strong>${(category?category+' ':'')}${activity}<\/strong><\/span>\n          <\/div>\n          <div class=\"m-sub\">\n            <span class=\"m-badge\">\ud83d\udccd ${e[\"Location\"]||\"Venue TBA\"}<\/span>\n            ${e[\"Group\"]?`<span class=\"m-badge\">${e[\"Group\"]}<\/span>`:\"\"}\n          <\/div>\n        <\/div>`;\n    }).join(\"\");\n    list.innerHTML = html;\n  }\n\n  \/** ========== WIRING ========== *\/\n  const activitySelect = document.getElementById(\"activitySelect\");\n  const categorySelect = document.getElementById(\"categorySelect\");\n\n  function updateBothViews() {\n    const a = activitySelect.value;\n    const c = categorySelect.value;\n    buildDesktopCalendar(window.__CALDATA__, a, c);\n    buildMobileList(window.__CALDATA__, a, c);\n  }\n\n  \/\/ Fetch + init\n  fetch(csvUrl)\n    .then(res => res.text())\n    .then(text => {\n      const data = parseCSV(text);\n      window.__CALDATA__ = data;\n\n      \/\/ Populate Activity dropdown\n      const activities = [...new Set(data.map(e => e[\"Activity\"]).filter(Boolean))].sort();\n      activities.forEach(act => {\n        const opt = document.createElement(\"option\");\n        opt.value = act;\n        opt.textContent = act;\n        activitySelect.appendChild(opt);\n      });\n\n      \/\/ Events\n      activitySelect.addEventListener(\"change\", updateBothViews);\n      categorySelect.addEventListener(\"change\", updateBothViews);\n\n      \/\/ Initial renders\n      renderChips();\n      buildDesktopCalendar(data);\n      buildMobileList(data);\n    });\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>Panthers Weekly Training Training starts from 5 MARCH 2026 and ends on 22 MAY 2026. Update on 26 February 2026 at 11:50 Use the filters [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6847,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[120,121,19],"tags":[],"class_list":["post-6842","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-primary","category-secondary","category-sports"],"_links":{"self":[{"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/posts\/6842"}],"collection":[{"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/comments?post=6842"}],"version-history":[{"count":4,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/posts\/6842\/revisions"}],"predecessor-version":[{"id":6848,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/posts\/6842\/revisions\/6848"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/media\/6847"}],"wp:attachment":[{"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/media?parent=6842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/categories?post=6842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tbspanthers.british-school.org\/index.php\/wp-json\/wp\/v2\/tags?post=6842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}