2.1 สมัครสมาชิกใหม่
การสมัครสมาชิกใช้เวลา ~2 นาที ทำได้ 3 ช่องทาง:
- 📝 สมัครด้วยฟอร์มปกติ (username + password)
- 🔵 สมัครผ่าน Google
- 🟢 สมัครผ่าน LINE
รูปที่ 2.1 — หน้า signup.php
ขั้นตอน (สมัครด้วยฟอร์ม)
- เข้า
thaibadtournaments.com/badminton/signup.php
- กรอก username (a-z, 0-9, _ — ไม่มีช่องว่าง)
- กรอก email (ระบบเช็ค MX DNS — ต้องใช้งานได้จริง)
- กรอก password + ยืนยัน (อย่างน้อย 8 ตัว)
- กรอก ชื่อจริง-นามสกุล ภาษาไทย
- ยอมรับ Privacy Policy → กด "สมัครสมาชิก"
⚠️ ตรวจ duplicate
ระบบจะเช็ค check_username.php, check_email.php, check_name_duplicate.php แบบ realtime — ถ้า username/email/ชื่อ ซ้ำ จะเตือนทันทีก่อน submit
💡 Tip — ทำไมต้องใช้ชื่อจริง?
ระบบใช้ชื่อจริงในการแมตช์ผู้เล่นกับการสมัครแข่งและ ranking — ใช้ชื่อเล่นไม่ได้
2.2 เข้าสู่ระบบ (Login)
รูปที่ 2.2 — หน้า login.php — มี 3 ช่องทาง
- ใส่ username หรือ email (ระบบรับทั้งคู่)
- ใส่ password → กด "ลงชื่อเข้าใช้"
- หากมี 2FA เปิดอยู่ ระบบจะถามรหัส OTP 6 หลัก
🔐 ระบบความปลอดภัย
- Account Lockout — ใส่ password ผิด 5 ครั้ง ติดล็อก 15 นาที
- Rate limit — IP เดียวกัน login ได้ 20 ครั้ง/10 นาที
- CSRF protection — ทุก POST ต้องมี
_csrf token
🔑 ลืมรหัสผ่าน
- กด "ลืมรหัสผ่าน?"
- ใส่ email ที่ลงทะเบียนไว้
- เปิด email → กดลิงก์ reset (อายุ 1 ชม.)
- ตั้ง password ใหม่
2.3 ผูกบัญชี LINE
การผูก LINE สำคัญมาก เพราะระบบจะส่ง reminder ก่อนแข่ง 30 นาที + 1 ชั่วโมง ผ่าน LINE
รูปที่ 2.3 — หน้า link_line.php แสดง QR + PIN 6 หลัก
วิธีผูก
- Login เข้าระบบ → ไปที่ โปรไฟล์ → "ผูก LINE"
- ระบบสร้าง PIN 6 หลัก (อายุ 15 นาที)
- เพิ่มเพื่อน LINE Bot:
@thaibadtournaments (สแกน QR)
- พิมพ์
ลงทะเบียน 123456 ในแชท (แทน 123456 ด้วย PIN ของคุณ)
- Bot ตอบกลับ "เชื่อมต่อสำเร็จ" → จบ
🔒 ความปลอดภัย
PIN ใช้ได้ครั้งเดียวเท่านั้น, expire ใน 15 นาที — ถ้าไม่ใช้ทัน ต้องสร้างใหม่ ระบบจะเช็คว่า LINE UID ไม่ได้ผูกกับ user อื่นก่อน
ยกเลิกการผูก
ไปที่ โปรไฟล์ → กดปุ่ม "ยกเลิกการผูก LINE" — ระบบจะลบ link และหยุดส่ง notification ทันที
2.4 ตั้งค่า 2FA (Two-Factor Authentication)
เปิด 2FA เพื่อความปลอดภัยขั้นสูง — ต้องใช้ Google Authenticator หรือ app TOTP อื่น
วิธีเปิด 2FA
- ไปที่ โปรไฟล์ → แก้ไขข้อมูล → tab "ความปลอดภัย"
- กด "เปิดใช้ 2FA"
- สแกน QR code ด้วย Google Authenticator (หรือ Authy, 1Password)
- กรอกรหัส 6 หลักจาก app → ยืนยัน
- ระบบให้ backup codes 10 รหัส — บันทึกไว้ในที่ปลอดภัย
🚨 ระวัง — Backup Codes
Backup codes แต่ละรหัสใช้ได้ ครั้งเดียว — ใช้เมื่อมือถือหาย/Authenticator app เปลี่ยนเครื่อง ห้ามแชร์ ห้าม screenshot บน cloud
เวลา login ด้วย 2FA
- ใส่ username + password ปกติ
- ระบบพาไปหน้า
verify_2fa.php
- เปิด Authenticator → กรอกรหัส 6 หลัก → ผ่าน
2.5 ยืนยันตัวตน (Identity Verification)
ทัวร์บางรายการ (โดยเฉพาะ Association tournament รุ่นอายุ) บังคับให้ยืนยันตัวตนก่อนสมัคร เพื่อยืนยันอายุจริง
ขั้นตอน
- ไปที่ โปรไฟล์ → "ยืนยันตัวตน"
- อัปโหลดรูปบัตรประชาชน (ปิดเลข 4 ตัวท้ายได้)
- กรอกข้อมูล: ชื่อ-นามสกุล, วันเกิด, เพศ (ต้องตรงกับบัตร)
- กด "ส่งคำขอ" → รอแอดมินตรวจ (ปกติ 1-2 วันทำการ)
🔒 Privacy-First
เมื่อแอดมินอนุมัติแล้ว ระบบจะลบรูปบัตรประชาชนทันที — เก็บแค่ flag "verified" + วันเกิด + เพศ ไม่มีการเก็บภาพถาวร
หลังยืนยันแล้ว
- โปรไฟล์ขึ้น badge "✓ ยืนยันแล้ว"
- สามารถสมัครรุ่นอายุได้
- หากไม่ผ่าน — แอดมินจะแจ้งเหตุผลผ่าน Inbox + LINE
2.6 ดูและแก้ไขโปรไฟล์
รูปที่ 2.6 — หน้าโปรไฟล์ profile.php
ส่วนประกอบ
- UID — รหัสประจำตัว 4 หลัก (เช่น UID0002) ใช้ในการเชิญคู่
- สถานะ LINE — แสดงว่าผูก LINE แล้วหรือยัง
- สถิติ Stats — จำนวนแข่ง, เหรียญทอง/เงิน/ทองแดง
- รายละเอียดผลงาน — ประวัติทัวร์ทั้งหมดที่เคยลงแข่ง
แก้ไขข้อมูล
รูปที่ 2.6.2 — edit_profile.php
แก้ไขได้ทันที (ไม่ต้อง OTP):
- รูปโปรไฟล์, เบอร์โทร, จังหวัด
- การตั้งค่าภาษา (TH/EN)
ต้องใช้ OTP ผ่าน email ก่อนเปลี่ยน:
- email, password, ชื่อ-นามสกุล, วันเกิด, เพศ
💡 ทำไมต้อง OTP?
ข้อมูลพวกนี้ส่งผลต่อ identity + การสมัครรุ่นอายุ — ระบบบังคับให้ยืนยันผ่าน OTP เพื่อป้องกัน account takeover
2.7 ดูปฏิทินการแข่งขัน
รูปที่ 2.7 — calendar.php — แสดงรายการแข่งทุกสถานะ
วิธีกรอง
- ตามจังหวัด — dropdown เลือกจังหวัด
- ตามเดือน — เลื่อนซ้าย/ขวา
- ตามสถานะ — สีของ pill บอกสถานะ
วิธีอ่านสีบนปฏิทิน
| เปิดรับสมัคร | สีเขียว — สมัครได้ตอนนี้ |
| ปิดรับสมัคร | สีแดง — หมดเวลาสมัครแล้ว |
| กำลังแข่งขัน | สีเหลือง — แข่งวันนี้/สัปดาห์นี้ |
| เสร็จสิ้น | สีเทา — จบแล้ว ดูผลย้อนหลัง |
คลิกที่รายการเพื่อเข้าสู่หน้า match_detail.php?id=...
2.8 หน้ารายละเอียดรายการแข่ง (Match Detail Tabs)
หน้ารายการแข่ง match_detail.php?id=N มี 9 tabs ที่จะแสดง/ซ่อนตามสถานะของรายการ
รูปที่ 2.8 — Tab "รายละเอียดการแข่งขัน" (default)
| Tab | ไอคอน | เนื้อหา | เห็นเมื่อ |
| รายละเอียด | ℹ️ | วันแข่ง, สถานที่, โปสเตอร์, Google Map | เสมอ |
| กติกา | 📜 | กฎการแข่ง + รูปประกอบ | เปิดโดยแอดมิน |
| รายชื่อผู้สมัคร | 📋 | ทีมที่สมัครแล้ว + สถานะชำระเงิน | เปิดโดยแอดมิน |
| ตารางแข่งขัน | ⏰ | คิว + สนาม + เวลา (อัปเดตสด) | หลังจัดสาย |
| รอบแบ่งกลุ่ม | 📊 | ตารางคะแนนกลุ่ม (W/D/L) | มี group stage |
| รอบน็อกเอาต์ | 🌳 | สายแข่ง (bracket tree) | มี knockout |
| ผลการแข่งขัน | 🏆 | ผู้ชนะ + เหรียญ | หลังจบ |
| จำนวนลูกแบด | 🏸 | track ลูกแบดมินตันที่ใช้ | เปิดโดยแอดมิน |
| รูปภาพ | 📸 | gallery รูปจากการแข่ง | เปิดโดยแอดมิน |
📡 Tab "การแข่งสด" (Live)
เมื่อรายการอยู่สถานะ กำลังแข่งขัน และเปิด YouTube Live URL — จะมีปุ่ม "🔴 ดูการแข่งสด" แยกพิเศษ ฝัง YouTube embed
2.9 สมัครเข้าแข่ง
กดได้เมื่อรายการอยู่สถานะ เปิดรับสมัคร เท่านั้น
ขั้นตอน
- เข้าหน้า
match_detail.php?id=N
- กดปุ่ม "สมัครเข้าแข่งขัน" (สีเขียว ขวามือ)
- เลือก event ที่ต้องการ (เช่น ชายคู่, หญิงคู่, คู่ผสม)
- เลือก รุ่นอายุ (ถ้ามี — บังคับยืนยันตัวตนก่อน)
- กรอก ชื่อทีม (ค้นหาจากชื่อชมรมอัตโนมัติ)
- ส่วน คู่ที่ 2: 3 ทางเลือก
- 📨 ชวนผ่าน UID — กรอก UID ของคู่ → ระบบส่ง invite ใน Inbox + LINE
- 🔍 ค้นหาด้วยชื่อ — autocomplete จาก search_users_by_name
- ✍️ ใส่ชื่อ guest — สำหรับผู้ที่ไม่มีบัญชีในระบบ
- กด "ส่งใบสมัคร"
⚠️ ค่าธรรมเนียม
หลังส่งใบสมัคร สถานะจะเป็น "รอชำระเงิน" ต้องอัปโหลดสลิปภายในเวลาที่กำหนด (ส่วนใหญ่ 24-48 ชม.) ไม่งั้นใบสมัครจะถูกยกเลิกอัตโนมัติ
2.10 ตอบรับการเชิญจากคู่
เมื่อมีคนชวนคุณ — คุณจะได้รับการแจ้งเตือน 2 ช่องทาง:
- 📥 Inbox ในระบบ (inbox.php)
- 📱 LINE (ถ้าผูก LINE ไว้)
รูปที่ 2.10 — Inbox แสดง invite จากคู่
ขั้นตอนตอบรับ
- เปิด Inbox → คลิกที่ข้อความ "🎾 [ชื่อ] ชวนคุณลงแข่ง [ทัวร์]"
- ระบบพาไป
respond_invite.php?token=...
- ตรวจข้อมูล: รายการ, event, คู่ของคุณ
- กด "ยอมรับ" หรือ "ปฏิเสธ"
- หากยอมรับ — ใบสมัครเข้าสถานะ "รอชำระเงิน" ทันที (คนชวนต้องชำระเอง หรือคุยกันเอง)
💡 Token Security
Token ของ invite ใช้ครั้งเดียว, ผูกกับ user_id ของคุณ — คนอื่นเปิดลิงก์ไม่ได้
2.11 ชำระเงิน + อัปโหลดสลิป
ระบบรองรับ 3 โหมดการชำระ:
| โหมด | วิธีการ | การตรวจ |
| manual | ไม่มีระบบ online — โอนแล้วแจ้งแอดมินเอง | แอดมิน manual |
| manual_qr | สแกน QR code → อัปโหลดสลิป | แอดมิน manual |
| slipok | สแกน QR → อัปโหลดสลิป → SlipOK API ตรวจอัตโนมัติ | อัตโนมัติ |
ขั้นตอนอัปโหลดสลิป
- เข้าหน้า
match_detail.php → tab "รายชื่อผู้สมัคร" → หาแถวของคุณ
- กด "อัปโหลดสลิป"
- เลือกรูปสลิป (JPG/PNG, ขนาด < 5 MB)
- กด "ส่ง" → ระบบตรวจสลิป
- SlipOK mode — ตรวจอัตโนมัติใน 5-10 วินาที → สถานะ "ผ่านชำระแล้ว"
- Manual mode — รอแอดมินตรวจ (1-24 ชม.)
⚠️ SlipOK เช็คอะไรบ้าง
API ตรวจ: ยอดเงิน, ชื่อผู้รับโอน, เลข trans_ref, และ unique check ไม่ให้ใช้สลิปเดียวกันซ้ำ
2.12 Inbox — กล่องข้อความ
ประเภทข้อความที่จะเข้า Inbox
- 🎾 คำเชิญจากคู่ — มีปุ่มตอบรับ/ปฏิเสธ
- 💰 สลิปได้รับอนุมัติ / ปฏิเสธ
- 📅 การเปลี่ยนแปลงตารางแข่ง — เปลี่ยนสนาม/เวลา
- 🆔 ผลการตรวจ identity
- 📢 ประกาศจากแอดมิน (broadcast)
- 🌅 Morning Broadcast — สรุปตารางวันแข่ง 06:00
เปิดข้อความ → ระบบ mark เป็น "read" อัตโนมัติ
2.13 ตั้งค่าการแจ้งเตือน
เปิด/ปิดการแจ้งเตือนแต่ละประเภทได้ใน notification_settings.php
ช่องทาง
- 📨 Email
- 📱 LINE (ต้องผูก LINE ก่อน)
- 📥 Inbox (ในระบบ)
- 🔔 Web Push (ผ่าน Service Worker — ต้อง grant permission ในเบราว์เซอร์)
ประเภทที่ตั้งค่าได้
| Flag | เมื่อไร |
notify_match_reminder | ก่อนแข่ง 30 นาที + 1 ชั่วโมง |
notify_court_change | แอดมินเปลี่ยนสนาม/คิว |
notify_morning_broadcast | สรุปตารางวันแข่ง 06:00 |
notify_partner_invite | มีคนชวนเป็นคู่ |
notify_result_posted | ผลแข่งของคุณถูก post |
notify_payment_status | สลิปได้รับอนุมัติ/ปฏิเสธ |
ตั้งค่าได้ ต่อรายการแข่ง (per-tournament) ไม่ใช่ global เท่านั้น
2.14 ข่าวสาร (News)
รูปที่ 2.14 — หน้าข่าวสาร news.php
ข่าวสารโพสต์โดยแอดมิน — รวม:
- 📢 ประกาศจากระบบ
- 🏆 ข่าวการแข่งขัน
- 📝 บทความเกี่ยวกับแบดมินตัน
2.15 ค้นหารูปภาพด้วยใบหน้า (Photo Face Search)
🚧 ฟีเจอร์อยู่ระหว่างพัฒนา
ระบบ AI Face Recognition กำลังติดตั้งบน Proxmox VM (GPU) — รายละเอียดเทคนิคอ่านที่ส่วนที่ 7
การใช้งานที่วางแผนไว้
- เข้าหน้า
photo_search.php
- อัปโหลด selfie (รูปหน้าตัวเอง 1 รูป)
- เลือกรายการที่ต้องการค้นหารูป
- ระบบส่ง embedding ไปยัง AI → match กับรูปทั้งหมดในรายการ
- แสดงผล: รูปที่มีใบหน้าใกล้เคียง พร้อม similarity score
- ดาวน์โหลดรูปที่ต้องการ