Airtime
Measure jump height from video by stepping through takeoff and landing frames
翻譯準備中
AI 摘要 · 網站內容
尚未收集儲存庫資訊。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗ระบบจัดการลีกฟุตบอล — หน้าบ้านสำหรับผู้ชม และหลังบ้านสำหรับผู้ดูแลกับกรรมการ
เป็นโปรเจกต์เดียว (Next.js) หน้าบ้านกับหลังบ้านใช้ฐานข้อมูลและ data model ชุดเดียวกัน
npm install
npm run db:reset # สร้างฐานข้อมูล + ใส่ข้อมูลตัวอย่าง (10 ทีม 160 นักเตะ 45 นัด)
npm run dev
npm run dev ผูกกับทุก network interface อยู่แล้ว (next dev -H 0.0.0.0)
หา IP ของเครื่องแล้วเปิดจากมือถือได้เลย
ipconfig getifaddr en0 # เช่น 192.168.1.40
แล้วเข้า http://<IP>:3000 จากมือถือ
ถ้าเข้าไม่ได้ ให้เช็กว่า macOS ไม่ได้บล็อกไว้ที่ System Settings → Network → Firewall (ปิด หรืออนุญาต node)
| สิทธิ์ | อีเมล | รหัสผ่าน |
|---|---|---|
| ผู้ดูแลระบบ | [email protected] | admin1234 |
| กรรมการ | [email protected] | referee1234 |
เปลี่ยนรหัสผ่านและ
AUTH_SECRETใน.envก่อนขึ้นใช้งานจริงเสมอ
สีทั้งหมดมาจากโลโก้ Artist FC
| สี | ค่า | ใช้ที่ไหน |
|---|---|---|
| ส้ม | #F25C05 | ปุ่มหลัก แท็บที่เลือก ลิงก์ hover |
| ดำ | #0D0D0D | พื้นหลังโหมดมืด / ตัวอักษรโหมดสว่าง |
| ขาวนวล | #F5F3F4 | พื้นหลังโหมดสว่าง / ตัวอักษรโหมดมืด |
พื้นหลังสลับขาว/ดำตามเวลาประเทศไทยอัตโนมัติ
06:00–17:59 น. → พื้นขาว18:00–05:59 น. → พื้นดำธีมคำนวณจากฝั่งเซิร์ฟเวอร์ตั้งแต่ HTML แรก หน้าเว็บจึงไม่กะพริบตอนโหลด และใช้เวลาไทยเสมอไม่ว่าเครื่องผู้ใช้จะตั้ง timezone ไว้ยังไง
ปุ่มรูปนาฬิกามุมขวาบนกดสลับได้: ตามเวลาไทย → สว่าง → มืด → ตามเวลาไทย (จำค่าไว้ในเครื่องผู้ใช้) เปิดหน้าค้างไว้ข้ามเวลา ระบบจะเปลี่ยนธีมให้เองภายใน 1 นาที
แก้เวลาตัดได้ที่ DAY_START / NIGHT_START ใน src/lib/theme.ts
ไฟล์โลโก้: src/assets/artist-fc.png (ใช้เป็น favicon ด้วยผ่าน src/app/icon.png)
ออกแบบให้ใช้ได้ตั้งแต่จอ 320px (iPhone SE) ขึ้นไป ไม่มีการเลื่อนแนวนอนทั้งหน้า
ตารางคะแนน ซ่อนคอลัมน์ทีละชั้นตามความกว้างจอ แทนการบีบให้เลื่อนซ้ายขวา
| ความกว้าง | คอลัมน์ที่เห็น |
|---|---|
| < 640px | อันดับ · สโมสร · แข่ง · ต่าง · แต้ม |
| ≥ 640px | + ชนะ เสมอ แพ้ |
| ≥ 768px | + ได้ เสีย |
| ≥ 1024px | + ฟอร์ม 5 นัดล่าสุด |
หน้าบันทึกผล (/admin/matches) เปลี่ยนเป็นการ์ดบนจอเล็ก เพราะกรรมการใช้มือถือกรอกผลข้างสนาม
ตารางแบบเดิมจะโผล่เมื่อจอกว้าง ≥ 768px
ปุ่มบนแถบหัวเรื่อง ย่อเป็นไอคอนขนาด 36px บนมือถือ (ดูหน้าเว็บ / สลับธีม / ออกจากระบบ)
ตารางอื่น ๆ ซ่อนคอลัมน์รองแล้วย้ายข้อมูลสำคัญไปอยู่ใต้ชื่อแทน และยังซูมด้วยนิ้วได้ปกติ (ไม่ได้ล็อก user-scalable)
| ความสามารถ | ผู้ดูแลระบบ | กรรมการ |
|---|---|---|
| ดูหน้าเว็บ | ✓ | ✓ |
| บันทึกผลนัดที่ตัวเองเป็นผู้ตัดสิน | ✓ | ✓ |
| บันทึกผลนัดอื่น | ✓ | — |
| อนุมัติ / ตีกลับผล | ✓ | — |
| จัดการฤดูกาล สโมสร นักเตะ ผู้ใช้ | ✓ | — |
| ดูประวัติการแก้ไข | ✓ | — |
ขั้นตอนบันทึกผล: กรรมการกรอกสกอร์ → สถานะ รออนุมัติ (ยังไม่นับคะแนน) → ผู้ดูแลอนุมัติ → สถานะ จบแล้ว และตารางคะแนนขยับ ถ้าผู้ดูแลกรอกเอง จะถือว่าอนุมัติทันที
prisma/schema.prisma นิยามข้อมูล
src/
lib/ ตรรกะบริสุทธิ์ — ไม่แตะ DB ไม่แตะ React (เทสต์ได้ทันที)
standings.ts คำนวณตารางคะแนน + กฎตัดสินคะแนนเท่ากัน
fixtures.ts สร้างตารางแข่งแบบพบกันหมด
theme.ts ธีมขาว/ดำตามเวลาไทย
format.ts วันที่ เวลา ตัวเลข
labels.ts คำภาษาไทยของค่าคงที่ทุกตัว
server/ ทุกอย่างที่แตะฐานข้อมูลและ session
db.ts Prisma client ตัวเดียวของแอป
auth.ts session + รหัสผ่าน + audit log
guards.ts กฎว่าใครแก้อะไรได้ (จุดเดียวของทั้งระบบ)
validation.ts zod schema ของทุกฟอร์ม
queries/ อ่านข้อมูล แยกตามโดเมน
actions/ เขียนข้อมูล แยกตามโดเมน
components/ UI ที่ใช้ซ้ำ
app/
(public)/ หน้าบ้าน
admin/login/ หน้าเข้าสู่ระบบ
admin/(dash)/ หลังบ้าน (layout บังคับล็อกอินให้อัตโนมัติ)
scripts/ ชุดทดสอบ
ชั้นบนเรียกชั้นล่างได้อย่างเดียว และมีกฎ ESLint บังคับไว้จริง —
src/lib ห้าม import @/server, หน้าเพจห้ามเรียก db ตรง ๆ
📖 รายละเอียดว่า "จะแก้เรื่องนี้ ต้องไปไฟล์ไหน" อยู่ที่ ARCHITECTURE.md
ตารางคะแนน นับเฉพาะนัดสถานะ FINISHED เท่านั้น
แต้ม ตั้งค่าได้ต่อฤดูกาล (ค่าเริ่มต้น ชนะ 3 / เสมอ 1 / แพ้ 0)
เมื่อคะแนนเท่ากัน เลือกลำดับกฎเองได้ที่ /admin/seasons — ผลต่างประตู, ประตูได้, ผลการเจอกันเอง, จำนวนนัดที่ชนะ, เสียประตูน้อยกว่า, ประตูในเกมเยือน
ตารางแข่ง สร้างด้วย circle method — ทุกทีมเจอกันครบ ไม่มีทีมไหนแข่งซ้อนในนัดเดียวกัน จำนวนทีมเป็นเลขคี่จะมี 1 ทีมได้พักในแต่ละนัด เลือกได้ว่าเจอกันรอบเดียวหรือเหย้า–เยือน
npm run typecheck
npm run lint
npm run test # ต้องเปิด npm run dev ไว้อีกหน้าต่างหนึ่ง
| คำสั่ง | ทดสอบอะไร |
|---|---|
test:logic | ตารางคะแนนและตัวสร้างตารางแข่ง (4–20 ทีม) |
test:theme | ธีมสลับตามเวลาไทยครบ 24 ชั่วโมง |
test:workflow | ผลรออนุมัติไม่ถูกนับ และคะแนนขยับถูกต้องเมื่ออนุมัติ |
test:pages | ทุกหน้าขึ้นถูกต้องตามสิทธิ์ |
test:responsive | ทุกหน้าไม่ล้นจอที่ 320px และตั้ง viewport ถูกต้อง |
test:login | เข้าสู่ระบบ รหัสผ่านผิด และ session ปลอม |
test:flow | กรรมการกรอกผล → แอดมินอนุมัติ → ตารางคะแนนขยับ (ผ่าน HTTP จริง) |
ชุดทดสอบคืนค่าข้อมูลกลับสภาพเดิมทุกครั้ง
ใช้ PostgreSQL (เช่น Neon ผ่าน Vercel Storage) ทั้งตอน dev และ production
.env ให้มี DATABASE_URL (pooled) และ DATABASE_URL_UNPOOLED (ต่อตรง ใช้กับ migration)npx prisma migrate dev --name init แล้ว npm run db:seedDATABASE_URL, DATABASE_URL_UNPOOLED, AUTH_SECRET — vercel.json จะรัน prisma migrate deploy ก่อน next build ให้อัตโนมัติก่อน deploy อย่าลืมตั้ง AUTH_SECRET เป็นค่าสุ่ม:
openssl rand -base64 32