2026-10-16 22:03:47 +07:00
<!DOCTYPE html>
< html lang = "th" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > GaC-Srtool — FreeSR & Game Management Dashboard</ title >
< link rel = "stylesheet" href = "css/styles.css" >
< link rel = "icon" href = "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🌌</text></svg>" >
</ head >
< body >
<!-- App Header -->
< header class = "app-header" >
< div class = "brand" >
< div class = "brand-icon" > ✦</ div >
< div >
2026-10-16 22:16:53 +07:00
< div class = "brand-title" data-i18n = "appName" > GaC-Srtool</ div >
< div class = "brand-subtitle" data-i18n = "appSubtitle" > Star Rail FreeSR & Server Controller</ div >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
< div class = "header-controls" >
2026-10-16 22:16:53 +07:00
<!-- Language Selector -->
< select id = "lang-select" class = "form-select btn-sm" style = "width: auto; padding: 0.35rem 0.65rem; background: var(--bg-secondary); cursor: pointer;" title = "Language / 语言 / 言語 / ภาษา" >
<!-- Injected by i18n.js -->
</ select >
< div class = "connection-pill" id = "btn-open-settings" title = "Click to configure API connection" >
2026-10-16 22:03:47 +07:00
< span class = "status-dot" id = "status-dot" ></ span >
2026-10-16 22:16:53 +07:00
< span id = "connection-status-text" data-i18n = "checking" > กำลังตรวจสอบ...</ span >
2026-10-16 22:03:47 +07:00
</ div >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-secondary btn-sm" id = "btn-quick-ping" title = "Refresh connection" >
< span data-i18n = "refresh" > 🔄 รีเฟรช</ span >
2026-10-16 22:03:47 +07:00
</ button >
</ div >
</ header >
<!-- Navigation Bar -->
< nav class = "nav-tabs" >
2026-10-16 22:16:53 +07:00
< button class = "tab-btn active" data-tab = "tab-dashboard" data-i18n = "tabDashboard" > 📊 แดชบอร์ด (Overview)</ button >
< button class = "tab-btn" data-tab = "tab-avatars" data-i18n = "tabAvatars" > 👥 ตัวละคร (Avatars)</ button >
< button class = "tab-btn" data-tab = "tab-exrank" data-i18n = "tabExrank" > ⚡ Ex-Rank (สกิลพิเศษ)</ button >
< button class = "tab-btn" data-tab = "tab-teleport" data-i18n = "tabTeleport" > 🚀 วาร์ปฉาก (Teleport)</ button >
< button class = "tab-btn" data-tab = "tab-json" data-i18n = "tabJson" > 📝 จัดการไฟล์ JSON</ button >
< button class = "tab-btn" data-tab = "tab-settings" data-i18n = "tabSettings" > ⚙️ ตั้งค่า & คู่มือ Host</ button >
2026-10-16 22:03:47 +07:00
</ nav >
<!-- Main Container -->
< main class = "main-container" >
<!-- 1. Dashboard Tab -->
< section id = "tab-dashboard" class = "tab-content active" >
< div class = "grid-3" style = "margin-bottom: 1.5rem;" >
< div class = "card stat-box" >
< div class = "stat-number" id = "stat-avatars" > 0</ div >
2026-10-16 22:16:53 +07:00
< div class = "stat-label" data-i18n = "statAvatars" > ตัวละครที่ครอบครอง (Avatars)</ div >
2026-10-16 22:03:47 +07:00
</ div >
< div class = "card stat-box" >
< div class = "stat-number" id = "stat-lightcones" > 0</ div >
2026-10-16 22:16:53 +07:00
< div class = "stat-label" data-i18n = "statLightcones" > กรวยแสง (Lightcones)</ div >
2026-10-16 22:03:47 +07:00
</ div >
< div class = "card stat-box" >
< div class = "stat-number" id = "stat-relics" > 0</ div >
2026-10-16 22:16:53 +07:00
< div class = "stat-label" data-i18n = "statRelics" > รีลิกส์ (Relics)</ div >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
< div class = "grid-2" >
<!-- Server & Map Card -->
< div class = "card" >
< div class = "card-title" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "serverStatusTitle" > 📍 สถานะเซิร์ฟเวอร์ & ตำแหน่งปัจจุบัน</ span >
2026-10-16 22:03:47 +07:00
< span class = "btn-sm btn-secondary" id = "badge-version" > API Live</ span >
</ div >
< div style = "display: flex; flex-direction: column; gap: 0.75rem;" >
< div >
2026-10-16 22:16:53 +07:00
< span class = "form-label" data-i18n = "lblApiGatewayUrl" > API Gateway Endpoint</ span >
2026-10-16 22:03:47 +07:00
< code id = "lbl-api-url" style = "color: var(--accent-cyan); font-size: 0.9rem;" > -</ code >
</ div >
< div style = "display: flex; gap: 1rem;" >
< div >
< span class = "form-label" > Plane ID</ span >
< span id = "lbl-plane-id" style = "font-weight: bold;" > -</ span >
</ div >
< div >
< span class = "form-label" > Floor ID</ span >
< span id = "lbl-floor-id" style = "font-weight: bold;" > -</ span >
</ div >
</ div >
< div >
2026-10-16 22:16:53 +07:00
< span class = "form-label" data-i18n = "coords" > พิกัดตัวละคร (X, Y, Z)</ span >
2026-10-16 22:03:47 +07:00
< span id = "lbl-coordinates" style = "color: var(--text-muted); font-size: 0.85rem;" > -</ span >
</ div >
</ div >
</ div >
<!-- Quick Actions Card -->
< div class = "card" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "quickActionsTitle" > ⚡ ดำเนินการด่วน (Quick Actions)</ div >
< p class = "card-subtitle" data-i18n = "quickActionsSubtitle" > สั่งการส่งไปยัง REST API Gateway ทันที</ p >
2026-10-16 22:03:47 +07:00
< div style = "display: flex; flex-direction: column; gap: 0.75rem;" >
< button class = "btn btn-gold" id = "btn-quick-max-all" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "btnMaxAll" > ⭐ ปรับเลเวล 80 & ปลด E6 ตัวละครทั้งหมด (Max All)</ span >
2026-10-16 22:03:47 +07:00
</ button >
< button class = "btn btn-primary" id = "btn-quick-warp-express" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "btnWarpExpress" > 🚂 วาร์ปกลับรถไฟ Astral Express ทันที</ span >
2026-10-16 22:03:47 +07:00
</ button >
< button class = "btn btn-secondary" id = "btn-quick-sync-persistent" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "btnSyncPersistent" > 💾 ซิงค์ข้อมูล Persistent ล่าสุด</ span >
2026-10-16 22:03:47 +07:00
</ button >
</ div >
</ div >
</ div >
<!-- Current Lineup -->
< div class = "card" style = "margin-top: 1.5rem;" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "currentLineupTitle" > 🎮 ทีมปัจจุบัน (Current Lineup)</ div >
2026-10-16 22:03:47 +07:00
< div id = "lineup-container" class = "grid-4" style = "margin-top: 0.5rem;" >
< div class = "card" style = "text-align: center; color: var(--text-muted);" > กำลังโหลดข้อมูลทีม...</ div >
</ div >
</ div >
</ section >
<!-- 2. Avatars Tab -->
< section id = "tab-avatars" class = "tab-content" >
< div style = "display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.25rem; flex-wrap: wrap; gap: 1rem;" >
< div style = "display: flex; gap: 0.75rem; flex: 1; max-width: 480px;" >
2026-10-16 22:16:53 +07:00
< input type = "text" id = "avatar-search" class = "form-input" data-i18n-placeholder = "searchPlaceholder" placeholder = "🔍 ค้นหาชื่อหรือ ID ตัวละคร..." >
2026-10-16 22:03:47 +07:00
< select id = "avatar-filter-rarity" class = "form-select" style = "max-width: 140px;" >
2026-10-16 22:16:53 +07:00
< option value = "all" data-i18n = "filterAllRarity" > ทุกระดับดาว</ option >
< option value = "5" data-i18n = "filter5Star" > 5 ดาว (SSR)</ option >
< option value = "4" data-i18n = "filter4Star" > 4 ดาว (SR)</ option >
2026-10-16 22:03:47 +07:00
</ select >
</ div >
< div style = "display: flex; gap: 0.5rem;" >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-gold" id = "btn-max-all-avatars" data-i18n = "btnMaxAll" > ⭐ ปรับ Max E6 ทุกตัว</ button >
< button class = "btn btn-secondary" id = "btn-reload-avatars" data-i18n = "btnReload" > 🔄 รีโหลด</ button >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
< div id = "avatars-grid" class = "grid-4" >
< div style = "color: var(--text-muted); grid-column: 1/-1; text-align: center; padding: 2rem;" >
กำลังดึงข้อมูลตัวละครจากเซิร์ฟเวอร์...
</ div >
</ div >
</ section >
<!-- 3. Ex-Rank Tab -->
< section id = "tab-exrank" class = "tab-content" >
< div class = "card" style = "margin-bottom: 1.5rem;" >
< div class = "card-title" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "exrankTitle" > ⚡ ระบบปลดล็อค Ex-Rank Skill</ span >
2026-10-16 22:03:47 +07:00
< div style = "display: flex; gap: 0.5rem;" >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-success btn-sm" id = "btn-exrank-enable-all" data-i18n = "btnEnableAll" > เปิด Ex-Rank ทั้งหมด</ button >
< button class = "btn btn-secondary btn-sm" id = "btn-exrank-disable-all" data-i18n = "btnDisableAll" > ปิด Ex-Rank ทั้งหมด</ button >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
2026-10-16 22:16:53 +07:00
< p class = "card-subtitle" data-i18n = "exrankSubtitle" >
2026-10-16 22:03:47 +07:00
เปิดใช้งานพรสวรรค์และกลไกพิเศษ Ex-Rank สำหรับตัวละครเฉพาะใน FreeSR (เช่น Jing Yuan โดน CC ไม่หยุดชะงัก, Dan Heng IL, Acheron)
</ p >
</ div >
< div id = "exrank-list" style = "display: flex; flex-direction: column; gap: 0.75rem;" >
< div style = "color: var(--text-muted); text-align: center; padding: 2rem;" >
กำลังโหลดข้อมูล Ex-Rank...
</ div >
</ div >
</ section >
<!-- 4. Teleport Tab -->
< section id = "tab-teleport" class = "tab-content" >
< div class = "grid-2" >
<!-- Presets -->
< div class = "card" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "presetsTitle" > 📍 จุดวาร์ปปลอดภัยยอดนิยม (Safe Presets)</ div >
< p class = "card-subtitle" data-i18n = "presetsSubtitle" > คลิกจุดวาร์ปเพื่อย้ายฉากของผู้เล่นในไฟล์เซฟได้ทันที</ p >
2026-10-16 22:03:47 +07:00
< div id = "teleport-presets-list" style = "display: flex; flex-direction: column; gap: 0.6rem;" >
<!-- Rendered by JS -->
</ div >
</ div >
<!-- Custom Coordinate Warp -->
< div class = "card" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "customTeleportTitle" > 🎯 กำหนดพิกัดวาร์ปเอง (Custom Teleport)</ div >
< p class = "card-subtitle" data-i18n = "customTeleportSubtitle" > ใส่ PlaneID, FloorID และ EntryID ตามต้องการ</ p >
2026-10-16 22:03:47 +07:00
< form id = "form-custom-teleport" >
< div class = "grid-2" style = "gap: 0.75rem;" >
< div class = "form-group" >
< label class = "form-label" > Plane ID</ label >
2026-10-16 22:16:53 +07:00
< input type = "number" id = "tp-plane" class = "form-input" required placeholder = "20001" >
2026-10-16 22:03:47 +07:00
</ div >
< div class = "form-group" >
< label class = "form-label" > Floor ID</ label >
2026-10-16 22:16:53 +07:00
< input type = "number" id = "tp-floor" class = "form-input" required placeholder = "20001001" >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
< div class = "form-group" >
< label class = "form-label" > Entry ID</ label >
2026-10-16 22:16:53 +07:00
< input type = "number" id = "tp-entry" class = "form-input" required placeholder = "2000101" >
2026-10-16 22:03:47 +07:00
</ div >
< div class = "grid-3" style = "gap: 0.75rem;" >
< div class = "form-group" >
< label class = "form-label" > X</ label >
< input type = "number" id = "tp-x" class = "form-input" placeholder = "0" >
</ div >
< div class = "form-group" >
< label class = "form-label" > Y</ label >
< input type = "number" id = "tp-y" class = "form-input" placeholder = "0" >
</ div >
< div class = "form-group" >
< label class = "form-label" > Z</ label >
< input type = "number" id = "tp-z" class = "form-input" placeholder = "0" >
</ div >
</ div >
2026-10-16 22:16:53 +07:00
< button type = "submit" class = "btn btn-primary" style = "width: 100%; margin-top: 0.5rem;" data-i18n = "btnExecuteWarp" >
2026-10-16 22:03:47 +07:00
🚀 ยืนยันการวาร์ป (Execute Teleport)
</ button >
</ form >
</ div >
</ div >
</ section >
<!-- 5. JSON Management Tab -->
< section id = "tab-json" class = "tab-content" >
< div class = "card" >
< div class = "card-title" style = "flex-wrap: wrap; gap: 0.75rem;" >
< div style = "display: flex; gap: 0.5rem;" >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-sm btn-primary active" id = "btn-select-freesr" data-i18n = "btnFreesr" > 📄 freesr-data.json</ button >
< button class = "btn btn-sm btn-secondary" id = "btn-select-persistent" data-i18n = "btnPersistent" > 💾 persistent (Save)</ button >
2026-10-16 22:03:47 +07:00
</ div >
< div style = "display: flex; gap: 0.5rem;" >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-sm btn-secondary" id = "btn-json-beautify" data-i18n = "btnBeautify" > ✨ จัดรูปแบบ JSON</ button >
< button class = "btn btn-sm btn-secondary" id = "btn-json-download" data-i18n = "btnDownload" > 📥 ดาวน์โหลด Backup</ button >
2026-10-16 22:03:47 +07:00
< label class = "btn btn-sm btn-secondary" style = "cursor: pointer; margin: 0;" >
2026-10-16 22:16:53 +07:00
< span data-i18n = "btnUpload" > 📤 อัปโหลดไฟล์</ span > < input type = "file" id = "json-file-input" accept = ".json,text/plain" style = "display: none;" >
2026-10-16 22:03:47 +07:00
</ label >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-sm btn-success" id = "btn-json-save" data-i18n = "btnSaveServer" > 💾 บันทึกไปยังเซิร์ฟเวอร์</ button >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
< div class = "json-editor-wrapper" >
2026-10-16 22:16:53 +07:00
< textarea id = "json-editor" class = "json-textarea" spellcheck = "false" placeholder = "..." ></ textarea >
2026-10-16 22:03:47 +07:00
< div style = "display: flex; justify-content: space-between; font-size: 0.8rem; color: var(--text-muted);" >
2026-10-16 22:16:53 +07:00
< span id = "json-status-info" data-i18n = "jsonStatusReady" > พร้อมใช้งาน</ span >
< span data-i18n = "jsonTip" > Tip: สามารถแก้ไขค่าดิบแล้วกด 'บันทึกไปยังเซิร์ฟเวอร์' ได้ทันที</ span >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
</ div >
</ section >
<!-- 6. Settings & GitHub Hosting Guide -->
< section id = "tab-settings" class = "tab-content" >
< div class = "grid-2" >
<!-- Endpoint config -->
< div class = "card" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "apiSettingsTitle" > ⚙️ ตั้งค่าการเชื่อมต่อ API Gateway</ div >
< p class = "card-subtitle" data-i18n = "apiSettingsSubtitle" > ปรับเปลี่ยนพอร์ตหรือ IP ได้ตามไฟล์ server.json ของคุณ</ p >
2026-10-16 22:03:47 +07:00
< form id = "form-settings" >
< div class = "form-group" >
2026-10-16 22:16:53 +07:00
< label class = "form-label" data-i18n = "lblApiGatewayUrl" > REST API Gateway URL</ label >
2026-10-16 22:03:47 +07:00
< input type = "text" id = "setting-api-url" class = "form-input" placeholder = "http://localhost:21000" >
< small style = "color: var(--text-muted); display: block; margin-top: 0.35rem;" >
2026-10-16 22:16:53 +07:00
* Port 21000 by default (GaC-hkrpg-go SDK Server)
2026-10-16 22:03:47 +07:00
</ small >
</ div >
< div class = "form-group" >
2026-10-16 22:16:53 +07:00
< label class = "form-label" data-i18n = "lblPingInterval" > ความถี่ในการตรวจสอบสถานะ (วินาที)</ label >
2026-10-16 22:03:47 +07:00
< input type = "number" id = "setting-ping-interval" class = "form-input" min = "3" max = "60" value = "10" >
</ div >
< div style = "display: flex; gap: 0.75rem;" >
2026-10-16 22:16:53 +07:00
< button type = "submit" class = "btn btn-success" style = "flex: 1;" data-i18n = "btnSaveSettings" > 💾 บันทึกการตั้งค่า</ button >
< button type = "button" class = "btn btn-secondary" id = "btn-reset-settings" data-i18n = "btnResetDefault" > คืนค่าเริ่มต้น</ button >
2026-10-16 22:03:47 +07:00
</ div >
</ form >
</ div >
<!-- GitHub Pages Hosting Guide -->
< div class = "card" >
2026-10-16 22:16:53 +07:00
< div class = "card-title" data-i18n = "hostGuideTitle" > 🌐 วิธีนำขึ้นโฮสต์ GitHub Pages (ฟรี 100%)</ div >
< p class = "card-subtitle" data-i18n = "hostGuideSubtitle" > สามารถเปิดใช้งานเว็บนี้บนอินเทอร์เน็ตได้โดยไม่ต้องเสียค่าโฮสต์ใดๆ</ p >
2026-10-16 22:03:47 +07:00
< ol style = "margin-left: 1.25rem; font-size: 0.875rem; color: var(--text-muted); display: flex; flex-direction: column; gap: 0.65rem;" >
< li >
2026-10-16 22:16:53 +07:00
< strong style = "color: var(--text-main);" > 1. Create GitHub Repository:</ strong >< br >
Create new repo e.g. < code > GaC-srtool</ code >
2026-10-16 22:03:47 +07:00
</ li >
< li >
2026-10-16 22:16:53 +07:00
< strong style = "color: var(--text-main);" > 2. Push to GitHub:</ strong >< br >
2026-10-16 22:03:47 +07:00
< code > git remote add origin https://github.com/< user> /GaC-srtool.git</ code >< br >
2026-10-16 22:16:53 +07:00
< code > git add . && git commit -m "Init" && git push -u origin main</ code >
2026-10-16 22:03:47 +07:00
</ li >
< li >
2026-10-16 22:16:53 +07:00
< strong style = "color: var(--text-main);" > 3. Enable GitHub Pages:</ strong >< br >
Go to Repo > < strong > Settings</ strong > > < strong > Pages</ strong > > Source: < strong > Deploy from a branch</ strong > > Branch: < strong > main</ strong > / (root) > Click < strong > Save</ strong >
2026-10-16 22:03:47 +07:00
</ li >
< li >
2026-10-16 22:16:53 +07:00
< strong style = "color: var(--text-main);" > 4. Done:</ strong >< br >
Your dashboard will be online at < code > https://< user> .github.io/GaC-srtool/</ code > !
2026-10-16 22:03:47 +07:00
</ li >
</ ol >
</ div >
</ div >
</ section >
</ main >
<!-- Settings Modal -->
< div class = "modal-overlay" id = "modal-settings" >
< div class = "modal-content" >
< div class = "modal-header" >
2026-10-16 22:16:53 +07:00
< h3 style = "font-weight: 700;" data-i18n = "apiSettingsTitle" > ⚙️ ตั้งค่าการเชื่อมต่อ API Server</ h3 >
2026-10-16 22:03:47 +07:00
< button class = "btn btn-sm btn-secondary" id = "btn-close-modal" > ✕</ button >
</ div >
< div >
< div class = "form-group" >
2026-10-16 22:16:53 +07:00
< label class = "form-label" data-i18n = "lblApiGatewayUrl" > Server REST API URL</ label >
2026-10-16 22:03:47 +07:00
< input type = "text" id = "modal-api-url" class = "form-input" >
</ div >
< div style = "display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem;" >
2026-10-16 22:16:53 +07:00
< button class = "btn btn-secondary" id = "btn-modal-cancel" > Cancel</ button >
< button class = "btn btn-primary" id = "btn-modal-save" data-i18n = "btnSaveSettings" > บันทึก & ทดสอบ</ button >
2026-10-16 22:03:47 +07:00
</ div >
</ div >
</ div >
</ div >
<!-- Toast Notification Container -->
< div class = "toast-container" id = "toast-container" ></ div >
<!-- Script Modules -->
< script type = "module" src = "js/app.js" ></ script >
</ body >
</ html >