{"id":1318,"date":"2026-05-16T20:39:48","date_gmt":"2026-05-16T20:39:48","guid":{"rendered":"https:\/\/njpth.com\/?page_id=1318"},"modified":"2026-05-21T11:32:11","modified_gmt":"2026-05-21T11:32:11","slug":"booking","status":"publish","type":"page","link":"https:\/\/njpth.com\/index.php\/booking\/","title":{"rendered":"Booking"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"th\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>\u0e23\u0e30\u0e1a\u0e1a\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e16\u0e48\u0e32\u0e22\u0e20\u0e32\u0e1e Portrait 1990.-<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n<\/head>\n<body class=\"bg-gray-100 min-h-screen p-4 md:p-8\">\n\n    <div class=\"max-w-6xl mx-auto grid grid-cols-1 md:grid-cols-3 gap-8\">\n        \n        <div class=\"md:col-span-1 bg-white p-6 rounded-xl shadow-lg h-fit\">\n            <h2 class=\"text-2xl font-bold text-center text-gray-800 mb-2\">\ud83d\udcf8 \u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e16\u0e48\u0e32\u0e22\u0e20\u0e32\u0e1e<\/h2>\n            <p class=\"text-center text-indigo-600 font-semibold mb-6\">\u0e41\u0e1e\u0e47\u0e01\u0e40\u0e01\u0e08\u0e40\u0e14\u0e35\u0e22\u0e27: Portrait 1990.-<\/p>\n            \n            <form id=\"bookingForm\" class=\"space-y-4\">\n                <div>\n                    <label class=\"block text-sm font-medium text-gray-700\">\u0e0a\u0e37\u0e48\u0e2d-\u0e19\u0e32\u0e21\u0e2a\u0e01\u0e38\u0e25<\/label>\n                    <input type=\"text\" name=\"name\" required class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 border focus:ring-indigo-500 focus:border-indigo-500\">\n                <\/div>\n\n                <div>\n                    <label class=\"block text-sm font-medium text-gray-700\">\u0e40\u0e1a\u0e2d\u0e23\u0e4c\u0e42\u0e17\u0e23\u0e28\u0e31\u0e1e\u0e17\u0e4c<\/label>\n                    <input type=\"tel\" name=\"phone\" required class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 border focus:ring-indigo-500 focus:border-indigo-500\">\n                <\/div>\n\n                <div>\n                    <label class=\"block text-sm font-medium text-gray-700\">\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07<\/label>\n                    <input type=\"date\" id=\"bookingDate\" name=\"date\" required class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 border focus:ring-indigo-500 focus:border-indigo-500\">\n                    <p id=\"dateWarning\" class=\"text-xs text-red-500 mt-1 hidden\">\u26a0\ufe0f \u0e02\u0e2d\u0e2d\u0e20\u0e31\u0e22! \u0e27\u0e31\u0e19\u0e19\u0e35\u0e49\u0e21\u0e35\u0e25\u0e39\u0e01\u0e04\u0e49\u0e32\u0e17\u0e48\u0e32\u0e19\u0e2d\u0e37\u0e48\u0e19\u0e08\u0e2d\u0e07\u0e40\u0e15\u0e47\u0e21\u0e41\u0e25\u0e49\u0e27<\/p>\n                <\/div>\n\n                <div>\n                    <label class=\"block text-sm font-medium text-gray-700\">\u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07<\/label>\n                    <input type=\"time\" id=\"bookingTime\" name=\"time\" required class=\"mt-1 block w-full rounded-md border-gray-300 shadow-sm p-2 border focus:ring-indigo-500 focus:border-indigo-500\">\n                <\/div>\n\n                <button type=\"submit\" id=\"submitBtn\" class=\"w-full bg-indigo-600 text-white p-3 rounded-md font-semibold hover:bg-indigo-700 transition duration-200\">\n                    \u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\n                <\/button>\n            <\/form>\n\n            <div id=\"statusMessage\" class=\"mt-4 text-center hidden font-medium\"><\/div>\n        <\/div>\n\n        <div class=\"md:col-span-2 bg-white p-6 rounded-xl shadow-lg\">\n            <div class=\"flex justify-between items-center mb-4\">\n                <h3 class=\"text-xl font-bold text-gray-800\">\ud83d\uddd3\ufe0f \u0e15\u0e32\u0e23\u0e32\u0e07\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e04\u0e34\u0e27\u0e08\u0e2d\u0e07<\/h3>\n                <span class=\"text-xs bg-green-100 text-green-800 px-2 py-1 rounded-full animate-pulse\">Real-time<\/span>\n            <\/div>\n            \n            <div class=\"overflow-x-auto\">\n                <table class=\"min-w-full divide-y divide-gray-200 text-sm text-left\">\n                    <thead class=\"bg-gray-50 text-gray-700 uppercase font-semibold\">\n                        <tr>\n                            <th class=\"px-4 py-3\">\u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e08\u0e2d\u0e07<\/th>\n                            <th class=\"px-4 py-3\">\u0e40\u0e27\u0e25\u0e32\u0e04\u0e34\u0e27<\/th>\n                            <th class=\"px-4 py-3\">\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e01\u0e32\u0e23\u0e21\u0e31\u0e14\u0e08\u0e33<\/th>\n                        <\/tr>\n                    <\/thead>\n                    <tbody id=\"queueTableBody\" class=\"divide-y divide-gray-200 text-gray-600\">\n                        <tr>\n                            <td colspan=\"3\" class=\"px-4 py-4 text-center\">\u0e01\u0e33\u0e25\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e04\u0e34\u0e27\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14&#8230;<\/td>\n                        <\/tr>\n                    <\/tbody>\n                <\/table>\n            <\/div>\n        <\/div>\n\n    <\/div>\n\n    <script>\n        const WEB_APP_URL = \"https:\/\/script.google.com\/macros\/s\/AKfycbzc8eJFgWIKkdHi3k8T7d7DNV-MTG45YscWPZz3B3Ucf1JLyLxgWR2EZZJaGMWcNRII\/exec\"; \n        let bookedSlots = []; \n\n        const today = new Date().toISOString().split('T')[0];\n        document.getElementById('bookingDate').min = today;\n\n        function fetchQueueData() {\n            fetch(WEB_APP_URL)\n            .then(response => {\n                if (!response.ok) throw new Error('Network response was not ok');\n                return response.json();\n            })\n            .then(data => {\n                bookedSlots = data.filter(slot => slot.status !== \"\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\");\n                renderTable();\n            })\n            .catch(error => {\n                console.error('Error fetching data:', error);\n                document.getElementById('queueTableBody').innerHTML = `<tr><td colspan=\"3\" class=\"px-4 py-4 text-center text-red-500 font-medium\">\u274c \u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14\u0e43\u0e19\u0e01\u0e32\u0e23\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e04\u0e34\u0e27<\/td><\/tr>`;\n            });\n        }\n\n        function renderTable() {\n            const tableBody = document.getElementById('queueTableBody');\n            if (!bookedSlots || bookedSlots.length === 0) {\n                tableBody.innerHTML = `<tr><td colspan=\"3\" class=\"px-4 py-4 text-center text-gray-400\">\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e21\u0e35\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07\u0e43\u0e19\u0e23\u0e30\u0e1a\u0e1a \u0e17\u0e38\u0e01\u0e27\u0e31\u0e19\u0e22\u0e31\u0e07\u0e27\u0e48\u0e32\u0e07\u0e2d\u0e22\u0e39\u0e48<\/td><\/tr>`;\n                return;\n            }\n\n            bookedSlots.sort((a, b) => new Date(a.date) - new Date(b.date));\n\n            tableBody.innerHTML = bookedSlots.map(slot => {\n                const [year, month, day] = slot.date.split('-');\n                const displayDate = `${day}\/${month}\/${year}`;\n                \n                let statusBadge = \"\";\n                let rowBg = \"bg-red-50\";\n\n                if (slot.status === \"\u0e21\u0e31\u0e14\u0e08\u0e33\u0e41\u0e25\u0e49\u0e27\") {\n                    statusBadge = `<span class=\"px-2 py-1 text-xs font-bold rounded-full bg-green-100 text-green-800\">\ud83d\udfe2 \u0e21\u0e31\u0e14\u0e08\u0e33\u0e41\u0e25\u0e49\u0e27 (\u0e04\u0e2d\u0e19\u0e40\u0e1f\u0e34\u0e23\u0e4c\u0e21\u0e04\u0e34\u0e27)<\/span>`;\n                    rowBg = \"bg-green-50\/50\";\n                } else {\n                    statusBadge = `<span class=\"px-2 py-1 text-xs font-bold rounded-full bg-yellow-100 text-yellow-800\">\ud83d\udfe1 \u0e23\u0e2d\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e21\u0e31\u0e14\u0e08\u0e33<\/span>`;\n                    rowBg = \"bg-yellow-50\/50\";\n                }\n\n                return `\n                    <tr class=\"${rowBg} border-l-4 ${slot.status === '\u0e21\u0e31\u0e14\u0e08\u0e33\u0e41\u0e25\u0e49\u0e27' ? 'border-green-500' : 'border-yellow-500'} hover:bg-gray-50 transition duration-150\">\n                        <td class=\"px-4 py-3 font-bold text-gray-900\">${displayDate}<\/td>\n                        <td class=\"px-4 py-3 text-gray-700\">${slot.time} \u0e19.<\/td>\n                        <td class=\"px-4 py-3\">${statusBadge}<\/td>\n                    <\/tr>\n                `;\n            }).join('');\n        }\n\n        const dateInput = document.getElementById('bookingDate');\n        const dateWarning = document.getElementById('dateWarning');\n        const submitBtn = document.getElementById('submitBtn');\n\n        function checkDateAvailability() {\n            const selectedDate = dateInput.value;\n            const isDateBooked = bookedSlots.some(slot => slot.date === selectedDate);\n\n            if (isDateBooked && selectedDate) {\n                dateWarning.classList.remove('hidden');\n                submitBtn.disabled = true; \n                submitBtn.className = \"w-full bg-gray-400 text-white p-3 rounded-md font-semibold cursor-not-allowed\";\n            } else {\n                dateWarning.classList.add('hidden');\n                submitBtn.disabled = false; \n                submitBtn.className = \"w-full bg-indigo-600 text-white p-3 rounded-md font-semibold hover:bg-indigo-700 transition duration-200\";\n            }\n        }\n\n        dateInput.addEventListener('change', checkDateAvailability);\n\n        document.getElementById('bookingForm').addEventListener('submit', function(e) {\n            e.preventDefault();\n            const form = e.target;\n            const statusMessage = document.getElementById('statusMessage');\n\n            submitBtn.disabled = true;\n            submitBtn.innerText = \"\u0e01\u0e33\u0e25\u0e31\u0e07\u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e2d\u0e07...\";\n            statusMessage.classList.add('hidden');\n\n            const formData = new FormData(form);\n            const searchParams = new URLSearchParams();\n            for (const pair of formData) {\n                searchParams.append(pair[0], pair[1]);\n            }\n\n            fetch(WEB_APP_URL, {\n                method: 'POST',\n                body: searchParams,\n                headers: { 'Content-Type': 'application\/x-www-form-urlencoded' }\n            })\n            .then(response => response.json())\n            .then(data => {\n                if(data.result === \"success\") {\n                    statusMessage.innerText = \"\ud83c\udf89 \u0e2a\u0e48\u0e07\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e2a\u0e33\u0e40\u0e23\u0e47\u0e08 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e23\u0e2d\u0e41\u0e2d\u0e14\u0e21\u0e34\u0e19\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e21\u0e31\u0e14\u0e08\u0e33!\";\n                    statusMessage.className = \"mt-4 text-center font-medium text-green-600\";\n                    form.reset();\n                    fetchQueueData(); \n                } else if(data.result === \"dup\") {\n                    statusMessage.innerText = \"\u274c \u0e02\u0e2d\u0e2d\u0e20\u0e31\u0e22! \u0e27\u0e31\u0e19\u0e19\u0e35\u0e49\u0e16\u0e39\u0e01\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e15\u0e31\u0e14\u0e2b\u0e19\u0e49\u0e32\u0e44\u0e1b\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e2a\u0e31\u0e01\u0e04\u0e23\u0e39\u0e48\";\n                    statusMessage.className = \"mt-4 text-center font-medium text-red-600\";\n                    fetchQueueData();\n                } else {\n                    statusMessage.innerText = \"\u274c \u0e40\u0e01\u0e34\u0e14\u0e02\u0e49\u0e2d\u0e1c\u0e34\u0e14\u0e1e\u0e25\u0e32\u0e14 \u0e01\u0e23\u0e38\u0e13\u0e32\u0e25\u0e2d\u0e07\u0e43\u0e2b\u0e21\u0e48\";\n                    statusMessage.className = \"mt-4 text-center font-medium text-red-600\";\n                }\n            })\n            .catch(error => {\n                console.error('Error:', error);\n                statusMessage.innerText = \"\u274c \u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e15\u0e34\u0e14\u0e15\u0e48\u0e2d\u0e10\u0e32\u0e19\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e44\u0e14\u0e49\";\n                statusMessage.className = \"mt-4 text-center font-medium text-red-600\";\n            })\n            .finally(() => {\n                submitBtn.innerText = \"\u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\";\n                statusMessage.classList.remove('hidden');\n            });\n        });\n\n        fetchQueueData();\n    <\/script>\n<\/body>\n<\/html>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0e23\u0e30\u0e1a\u0e1a\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e16\u0e48\u0e32\u0e22\u0e20\u0e32\u0e1e Portrait 1990.- \ud83d\udcf8 \u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27\u0e16\u0e48\u0e32\u0e22\u0e20\u0e32\u0e1e \u0e41\u0e1e\u0e47\u0e01\u0e40\u0e01\u0e08\u0e40\u0e14\u0e35\u0e22\u0e27: Portrait 1990.- \u0e0a\u0e37\u0e48\u0e2d-\u0e19\u0e32\u0e21\u0e2a\u0e01\u0e38\u0e25 \u0e40\u0e1a\u0e2d\u0e23\u0e4c\u0e42\u0e17\u0e23\u0e28\u0e31\u0e1e\u0e17\u0e4c \u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07 \u26a0\ufe0f \u0e02\u0e2d\u0e2d\u0e20\u0e31\u0e22! \u0e27\u0e31\u0e19\u0e19\u0e35\u0e49\u0e21\u0e35\u0e25\u0e39\u0e01\u0e04\u0e49\u0e32\u0e17\u0e48\u0e32\u0e19\u0e2d\u0e37\u0e48\u0e19\u0e08\u0e2d\u0e07\u0e40\u0e15\u0e47\u0e21\u0e41\u0e25\u0e49\u0e27 \u0e40\u0e27\u0e25\u0e32\u0e17\u0e35\u0e48\u0e15\u0e49\u0e2d\u0e07\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07 \u0e22\u0e37\u0e19\u0e22\u0e31\u0e19\u0e01\u0e32\u0e23\u0e08\u0e2d\u0e07\u0e04\u0e34\u0e27 \ud83d\uddd3\ufe0f \u0e15\u0e32\u0e23\u0e32\u0e07\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a\u0e2a\u0e16\u0e32\u0e19\u0e30\u0e04\u0e34\u0e27\u0e08\u0e2d\u0e07 Real-time \u0e27\u0e31\u0e19\u0e17\u0e35\u0e48\u0e08\u0e2d\u0e07 \u0e40\u0e27\u0e25\u0e32\u0e04\u0e34\u0e27 \u0e2a\u0e16\u0e32\u0e19\u0e30\u0e01\u0e32\u0e23\u0e21\u0e31\u0e14\u0e08\u0e33 \u0e01\u0e33\u0e25\u0e31\u0e07\u0e42\u0e2b\u0e25\u0e14\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e04\u0e34\u0e27\u0e25\u0e48\u0e32\u0e2a\u0e38\u0e14&#8230;<\/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-1318","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/pages\/1318","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/comments?post=1318"}],"version-history":[{"count":4,"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/pages\/1318\/revisions"}],"predecessor-version":[{"id":1331,"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/pages\/1318\/revisions\/1331"}],"wp:attachment":[{"href":"https:\/\/njpth.com\/index.php\/wp-json\/wp\/v2\/media?parent=1318"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}