DEVELOPMENT.th
📘 FinderHub คู่มือสำหรับนักพัฒนา
[!NOTE] เอกสารนี้ให้ข้อมูลเชิงลึกเกี่ยวกับโค้ดเบสของ FinderHub
- สำหรับเวอร์ชันภาษาอังกฤษ โปรดดู English Docs
- สำหรับข้อมูล API โปรดดู API Docs
คู่มือนี้ให้ภาพรวมที่ครอบคลุมเกี่ยวกับสถาปัตยกรรมของ FinderHub อธิบายการทำงานที่ซับซ้อนของส่วนประกอบหลัก การไหลของข้อมูล และฟังก์ชันยูทิลิตี้ เพื่ออำนวยความสะดวกในการพัฒนาและบำรุงรักษาในอนาคตอย่างราบรื่น
สารบัญ
- โครงสร้างโปรเจกต์
- ส่วนประกอบหลัก
- การจัดการสถานะ (State Management)
- ชั้นข้อมูลและ Supabase
- สคริปต์และเครื่องมือ
- การตกแต่งและระบบ UI
- บันทึกการเปลี่ยนแปลง (Changelog)
โครงสร้างโปรเจกต์
โปรเจกต์นี้ยึดตามสถาปัตยกรรม Next.js App Router เพื่อให้มั่นใจในความสามารถในการขยายและบำรุงรักษา
การจัดการรูปภาพ (Image Handling)
ระบบมีการจัดการรูปภาพที่มีประสิทธิภาพเพื่อลดภาระของ Server และ Storage:
- Instant Preview: เมื่อผู้ใช้เลือกรูปภาพ ระบบจะสร้าง Local Object URL เพื่อแสดงตัวอย่างทันที (ไม่มีการอัปโหลด)
- Deferred Upload: การอัปโหลดจริงจะเกิดขึ้นเมื่อผู้ใช้กด "ยืนยัน" ในขั้นตอนสุดท้ายเท่านั้น
- Optimization: รูปภาพจะถูกแปลงเป็น WebP โดยอัตโนมัติก่อนบันทึกลง Supabase Storage เพื่อลดขนาดไฟล์
รากฐาน (Root Directory)
ไฟล์กำหนดค่าและเอกสารสำคัญที่อยู่ในระดับสูงสุด:
📄 package.json: จัดการ dependencies และสคริปต์📄 .env: ตัวแปรสภาพแวดล้อม (Environment Variables)📄 README.md: เอกสารเริ่มต้นใช้งาน📂 public/: ไฟล์ Static assets (รูปภาพ, ไอคอน)
ซอร์สโค้ด (src/)
โค้ดหลักของแอปพลิเคชันทั้งหมดอยู่ในโฟลเดอร์ src/:
src/
├── 📂 app/ # เส้นทางหน้าเว็บและเลย์เอาต์
│ ├── 📄 layout.js # พื้นที่เก็บชุดคำสั่งระดับหัว (เรียกใช้สคริปต์, เรียกใช้บริการ (CDN))
│ ├── 📄 page.jsx # เส้นทางหน้าแรกสาธารณะ (ตารางรายการของหาย)
│ ├── 📂 admin/ # เส้นทางที่ได้รับการป้องกันสำหรับผู้ดูแลระบบ
│ ├── 📂 dev/ # 🆕 Developer Portal (เอกสาร & Sitemap)
│ └── 📂 login/ # เส้นทางการยืนยันตัวตน
├── 📂 components/ # คอมโพเนนต์ React
│ ├── 📂 admin/ # คอมโพเนนต์เฉพาะสำหรับ Admin (ตาราง, ส่วนหัว)
│ ├── 📂 common/ # คอมโพเนนต์ทั่วไป (PrelineScript)
│ ├── 📂 items/ # คอมโพเนนต์เกี่ยวกับรายการ (ItemCard)
│ ├── 📂 layout/ # โครงสร้างหลัก (Navbar, Footer)
│ ├── 📂 modals/ # กล่องโต้ตอบ (Dialogs) และวิซาร์ด (Wizards)
│ └── 📂 ui/ # องค์ประกอบ UI พื้นฐานที่ใช้ซ้ำได้ (ปุ่ม, ช่องกรอกข้อมูล)
├── 📂 hooks/ # React Hooks แบบกำหนดเอง (ตรรกะของระบบ)
├── 📂 lib/ # ยูทิลิตี้, ไคลเอนต์ API, และการเชื่อมต่อฐานข้อมูล
│ ├── 📄 data.js # Data Access Object (DAO)
│ ├── 📄 docs.js # 🆕 Markdown Parser สำหรับ Docs
│ └── 📄 supabase.js # Supabase Client Initialization
└── 📂 scripts/ # สคริปต์สำหรับการบำรุงรักษาและการตั้งค่า
ส่วนประกอบหลัก
แดชบอร์ดผู้ดูแลระบบ
Admin Dashboard (src/app/admin/page.jsx) คือศูนย์กลางสำหรับการจัดการรายการไอเทม
useAdminDashboard Hook
Custom hook นี้ (src/hooks/useAdminDashboard.js) ทำหน้าที่เป็น สมอง ของแดชบอร์ด โดยแยกตรรกะออกจาก UI
- การดึงข้อมูล: โหลดรายการโดยอัตโนมัติเมื่อเริ่มต้น
- เครื่องมือกรอง: ใช้การกรองฝั่งไคลเอนต์สำหรับ:
- 🔍 ค้นหา (ชื่อ, สถานที่, รายละเอียด)
- 🏷️ หมวดหมู่ (ไอที, ของใช้ส่วนตัว, เครื่องเขียน)
- 📍 สถานะ (พบแล้ว/คืนแล้ว)
- การควบคุมสถานะ: จัดการการแสดงผลของมอดูลทั้งหมด (เพิ่ม, ดู, รับคืน)
AdminTable & AdminMobileCard
มีการปรับใช้ Responsive Design เพื่อให้ได้ UX/UI ที่ดีบนทุกอุปกรณ์
- เดสก์ท็อป: แสดงผล
<table>โดยละเอียดพร้อมคอลัมน์ที่จัดเรียงได้ - มือถือ: เปลี่ยนเป็นรูปแบบการ์ด (
AdminMobileCard) เพื่อ UX ที่ดีขึ้น
นอกจากนี้ยังมีส่วนประกอบย่อยที่สำคัญ:
AdminTableFilters: จัดการ UI สำหรับการค้นหา กรองหมวดหมู่ และกรองสถานะAdminTableRow: รับผิดชอบการแสดงผลข้อมูลในแต่ละแถวของตาราง
มอดูลและวิซาร์ด
เราใช้มอดูลเพื่อจัดการขั้นตอนการทำงานที่ซับซ้อนโดยไม่ต้องเปลี่ยนหน้าออกจากหน้าหลัก
AddItemModal (The Wizard)
กระบวนการ 2 ขั้นตอนสำหรับการเพิ่มรายการ:
-
ขั้นตอนที่ 1: การกรอกข้อมูล (
AddItemForm)- เก็บรายละเอียดรายการ (ชื่อ, หมวดหมู่, สถานที่)
- Smart Upload: รองรับการเลือก กล้อง 📷, แกลเลอรี 🖼️, และไฟล์ 📁
- Auto-Date: ปุ่ม "ตอนนี้" เพื่อตั้งค่าเวลาปัจจุบันอย่างรวดเร็ว
⬇️ ถัดไป
-
ขั้นตอนที่ 2: การตรวจสอบ (
AddItemPreview)- แสดงตัวอย่างสดของ
ItemCardเหมือนที่จะปรากฏต่อสาธารณะ - ให้ผู้ใช้ ยืนยัน ✅ หรือ ย้อนกลับ ↩️ เพื่อแก้ไข
- แสดงตัวอย่างสดของ
FoundItemModal
มอดูลสำหรับผู้ใช้ทั่วไปเพื่อแจ้งการพบของหาย (คล้ายกับ AddItemModal แต่สำหรับฝั่ง Public)
ItemModal
มอดูลแสดงรายละเอียดของรายการสำหรับผู้ใช้ทั่วไป (Public View) แสดงข้อมูลครบถ้วนพร้อมรูปภาพขนาดใหญ่
AdminItemModal & ClaimItemModal
มุมมองและการจัดการสำหรับผู้ดูแลระบบ:
AdminItemModal: ตรวจสอบรายละเอียดรายการ พร้อมปุ่มดำเนินการClaimItemModal: แบบฟอร์มสำหรับบันทึกข้อมูลผู้มารับของคืน (ชื่อ, เบอร์โทร) เมื่อเปลี่ยนสถานะเป็น "คืนแล้ว"
องค์ประกอบ UI ที่ใช้ร่วมกัน (Shared UI)
ใน src/components/ui เรามีชุดคอมโพเนนต์พื้นฐานที่สร้างขึ้นด้วย Radix UI และ Tailwind CSS:
Badge: ป้ายสถานะ (เช่น "Found", "Returned")Button: ปุ่มกดที่มีหลายรูปแบบ (default, outline, ghost)Card: คอนเทนเนอร์พื้นฐานสำหรับการ์ดข้อมูลDialog: พื้นฐานของมอดูลทั้งหมดInput/Textarea: ช่องกรอกข้อมูลTable: โครงสร้างตารางที่ตอบสนองได้Select: เมนูตัวเลือก (Dropdown)
การโหลดข้อมูล
มีการใช้แนวทางการโหลดข้อมูลเริ่มต้นที่ดีที่สุด
- 🚀 Global Loader (
LoadingScreen): การเปลี่ยนผ่านแบบเต็มหน้าจอที่ใช้ระหว่างการตรวจสอบสิทธิ์เริ่มต้นและการดึงข้อมูลสำคัญ - 🔄 Background Refresh: การรีเฟรชข้อมูลใน Admin Dashboard จะทำในเบื้องหลังพร้อมแสดงสถานะที่ตาราง (Table Loading) แทนการโหลดหน้าใหม่ทั้งหมด เพื่อประสบการณ์ที่ลื่นไหล
- 💀 Skeletons (
ItemCardSkeleton): ใช้ในตารางสาธารณะเพื่อป้องกัน Cumulative Layout Shift (CLS) ในขณะที่รูปภาพและข้อมูลกำลังโหลด - 🖼️ Progressive Image Loading:
ItemCardมีเอฟเฟกต์ blur-up ในตัว แสดงภาพตัวอย่างที่เต้นเป็นจังหวะจนกว่าภาพความละเอียดสูงจะพร้อม
การจัดการสถานะ (State Management)
เราให้ความสำคัญกับ ความเรียบง่าย และ Local State มากกว่า Global Stores ที่ซับซ้อน
- React Hooks:
useStateและuseEffectขับเคลื่อน 90% ของแอปพลิเคชัน - Prop Drilling: ใช้อย่างมีประสิทธิภาพสำหรับการส่งข้อมูลไปยังลูกโดยตรง (เช่น
AdminPage->AdminTable) - ไม่มี Redux/Context: ขอบเขตปัจจุบันไม่ต้องการ Global State ที่หนักหน่วง ช่วยให้ขนาดไฟล์เล็ก
ชั้นข้อมูลและ Supabase
แอปพลิเคชันโต้ตอบโดยตรงกับ Supabase สำหรับบริการ Backend
DataManager Class (src/lib/data.js)
คลาสสแตติกที่ทำหน้าที่เป็นชั้นนามธรรม (Abstraction Layer) เหนือ Supabase SDK
| เมธอด | คำอธิบาย |
| :---------------------- | :------------------------------------------------------------------------------ |
| getAllItems() | ดึงรายการสินค้าคงคลังทั้งหมด เรียงตามวันที่ |
| addItem(item) | เพิ่มบันทึกรายการใหม่ลงในตาราง items |
| updateItemStatus(...) | อัปเดตสถานะเป็น false (คืนแล้ว) พร้อมบันทึกข้อมูลผู้รับคืนและหลักฐาน (รูปภาพ) |
| deleteItem(id) | ลบรายการและรูปภาพที่เกี่ยวข้องอย่างถาวร |
สคริปต์และเครื่องมือ
scripts/supabase-init.js
ผู้ช่วยการตั้งค่าอัจฉริยะ และตัวเริ่มเซิร์ฟเวอร์สำหรับการพัฒนา (Intelligent Setup Assistant & Dev Server Launcher)
สคริปต์นี้ถูกนำมาใช้แทนคำสั่ง next dev แบบปกติ เพื่อให้มั่นใจว่าสภาพแวดล้อมพร้อมใช้งาน:
- ตรวจสอบ Environment: เช็คว่ามีไฟล์
.envหรือไม่ - การตั้งค่าแบบโต้ตอบ: หากไม่มีไฟล์
.envระบบจะถาม Supabase URL และ Key จากผู้ใช้เพื่อสร้างไฟล์ให้ทันที - ทดสอบการเชื่อมต่อ: ตรวจสอบว่าสามารถเชื่อมต่อกับ Supabase ได้จริงก่อนเ### 3. รันเซิร์ฟเวอร์
npm run dev
Note: หากพบปัญหา "Unable to acquire lock" หรือพอร์ตไม่ว่าง ให้ใช้คำสั่ง:
npm run dev:cleanคำสั่งนี้จะล้าง process ที่ค้างอยู่และลบ lock file ให้โดยอัตโนมัติ
เปิด http://localhost:3000 เพื่อดูผลลัพธ์ให้แน่ใจว่าทุกอย่างพร้อม แล้วจึงรันคำสั่ง npx next dev
วิธีนี้ช่วยแก้ปัญหา "command not found" และป้องกันข้อผิดพลาดจากการที่แอปเริ่มทำงานโดยที่ยังเชื่อมต่อฐานข้อมูลไม่ได้
การตกแต่งและระบบ UI
ระบบการออกแบบของเราสร้างขึ้นบนเทคโนโลยีสมัยใหม่เพื่อความเร็วและความสม่ำเสมอ
- 🌊 Tailwind CSS: การตกแต่งแบบ Utility-first สำหรับการพัฒนา UI ที่รวดเร็ว
- 🧩 Shadcn UI: ให้ส่วนประกอบพื้นฐานที่เข้าถึงได้และไม่มีสไตล์ (Dialogs, Inputs) ซึ่งเรานำมาปรับแต่ง
- ✨ Lucide React: ชุดไอคอนที่สม่ำเสมอและมีน้ำหนักเบาที่ใช้ทั่วทั้งแอป
- 📱 Responsive Design: แนวทาง Mobile-first เพื่อให้มั่นใจในการใช้งานบนทุกขนาดหน้าจอ
บันทึกการเปลี่ยนแปลง (Changelog)
สำหรับประวัติการเปลี่ยนแปลงโดยละเอียด โปรดดูที่ บันทึกการเปลี่ยนแปลง