manatwee commited on
Commit
862be38
·
verified ·
1 Parent(s): c748e1e

Upload index.html

Browse files
Files changed (1) hide show
  1. index.html +625 -19
index.html CHANGED
@@ -1,19 +1,625 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="th">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Dashboard จำนวนรับเข้านักศึกษาใหม่ (Teal Theme)</title>
7
+
8
+ <!-- Tailwind CSS (สำหรับโครงสร้างการจัดวางแบบพรีเมียมและยืดหยุ่น) -->
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <!-- Font Awesome -->
11
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
12
+ <!-- SweetAlert2 CSS -->
13
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
14
+ <!-- Google Fonts: Sarabun -->
15
+ <link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
16
+
17
+ <!-- Configure Tailwind with custom brand colors -->
18
+ <script>
19
+ tailwind.config = {
20
+ theme: {
21
+ extend: {
22
+ fontFamily: {
23
+ sans: ['Sarabun', 'sans-serif'],
24
+ },
25
+ colors: {
26
+ brand: {
27
+ 50: '#f0fdfa',
28
+ 100: '#ccfbf1',
29
+ 200: '#99f6e4',
30
+ 500: '#14b8a6',
31
+ 600: '#0d9488', // Main Teal
32
+ 700: '#0f766e',
33
+ 800: '#115e59',
34
+ 900: '#134e4a',
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ </script>
41
+
42
+ <style>
43
+ body { background-color: #f8fafc; } /* Soft Slate Background */
44
+
45
+ /* สไตล์ตารางสไตล์ Drill-down */
46
+ .clickable-row { cursor: pointer; user-select: none; transition: background-color 0.15s ease; }
47
+ .toggle-icon { width: 20px; text-align: center; transition: transform 0.2s; }
48
+
49
+ /* เอฟเฟคเมื่อคลิกเลือกจังหวัดจากแผนที่และส่งมาโฟกัสตาราง */
50
+ .highlight-row {
51
+ animation: highlight-effect 2s cubic-bezier(0.4, 0, 0.2, 1);
52
+ }
53
+ @keyframes highlight-effect {
54
+ 0% { background-color: rgba(20, 184, 166, 0.25); } /* Light Teal Highlight */
55
+ 100% { background-color: transparent; }
56
+ }
57
+
58
+ /* แฟนซีพิกัดแผนภูมิประเทศไทย */
59
+ .map-container { position: relative; height: 480px; width: 100%; }
60
+ #regions_div { width: 100%; height: 100%; }
61
+ </style>
62
+ </head>
63
+ <body class="font-sans text-slate-800 antialiased">
64
+
65
+ <!-- Premium White Navbar with Teal Top Accent -->
66
+ <header class="sticky top-0 z-50 border-b border-slate-100 bg-white/95 shadow-sm backdrop-blur">
67
+ <div class="mx-auto flex max-w-7xl items-center justify-between px-6 py-4">
68
+ <div class="flex items-center space-x-3">
69
+ <div class="flex h-10 w-10 items-center justify-center rounded-xl bg-brand-50 text-brand-600">
70
+ <i class="fa-solid fa-graduation-cap text-xl"></i>
71
+ </div>
72
+ <div>
73
+ <span class="text-xs font-semibold tracking-wider text-slate-400">ระบบรายงานสารสนเทศ</span>
74
+ <h1 class="text-lg font-bold text-slate-800">สถิติการรับเข้านักศึกษาใหม่</h1>
75
+ </div>
76
+ </div>
77
+ <button onclick="showInfo()" class="flex items-center space-x-2 rounded-lg border border-slate-200 bg-white px-3.5 py-1.5 text-sm font-medium text-slate-600 shadow-sm transition hover:bg-slate-50">
78
+ <i class="fa-solid fa-circle-info text-brand-600"></i>
79
+ <span>ข้อมูลระบบ</span>
80
+ </button>
81
+ </div>
82
+ </header>
83
+
84
+ <main class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8">
85
+
86
+ <!-- Filter Card -->
87
+ <section class="mb-6 rounded-2xl border border-slate-100 bg-white p-5 shadow-sm">
88
+ <div class="flex flex-col space-y-4 lg:flex-row lg:items-center lg:justify-between lg:space-y-0">
89
+ <div class="flex items-center space-x-2.5">
90
+ <span class="flex h-8 w-8 items-center justify-center rounded-lg bg-slate-50 text-slate-500">
91
+ <i class="fa-solid fa-filter text-sm"></i>
92
+ </span>
93
+ <h2 class="text-sm font-bold text-slate-700">ตัวกรองวิเคราะห์ข้อมูล:</h2>
94
+ </div>
95
+ <div class="grid flex-1 gap-4 lg:ml-6 lg:grid-cols-3">
96
+ <select id="facultyFilter" onchange="onFacultyChange()" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-600 outline-none transition focus:border-brand-500 focus:ring-2 focus:ring-brand-100">
97
+ <option value="">-- คณะทั้งหมด --</option>
98
+ </select>
99
+ <select id="majorFilter" onchange="applyFilters()" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-600 outline-none transition focus:border-brand-500 focus:ring-2 focus:ring-brand-100">
100
+ <option value="">-- สาขาวิชาทั้งหมด --</option>
101
+ </select>
102
+ <select id="roundFilter" onchange="applyFilters()" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-600 outline-none transition focus:border-brand-500 focus:ring-2 focus:ring-brand-100">
103
+ <option value="">-- รอบการสมัครทั้งหมด --</option>
104
+ </select>
105
+ </div>
106
+ </div>
107
+ </section>
108
+
109
+ <!-- Summary Cards Grid -->
110
+ <section class="mb-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
111
+ <!-- Stat 1 -->
112
+ <div class="relative overflow-hidden rounded-2xl border border-slate-100 bg-white p-6 shadow-sm transition hover:shadow-md">
113
+ <div class="absolute top-0 left-0 h-1 w-full bg-brand-500"></div>
114
+ <div class="flex items-center justify-between">
115
+ <div>
116
+ <p class="text-xs font-semibold uppercase tracking-wider text-slate-400">นักศึกษาผ่านการกรอง</p>
117
+ <h3 id="totalStudents" class="mt-2 text-3xl font-extrabold text-slate-800">0</h3>
118
+ </div>
119
+ <div class="flex h-12 w-12 items-center justify-center rounded-xl bg-brand-50 text-brand-600">
120
+ <i class="fa-solid fa-users text-lg"></i>
121
+ </div>
122
+ </div>
123
+ </div>
124
+
125
+ <!-- Stat 2 -->
126
+ <div class="relative overflow-hidden rounded-2xl border border-slate-100 bg-white p-6 shadow-sm transition hover:shadow-md">
127
+ <div class="absolute top-0 left-0 h-1 w-full bg-brand-500"></div>
128
+ <div class="flex items-center justify-between">
129
+ <div>
130
+ <p class="text-xs font-semibold uppercase tracking-wider text-slate-400">จังหวัดที่รับเข้ามากที่สุด</p>
131
+ <h3 id="topProvince" class="mt-2 text-lg font-bold text-slate-700">-</h3>
132
+ </div>
133
+ <div class="flex h-12 w-12 items-center justify-center rounded-xl bg-teal-50 text-teal-600">
134
+ <i class="fa-solid fa-map-location-dot text-lg"></i>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <!-- Stat 3 -->
140
+ <div class="relative overflow-hidden rounded-2xl border border-slate-100 bg-white p-6 shadow-sm transition hover:shadow-md sm:col-span-2 lg:col-span-1">
141
+ <div class="absolute top-0 left-0 h-1 w-full bg-brand-500"></div>
142
+ <div class="flex items-center justify-between">
143
+ <div>
144
+ <p class="text-xs font-semibold uppercase tracking-wider text-slate-400">สถานศึกษาที่ส่งเข้ามากที่สุด</p>
145
+ <h3 id="topSchool" class="mt-2 text-base font-bold text-slate-700">-</h3>
146
+ </div>
147
+ <div class="flex h-12 w-12 items-center justify-center rounded-xl bg-amber-50 text-amber-600">
148
+ <i class="fa-solid fa-school text-lg"></i>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ </section>
153
+
154
+ <!-- Map Module -->
155
+ <section class="mb-8 rounded-2xl border border-slate-100 bg-white shadow-sm overflow-hidden">
156
+ <div class="flex items-center justify-between border-b border-slate-100 bg-slate-50/50 px-6 py-4">
157
+ <div class="flex items-center space-x-2">
158
+ <span class="text-brand-600"><i class="fa-solid fa-map"></i></span>
159
+ <h3 class="font-bold text-slate-800">แผนภูมิรูปแผนที่ประเทศ (เฉดสีจำแนกตามรายจ��งหวัด)</h3>
160
+ </div>
161
+ <span class="hidden text-xs text-slate-400 sm:inline-flex items-center">
162
+ <i class="fa-solid fa-mouse-pointer mr-1.5 text-brand-500"></i> คลิกที่แต่ละจังหวัดเพื่อนำทางสู่ตารางสถิติด้านล่าง
163
+ </span>
164
+ </div>
165
+ <div class="map-container flex items-center justify-center bg-white">
166
+ <!-- Map Loader Spinner -->
167
+ <div id="map-loading" class="absolute z-10 flex flex-col items-center justify-center text-slate-400">
168
+ <div class="h-8 w-8 animate-spin rounded-full border-4 border-slate-200 border-t-brand-600"></div>
169
+ <span class="mt-3 text-xs font-medium">กำลังเตรียมแผนที่ประเทศและคำนวณสถิติ...</span>
170
+ </div>
171
+ <div id="regions_div"></div>
172
+ </div>
173
+ </section>
174
+
175
+ <!-- Data Table Container -->
176
+ <section class="rounded-2xl border border-slate-100 bg-white p-6 shadow-sm">
177
+ <div class="mb-4 flex items-center space-x-2">
178
+ <span class="text-brand-600"><i class="fa-solid fa-table-list"></i></span>
179
+ <h3 class="font-bold text-slate-800">โครงสร้างรายละเอียด (จังหวัด &gt; สถานศึกษาเดิม &gt; คณะ &gt; สาขาวิชา)</h3>
180
+ </div>
181
+
182
+ <div class="overflow-x-auto rounded-xl border border-slate-100">
183
+ <table class="w-full border-collapse text-left text-sm text-slate-600">
184
+ <thead class="bg-slate-50 text-xs font-bold uppercase tracking-wider text-slate-500">
185
+ <tr class="border-b border-slate-100">
186
+ <th scope="col" class="px-6 py-4" style="width: 75%">โครงสร้างหน่วยและสายการรับสมัคร</th>
187
+ <th scope="col" class="px-6 py-4 text-center" style="width: 25%">จำนวนนักศึกษาใหม่ (คน)</th>
188
+ </tr>
189
+ </thead>
190
+ <tbody id="dataTableBody" class="divide-y divide-slate-50">
191
+ <!-- Filled by JavaScript -->
192
+ </tbody>
193
+ </table>
194
+ </div>
195
+ </section>
196
+
197
+ </main>
198
+
199
+ <!-- Scripts -->
200
+ <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
201
+ <script src="https://www.gstatic.com/charts/loader.js"></script>
202
+
203
+ <script>
204
+ const rawData = [
205
+ { id: 1, name: "โรงเรียนเตรียมอุดมศึกษา", province: "กรุงเทพมหานคร", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมคอมพิวเตอร์", round: "รอบที่ 1 Portfolio", count: 50 },
206
+ { id: 2, name: "โรงเรียนเตรียมอุดมศึกษา", province: "กรุงเทพมหานคร", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมคอมพิวเตอร์", round: "รอบที่ 3 Admission", count: 30 },
207
+ { id: 3, name: "โรงเรียนเตรียมอุดมศึกษา", province: "กรุงเทพมหานคร", faculty: "วิทยาศาสตร์", major: "วิทยาการคอมพิวเตอร์", round: "รอบที่ 1 Portfolio", count: 40 },
208
+ { id: 4, name: "โรงเรียนเตรียมอุดมศึกษา", province: "กรุงเทพมหานคร", faculty: "วิทยาศาสตร์", major: "วิทยาการคอมพิวเตอร์", round: "รอบที่ 2 Quota", count: 30 },
209
+ { id: 5, name: "โรงเรียนสวนกุหลาบวิทยาลัย", province: "กรุงเทพมหานคร", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมโยธา", round: "รอบที่ 2 Quota", count: 60 },
210
+ { id: 6, name: "โรงเรียนสวนกุหลาบวิทยาลัย", province: "กรุงเทพมหานคร", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมโยธา", round: "รอบที่ 3 Admission", count: 40 },
211
+ { id: 7, name: "โรงเรียนสวนกุหลาบวิทยาลัย", province: "กรุงเทพมหานคร", faculty: "บริหารธุรกิจ", major: "การตลาด", round: "รอบที่ 1 Portfolio", count: 20 },
212
+ { id: 8, name: "โรงเรียนมหิดลวิทยานุสรณ์", province: "นครปฐม", faculty: "วิทยาศาสตร์", major: "ชีววิทยา", round: "รอบที่ 1 Portfolio", count: 55 },
213
+ { id: 9, name: "โรงเรียนมหิดลวิทยานุสรณ์", province: "นครปฐม", faculty: "วิทยาศาสตร์", major: "ชีววิทยา", round: "รอบที่ 3 Admission", count: 30 },
214
+ { id: 10, name: "โรงเรียนพิษณุโลกพิทยาคม", province: "พิษณุโลก", faculty: "บริหารธุรกิจ", major: "การบัญชี", round: "รอบที่ 2 Quota", count: 70 },
215
+ { id: 11, name: "โรงเรียนพิษณุโลกพิทยาคม", province: "พิษณุโลก", faculty: "บริหารธุรกิจ", major: "การบัญชี", round: "รอบที่ 3 Admission", count: 40 },
216
+ { id: 12, name: "โรงเรียนพิษณุโลกพิทยาคม", province: "พิษณุโลก", faculty: "มนุษยศาสตร์", major: "ภาษาอังกฤษ", round: "รอบที่ 1 Portfolio", count: 100 },
217
+ { id: 13, name: "โรงเรียนขอนแก่นวิทยายน", province: "ขอนแก่น", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมคอมพิวเตอร์", round: "รอบที่ 2 Quota", count: 85 },
218
+ { id: 14, name: "โรงเรียนขอนแก่นวิทยายน", province: "ขอนแก่น", faculty: "วิศวกรรมศาสตร์", major: "วิศวกรรมคอมพิวเตอร์", round: "รอบที่ 3 Admission", count: 50 },
219
+ { id: 15, name: "โรงเรียนหาดใหญ่วิทยาลัย", province: "สงขลา", faculty: "วิทยาศาสตร์", major: "วิทยาการคอมพิวเตอร์", round: "รอบที่ 1 Portfolio", count: 65 },
220
+ { id: 16, name: "โรงเรียนหาดใหญ่วิทยาลัย", province: "สงขลา", faculty: "วิทยาศาสตร์", major: "วิทยาการคอมพิวเตอร์", round: "รอบที่ 2 Quota", count: 40 },
221
+ { id: 17, name: "โรงเรียนภูเก็ตวิทยาลัย", province: "ภูเก็ต", faculty: "บริหารธุรกิจ", major: "ธุรกิจระหว่างประเทศ", round: "รอบที่ 3 Admission", count: 60 }
222
+ ];
223
+
224
+ const provinceIsoMap = {
225
+ "กรุงเทพมหานคร": "TH-10", "สมุทรปราการ": "TH-11", "นนทบุรี": "TH-12", "ปทุมธานี": "TH-13",
226
+ "พระนครศรีอยุธยา": "TH-14", "อ่างทอง": "TH-15", "ลพบุรี": "TH-16", "สิงห์บุรี": "TH-17",
227
+ "ชัยนาท": "TH-18", "สระบุรี": "TH-19", "ชลบุรี": "TH-20", "ระยอง": "TH-21",
228
+ "จันทบุรี": "TH-22", "ตราด": "TH-23", "ฉะเชิงเทรา": "TH-24", "ปราจีนบุรี": "TH-25",
229
+ "นครนายก": "TH-26", "สระแก้ว": "TH-27", "นครราชสีมา": "TH-30", "บุรีรัมย์": "TH-31",
230
+ "สุรินทร์": "TH-32", "ศรีสะเกษ": "TH-33", "อุบลราชธานี": "TH-34", "ยโสธร": "TH-35",
231
+ "ชัยภูมิ": "TH-36", "อำนาจเจริญ": "TH-37", "บึงกาฬ": "TH-38", "หนองบัวลำภู": "TH-39",
232
+ "ขอนแก่น": "TH-40", "อุดรธานี": "TH-41", "เลย": "TH-42", "หนองคาย": "TH-43",
233
+ "มหาสารคาม": "TH-44", "ร้อยเอ็ด": "TH-45", "กาฬสินธุ์": "TH-46", "สกลนคร": "TH-47",
234
+ "นครพนม": "TH-48", "มุกดาหาร": "TH-49", "เชียงใหม่": "TH-50", "ลำพูน": "TH-51",
235
+ "ลำปาง": "TH-52", "อุตรดิตถ์": "TH-53", "แพร่": "TH-54", "น่าน": "TH-55",
236
+ "พะเยา": "TH-56", "เชียงราย": "TH-57", "แม่ฮ่องสอน": "TH-58", "นครสวรรค์": "TH-60",
237
+ "อุทัยธานี": "TH-61", "กำแพงเพชร": "TH-62", "ตาก": "TH-63", "สุโขทัย": "TH-64",
238
+ "พิษณุโลก": "TH-65", "พิจิตร": "TH-66", "เพชรบูรณ์": "TH-67", "ราชบุรี": "TH-70",
239
+ "กาญจนบุรี": "TH-71", "สุพรรณบุรี": "TH-72", "นครปฐม": "TH-73", "สมุทรสาคร": "TH-74",
240
+ "สมุทรสงคราม": "TH-75", "เพชรบุรี": "TH-76", "ประจวบคีรีขันธ์": "TH-77", "นครศรีธรรมราช": "TH-80",
241
+ "กระบี่": "TH-81", "พังงา": "TH-82", "ภูเก็ต": "TH-83", "สุราษฎร์ธานี": "TH-84",
242
+ "ระนอง": "TH-85", "ชุมพร": "TH-86", "สงขลา": "TH-90", "สตูล": "TH-91",
243
+ "ตรัง": "TH-92", "พัทลุง": "TH-93", "ปัตตานี": "TH-94", "ยะลา": "TH-95", "นราธิวาส": "TH-96"
244
+ };
245
+
246
+ const isoToProvinceName = Object.fromEntries(
247
+ Object.entries(provinceIsoMap).map(([province, iso]) => [iso, province])
248
+ );
249
+
250
+ let activeFilteredData = [];
251
+ let geoChart = null;
252
+ let isGoogleChartsLoaded = false;
253
+
254
+ google.charts.load('current', { 'packages': ['geochart'] });
255
+ google.charts.setOnLoadCallback(function() {
256
+ isGoogleChartsLoaded = true;
257
+ document.getElementById('map-loading').style.display = 'none';
258
+ applyFilters();
259
+ });
260
+
261
+ document.addEventListener('DOMContentLoaded', function() {
262
+ initDropdowns();
263
+ });
264
+
265
+ function initDropdowns() {
266
+ const facultyFilter = document.getElementById('facultyFilter');
267
+ const faculties = [...new Set(rawData.map(item => item.faculty))].sort();
268
+
269
+ faculties.forEach(fac => {
270
+ const option = document.createElement('option');
271
+ option.value = fac;
272
+ option.textContent = fac;
273
+ facultyFilter.appendChild(option);
274
+ });
275
+
276
+ const roundFilter = document.getElementById('roundFilter');
277
+ const rounds = [...new Set(rawData.map(item => item.round))].sort();
278
+
279
+ rounds.forEach(rnd => {
280
+ const option = document.createElement('option');
281
+ option.value = rnd;
282
+ option.textContent = rnd;
283
+ roundFilter.appendChild(option);
284
+ });
285
+ }
286
+
287
+ function onFacultyChange() {
288
+ const faculty = document.getElementById('facultyFilter').value;
289
+ const majorFilter = document.getElementById('majorFilter');
290
+ majorFilter.innerHTML = '<option value="">-- สาขาวิชาทั้งหมด --</option>';
291
+
292
+ if (faculty) {
293
+ const majors = [...new Set(rawData.filter(item => item.faculty === faculty).map(item => item.major))].sort();
294
+ majors.forEach(maj => {
295
+ const option = document.createElement('option');
296
+ option.value = maj;
297
+ option.textContent = maj;
298
+ majorFilter.appendChild(option);
299
+ });
300
+ }
301
+ applyFilters();
302
+ }
303
+
304
+ function applyFilters() {
305
+ const faculty = document.getElementById('facultyFilter').value;
306
+ const major = document.getElementById('majorFilter').value;
307
+ const round = document.getElementById('roundFilter').value;
308
+
309
+ activeFilteredData = rawData.filter(item => {
310
+ return (faculty === "" || item.faculty === faculty) &&
311
+ (major === "" || item.major === major) &&
312
+ (round === "" || item.round === round);
313
+ });
314
+
315
+ updateStats(activeFilteredData);
316
+ renderTable(activeFilteredData);
317
+
318
+ if (isGoogleChartsLoaded) {
319
+ drawGeoChart(activeFilteredData);
320
+ }
321
+ }
322
+
323
+ function updateStats(data) {
324
+ let total = 0, provinceCounts = {}, schoolCounts = {};
325
+
326
+ data.forEach(item => {
327
+ total += item.count;
328
+ provinceCounts[item.province] = (provinceCounts[item.province] || 0) + item.count;
329
+ schoolCounts[item.name] = (schoolCounts[item.name] || 0) + item.count;
330
+ });
331
+
332
+ let topProv = '-', maxProv = 0, topSch = '-', maxSch = 0;
333
+ for (let p in provinceCounts) { if(provinceCounts[p] > maxProv) { maxProv = provinceCounts[p]; topProv = p; } }
334
+ for (let s in schoolCounts) { if(schoolCounts[s] > maxSch) { maxSch = schoolCounts[s]; topSch = s; } }
335
+
336
+ document.getElementById('totalStudents').innerText = total.toLocaleString();
337
+ document.getElementById('topProvince').innerText = topProv === '-' ? '-' : `${topProv} (${maxProv} คน)`;
338
+ document.getElementById('topSchool').innerText = topSch === '-' ? '-' : `${topSch} (${maxSch} คน)`;
339
+ }
340
+
341
+ function drawGeoChart(data) {
342
+ const provinceSummary = {};
343
+ data.forEach(item => {
344
+ provinceSummary[item.province] = (provinceSummary[item.province] || 0) + item.count;
345
+ });
346
+
347
+ const chartData = new google.visualization.DataTable();
348
+ chartData.addColumn('string', 'Province');
349
+ chartData.addColumn('number', 'จำนวนนักศึกษา (คน)');
350
+
351
+ for (const [province, count] of Object.entries(provinceSummary)) {
352
+ const isoCode = provinceIsoMap[province];
353
+ if (isoCode) {
354
+ chartData.addRow([{ v: isoCode, f: `จังหวัด${province}` }, count]);
355
+ }
356
+ }
357
+
358
+ // ใช้ชุดคู่สีพาสเทล Teal ที่ดูพรีเมียมและสวยงาม
359
+ const options = {
360
+ region: 'TH',
361
+ resolution: 'provinces',
362
+ colorAxis: { colors: ['#f0fdfa', '#0d9488'] }, /* Teal 50 to Teal 600 */
363
+ backgroundColor: '#ffffff',
364
+ datalessRegionColor: '#f8fafc',
365
+ defaultColor: '#f8fafc',
366
+ legend: { textStyle: { color: '#64748b', fontName: 'Sarabun', fontSize: 12 } },
367
+ tooltip: { textStyle: { fontName: 'Sarabun', fontSize: 13 }, trigger: 'focus' }
368
+ };
369
+
370
+ const container = document.getElementById('regions_div');
371
+ geoChart = new google.visualization.GeoChart(container);
372
+
373
+ google.visualization.events.addListener(geoChart, 'select', function() {
374
+ const selection = geoChart.getSelection();
375
+ if (selection.length > 0) {
376
+ const row = selection[0].row;
377
+ const isoCode = chartData.getValue(row, 0);
378
+ const clickedProvince = isoToProvinceName[isoCode];
379
+
380
+ if (clickedProvince) {
381
+ focusOnProvinceInTable(clickedProvince);
382
+ }
383
+ }
384
+ });
385
+
386
+ geoChart.draw(chartData, options);
387
+ }
388
+
389
+ window.addEventListener('resize', function() {
390
+ if (isGoogleChartsLoaded && activeFilteredData.length > 0) {
391
+ drawGeoChart(activeFilteredData);
392
+ }
393
+ });
394
+
395
+ function focusOnProvinceInTable(provinceName) {
396
+ const rows = document.querySelectorAll('#dataTableBody tr');
397
+ let targetRow = null;
398
+ let targetId = null;
399
+
400
+ rows.forEach(row => {
401
+ if (row.textContent.includes(`จังหวัด${provinceName}`)) {
402
+ targetRow = row;
403
+ const iconEl = row.querySelector('.toggle-icon');
404
+ if (iconEl) {
405
+ targetId = iconEl.id.replace('icon-', '');
406
+ }
407
+ }
408
+ });
409
+
410
+ if (targetRow && targetId) {
411
+ const icon = document.getElementById(`icon-${targetId}`);
412
+ if (icon && icon.classList.contains('fa-chevron-right')) {
413
+ toggleRow(targetId);
414
+ }
415
+
416
+ targetRow.scrollIntoView({ behavior: 'smooth', block: 'center' });
417
+
418
+ targetRow.classList.add('highlight-row');
419
+ setTimeout(() => {
420
+ targetRow.classList.remove('highlight-row');
421
+ }, 2000);
422
+ }
423
+ }
424
+
425
+ function renderTable(data) {
426
+ const tbody = document.getElementById('dataTableBody');
427
+ tbody.innerHTML = '';
428
+
429
+ if(data.length === 0) {
430
+ tbody.innerHTML = '<tr><td colspan="2" class="text-center text-rose-500 py-8 font-medium">ไม่พบข้อมูลที่ตรงกับเงื่อนไขตัวกรองในขณะนี้</td></tr>';
431
+ return;
432
+ }
433
+
434
+ const grouped = {};
435
+ data.forEach(item => {
436
+ if (!grouped[item.province]) grouped[item.province] = { count: 0, schools: {} };
437
+ grouped[item.province].count += item.count;
438
+
439
+ if (!grouped[item.province].schools[item.name]) {
440
+ grouped[item.province].schools[item.name] = { count: 0, faculties: {} };
441
+ }
442
+ grouped[item.province].schools[item.name].count += item.count;
443
+
444
+ if (!grouped[item.province].schools[item.name].faculties[item.faculty]) {
445
+ grouped[item.province].schools[item.name].faculties[item.faculty] = { count: 0, majors: {} };
446
+ }
447
+ grouped[item.province].schools[item.name].faculties[item.faculty].count += item.count;
448
+
449
+ // รวมยอดตามสาขาวิชา (ไม่แยกตามรอบการสมัครในตาราง)
450
+ if (!grouped[item.province].schools[item.name].faculties[item.faculty].majors[item.major]) {
451
+ grouped[item.province].schools[item.name].faculties[item.faculty].majors[item.major] = { count: 0 };
452
+ }
453
+ grouped[item.province].schools[item.name].faculties[item.faculty].majors[item.major].count += item.count;
454
+ });
455
+
456
+ const sortedProvinces = Object.keys(grouped).sort((a, b) => grouped[b].count - grouped[a].count);
457
+
458
+ let provIndex = 1;
459
+ sortedProvinces.forEach(prov => {
460
+ const provId = `prov-${provIndex}`;
461
+ const provData = grouped[prov];
462
+
463
+ // --- แถวระดับที่ 1: จังหวัด ---
464
+ const trProv = document.createElement('tr');
465
+ trProv.className = 'clickable-row bg-slate-50 hover:bg-slate-100/70 border-b border-slate-100';
466
+ trProv.onclick = () => toggleRow(provId);
467
+ trProv.innerHTML = `
468
+ <td class="px-6 py-3.5 text-left font-bold text-slate-800 flex items-center">
469
+ <i class="fa-solid fa-chevron-right text-slate-400 toggle-icon mr-2" id="icon-${provId}"></i>
470
+ <span class="inline-flex h-7 w-7 items-center justify-center rounded-lg bg-brand-50 text-brand-600 mr-2.5">
471
+ <i class="fa-solid fa-map-location-dot text-xs"></i>
472
+ </span>
473
+ <span>จังหวัด${prov}</span>
474
+ </td>
475
+ <td class="px-6 py-3.5 text-center">
476
+ <span class="inline-flex items-center rounded-full bg-brand-50 px-3 py-1 text-sm font-extrabold text-brand-800 ring-1 ring-inset ring-brand-600/20">
477
+ ${provData.count.toLocaleString()}
478
+ </span>
479
+ </td>
480
+ `;
481
+ tbody.appendChild(trProv);
482
+
483
+ const sortedSchools = Object.keys(provData.schools).sort((a, b) => provData.schools[b].count - provData.schools[a].count);
484
+
485
+ let schIndex = 1;
486
+ sortedSchools.forEach(sch => {
487
+ const schId = `${provId}-sch-${schIndex}`;
488
+ const schData = provData.schools[sch];
489
+
490
+ // --- แถวระดับที่ 2: สถานศึกษา ---
491
+ const trSch = document.createElement('tr');
492
+ trSch.className = `child-${provId} clickable-row bg-white hover:bg-slate-50/50 border-b border-slate-100`;
493
+ trSch.style.display = 'none';
494
+ trSch.onclick = () => toggleRow(schId);
495
+ trSch.innerHTML = `
496
+ <td class="px-6 py-3.5 text-left font-semibold text-slate-700 flex items-center" style="padding-left: 2.75rem;">
497
+ <i class="fa-solid fa-chevron-right text-slate-400 toggle-icon mr-2" id="icon-${schId}"></i>
498
+ <span class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-amber-50 text-amber-600 mr-2">
499
+ <i class="fa-solid fa-school text-xs"></i>
500
+ </span>
501
+ <span>${sch}</span>
502
+ </td>
503
+ <td class="px-6 py-3.5 text-center">
504
+ <span class="inline-flex items-center rounded-full bg-amber-50 px-2.5 py-0.5 text-xs font-bold text-amber-700 ring-1 ring-inset ring-amber-600/20">
505
+ ${schData.count.toLocaleString()}
506
+ </span>
507
+ </td>
508
+ `;
509
+ tbody.appendChild(trSch);
510
+
511
+ const sortedFaculties = Object.keys(schData.faculties).sort((a, b) => schData.faculties[b].count - schData.faculties[a].count);
512
+
513
+ let facIndex = 1;
514
+ sortedFaculties.forEach(fac => {
515
+ const facId = `${schId}-fac-${facIndex}`;
516
+ const facData = schData.faculties[fac];
517
+
518
+ // --- แถวระดับที่ 3: คณะ ---
519
+ const trFac = document.createElement('tr');
520
+ trFac.className = `child-${schId} parent-${provId} clickable-row bg-white hover:bg-slate-50/30 border-b border-slate-100`;
521
+ trFac.style.display = 'none';
522
+ trFac.onclick = () => toggleRow(facId);
523
+ trFac.innerHTML = `
524
+ <td class="px-6 py-3 text-left font-medium text-slate-600 flex items-center" style="padding-left: 4.75rem;">
525
+ <i class="fa-solid fa-chevron-right text-slate-400 toggle-icon mr-2" id="icon-${facId}"></i>
526
+ <span class="inline-flex h-5 w-5 items-center justify-center rounded-md bg-brand-50 text-brand-600 mr-2">
527
+ <i class="fa-solid fa-building-columns text-[10px]"></i>
528
+ </span>
529
+ <span>คณะ${fac}</span>
530
+ </td>
531
+ <td class="px-6 py-3 text-center">
532
+ <span class="inline-flex items-center rounded-full bg-sky-50 px-2.5 py-0.5 text-xs font-semibold text-sky-700 ring-1 ring-inset ring-sky-600/20">
533
+ ${facData.count.toLocaleString()}
534
+ </span>
535
+ </td>
536
+ `;
537
+ tbody.appendChild(trFac);
538
+
539
+ const sortedMajors = Object.keys(facData.majors).sort((a, b) => facData.majors[b].count - facData.majors[a].count);
540
+
541
+ // --- แถวระดับที่ 4: สาขาวิชา ---
542
+ sortedMajors.forEach(majorName => {
543
+ const majorCount = facData.majors[majorName].count;
544
+ const trDet = document.createElement('tr');
545
+ trDet.className = `child-${facId} parent-${schId} parent-${provId} bg-slate-50/30`;
546
+ trDet.style.display = 'none';
547
+ trDet.innerHTML = `
548
+ <td class="px-6 py-2.5 text-left text-slate-500 flex items-center" style="padding-left: 6.75rem;">
549
+ <i class="fa-solid fa-turn-up fa-rotate-90 text-slate-300 mr-3"></i>
550
+ <span class="mr-2"><i class="fa-solid fa-book-open text-slate-400 text-xs mr-1.5"></i>${majorName}</span>
551
+ </td>
552
+ <td class="px-6 py-2.5 text-center">
553
+ <span class="inline-flex items-center rounded-full bg-emerald-50 px-2.5 py-0.5 text-xs font-medium text-emerald-700 ring-1 ring-inset ring-emerald-600/20">
554
+ ${majorCount.toLocaleString()}
555
+ </span>
556
+ </td>
557
+ `;
558
+ tbody.appendChild(trDet);
559
+ });
560
+
561
+ facIndex++;
562
+ });
563
+
564
+ schIndex++;
565
+ });
566
+ provIndex++;
567
+ });
568
+ }
569
+
570
+ // ฟังก์ชันเปิด-ปิดสลับไอคอนแบบ Drill-down
571
+ function toggleRow(targetId) {
572
+ const icon = document.getElementById(`icon-${targetId}`);
573
+ const isExpanded = icon.classList.contains('fa-chevron-down');
574
+
575
+ if (isExpanded) {
576
+ icon.classList.replace('fa-chevron-down', 'fa-chevron-right');
577
+
578
+ const children = document.querySelectorAll(`.child-${targetId}`);
579
+ children.forEach(el => el.style.display = 'none');
580
+
581
+ const descendants = document.querySelectorAll(`.parent-${targetId}`);
582
+ descendants.forEach(el => el.style.display = 'none');
583
+
584
+ // พับไอคอนของลูกหลานทั้งหมดให้ถูกต้อง
585
+ children.forEach(row => {
586
+ const subIcon = row.querySelector('.toggle-icon');
587
+ if (subIcon && subIcon.classList.contains('fa-chevron-down')) {
588
+ subIcon.classList.replace('fa-chevron-down', 'fa-chevron-right');
589
+ }
590
+ });
591
+ descendants.forEach(row => {
592
+ const subIcon = row.querySelector('.toggle-icon');
593
+ if (subIcon && subIcon.classList.contains('fa-chevron-down')) {
594
+ subIcon.classList.replace('fa-chevron-down', 'fa-chevron-right');
595
+ }
596
+ });
597
+ } else {
598
+ icon.classList.replace('fa-chevron-right', 'fa-chevron-down');
599
+
600
+ const children = document.querySelectorAll(`.child-${targetId}`);
601
+ children.forEach(el => el.style.display = 'table-row');
602
+ }
603
+ }
604
+
605
+ function showInfo() {
606
+ Swal.fire({
607
+ title: 'ข้อมูลระบบรายงานสถิติ',
608
+ html: `
609
+ <div class="text-left text-sm text-slate-600 space-y-3.5 mt-2">
610
+ <p class="font-semibold text-brand-700">การนำเสนอรายงานสถิตินักศึกษาใหม่ระดับพรีเมียม</p>
611
+ <ul class="list-disc pl-5 space-y-2">
612
+ <li><b>วิเคราะห์ข้อมูลจำแนก 4 ระดับ:</b> แตกโครงสร้างอย่างโปร่งใสโดยคลิกที่ จังหวัด ➔ โรงเรียนเดิม ➔ คณะ ➔ สาขาวิชา</li>
613
+ <li><b>แผนภูมิแผนที่ประเทศ���ทย (GeoChart):</b> แสดงความหนาแน่นของผู้เรียนแบบไล่ระดับความเข้มของสี Teal</li>
614
+ <li><b>การแยกแยะสีของตัวเลขสถิติอย่างคมชัด:</b> ปรับตัวเลขยอดรวมตามระดับชั้นข้อมูลเป็นป้ายสีเฉพาะทางเพื่อให้มองเห็นความแตกต่างอย่างชัดเจน</li>
615
+ </ul>
616
+ </div>
617
+ `,
618
+ icon: 'info',
619
+ confirmButtonText: 'ตกลง',
620
+ confirmButtonColor: '#0d9488', // Premium Teal Buttons
621
+ });
622
+ }
623
+ </script>
624
+ </body>
625
+ </html>