{"id":15624,"date":"2026-02-21T09:14:17","date_gmt":"2026-02-21T02:14:17","guid":{"rendered":"https:\/\/scphtrang.ac.th\/?page_id=15624"},"modified":"2026-02-25T08:30:45","modified_gmt":"2026-02-25T01:30:45","slug":"%e0%b8%9b%e0%b8%8f%e0%b8%b4%e0%b8%97%e0%b8%b4%e0%b8%99%e0%b8%81%e0%b8%b4%e0%b8%88%e0%b8%81%e0%b8%a3%e0%b8%a3%e0%b8%a1","status":"publish","type":"page","link":"https:\/\/scphtrang.ac.th\/?page_id=15624","title":{"rendered":"\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<!-- \n  \u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48 1: \u0e42\u0e2b\u0e25\u0e14 Tailwind CSS \u0e1c\u0e48\u0e32\u0e19 CDN \n  \u0e21\u0e35\u0e01\u0e32\u0e23\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32 preflight: false \u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e1b\u0e49\u0e2d\u0e07\u0e01\u0e31\u0e19\u0e44\u0e21\u0e48\u0e43\u0e2b\u0e49 Tailwind \u0e23\u0e35\u0e40\u0e0b\u0e47\u0e15\u0e2a\u0e44\u0e15\u0e25\u0e4c (CSS) \u0e02\u0e2d\u0e07 Theme \u0e2b\u0e25\u0e31\u0e01\u0e43\u0e19 WordPress\n-->\n<script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n<script>\n  tailwind.config = {\n    corePlugins: {\n      preflight: false,\n    },\n    theme: {\n      extend: {\n        colors: {\n          \/\/ \u0e41\u0e17\u0e19\u0e17\u0e35\u0e48\u0e40\u0e09\u0e14\u0e2a\u0e35\u0e2b\u0e25\u0e31\u0e01 (Indigo \u0e40\u0e14\u0e34\u0e21) \u0e14\u0e49\u0e27\u0e22\u0e42\u0e17\u0e19\u0e2a\u0e35\u0e43\u0e2b\u0e21\u0e48\u0e17\u0e35\u0e48\u0e2d\u0e34\u0e07\u0e08\u0e32\u0e01 #711D76\n          indigo: {\n            50: '#fdf6fd',\n            100: '#faeafa',\n            200: '#f3d4f3',\n            300: '#ebb3eb',\n            400: '#df86e0',\n            500: '#cd52ce',\n            600: '#711D76', \/\/ \u0e2a\u0e35\u0e2b\u0e25\u0e31\u0e01\u0e17\u0e35\u0e48\u0e04\u0e38\u0e13\u0e01\u0e33\u0e2b\u0e19\u0e14\n            700: '#5e1562',\n            800: '#4c1150',\n            900: '#3f1141',\n          }\n        }\n      }\n    }\n  }\n<\/script>\n\n<!-- \u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48 2: \u0e42\u0e04\u0e23\u0e07\u0e2a\u0e23\u0e49\u0e32\u0e07 UI \u0e41\u0e25\u0e30 CSS \u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21 -->\n<style>\n  \/* \u0e1b\u0e49\u0e2d\u0e07\u0e01\u0e31\u0e19\u0e01\u0e32\u0e23\u0e2a\u0e37\u0e1a\u0e17\u0e2d\u0e14 Style \u0e1a\u0e32\u0e07\u0e2d\u0e22\u0e48\u0e32\u0e07\u0e08\u0e32\u0e01 WordPress Theme \u0e17\u0e35\u0e48\u0e2d\u0e32\u0e08\u0e17\u0e33\u0e43\u0e2b\u0e49\u0e2b\u0e19\u0e49\u0e32\u0e15\u0e32\u0e40\u0e1e\u0e35\u0e49\u0e22\u0e19 *\/\n  #wp-event-calendar, #wp-event-calendar * {\n    box-sizing: border-box;\n  }\n  #wp-event-calendar button {\n    font-family: inherit;\n    appearance: none;\n    outline: none;\n  }\n  \n  \/* \u0e15\u0e01\u0e41\u0e15\u0e48\u0e07 Scrollbar \u0e43\u0e2b\u0e49\u0e14\u0e39\u0e40\u0e23\u0e35\u0e22\u0e1a\u0e2b\u0e23\u0e39 *\/\n  #wp-event-calendar .custom-scrollbar::-webkit-scrollbar {\n    width: 6px;\n  }\n  #wp-event-calendar .custom-scrollbar::-webkit-scrollbar-track {\n    background: transparent;\n  }\n  #wp-event-calendar .custom-scrollbar::-webkit-scrollbar-thumb {\n    background-color: #cbd5e1;\n    border-radius: 20px;\n  }\n  #wp-event-calendar .custom-scrollbar::-webkit-scrollbar-thumb:hover {\n    background-color: #94a3b8;\n  }\n\n  \/* \u0e0b\u0e48\u0e2d\u0e19\u0e1b\u0e38\u0e48\u0e21\u0e25\u0e39\u0e01\u0e28\u0e23\u0e43\u0e19\u0e42\u0e2b\u0e21\u0e14 Schedule *\/\n  .hide-nav #btn-prev, .hide-nav #btn-next, .hide-nav #btn-today {\n    opacity: 0.3;\n    pointer-events: none;\n  }\n<\/style>\n\n<div id=\"wp-event-calendar\" class=\"w-full bg-transparent flex items-center justify-center py-6 font-sans text-slate-800\">\n  <div class=\"max-w-[1000px] w-full bg-white rounded-3xl shadow-[0_8px_30px_rgb(0,0,0,0.06)] overflow-hidden flex flex-col border border-slate-100\">\n    \n    <!-- \u0e2a\u0e48\u0e27\u0e19\u0e2b\u0e31\u0e27 Top Bar: \u0e04\u0e27\u0e1a\u0e04\u0e38\u0e21\u0e21\u0e38\u0e21\u0e21\u0e2d\u0e07\u0e41\u0e25\u0e30\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48 -->\n    <div class=\"bg-slate-50\/80 px-4 py-4 sm:px-8 sm:py-5 border-b border-slate-100 flex flex-col sm:flex-row justify-between items-center gap-4\">\n      \n      <!-- \u0e1b\u0e38\u0e48\u0e21\u0e2a\u0e25\u0e31\u0e1a\u0e42\u0e2b\u0e21\u0e14 (\u0e2a\u0e31\u0e1b\u0e14\u0e32\u0e2b\u0e4c, \u0e40\u0e14\u0e37\u0e2d\u0e19, \u0e1b\u0e35, \u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23) -->\n      <div class=\"flex items-center space-x-1 bg-slate-200\/60 p-1.5 rounded-xl w-full sm:w-auto overflow-x-auto custom-scrollbar\">\n        <button id=\"tab-week\" onclick=\"changeView('week')\" class=\"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap text-slate-500 bg-transparent hover:text-slate-800\">\u0e2a\u0e31\u0e1b\u0e14\u0e32\u0e2b\u0e4c<\/button>\n        <button id=\"tab-month\" onclick=\"changeView('month')\" class=\"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap bg-white text-indigo-600 shadow-sm\">\u0e40\u0e14\u0e37\u0e2d\u0e19<\/button>\n        <button id=\"tab-year\" onclick=\"changeView('year')\" class=\"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap text-slate-500 bg-transparent hover:text-slate-800\">\u0e1b\u0e35<\/button>\n        <button id=\"tab-schedule\" onclick=\"changeView('schedule')\" class=\"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap text-slate-500 bg-transparent hover:text-slate-800\">\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23<\/button>\n      <\/div>\n\n      <!-- \u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e41\u0e2a\u0e14\u0e07\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e27\u0e25\u0e32 \u0e41\u0e25\u0e30\u0e1b\u0e38\u0e48\u0e21\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19\u0e2b\u0e19\u0e49\u0e32\/\u0e2b\u0e25\u0e31\u0e07 -->\n      <div id=\"nav-controls\" class=\"flex items-center justify-between w-full sm:w-auto space-x-4\">\n        <h1 id=\"global-date-title\" class=\"text-base sm:text-lg font-bold text-slate-800 m-0 leading-tight\"><\/h1>\n        \n        <div class=\"flex items-center space-x-1 bg-white p-1 rounded-full border border-slate-200 shadow-sm flex-shrink-0\">\n          <button id=\"btn-prev\" onclick=\"handlePrev()\" class=\"bg-transparent border-0 p-1.5 sm:p-2 rounded-full hover:bg-slate-50 text-slate-600 transition-colors cursor-pointer flex items-center justify-center\">\n            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m15 18-6-6 6-6\"\/><\/svg>\n          <\/button>\n          <div class=\"w-px h-4 bg-slate-200\"><\/div>\n          <button id=\"btn-today\" onclick=\"handleToday()\" class=\"bg-transparent border-0 px-3 py-1 text-sm font-medium text-slate-600 hover:text-indigo-600 transition-colors cursor-pointer\">\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49<\/button>\n          <div class=\"w-px h-4 bg-slate-200\"><\/div>\n          <button id=\"btn-next\" onclick=\"handleNext()\" class=\"bg-transparent border-0 p-1.5 sm:p-2 rounded-full hover:bg-slate-50 text-slate-600 transition-colors cursor-pointer flex items-center justify-center\">\n            <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m9 18 6-6-6-6\"\/><\/svg>\n          <\/button>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- \u0e1e\u0e37\u0e49\u0e19\u0e17\u0e35\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e1c\u0e25\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32 (\u0e0b\u0e49\u0e32\u0e22: \u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19, \u0e02\u0e27\u0e32: \u0e23\u0e32\u0e22\u0e01\u0e32\u0e23) -->\n    <div class=\"flex flex-col lg:flex-row flex-1 min-h-[500px]\">\n      \n      <!-- \u0e1d\u0e31\u0e48\u0e07\u0e0b\u0e49\u0e32\u0e22: \u0e41\u0e1c\u0e07\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19 (\u0e0b\u0e48\u0e2d\u0e19\u0e43\u0e19\u0e42\u0e2b\u0e21\u0e14\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23) -->\n      <div id=\"left-panel\" class=\"lg:w-[55%] p-6 sm:p-8 transition-all duration-300\">\n        \n        <!-- \u0e04\u0e2d\u0e19\u0e40\u0e17\u0e19\u0e40\u0e19\u0e2d\u0e23\u0e4c\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a \u0e2a\u0e31\u0e1b\u0e14\u0e32\u0e2b\u0e4c & \u0e40\u0e14\u0e37\u0e2d\u0e19 -->\n        <div id=\"container-month-week\">\n          <div class=\"grid grid-cols-7 gap-2 mb-4\">\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-red-400\">\u0e2d\u0e32.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-slate-400\">\u0e08.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-slate-400\">\u0e2d.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-slate-400\">\u0e1e.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-slate-400\">\u0e1e\u0e24.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-slate-400\">\u0e28.<\/div>\n            <div class=\"text-center text-xs sm:text-sm font-bold tracking-wide text-indigo-400\">\u0e2a.<\/div>\n          <\/div>\n          <div id=\"cal-grid\" class=\"grid grid-cols-7 gap-2 sm:gap-3\">\n            <!-- \u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e08\u0e30\u0e16\u0e39\u0e01\u0e41\u0e17\u0e23\u0e01\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48\u0e1c\u0e48\u0e32\u0e19 JS -->\n          <\/div>\n        <\/div>\n\n        <!-- \u0e04\u0e2d\u0e19\u0e40\u0e17\u0e19\u0e40\u0e19\u0e2d\u0e23\u0e4c\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a \u0e1b\u0e35 (12 \u0e40\u0e14\u0e37\u0e2d\u0e19) -->\n        <div id=\"container-year\" class=\"hidden\">\n          <div id=\"year-grid\" class=\"grid grid-cols-3 sm:grid-cols-4 gap-3 sm:gap-4 h-full\">\n            <!-- \u0e40\u0e14\u0e37\u0e2d\u0e19\u0e08\u0e30\u0e16\u0e39\u0e01\u0e41\u0e17\u0e23\u0e01\u0e17\u0e35\u0e48\u0e19\u0e35\u0e48\u0e1c\u0e48\u0e32\u0e19 JS -->\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <!-- \u0e1d\u0e31\u0e48\u0e07\u0e02\u0e27\u0e32: \u0e41\u0e1c\u0e07\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21 -->\n      <div id=\"right-panel\" class=\"lg:w-[45%] bg-[#FDFDFE] p-6 sm:p-8 border-t lg:border-t-0 lg:border-l border-slate-100 transition-all duration-300\">\n        <div class=\"h-full flex flex-col\">\n          \n          <div id=\"right-panel-header\" class=\"flex items-center justify-between mb-6\">\n            <h2 id=\"cal-header-title\" class=\"text-lg font-bold text-slate-800 flex items-center m-0 leading-tight\">\n              <!-- \u0e15\u0e31\u0e27\u0e41\u0e1b\u0e23 JS \u0e08\u0e30\u0e21\u0e32\u0e40\u0e15\u0e34\u0e21\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e15\u0e23\u0e07\u0e19\u0e35\u0e49 -->\n            <\/h2>\n            <button id=\"cal-view-all-btn\" onclick=\"clearSelection()\" class=\"bg-transparent border-0 text-sm text-indigo-600 font-medium hover:text-indigo-800 transition-colors hidden cursor-pointer p-0 m-0\">\n              \u0e14\u0e39\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\n            <\/button>\n          <\/div>\n\n          <div id=\"cal-events-list\" class=\"flex-1 overflow-y-auto pr-2 custom-scrollbar pb-4 max-h-[500px] lg:max-h-[600px] h-full relative\">\n            <!-- \u0e15\u0e31\u0e27\u0e41\u0e1b\u0e23 JS \u0e08\u0e30\u0e21\u0e32\u0e40\u0e15\u0e34\u0e21\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e15\u0e23\u0e07\u0e19\u0e35\u0e49 -->\n          <\/div>\n\n        <\/div>\n      <\/div>\n\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- \u0e2a\u0e48\u0e27\u0e19\u0e17\u0e35\u0e48 3: \u0e23\u0e30\u0e1a\u0e1a\u0e01\u0e32\u0e23\u0e17\u0e33\u0e07\u0e32\u0e19 (JavaScript) -->\n<script>\n  \/\/ Configuration\n  const API_KEY = 'AIzaSyCy7BxmIERe78R7bc3zehODdHFFc5luuqA';\n  const CALENDAR_ID = 'c_3181cf3ae0d819de153c4e1e9fdf16f2bf1c576cf113bd2406d25d308d390dd8@group.calendar.google.com';\n\n  \/\/ SVG Icons\n  const CalendarIconSVG = `<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect width=\"18\" height=\"18\" x=\"3\" y=\"4\" rx=\"2\" ry=\"2\"\/><line x1=\"16\" x2=\"16\" y1=\"2\" y2=\"6\"\/><line x1=\"8\" x2=\"8\" y1=\"2\" y2=\"6\"\/><line x1=\"3\" x2=\"21\" y1=\"10\" y2=\"10\"\/><\/svg>`;\n  const ClockIconSVG = `<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><polyline points=\"12 6 12 12 16 14\"\/><\/svg>`;\n  const MapPinIconSVG = `<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z\"\/><circle cx=\"12\" cy=\"10\" r=\"3\"\/><\/svg>`;\n\n  \/\/ State Variables\n  let currentView = 'month'; \/\/ 'week', 'month', 'year', 'schedule'\n  let currentDate = new Date();\n  let selectedDateStr = null; \/\/ \u0e23\u0e39\u0e1b\u0e41\u0e1a\u0e1a YYYY-MM-DD\n  let selectedMonthIndex = null; \/\/ 0 - 11 \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e42\u0e2b\u0e21\u0e14\u0e1b\u0e35\n  let allEvents = [];\n  let isLoading = false;\n  let apiError = null;\n\n  const monthsThaiFull = ['\u0e21\u0e01\u0e23\u0e32\u0e04\u0e21', '\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c', '\u0e21\u0e35\u0e19\u0e32\u0e04\u0e21', '\u0e40\u0e21\u0e29\u0e32\u0e22\u0e19', '\u0e1e\u0e24\u0e29\u0e20\u0e32\u0e04\u0e21', '\u0e21\u0e34\u0e16\u0e38\u0e19\u0e32\u0e22\u0e19', '\u0e01\u0e23\u0e01\u0e0e\u0e32\u0e04\u0e21', '\u0e2a\u0e34\u0e07\u0e2b\u0e32\u0e04\u0e21', '\u0e01\u0e31\u0e19\u0e22\u0e32\u0e22\u0e19', '\u0e15\u0e38\u0e25\u0e32\u0e04\u0e21', '\u0e1e\u0e24\u0e28\u0e08\u0e34\u0e01\u0e32\u0e22\u0e19', '\u0e18\u0e31\u0e19\u0e27\u0e32\u0e04\u0e21'];\n  const monthsThaiShort = ['\u0e21.\u0e04.', '\u0e01.\u0e1e.', '\u0e21\u0e35.\u0e04.', '\u0e40\u0e21.\u0e22.', '\u0e1e.\u0e04.', '\u0e21\u0e34.\u0e22.', '\u0e01.\u0e04.', '\u0e2a.\u0e04.', '\u0e01.\u0e22.', '\u0e15.\u0e04.', '\u0e1e.\u0e22.', '\u0e18.\u0e04.'];\n\n  \/\/ Initialize App\n  document.addEventListener(\"DOMContentLoaded\", () => {\n    updateViewUI();\n    fetchEvents();\n  });\n\n  \/\/ \u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e42\u0e2b\u0e21\u0e14\u0e21\u0e38\u0e21\u0e21\u0e2d\u0e07\n  function changeView(view) {\n    currentView = view;\n    selectedDateStr = null;\n    selectedMonthIndex = null;\n    \n    if (view === 'schedule') {\n      currentDate = new Date(); \/\/ \u0e23\u0e35\u0e40\u0e0b\u0e47\u0e15\u0e40\u0e1b\u0e47\u0e19\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49\u0e40\u0e2a\u0e21\u0e2d\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23\n    }\n    \n    updateViewUI();\n    fetchEvents();\n  }\n\n  \/\/ \u0e2d\u0e31\u0e1b\u0e40\u0e14\u0e15 UI \u0e02\u0e2d\u0e07\u0e41\u0e16\u0e1a\u0e04\u0e27\u0e1a\u0e04\u0e38\u0e21\u0e41\u0e25\u0e30\u0e41\u0e1c\u0e07\u0e15\u0e48\u0e32\u0e07\u0e46 \u0e15\u0e32\u0e21\u0e42\u0e2b\u0e21\u0e14\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19\n  function updateViewUI() {\n    const tabs = ['week', 'month', 'year', 'schedule'];\n    tabs.forEach(tab => {\n      const btn = document.getElementById(`tab-${tab}`);\n      if (tab === currentView) {\n        btn.className = \"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap bg-white text-indigo-600 shadow-sm\";\n      } else {\n        btn.className = \"flex-1 sm:flex-none px-4 py-2 rounded-lg text-sm font-semibold transition-all duration-200 border-none cursor-pointer whitespace-nowrap text-slate-500 bg-transparent hover:text-slate-800 hover:bg-slate-200\/50\";\n      }\n    });\n\n    const leftPanel = document.getElementById('left-panel');\n    const rightPanel = document.getElementById('right-panel');\n    const navControls = document.getElementById('nav-controls');\n    const rightPanelHeader = document.getElementById('right-panel-header');\n\n    if (currentView === 'schedule') {\n      leftPanel.style.display = 'none';\n      rightPanel.classList.remove('lg:w-[45%]');\n      rightPanel.classList.add('lg:w-full');\n      rightPanel.classList.remove('border-l');\n      navControls.classList.add('hide-nav');\n      rightPanelHeader.style.display = 'none'; \/\/ \u0e0b\u0e48\u0e2d\u0e19\u0e2b\u0e31\u0e27\u0e02\u0e49\u0e2d\u0e02\u0e27\u0e32\u0e43\u0e19\u0e42\u0e2b\u0e21\u0e14\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e30\u0e2d\u0e32\u0e14\u0e15\u0e32\n    } else {\n      leftPanel.style.display = 'block';\n      rightPanel.classList.add('lg:w-[45%]');\n      rightPanel.classList.remove('lg:w-full');\n      rightPanel.classList.add('border-l');\n      navControls.classList.remove('hide-nav');\n      rightPanelHeader.style.display = 'flex';\n    }\n\n    updateGlobalDateTitle();\n  }\n\n  \/\/ \u0e2d\u0e31\u0e1b\u0e40\u0e14\u0e15\u0e02\u0e49\u0e2d\u0e04\u0e27\u0e32\u0e21\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e1a\u0e19 Top Bar\n  function updateGlobalDateTitle() {\n    const titleEl = document.getElementById('global-date-title');\n    const y = currentDate.getFullYear();\n    const m = currentDate.getMonth();\n\n    if (currentView === 'month') {\n      titleEl.innerText = `${monthsThaiFull[m]} ${y + 543}`;\n    } else if (currentView === 'year') {\n      titleEl.innerText = `\u0e1b\u0e35 \u0e1e.\u0e28. ${y + 543}`;\n    } else if (currentView === 'schedule') {\n      titleEl.innerText = `\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23 (\u0e40\u0e23\u0e34\u0e48\u0e21\u0e15\u0e49\u0e19\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49)`;\n    } else if (currentView === 'week') {\n      const start = getStartOfWeek(currentDate);\n      const end = new Date(start);\n      end.setDate(end.getDate() + 6);\n      \n      if (start.getMonth() === end.getMonth()) {\n        titleEl.innerText = `${start.getDate()} - ${end.getDate()} ${monthsThaiFull[start.getMonth()]} ${start.getFullYear() + 543}`;\n      } else if (start.getFullYear() === end.getFullYear()) {\n        titleEl.innerText = `${start.getDate()} ${monthsThaiShort[start.getMonth()]} - ${end.getDate()} ${monthsThaiShort[end.getMonth()]} ${start.getFullYear() + 543}`;\n      } else {\n        titleEl.innerText = `${start.getDate()} ${monthsThaiShort[start.getMonth()]} ${start.getFullYear() + 543} - ${end.getDate()} ${monthsThaiShort[end.getMonth()]} ${end.getFullYear() + 543}`;\n      }\n    }\n  }\n\n  \/\/ \u0e14\u0e36\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e32\u0e01 API \u0e15\u0e32\u0e21\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e27\u0e25\u0e32\u0e02\u0e2d\u0e07\u0e42\u0e2b\u0e21\u0e14\u0e19\u0e31\u0e49\u0e19\u0e46\n  async function fetchEvents() {\n    isLoading = true;\n    apiError = null;\n    renderLeftPanel();\n    renderRightPanel();\n\n    let timeMin, timeMax;\n    const y = currentDate.getFullYear();\n    const m = currentDate.getMonth();\n\n    if (currentView === 'month') {\n      timeMin = new Date(y, m, 1).toISOString();\n      timeMax = new Date(y, m + 1, 0, 23, 59, 59).toISOString();\n    } else if (currentView === 'week') {\n      const start = getStartOfWeek(currentDate);\n      const end = new Date(start);\n      end.setDate(end.getDate() + 6);\n      end.setHours(23, 59, 59);\n      timeMin = start.toISOString();\n      timeMax = end.toISOString();\n    } else if (currentView === 'year') {\n      timeMin = new Date(y, 0, 1).toISOString();\n      timeMax = new Date(y, 11, 31, 23, 59, 59).toISOString();\n    } else if (currentView === 'schedule') {\n      const today = new Date();\n      today.setHours(0,0,0,0);\n      const nextYear = new Date(today);\n      nextYear.setFullYear(nextYear.getFullYear() + 1); \/\/ \u0e25\u0e48\u0e27\u0e07\u0e2b\u0e19\u0e49\u0e32 1 \u0e1b\u0e35\n      timeMin = today.toISOString();\n      timeMax = nextYear.toISOString();\n    }\n\n    const url = `https:\/\/www.googleapis.com\/calendar\/v3\/calendars\/${encodeURIComponent(CALENDAR_ID)}\/events?key=${API_KEY}&timeMin=${timeMin}&timeMax=${timeMax}&singleEvents=true&orderBy=startTime&maxResults=250`;\n\n    try {\n      const response = await fetch(url);\n      if (!response.ok) throw new Error('\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e14\u0e36\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e44\u0e14\u0e49');\n      const data = await response.json();\n      allEvents = data.items || [];\n    } catch (err) {\n      console.error(err);\n      apiError = '\u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\u0e2d\u0e35\u0e01\u0e04\u0e23\u0e31\u0e49\u0e07';\n    } finally {\n      isLoading = false;\n      renderLeftPanel();\n      renderRightPanel();\n    }\n  }\n\n  \/\/ Helper Functions \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\n  function getStartOfWeek(date) {\n    const d = new Date(date);\n    const day = d.getDay();\n    const diff = d.getDate() - day;\n    return new Date(d.getFullYear(), d.getMonth(), diff, 0, 0, 0);\n  }\n\n  function formatDateStr(year, month, day) {\n    return `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;\n  }\n\n  function parseEventDate(event) {\n    return event.start?.dateTime ? new Date(event.start.dateTime) : new Date(event.start?.date);\n  }\n\n  \/\/ \u0e2a\u0e23\u0e49\u0e32\u0e07\u0e08\u0e38\u0e14 (Dots) \u0e2a\u0e35\u0e43\u0e15\u0e49\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\n  function generateDotsHTML(eventsCount, isSelected) {\n    if (eventsCount === 0) return `<div class=\"h-1.5 mt-1 sm:mt-1.5\"><\/div>`;\n    let dotsHtml = `<div class=\"flex space-x-0.5 mt-1 sm:mt-1.5 h-1.5 items-center justify-center\">`;\n    const maxDots = Math.min(eventsCount, 3);\n    for (let j = 0; j < maxDots; j++) {\n      dotsHtml += `<div class=\"w-1.5 h-1.5 rounded-full ${isSelected ? 'bg-white\/90' : 'bg-indigo-400'}\"><\/div>`;\n    }\n    if (eventsCount > 3) {\n      dotsHtml += `<div class=\"w-1 h-1 rounded-full ${isSelected ? 'bg-white\/80' : 'bg-indigo-300'}\"><\/div>`;\n    }\n    dotsHtml += `<\/div>`;\n    return dotsHtml;\n  }\n\n  \/\/ \u0e40\u0e23\u0e19\u0e40\u0e14\u0e2d\u0e23\u0e4c\u0e1d\u0e31\u0e48\u0e07\u0e0b\u0e49\u0e32\u0e22 (\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e41\u0e1a\u0e1a\u0e15\u0e32\u0e23\u0e32\u0e07)\n  function renderLeftPanel() {\n    if (currentView === 'schedule') return; \/\/ \u0e0b\u0e48\u0e2d\u0e19\u0e44\u0e1b\u0e41\u0e25\u0e49\u0e27\n\n    const containerMW = document.getElementById('container-month-week');\n    const containerYear = document.getElementById('container-year');\n    const gridMW = document.getElementById('cal-grid');\n    const gridYear = document.getElementById('year-grid');\n\n    const today = new Date();\n    const y = currentDate.getFullYear();\n    const m = currentDate.getMonth();\n\n    if (currentView === 'month' || currentView === 'week') {\n      containerMW.style.display = 'block';\n      containerYear.style.display = 'none';\n      gridMW.innerHTML = '';\n\n      let daysToRender = [];\n      let blanksCount = 0;\n\n      if (currentView === 'month') {\n        const firstDay = new Date(y, m, 1).getDay();\n        const daysInMonth = new Date(y, m + 1, 0).getDate();\n        blanksCount = firstDay;\n        for (let i = 1; i <= daysInMonth; i++) daysToRender.push(new Date(y, m, i));\n      } else if (currentView === 'week') {\n        const start = getStartOfWeek(currentDate);\n        blanksCount = 0; \/\/ \u0e27\u0e31\u0e19\u0e2d\u0e32\u0e17\u0e34\u0e15\u0e22\u0e4c\u0e2d\u0e22\u0e39\u0e48\u0e0a\u0e48\u0e2d\u0e07\u0e41\u0e23\u0e01\u0e40\u0e2a\u0e21\u0e2d\n        for (let i = 0; i < 7; i++) {\n          const d = new Date(start);\n          d.setDate(d.getDate() + i);\n          daysToRender.push(d);\n        }\n      }\n\n      \/\/ \u0e27\u0e32\u0e14\u0e0a\u0e48\u0e2d\u0e07\u0e27\u0e48\u0e32\u0e07\n      for (let i = 0; i < blanksCount; i++) {\n        gridMW.innerHTML += `<div class=\"aspect-square\"><\/div>`;\n      }\n\n      \/\/ \u0e27\u0e32\u0e14\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\n      daysToRender.forEach(dateObj => {\n        const dayYear = dateObj.getFullYear();\n        const dayMonth = dateObj.getMonth();\n        const dayDate = dateObj.getDate();\n        const dateStr = formatDateStr(dayYear, dayMonth, dayDate);\n        \n        const dayEvents = allEvents.filter(e => {\n          const eStart = e.start?.dateTime || e.start?.date;\n          return eStart?.startsWith(dateStr);\n        });\n\n        const isSelected = selectedDateStr === dateStr;\n        const isTodayDay = today.getDate() === dayDate && today.getMonth() === dayMonth && today.getFullYear() === dayYear;\n        const isOutsideMonth = currentView === 'month' && dayMonth !== m; \/\/ \u0e01\u0e23\u0e13\u0e35\u0e40\u0e14\u0e37\u0e2d\u0e19\u0e0a\u0e19\u0e40\u0e14\u0e37\u0e2d\u0e19 (\u0e41\u0e15\u0e48\u0e2d\u0e31\u0e19\u0e19\u0e35\u0e49\u0e27\u0e32\u0e14\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e43\u0e19\u0e40\u0e14\u0e37\u0e2d\u0e19)\n\n        let btnClass = `w-full h-full flex flex-col items-center justify-center rounded-2xl text-sm sm:text-base font-medium transition-all duration-300 border-none cursor-pointer p-1 `;\n        \n        if (isSelected) {\n          btnClass += `bg-indigo-600 text-white shadow-md shadow-indigo-200 scale-105 `;\n        } else {\n          btnClass += `bg-transparent hover:bg-slate-50 text-slate-700 `;\n          if (currentView === 'week' && dayMonth !== currentDate.getMonth()) btnClass += `opacity-40 `;\n        }\n\n        if (isTodayDay && !isSelected) {\n          btnClass += `border-2 border-solid border-indigo-100 text-indigo-700 bg-indigo-50\/40 `;\n        } else if (!isSelected && !isTodayDay) {\n          btnClass += `border border-solid border-transparent `;\n        }\n\n        gridMW.innerHTML += `\n          <div class=\"relative aspect-square\">\n            <button onclick=\"handleDateClick('${dateStr}')\" class=\"${btnClass}\">\n              <span class=\"m-0 leading-none\">${dayDate}<\/span>\n              ${generateDotsHTML(dayEvents.length, isSelected)}\n            <\/button>\n          <\/div>\n        `;\n      });\n    } else if (currentView === 'year') {\n      containerMW.style.display = 'none';\n      containerYear.style.display = 'block';\n      gridYear.innerHTML = '';\n\n      for (let i = 0; i < 12; i++) {\n        \/\/ \u0e19\u0e31\u0e1a\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e43\u0e19\u0e40\u0e14\u0e37\u0e2d\u0e19\u0e19\u0e35\u0e49 (\u0e04\u0e23\u0e48\u0e32\u0e27\u0e46)\n        const monthPrefix = `${y}-${String(i + 1).padStart(2, '0')}`;\n        const monthEvents = allEvents.filter(e => {\n          const eStart = e.start?.dateTime || e.start?.date;\n          return eStart?.startsWith(monthPrefix);\n        });\n\n        const isSelected = selectedMonthIndex === i;\n        const isCurrentMonth = today.getFullYear() === y && today.getMonth() === i;\n\n        let btnClass = `w-full py-6 flex flex-col items-center justify-center rounded-2xl transition-all duration-300 border-none cursor-pointer `;\n        \n        if (isSelected) {\n          btnClass += `bg-indigo-600 text-white shadow-md shadow-indigo-200 scale-[1.02] `;\n        } else {\n          btnClass += `bg-slate-50 hover:bg-indigo-50 text-slate-700 border border-solid border-slate-100 hover:border-indigo-200 `;\n        }\n        \n        if (isCurrentMonth && !isSelected) {\n          btnClass += `ring-2 ring-indigo-200 ring-offset-2 `;\n        }\n\n        gridYear.innerHTML += `\n          <button onclick=\"handleMonthClick(${i})\" class=\"${btnClass}\">\n            <span class=\"text-base sm:text-lg font-bold mb-1\">${monthsThaiShort[i]}<\/span>\n            <span class=\"text-xs ${isSelected ? 'text-indigo-100' : 'text-slate-400'}\">${monthEvents.length > 0 ? `${monthEvents.length} \u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21` : '-'}<\/span>\n          <\/button>\n        `;\n      }\n    }\n  }\n\n  \/\/ \u0e40\u0e23\u0e19\u0e40\u0e14\u0e2d\u0e23\u0e4c\u0e1d\u0e31\u0e48\u0e07\u0e02\u0e27\u0e32 (\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21)\n  function renderRightPanel() {\n    const listContainer = document.getElementById('cal-events-list');\n    const headerTitle = document.getElementById('cal-header-title');\n    const viewAllBtn = document.getElementById('cal-view-all-btn');\n\n    \/\/ \u0e2a\u0e48\u0e27\u0e19\u0e2b\u0e31\u0e27\u0e02\u0e27\u0e32 (\u0e40\u0e09\u0e1e\u0e32\u0e30\u0e42\u0e2b\u0e21\u0e14\u0e17\u0e35\u0e48\u0e44\u0e21\u0e48\u0e43\u0e0a\u0e48 Schedule)\n    if (currentView !== 'schedule') {\n      if (currentView === 'year') {\n        if (selectedMonthIndex !== null) {\n          headerTitle.innerHTML = `<span class=\"bg-indigo-100 text-indigo-600 p-2 rounded-xl mr-3 flex items-center justify-center\">${CalendarIconSVG}<\/span>\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e14\u0e37\u0e2d\u0e19${monthsThaiFull[selectedMonthIndex]}`;\n          viewAllBtn.style.display = 'block';\n        } else {\n          headerTitle.innerHTML = `<span class=\"bg-indigo-100 text-indigo-600 p-2 rounded-xl mr-3 flex items-center justify-center\">${CalendarIconSVG}<\/span>\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e17\u0e31\u0e49\u0e07\u0e2b\u0e21\u0e14\u0e43\u0e19\u0e1b\u0e35 ${currentDate.getFullYear() + 543}`;\n          viewAllBtn.style.display = 'none';\n        }\n      } else {\n        if (selectedDateStr) {\n          const parts = selectedDateStr.split('-');\n          const d = parseInt(parts[2]);\n          const m = parseInt(parts[1]) - 1;\n          headerTitle.innerHTML = `<span class=\"bg-indigo-100 text-indigo-600 p-2 rounded-xl mr-3 flex items-center justify-center\">${CalendarIconSVG}<\/span>\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48 ${d} ${monthsThaiFull[m]}`;\n          viewAllBtn.style.display = 'block';\n        } else {\n          headerTitle.innerHTML = `<span class=\"bg-indigo-100 text-indigo-600 p-2 rounded-xl mr-3 flex items-center justify-center\">${CalendarIconSVG}<\/span>\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e43\u0e19${currentView === 'week' ? '\u0e2a\u0e31\u0e1b\u0e14\u0e32\u0e2b\u0e4c\u0e19\u0e35\u0e49' : '\u0e40\u0e14\u0e37\u0e2d\u0e19\u0e19\u0e35\u0e49'}`;\n          viewAllBtn.style.display = 'none';\n        }\n      }\n    }\n\n    \/\/ \u0e2a\u0e16\u0e32\u0e19\u0e30 Loading\n    if (isLoading) {\n      listContainer.innerHTML = [1, 2, 3].map(i => `\n        <div class=\"animate-pulse flex space-x-4 p-5 rounded-2xl border border-solid border-slate-100 bg-white mb-3\">\n          <div class=\"rounded-xl bg-slate-200 h-12 w-12\"><\/div>\n          <div class=\"flex-1 space-y-3 py-1\">\n            <div class=\"h-4 bg-slate-200 rounded w-3\/4\"><\/div>\n            <div class=\"h-3 bg-slate-200 rounded w-1\/2\"><\/div>\n          <\/div>\n        <\/div>\n      `).join('');\n      return;\n    }\n\n    \/\/ \u0e2a\u0e16\u0e32\u0e19\u0e30 Error\n    if (apiError) {\n      listContainer.innerHTML = `\n        <div class=\"text-center py-10 px-4 rounded-2xl bg-red-50 border border-solid border-red-100 mt-4\">\n          <p class=\"text-red-600 font-medium m-0\">${apiError}<\/p>\n        <\/div>\n      `;\n      return;\n    }\n\n    \/\/ \u0e1f\u0e34\u0e25\u0e40\u0e15\u0e2d\u0e23\u0e4c\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\n    let displayedEvents = allEvents;\n    \n    if (currentView === 'year' && selectedMonthIndex !== null) {\n      const prefix = `${currentDate.getFullYear()}-${String(selectedMonthIndex + 1).padStart(2, '0')}`;\n      displayedEvents = allEvents.filter(e => {\n        const eStart = e.start?.dateTime || e.start?.date;\n        return eStart?.startsWith(prefix);\n      });\n    } else if ((currentView === 'month' || currentView === 'week') && selectedDateStr) {\n      displayedEvents = allEvents.filter(e => {\n        const eStart = e.start?.dateTime || e.start?.date;\n        return eStart?.startsWith(selectedDateStr);\n      });\n    }\n\n    \/\/ \u0e2a\u0e16\u0e32\u0e19\u0e30\u0e27\u0e48\u0e32\u0e07\u0e40\u0e1b\u0e25\u0e48\u0e32 (Empty State)\n    if (displayedEvents.length === 0) {\n      listContainer.innerHTML = `\n        <div class=\"text-center py-16 px-4 flex flex-col items-center justify-center h-full\">\n          <div class=\"w-16 h-16 bg-slate-50 rounded-full flex items-center justify-center mb-4 text-slate-300\">\n            ${CalendarIconSVG}\n          <\/div>\n          <h3 class=\"text-lg font-bold text-slate-600 mb-1 m-0\">\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21<\/h3>\n          <p class=\"text-sm text-slate-400 m-0 mt-2\">\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23\u0e43\u0e14\u0e46 \u0e43\u0e19\u0e0a\u0e48\u0e27\u0e07\u0e40\u0e27\u0e25\u0e32\u0e19\u0e35\u0e49<\/p>\n        <\/div>\n      `;\n      return;\n    }\n\n    \/\/ \u0e2a\u0e23\u0e49\u0e32\u0e07 HTML \u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\n    if (currentView === 'schedule') {\n      \/\/ \u0e42\u0e2b\u0e21\u0e14\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23: \u0e08\u0e31\u0e14\u0e01\u0e25\u0e38\u0e48\u0e21\u0e15\u0e32\u0e21\u0e40\u0e14\u0e37\u0e2d\u0e19\n      let html = '';\n      let currentMonthStr = '';\n\n      displayedEvents.forEach(event => {\n        const eventStart = parseEventDate(event);\n        const mStr = `${monthsThaiFull[eventStart.getMonth()]} ${eventStart.getFullYear() + 543}`;\n        \n        if (mStr !== currentMonthStr) {\n          html += `<div class=\"sticky top-0 bg-[#FDFDFE]\/90 backdrop-blur-sm py-2 z-10 text-sm font-bold text-slate-400 mt-4 mb-2 first:mt-0\">${mStr}<\/div>`;\n          currentMonthStr = mStr;\n        }\n\n        html += generateEventCardHTML(event, true);\n      });\n      listContainer.innerHTML = html;\n    } else {\n      \/\/ \u0e42\u0e2b\u0e21\u0e14\u0e2d\u0e37\u0e48\u0e19\u0e46: \u0e41\u0e2a\u0e14\u0e07\u0e25\u0e34\u0e2a\u0e15\u0e4c\u0e40\u0e23\u0e35\u0e22\u0e07\u0e1b\u0e01\u0e15\u0e34\n      listContainer.innerHTML = displayedEvents.map(event => generateEventCardHTML(event, !selectedDateStr && currentView !== 'year')).join('');\n    }\n  }\n\n  \/\/ \u0e2a\u0e23\u0e49\u0e32\u0e07 Card \u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21 1 \u0e0a\u0e34\u0e49\u0e19\n  function generateEventCardHTML(event, showDateBadge) {\n    const eventStart = parseEventDate(event);\n    const isAllDay = !event.start?.dateTime;\n    const eventLink = event.htmlLink || '#';\n\n    let timeStr = '\u0e15\u0e25\u0e2d\u0e14\u0e27\u0e31\u0e19';\n    if (!isAllDay) {\n      const start = new Date(event.start.dateTime);\n      const end = new Date(event.end.dateTime);\n      timeStr = `${start.toLocaleTimeString('th-TH', { hour: '2-digit', minute: '2-digit' })} - ${end.toLocaleTimeString('th-TH', { hour: '2-digit', minute: '2-digit' })} \u0e19.`;\n    }\n\n    let leftDateHtml = '';\n    let badgeHtml = '';\n\n    if (currentView === 'schedule') {\n      \/\/ \u0e14\u0e35\u0e44\u0e0b\u0e19\u0e4c\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e42\u0e2b\u0e21\u0e14\u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23 (\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e15\u0e31\u0e27\u0e43\u0e2b\u0e0d\u0e48\u0e14\u0e49\u0e32\u0e19\u0e0b\u0e49\u0e32\u0e22)\n      leftDateHtml = `\n        <div class=\"flex flex-col items-center min-w-[50px] pt-1 pr-3 border-r border-slate-100 mr-4\">\n          <span class=\"text-xs font-bold text-indigo-400 mb-0.5\">${monthsThaiShort[eventStart.getMonth()]}<\/span>\n          <span class=\"text-2xl font-black text-slate-700 leading-none\">${eventStart.getDate()}<\/span>\n        <\/div>\n      `;\n    } else if (showDateBadge) {\n      \/\/ \u0e14\u0e35\u0e44\u0e0b\u0e19\u0e4c\u0e2a\u0e33\u0e2b\u0e23\u0e31\u0e1a\u0e42\u0e2b\u0e21\u0e14\u0e2d\u0e37\u0e48\u0e19\u0e46 \u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e1a\u0e2d\u0e01\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48 (\u0e1b\u0e49\u0e32\u0e22\u0e40\u0e25\u0e47\u0e01\u0e46 \u0e14\u0e49\u0e32\u0e19\u0e1a\u0e19)\n      badgeHtml = `<div class=\"text-[11px] font-bold tracking-wide text-indigo-500 mb-2 bg-indigo-50 inline-block px-2.5 py-1 rounded-md border border-indigo-100\/50\">${eventStart.getDate()} ${monthsThaiFull[eventStart.getMonth()]}<\/div>`;\n    }\n\n    let locationHtml = '';\n    if (event.location) {\n      locationHtml = `\n        <div class=\"flex items-start mt-1.5\">\n          <span class=\"text-slate-400 mr-1.5 mt-0.5 flex items-center\">${MapPinIconSVG}<\/span>\n          <span class=\"line-clamp-2 leading-snug m-0\">${event.location}<\/span>\n        <\/div>\n      `;\n    }\n\n    return `\n      <div class=\"group flex mb-3.5 last:mb-0 transition-all duration-300\">\n        ${leftDateHtml}\n        <a href=\"${eventLink}\" target=\"_blank\" rel=\"noopener noreferrer\" style=\"text-decoration: none; color: inherit;\" class=\"flex-1 bg-white p-4 sm:p-5 rounded-2xl border border-solid border-slate-100 shadow-sm hover:shadow-md hover:border-indigo-200 relative overflow-hidden transition-all block cursor-pointer\">\n          <div class=\"absolute top-0 left-0 w-1.5 h-full bg-indigo-400 rounded-l-2xl opacity-50 group-hover:opacity-100 group-hover:bg-indigo-500 transition-all\"><\/div>\n          <div class=\"pl-2\">\n            ${badgeHtml}\n            <h3 class=\"text-slate-800 font-bold text-base sm:text-lg leading-tight mb-2.5 m-0 group-hover:text-indigo-700 transition-colors\">\n              ${event.summary || '(\u0e44\u0e21\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21)'}\n            <\/h3>\n            <div class=\"text-xs sm:text-sm text-slate-500\">\n              <div class=\"flex items-center\">\n                <span class=\"text-slate-400 mr-1.5 flex items-center\">${ClockIconSVG}<\/span>\n                <span class=\"font-medium text-slate-600 m-0\">${timeStr}<\/span>\n              <\/div>\n              ${locationHtml}\n            <\/div>\n          <\/div>\n        <\/a>\n      <\/div>\n    `;\n  }\n\n  \/\/ -- \u0e1b\u0e38\u0e48\u0e21\u0e04\u0e27\u0e1a\u0e04\u0e38\u0e21\u0e17\u0e34\u0e28\u0e17\u0e32\u0e07 (Prev \/ Next \/ Today) --\n  function handlePrev() {\n    if (currentView === 'schedule') return;\n    if (currentView === 'month') currentDate.setMonth(currentDate.getMonth() - 1);\n    else if (currentView === 'week') currentDate.setDate(currentDate.getDate() - 7);\n    else if (currentView === 'year') currentDate.setFullYear(currentDate.getFullYear() - 1);\n    \n    selectedDateStr = null;\n    selectedMonthIndex = null;\n    updateGlobalDateTitle();\n    fetchEvents();\n  }\n\n  function handleNext() {\n    if (currentView === 'schedule') return;\n    if (currentView === 'month') currentDate.setMonth(currentDate.getMonth() + 1);\n    else if (currentView === 'week') currentDate.setDate(currentDate.getDate() + 7);\n    else if (currentView === 'year') currentDate.setFullYear(currentDate.getFullYear() + 1);\n    \n    selectedDateStr = null;\n    selectedMonthIndex = null;\n    updateGlobalDateTitle();\n    fetchEvents();\n  }\n\n  function handleToday() {\n    currentDate = new Date();\n    selectedDateStr = null;\n    selectedMonthIndex = null;\n    \n    \/\/ \u0e23\u0e35\u0e40\u0e0b\u0e47\u0e15\u0e27\u0e34\u0e27\u0e01\u0e25\u0e31\u0e1a\u0e44\u0e1b\u0e17\u0e35\u0e48 Month \u0e2b\u0e32\u0e01\u0e01\u0e14\u0e27\u0e31\u0e19\u0e19\u0e35\u0e49 (\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e43\u0e2b\u0e49\u0e04\u0e25\u0e49\u0e32\u0e22 Google Calendar) \u0e2b\u0e23\u0e37\u0e2d\u0e04\u0e07\u0e27\u0e34\u0e27\u0e40\u0e14\u0e34\u0e21\u0e44\u0e27\u0e49\n    \/\/ \u0e43\u0e19\u0e17\u0e35\u0e48\u0e19\u0e35\u0e49\u0e04\u0e07\u0e27\u0e34\u0e27\u0e40\u0e14\u0e34\u0e21\u0e44\u0e27\u0e49 \u0e41\u0e15\u0e48\u0e01\u0e23\u0e30\u0e42\u0e14\u0e14\u0e44\u0e1b\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19\n    updateGlobalDateTitle();\n    fetchEvents();\n  }\n\n  \/\/ -- \u0e01\u0e32\u0e23\u0e04\u0e25\u0e34\u0e01\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25 --\n  function handleDateClick(dateStr) {\n    selectedDateStr = dateStr;\n    renderLeftPanel(); \n    renderRightPanel(); \n  }\n\n  function handleMonthClick(monthIndex) {\n    selectedMonthIndex = monthIndex;\n    renderLeftPanel();\n    renderRightPanel();\n  }\n\n  function clearSelection() {\n    selectedDateStr = null;\n    selectedMonthIndex = null;\n    renderLeftPanel();\n    renderRightPanel();\n  }\n<\/script>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0e2a\u0e31\u0e1b\u0e14\u0e32\u0e2b\u0e4c \u0e40\u0e14\u0e37\u0e2d\u0e19 \u0e1b\u0e35 \u0e01\u0e33\u0e2b\u0e19\u0e14\u0e01\u0e32\u0e23 \u0e27\u0e31\u0e19\u0e19\u0e35\u0e49 \u0e2d\u0e32. \u0e08. \u0e2d. \u0e1e. \u0e1e\u0e24. \u0e28. \u0e2a. [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-15624","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/pages\/15624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=15624"}],"version-history":[{"count":16,"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/pages\/15624\/revisions"}],"predecessor-version":[{"id":15828,"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=\/wp\/v2\/pages\/15624\/revisions\/15828"}],"wp:attachment":[{"href":"https:\/\/scphtrang.ac.th\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}