IUX Frontend Team

Git Workflow & Code Structure Guide

แนวทางการทำงานสำหรับ Junior Frontend Developer

##

ภาพรวมโปรเจกต์ทั้งหมด

ทีม Frontend ดูแลหลายโปรเจกต์ที่ทำงานร่วมกัน แบ่งเป็น 3 ประเภทหลัก:

โปรเจกต์หลัก (Main Projects)

🌐
Iux-landing-nextts

Landing Page + Portal ปัจจุบันที่ใช้งานอยู่ รวมทั้ง Dashboard เดิมไว้ในโปรเจกต์เดียว — ในอนาคต Dashboard จะถูกแยกออกไปเหลือแค่ Landing อย่างเดียว เพื่อให้ build/deploy เร็วขึ้น

Main Project
📊
frontend / iux-dashboard-vite

Dashboard ใหม่ของ IUX ที่รวมฝั่ง Trade กับ Invest เข้าด้วยกัน design ใหม่ทั้งหมด สร้าง component เองภายในโปรเจกต์โดยไม่ใช้ library VT-UI

Standalone
🤝
iux-partner-nextjs

Portal สำหรับ IUX Affiliate — ครอบคลุมหน้า Dashboard, Login, Register ทั้งหมด

Standalone
frontend / iux-help-center-next

Help Center ใหม่ที่สร้างขึ้นเพื่อใช้กับ Zendesk — เบื้องต้นจะใช้งานที่ help.iux.za.com

Standalone
🦘
IUXAustralia / Frontend / Iuxau-landing-nextts

Landing Page สำหรับ iux.com.au (Australia)

Standalone

โปรเจกต์ Library (ใช้ร่วมกับโปรเจกต์หลัก)

📦
frontend / VT Landing UI (VTL)

UI Library ของ Landing Page — component ทุกหน้าใน iux.com (ยกเว้น Education) จะอยู่ในนี้ทั้งหมด รวมถึง animation, layout, style ใช้คู่กับ Iux-landing-nextts

Library → Iux-landing-nextts
📦
frontend / iux-ui (VT-UI)

UI Library ของ Dashboard Page — component หน้า Dashboard ปัจจุบันอยู่ในนี้ ใช้คู่กับ Iux-landing-nextts (จะไม่ถูกใช้ใน iux-dashboard-vite ตัวใหม่)

Library → Iux-landing-nextts
🧩
frontend / vt-widget

Widget UI ที่นำไปฝังใน WordPress และ Zendesk

Widget

ความสัมพันธ์ระหว่างโปรเจกต์

Diagram ด้านล่างแสดงว่า Library โปรเจกต์เชื่อมต่อกับ Main Project อย่างไร:

โครงสร้างโปรเจกต์ & ความสัมพันธ์
Iux-landing-nextts Landing + Portal + Dashboard (ปัจจุบัน) VT Landing UI (VTL) UI Library → Landing Pages iux-ui (VT-UI) UI Library → Dashboard Pages @vt/vtl-ui @vt/vt-ui ติดตั้งเป็น package ใน node_modules iux-dashboard-vite Dashboard ใหม่ — ไม่ใช้ Library, สร้าง component เอง อนาคต: แยก Dashboard ออก iux-partner-nextjs Affiliate Portal iux-help-center-next Help Center (ZA) vt-widget Widget (WP / Zendesk) Iuxau-landing Australia โปรเจกต์ Standalone — dev & deploy ตาม flow เดิมได้เลย Main Project Library New (อนาคต) Standalone

ภาพรวม Git Workflow

ทุกโปรเจกต์ใช้ระบบ Branch เดียวกัน โดยมี Branch หลักดังนี้:

BranchEnvironmentหน้าที่
main Production โค้ดที่ใช้งานจริง — เป็น source of truth สำหรับการแตก branch ใหม่ทุกครั้ง
beta Beta สำหรับ deploy ขึ้น Beta เพื่อทดสอบก่อนขึ้น Production
develop Staging ใช้ deploy ขึ้น Staging ให้ QA ทดสอบ — เป็น branch หลักที่เปิด MR เข้ามาเมื่อ dev เสร็จ
dev Dev / Testing สำหรับทดสอบตัว deploy ใหม่ เช่น ทดสอบ pipeline, CI/CD config หรือ deployment setup ก่อนนำไปใช้จริง
release-2.0.xxxx Release Branch สำหรับรวม feature ที่พร้อมขึ้น Beta/Prod ในแต่ละรอบ — Senior เป็นคนสร้าง
ข้อแตกต่างระหว่าง develop กับ dev

develop = branch หลักสำหรับ deploy ขึ้น Staging ให้ QA ทดสอบ feature ต่างๆ (ใช้ในขั้นตอนการทำงานปกติ)
dev = branch สำหรับทดสอบตัว deploy ใหม่โดยเฉพาะ เช่น ทดสอบการตั้งค่า CI/CD, pipeline หรือระบบ deployment ที่มีการปรับเปลี่ยน

สำคัญมาก

ทุกครั้งที่เริ่มงานใหม่ ต้องแตก branch จาก main เสมอ — ห้ามแตกจาก develop, dev หรือ branch อื่น เพราะ develop อาจมีโค้ดของ feature อื่นที่ยังไม่ผ่าน QA ปนอยู่ หากนำโค้ดเหล่านั้นติดไปจะทำให้เกิดปัญหาตอน merge เข้า release หรือ main

Feature Flow — งานปกติใน Sprint

แตก Branch จาก main

เมื่อได้รับ feature ใหม่ ให้แตก branch จาก main ตั้งชื่อ feature/ชื่อ-feature แล้วเริ่ม dev ใน branch นั้น

# ดึงโค้ดล่าสุดจาก main
git checkout main
git pull origin main

# แตก branch ใหม่
git checkout -b feature/new-help-center

Dev จนเสร็จ → Merge Request เข้า develop

เมื่อ dev เสร็จ push branch ขึ้น remote แล้วเปิด Merge Request (MR) จาก feature/xxxxdevelop ระบบจะ deploy ขึ้น Staging ให้ QA ทดสอบ

git push origin feature/new-help-center

# เปิด MR บน GitLab / GitHub
# source: feature/new-help-center → target: develop

QA ทดสอบบน Staging

QA ทดสอบ feature บน Staging environment ซึ่งจะมี 2 กรณี:

✅ กรณีผ่าน — พร้อมขึ้น Beta

Senior จะสร้าง branch release-2.0.xxxx → เปิด MR จาก feature/xxxx เข้า release → deploy ขึ้น Beta → เสร็จ

❌ กรณีไม่ผ่าน — มี Bug

แก้ Bug ตาม report จาก QA ให้ครบ → push ขึ้น branch เดิม → เปิด MR เข้า develop อีกครั้ง → QA Retest → วนจนกว่าจะผ่านทั้งหมด

Keep on Staging — Feature ที่รอ PO อนุมัติ

Feature ที่ยังไม่ขึ้น Prod ตามรอบ Sprint

บาง feature แม้จะ dev เสร็จและผ่าน QA แล้ว แต่ยังไม่พร้อมขึ้น Production — เรียกว่า "Keep on Staging"

ขั้นตอน dev และ MR เข้า develop ยังเหมือนเดิมทุกอย่าง แต่เมื่อถึงรอบ deploy จะยังไม่นำ feature นั้นขึ้น Beta/Prod

✅ PO แจ้ง "พร้อมขึ้น Prod"

ทำตาม flow ปกติ — MR จาก feature branch เข้า release-2.0.xxxx

⏸ PO แจ้ง "ยังไม่ขึ้น"

ไม่ต้องเปิด MR ใดๆ เพิ่ม — feature ค้างอยู่บน Staging ไปก่อน เมื่อ PO แจ้งพร้อมค่อยทำ

หมายเหตุ

เก็บ feature branch ไว้ ไม่ต้องลบ เพราะจะต้องใช้เปิด MR เข้า release branch ในภายหลัง

Hotfix Flow — งานแก้ด่วน

Hotfix — แก้ปัญหาเร่งด่วนบน Production

แตก branch จาก main เป็น hotfix/ชื่อ-bug
Dev แก้ไขจนเสร็จ
ถ้า QA ต้องการทดสอบก่อน → เปิด MR เข้า develop ให้ทดสอบบน Staging
เมื่อ QA ผ่าน → เปิด MR เข้า main โดยตรง
git checkout main && git pull origin main
git checkout -b hotfix/fix-login-crash

# แก้ไขเสร็จ → push → MR เข้า develop (ถ้า QA ต้องการ) → MR เข้า main

หลักการตั้งชื่อ Branch

Prefixใช้เมื่อตัวอย่าง
feature/ งาน feature ใหม่ทุกชนิด feature/help-center
hotfix/ แก้ bug เร่งด่วนบน Production hotfix/fix-login-crash
fix/ แก้ไข feature ที่ขึ้น Prod แล้ว (ไม่เร่งด่วน) หรือจะ dev ใน branch เดิมของ feature นั้นก็ได้ fix/carousel-direction
update/ อัปเดต dependency, config, งานเล็กๆ update/tailwind-v4
ข้อแนะนำ

ตั้งชื่อ branch ให้สื่อความหมาย ใช้ตัวพิมพ์เล็กทั้งหมด คั่นด้วย - (kebab-case) เช่น feature/user-profile-page ไม่ใช่ feature/UserProfilePage

Git Flow Diagrams

1 — Feature Flow ปกติ (ผ่าน QA → ขึ้น Beta)
main develop release-2.0.xxxx feature/xxxx MR → develop Deploy Staging → QA ✓ Senior สร้าง MR → release Deploy Beta Production Staging Feature Beta/Release
2 — QA ไม่ผ่าน → แก้ Bug → Retest
main develop feature/xxxx MR #1 QA ❌ Fix bugs MR #2 QA ✅ Retest cycle
3 — Hotfix Flow
main develop hotfix/xxxx MR → develop (optional) ถ้า QA ต้องการทดสอบ MR → main Deploy Prod QA ✅
4 — Keep on Staging → รอ PO อนุมัติ
main develop release-2.0.xxxx feature/xxxx MR → develop QA ✅ ⏸ รอ PO อนุมัติ PO ✅ MR → release

แนวทางการเขียน Commit Message

Commit message ที่ดีช่วยให้ทีมเข้าใจว่าแต่ละ commit ทำอะไร แนะนำ Conventional Commits:

# รูปแบบ: <type>: <description>

feat: add hero carousel component
fix: resolve direction bug in auto-slide
style: adjust padding on mobile layout
refactor: extract share logic to useShare hook
chore: update tailwind to v3.4
Typeใช้เมื่อ
featเพิ่ม feature ใหม่
fixแก้ bug
styleแก้ไข CSS, UI (ไม่มีผลต่อ logic)
refactorปรับโครงสร้างโค้ดโดยไม่เปลี่ยนพฤติกรรม
choreอัปเดต dependency, config
docsเพิ่ม/แก้ไขเอกสาร

การทำงานกับ Library (VTL / VT-UI)

เมื่อได้รับงานเกี่ยวกับ Landing Page หรือ Dashboard (เดิม) ต้องเข้าใจก่อนว่า component ทุกหน้าไม่ได้อยู่ในโปรเจกต์หลัก Iux-landing-nextts โดยตรง แต่อยู่ในโปรเจกต์ Library แทน:

Libraryชื่อย่อดูแลส่วนไหนใช้ใน
frontend/VT Landing UI VTL ทุกหน้า Landing Page (ยกเว้น Education) — UI, layout, style, animation Iux-landing-nextts
frontend/iux-ui VT-UI ทุกหน้า Dashboard — UI component ต่างๆ Iux-landing-nextts

หลักการสำคัญ: อะไรอยู่ที่ไหน?

กฎง่ายๆ

UI/Layout/Style/Animation → แก้ไขใน VTL หรือ VT-UI
Business Logic ฝั่ง Server (redirect, middleware, server-side check) → แก้ไขใน Iux-landing-nextts
ไฟล์แปลภาษา JSON → สร้างใน VTL/VT-UI ก่อน แล้ว copy ไปใส่ใน Iux-landing-nextts
Client-side Logic (เช่น toggle, modal state) → ทำใน VTL/VT-UI ได้เลยตามสถานการณ์

Dynamic Component — หลักการสร้าง Component ใน Library

Component ทุกตัวที่สร้างใน VTL หรือ VT-UI ต้องเป็น Dynamic Component หมายความว่า component ต้องรับ props เพื่อให้โปรเจกต์หลักสามารถส่ง business logic เข้ามาควบคุมได้ เช่น:

กรณี: แสดงปุ่มเฉพาะบางประเทศ

ถ้ามี component ที่ต้องแสดงปุ่มเฉพาะบางประเทศ การเช็คว่าผู้ใช้อยู่ประเทศไหนจะทำฝั่ง Server (ใน Iux-landing-nextts ผ่าน Cloudflare headers) แล้วโยน prop เข้ามาให้ component ใน VTL

// ใน VTL — component ต้องรับ prop ได้
interface HeroProps {
  showPromoButton?: boolean; // ← รับ prop จากโปรเจกต์หลัก
  countryCode?: string;
}

// ใน Iux-landing-nextts — ส่ง prop เข้ามา
<Hero showPromoButton={isThai} countryCode={country} />
สรุป

Server-side logic → ทำใน Iux-landing-nextts แล้วโยน prop เข้ามา
Client-side logic → ทำใน VTL/VT-UI ได้เลย
Component ต้องรับ prop ได้เสมอ เพื่อให้ยืดหยุ่นกับ business logic ที่มาจากโปรเจกต์หลัก

การแตก Branch เมื่อทำงาน Library + Main Project

สำคัญ

เมื่องานเกี่ยวข้องกับ Library ต้องแตก branch จาก main ทั้ง 2 โปรเจกต์ พร้อมกัน เช่น ถ้าทำ feature ใหม่ใน Landing → แตก branch ทั้งใน VTL และ Iux-landing-nextts, ถ้าทำ Dashboard → แตก branch ทั้งใน VT-UI และ Iux-landing-nextts

Library + Main Project — Parallel Branch Flow
VTL (Library) main feature/xxxx → MR develop → อัปเดต version → MR release Iux-landing-nextts (Main) main feature/xxxx → ใส่ไฟล์ JSON i18n + MR develop → MR release ทั้ง 2 โปรเจกต์ต้องแตก branch และ dev ไปพร้อมกัน

ระบบแปลภาษา (i18n) ในโปรเจกต์ Library

ทุก component ใน VTL หรือ VT-UI จะไม่แสดง text ตรงๆ ในโค้ด แต่จะใช้ key จากไฟล์ JSON มาแสดงแทน เพื่อรองรับหลายภาษา (เว้นแต่ PO แจ้งว่าหน้านั้นไม่มีการแปลภาษา)

ขั้นตอนการทำ i18n

รับ content จาก Confluence — PO จะเตรียม text ที่แปลแล้วทุกภาษาไว้ใน Confluence
สร้างไฟล์ JSON ใน VTL/VT-UI — สร้างไฟล์แปลภาษาทุกภาษาในโปรเจกต์ Library ก่อน
Component รับ i18n key ผ่าน prop — ทุก section component ต้องรับ prop key ของ i18n จากไฟล์ JSON เข้ามาด้วย (ดูตัวอย่างจากโปรเจกต์)
Dev UI ตาม Figma — ใช้ key จาก JSON แทนที่จะเขียน text ตรงๆ ลงใน component
Copy ไฟล์ JSON ไปใส่โปรเจกต์หลัก — เมื่อถึงเวลาทดสอบจริง ให้นำไฟล์ JSON ไปใส่ใน Iux-landing-nextts
// ❌ ไม่ถูก — เขียน text ตรงๆ
<h1>Welcome to IUX</h1>

// ✅ ถูกต้อง — ใช้ key จากไฟล์ JSON
<h1>{t("hero.title")}</h1>

// ไฟล์ JSON (en.json)
{ "hero": { "title": "Welcome to IUX" } }

การทดสอบ Library บน Local ก่อน Deploy

เมื่อ dev ใน VTL หรือ VT-UI เสร็จ และต้องการทดสอบบนโปรเจกต์หลักก่อน deploy จริง ให้ทำตามขั้นตอนนี้:

นำไฟล์ JSON แปลภาษาไปใส่ในโปรเจกต์หลัก Iux-landing-nextts ก่อน
Build โปรเจกต์ Library (ถ้าทำ Landing → build VTL, ถ้าทำ Dashboard → build VT-UI)
เมื่อ build เสร็จจะได้โฟลเดอร์ dist ออกมา
เข้าไปที่โฟลเดอร์ node_modules/@vt/vtl-ui (หรือ @vt/vt-ui) ในโปรเจกต์หลัก → ลบ dist เก่าออก
Copy dist ที่ build ใหม่จาก Library มาวางแทน
Run dev ในโปรเจกต์หลักเพื่อทดสอบ
# 1) Build library (ตัวอย่าง VTL)
cd frontend/VT-Landing-UI
npm run build

# 2) ลบ dist เก่าในโปรเจกต์หลัก
cd ../Iux-landing-nextts
rm -rf node_modules/@vt/vtl-ui/dist

# 3) Copy dist ใหม่มาวาง
cp -r ../VT-Landing-UI/dist node_modules/@vt/vtl-ui/

# 4) Run dev เพื่อทดสอบ
npm run dev
อย่าลืม

หลังจาก merge เข้า develop ในโปรเจกต์ Library แล้ว ต้องอัปเดต version ของ package ด้วย ไม่เช่นนั้นสิ่งที่แก้ไขจะไม่ถูกแสดงในโปรเจกต์หลักเมื่อ deploy จริง

Library Testing Flow — ขั้นตอนการทดสอบ Local
VTL / VT-UI Dev component npm run build สร้าง dist/ node_modules/@vt/ ลบ dist เก่า → วาง dist ใหม่ npm run dev ทดสอบในโปรเจกต์หลัก ✅ ทดสอบผ่าน เมื่อทดสอบผ่านแล้ว MR เข้า develop (Library) + อัปเดต version MR เข้า develop (Main) + ใส่ไฟล์ JSON i18n

วิธีหา Component ในโปรเจกต์

เมื่อได้รับงานแก้ไขบางจุดในหน้าเว็บ สิ่งแรกที่ต้องทำคือหา component ที่ตรงกับจุดนั้นให้เจอก่อน แล้วค่อยเริ่ม dev วิธีหามีดังนี้:

เปิดเว็บไซต์ที่ต้องการแก้ไข เช่น iux.com
นำเมาส์ไปวางที่จุดที่ต้องการแก้ไข แล้วคลิกขวา → เลือก Inspect (หรือกด F12)
หา Element ที่ตรงกับจุดที่ต้องการแก้ไขใน Elements panel
Copy ชื่อ class ที่อยู่ใน Element นั้น
เปิดโปรเจกต์ใน VS Code แล้วกด ⌘ + Shift + F (Mac) หรือ Ctrl + Shift + F (Windows) เพื่อค้นหาทั่วทั้งโปรเจกต์
วาง class ที่ copy ไว้ จะเห็นว่า component นั้นอยู่ที่ไฟล์ไหน
ไล่ดูลำดับว่า component นั้นอยู่ในส่วนไหนของโครงสร้างโปรเจกต์ แล้วค่อยเริ่ม dev
เทคนิคเพิ่มเติม

นอกจากการค้นหาด้วย class name แล้ว ยังสามารถค้นหาด้วย text content ที่แสดงบนหน้าเว็บ, ค้นหาด้วย i18n key จากไฟล์ JSON, หรือค้นหาด้วย ชื่อ component ที่แสดงใน React DevTools ได้อีกด้วย ถ้าค้นหาในโปรเจกต์หลักไม่เจอ ให้ลองค้นหาในโปรเจกต์ Library (VTL หรือ VT-UI) แทน เพราะ component อาจอยู่ในนั้น

โปรเจกต์ Standalone

โปรเจกต์เหล่านี้ไม่มี Library มาเกี่ยวข้อง สามารถ dev และ deploy ตาม Git Workflow ปกติได้เลย:

โปรเจกต์ที่ทำงานอิสระ

โปรเจกต์รายละเอียด
frontend/iux-dashboard-vite Dashboard ใหม่ (Trade + Invest) — design ใหม่ทั้งหมด สร้าง component เองในโปรเจกต์ ไม่ใช้ VT-UI
ในอนาคตจะแยก Dashboard ออกจาก Iux-landing-nextts เพื่อให้ build/deploy เร็วขึ้น
iux-partner-nextjs Affiliate Portal — ดูแลหน้า Dashboard, Login, Register ทั้งหมด
frontend/iux-help-center-next Help Center ใหม่สำหรับ Zendesk — เริ่มใช้ที่ help.iux.za.com
frontend/vt-widget Widget UI สำหรับฝังใน WordPress และ Zendesk
Iuxau-landing-nextts Landing Page สำหรับ iux.com.au (Australia)

โครงสร้างโปรเจกต์ iux-dashboard-vite

โปรเจกต์นี้ใช้แนวคิด Clean Architecture ซึ่งหลักการคือแบ่งโค้ดออกเป็นชั้น (Layer) ตามหน้าที่ แต่ละชั้นรับผิดชอบงานของตัวเอง ไม่ปนกัน — ชั้นที่เป็น UI ก็ทำแค่แสดงผล ชั้นที่เรียก API ก็ทำแค่เรียก API ชั้นที่เป็นกฎของระบบก็กำหนดแค่กฎ ทำให้โค้ดอ่านง่าย แก้ไขง่าย และหาจุดที่มีปัญหาได้เร็ว เพราะรู้ว่าต้องไปดูที่ชั้นไหน

แต่ละชั้น (Layer) ทำอะไร?

Layerโฟลเดอร์ทำอะไร (อธิบายง่ายๆ)
Domain src/domain/ กฎของระบบ — กำหนดว่าข้อมูลหน้าตาเป็นยังไง (เช่น บัญชี, ออเดอร์, พอร์ต) และมีกฎอะไรบ้าง ชั้นนี้ไม่สนว่าใช้ React หรือ Axios — เขียนเป็น TypeScript ล้วนๆ
Application src/application/ ขั้นตอนการทำงาน — เช่น "เมื่อกดเทรด ต้องทำอะไรบ้าง" เป็น hooks และ use cases ที่เอากฎจาก Domain มาใช้จริง จัดการ state ต่างๆ
Infrastructure src/infrastructure/ เชื่อมต่อภายนอก — เรียก API (Axios), เชื่อม gRPC, ต่อ Firebase, จัดการ mock data สำหรับตอน dev
Presentation src/presentation/ หน้าตาที่ผู้ใช้เห็น — React components ทั้งหมด แบ่งตาม feature เช่น dashboard, trading-panel, portfolio, settings
Core src/core/ เครื่องมือกลาง — ระบบพื้นฐานที่ทุกชั้นใช้ร่วมกัน เช่น auth, HTTP client, Redux store, ระบบราคาเรียลไทม์ (tick engine), i18n, Firebase config
Shared src/shared/ ของที่ใช้ร่วมกัน — UI components, hooks, helpers, constants ที่ใช้ข้าม feature เช่น Button, Modal, formatDate
Routes src/routes/ เส้นทาง URL — ใช้ TanStack Router แบบ file-based ชื่อไฟล์ = URL path เช่น $lang.dashboard.tsx = /th/dashboard

โครงสร้างโฟลเดอร์

แต่ละโฟลเดอร์จะแบ่งตาม feature ข้างใน เช่น domain/account/, domain/trade/ ทำให้หาโค้ดง่าย — เมื่อทำงานเกี่ยวกับ feature ไหน ก็เข้าไปดูในโฟลเดอร์ของ feature นั้นในแต่ละ Layer

src/ │ ├── domain/ ← กฎของระบบ (ไม่ผูกกับ framework) │ ├── account/ ข้อมูลบัญชีผู้ใช้ — entity, interface │ ├── trade/ ข้อมูลการเทรด — entity, interface │ ├── portfolio/ พอร์ตการลงทุน │ ├── deposit/ การฝากเงิน │ ├── withdraw/ การถอนเงิน │ └── ... notification, symbol, settings ฯลฯ │ ├── application/ ← ขั้นตอนการทำงาน (hooks, use cases) │ ├── trade/ เช่น usePlaceOrder, useClosePosition │ ├── watchlist/ เช่น useWatchlist, useAddSymbol │ ├── chart/ เช่น useChartData, useCandlestick │ └── ... account, auth, datafeed, notification ฯลฯ │ ├── infrastructure/ ← เชื่อมต่อ API / บริการภายนอก │ ├── grpc/ เชื่อม gRPC services │ ├── payment/ เชื่อม payment gateway │ ├── mock/ ข้อมูลจำลองสำหรับตอน dev │ └── ... account, auth, connectivity, phone ฯลฯ │ ├── presentation/ ← หน้าตา UI (React components) │ ├── dashboard/ หน้า dashboard หลัก │ ├── trading-panel/ panel สำหรับเทรด │ ├── portfolio/ หน้า portfolio │ ├── history/ ประวัติการเทรด │ └── ... auth, deposit, withdraw, settings ฯลฯ │ ├── core/ ← เครื่องมือกลางที่ทุกชั้นใช้ │ ├── auth/ ระบบ authentication │ ├── http/ HTTP client (Axios instance) │ ├── store/ Redux store setup │ ├── tick/ ราคาเรียลไทม์ (tick engine) │ ├── i18n/ ระบบแปลภาษา │ ├── firebase/ Firebase config │ └── ... config, constants, helpers, hooks ฯลฯ │ ├── shared/ ← ของที่ใช้ร่วมกันข้าม feature │ ├── ui/ UI components กลาง (Button, Modal, Input) │ ├── components/ shared components ที่ซับซ้อนกว่า ui │ ├── hooks/ shared custom hooks │ └── ... helpers, utils, constants ฯลฯ │ ├── routes/ ← เส้นทาง URL (TanStack Router) │ ├── $lang.dashboard.tsx → /th/dashboard │ ├── $lang.dashboard.portfolio.tsx → /th/dashboard/portfolio │ ├── $lang.login.tsx → /th/login │ └── ... │ ├── types/ ← Global TypeScript types ├── test/ ← Test utilities ├── mock/ ← Mock data └── main.tsx ← จุดเริ่มต้นของ App

การไหลของข้อมูลระหว่าง Layer

ข้อมูลจะไหลจากชั้นนอกเข้าชั้นใน — Presentation → Application → Domain ส่วน Infrastructure คือตัวที่ไปดึงข้อมูลจริงมาให้ตาม interface ที่ Domain กำหนดไว้:

การไหลของข้อมูลระหว่าง Layer
Domain กฎของระบบ Application ขั้นตอนการทำงาน Presentation หน้าตา UI Infrastructure เชื่อมต่อภายนอก Core เครื่องมือกลาง Shared ของใช้ร่วมกัน ใช้ ใช้ ทำจริงตามกฎ Core & Shared ถูกใช้โดยทุกชั้น
หลักการสำคัญ (จำง่ายๆ)

Domain ไม่ import อะไรจากชั้นอื่น — ถ้าต้องเรียก API ให้สร้าง interface ใน Domain แล้วให้ Infrastructure เป็นคนทำจริง
Presentation ไม่เรียก API โดยตรง — ต้องผ่าน Application layer (hooks/use cases) เสมอ
Core & Shared — เป็นของกลางที่ทุกชั้นเรียกใช้ได้
เมื่อทำงานกับ feature ใด — ให้ดูทุก Layer ที่เกี่ยวข้อง เช่น ทำเรื่อง trade ก็ต้องดู domain/trade, application/trade, infrastructure/trade, presentation/trading-panel

Tech Stack

หมวดเทคโนโลยีหน้าที่
UI Framework React 19 สร้าง UI components
Build Tool Vite Dev server & bundler — เร็วกว่า Webpack
Routing TanStack Router File-based routing รองรับ i18n ($lang prefix)
Server State TanStack Query จัดการ data fetching, caching, synchronization
Global State Redux Toolkit จัดการ state ที่ต้องแชร์ข้าม components (auth, user, settings)
Styling Tailwind CSS 4 Utility-first CSS framework
HTTP Client Axios + gRPC เรียก REST API และ gRPC services
Realtime Firebase Auth & Realtime data (Firestore)
i18n i18next + react-i18next ระบบแปลภาษาหลายภาษา
Forms React Hook Form จัดการ form state & validation
Desktop Tauri (Rust) Build เป็น desktop app ได้ (src-tauri/)
Testing Vitest + Playwright Unit tests & E2E tests
Docs Storybook Document & preview components แบบ isolated
CI/CD GitLab CI + Docker + Nginx Automated build, test, deploy
Perf Audit Lighthouse CI ตรวจสอบ performance อัตโนมัติ
ข้อแตกต่างจากโปรเจกต์อื่น

iux-dashboard-vite สร้าง component เองทั้งหมด — ไม่ใช้ Library VT-UI เหมือนกับ Dashboard เก่าใน Iux-landing-nextts ดังนั้น component ทุกตัวอยู่ภายในโปรเจกต์เลย ไม่ต้อง build library แยก

โครงสร้างโค้ด & Component

หลักการสำคัญ: Global vs Local

เมื่อเขียน component หรือ function ต้องถามตัวเองเสมอว่า "สิ่งนี้จะถูกใช้ซ้ำที่อื่นไหม?" ถ้าใช่ → Global, ถ้าใช้แค่ที่เดียว → Local

ประเภทลักษณะตำแหน่ง
Global Component ใช้ซ้ำหลายที่ เช่น Button, Modal, Input, Card, Breadcrumb components/ หรือ components/ui/
Local Component ใช้เฉพาะภายใน feature หรือ page นั้น ภายในโฟลเดอร์ของ feature/page
Global Utility ฟังก์ชันที่ใช้ซ้ำ เช่น formatDate, cn utils/ หรือ lib/
Global Hook Custom hook ที่ใช้ซ้ำ เช่น useCountdown, useMediaQuery hooks/
Global Constant ค่าคงที่ เช่น COUNTRY_LIST, ROUTES constants/

ตัวอย่างโครงสร้างโฟลเดอร์

src/ ├── components/ ← Global components ที่ใช้ซ้ำทั่วทั้งโปรเจกต์ │ ├── ui/ ← UI primitives: Button, Input, Modal, Card │ └── layout/ ← Header, Footer, Sidebar ├── hooks/ ← Global custom hooks ├── utils/ ← Global utility functions ├── constants/ ← Global constants ├── services/ ← API call functions ├── types/ ← Global TypeScript types └── app/ ← Pages & features (App Router) └── help-center/ ├── page.tsx └── _components/ ← Local components เฉพาะ help-center
กฎง่ายๆ

ใช้ 2 ที่ขึ้นไป = ควร Global — ถ้า component หรือ function ถูกใช้ใน 2 feature ขึ้นไป ให้ย้ายเป็น Global เพื่อลดการ duplicate โค้ด

หลักการเขียน Component ที่ดี

รับ Props ที่ยืดหยุ่น

Global component ควรรับ props เช่น variant, size, className เพื่อใช้ได้หลายบริบทโดยไม่ต้องสร้างใหม่

แยก Logic ออกจาก UI

ถ้า component มี logic ซับซ้อน ให้แยก logic ไว้ใน custom hook แล้วให้ component ทำหน้าที่แค่ render UI

ตั้งชื่อให้สื่อความหมาย

ชื่อต้องบอกได้ทันทีว่าทำอะไร เช่น ArticleCard ชัดเจนกว่า Card1, useCountdown ชัดเจนกว่า useTimer

การ Debug เบื้องต้น

การ debug คือทักษะสำคัญที่ Developer ต้องใช้ทุกวัน เมื่อเจอปัญหา สิ่งสำคัญคือตั้งสติ อ่าน error ให้จบ แล้วค่อยๆ หาสาเหตุอย่างเป็นระบบ

1. Console Methods — เครื่องมือพื้นฐานที่สุด

// ดูค่าตัวแปร, ดู flow การทำงาน
console.log("user:", user)

// แสดง array/object เป็นตาราง อ่านง่ายกว่า log
console.table(users)

// แยกประเภท log ให้ชัดเจน
console.error("API failed:", err)
console.warn("Missing prop: locale")

// วัดเวลาว่าโค้ดส่วนไหนทำงานช้า
console.time("fetch")
// ...โค้ดที่ต้องการวัด...
console.timeEnd("fetch")
สำคัญ

ลบ console.log ออกก่อน commit ทุกครั้ง — ไม่ควรมี console.log หลุดไปใน code review หรือขึ้น production

2. Browser DevTools — แต่ละ Tab ใช้ทำอะไร

เปิดด้วย F12 หรือ คลิกขวา → Inspect

Tabใช้ทำอะไร
Elements ดูและแก้ไข HTML/CSS แบบ real-time, ตรวจสอบว่า style ถูก override จากตรงไหน, ดู computed styles
Console ดู error message, ทดสอบ JavaScript สดๆ, ดูค่า console.log ที่เขียนไว้
Network ดู API request/response, ตรวจสอบ status code (200, 400, 401, 404, 500), ดู payload ที่ส่งไปและ response ที่ได้กลับมา
Application ตรวจสอบ cookies, localStorage, sessionStorage
Sources ตั้ง breakpoint เพื่อหยุดการทำงานและดูค่าตัวแปรทีละ step

3. React DevTools (Extension)

เป็น Chrome Extension ที่ต้องติดตั้งเพิ่ม จะเพิ่ม tab Components และ Profiler ใน DevTools

สิ่งที่ทำได้

ดู component tree — เห็นว่า component ไหนอยู่ตรงไหน ซ้อนกันอย่างไร

ดู props & state แบบ real-time — คลิกที่ component แล้วดูว่า props ที่ส่งเข้ามามีค่าอะไร state เปลี่ยนไปเป็นอะไร

ตรวจสอบ re-render — ดูว่า component re-render บ่อยเกินไปหรือไม่ ซึ่งอาจทำให้เว็บช้า

4. Breakpoints & Debugger

เมื่อ console.log หลายจุดแล้วยังหาสาเหตุไม่เจอ ให้ใช้ breakpoint เพื่อหยุดโค้ดและดูค่าทีละ step:

// วิธีที่ 1: ใส่คำสั่ง debugger ในโค้ดตรงจุดที่สงสัย
const handleSubmit = (data) => {
  debugger; // ← เบราว์เซอร์จะหยุดตรงนี้
  const result = processData(data);
  return result;
}

// วิธีที่ 2: ตั้ง breakpoint ผ่าน Sources tab ใน DevTools
// คลิกที่เลขบรรทัดในไฟล์ที่ต้องการ → จุดสีน้ำเงินจะปรากฏ
// ไม่ต้องแก้โค้ด เหมาะกับการ debug ไฟล์ที่ไม่ใช่ของเรา
เมื่อหยุดที่ breakpoint

สามารถดูค่าตัวแปรทั้งหมดในขณะนั้นได้ใน Scope panel ด้านขวา และใช้ปุ่มต่างๆ เพื่อเดินโค้ดทีละบรรทัด: Step Over (ข้ามฟังก์ชัน), Step Into (เข้าไปในฟังก์ชัน), Step Out (ออกจากฟังก์ชัน), Resume (ทำงานต่อจนกว่าจะเจอ breakpoint ถัดไป)

5. การอ่าน Error Message

เมื่อเจอ error อย่าตกใจ — อ่าน error message ให้จบก่อน บรรทัดแรกมักบอกสาเหตุ และดู stack trace เพื่อหาว่า error เกิดที่ไฟล์ไหน บรรทัดไหน

Error ที่เจอบ่อยสาเหตุวิธีแก้
TypeError: Cannot read properties of undefined ตัวแปรเป็น undefined ก่อนเข้าถึง property ใช้ optional chaining user?.name หรือเช็คค่าก่อนใช้งาน
ReferenceError: X is not defined ลืม import หรือพิมพ์ชื่อตัวแปรผิด ตรวจสอบ import statement และ spelling
Hydration Error (Next.js) HTML ที่ server render กับ client ไม่ตรงกัน หลีกเลี่ยงการใช้ window, document หรือค่าที่ต่างกันระหว่าง server/client โดยตรง
404 ใน Network tab API endpoint ผิด หรือ resource ไม่มีอยู่ ตรวจสอบ URL, path parameter, ตัวสะกด
401 / 403 ใน Network tab ไม่ได้ login หรือไม่มีสิทธิ์เข้าถึง ตรวจสอบ token, cookie, session, สิทธิ์ user
500 ใน Network tab Server มีปัญหา ดู response body, แจ้ง Backend team ตรวจสอบ

6. แนวคิดในการ Debug

วิธีคิดเมื่อเจอปัญหา

จำกัดขอบเขต — ค่อยๆ ตัดส่วนที่ไม่เกี่ยวออก จนเหลือแค่จุดที่มีปัญหา อย่าพยายามแก้ทุกอย่างพร้อมกัน

ย้อนกลับไปจุดที่ยังทำงานได้ — ถ้าแก้แล้วพัง ให้ revert กลับแล้วค่อยแก้ทีละจุด เพื่อระบุว่าจุดไหนที่ทำให้พัง

เปรียบเทียบกับส่วนที่ทำงานได้ — ถ้า component A ปกติแต่ B ไม่ ให้เทียบดูว่าต่างกันตรงไหน

ค้นหา error message — นำ error message ไปค้นใน Google หรือ Stack Overflow ส่วนใหญ่มีคนเจอปัญหาเดียวกันแล้ว

ถ้าหาไม่เจอภายใน 30 นาที ให้ถามทีม — ไม่ต้องเสียเวลานานเกินไปคนเดียว การถามไม่ได้แปลว่าทำไม่ได้ แต่เป็นการทำงานอย่างมีประสิทธิภาพ

การใช้งาน AI ในการเขียนโค้ด

การใช้ AI ช่วยเขียนโค้ดเป็นเรื่องปกติและสนับสนุนให้ใช้ แต่สิ่งสำคัญคือต้องเข้าใจในสิ่งที่ AI ทำให้

กฎเหล็ก

เมื่อให้ AI เขียนโค้ดให้ ต้องขอให้ AI อธิบายทุกครั้ง — ว่าโค้ดทำอะไร แต่ละส่วนมีหน้าที่อะไร component อยู่ตรงไหน ใช้ยังไง เพื่อเรียนรู้และพัฒนาทักษะของตัวเอง

สิ่งที่ควรทำ

1. ขอให้ AI อธิบายโค้ดทุกครั้ง — ถามว่าแต่ละ function ทำอะไร ทำไมถึงใช้ pattern นี้

2. ทำความเข้าใจก่อน commit — อ่านโค้ดจนเข้าใจทุกบรรทัด อธิบายให้คนอื่นฟังได้

3. ถามต่อเมื่อไม่เข้าใจ — ทุกคำถามมีคุณค่า ถ้าไม่เข้าใจให้ถามจนเข้าใจ

4. จดบันทึกสิ่งที่เรียนรู้ — เมื่อเข้าใจ pattern ใหม่ ให้จดไว้เพื่อใช้เองในครั้งต่อไป

สิ่งที่ไม่ควรทำ

1. Copy-paste โดยไม่อ่าน — ถ้าไม่เข้าใจแล้วนำไปใช้ เมื่อเกิด bug จะแก้ไม่ได้

2. ให้ AI ทำแทนทุกอย่าง — ลองเขียนเองก่อน เมื่อติดค่อยถาม

3. ไม่ตรวจสอบตำแหน่ง component — ต้องรู้ว่า AI วางไฟล์ไว้ที่ไหน เป็น Global หรือ Local

ตัวอย่าง prompt ที่ดี

"ช่วยสร้าง Breadcrumb component ที่รับ props เป็น array ของ items ให้หน่อย
แล้วช่วยอธิบายด้วยว่าแต่ละส่วนทำอะไร ควรวางไว้ตรงไหนในโปรเจกต์ และใช้งานยังไง"

เป้าหมายของการใช้ AI คือการเร่งความเร็วในการเรียนรู้ ไม่ใช่การหลีกเลี่ยงการเรียนรู้ เมื่อเวลาผ่านไปควรจะเขียนโค้ดเองได้มากขึ้น โดยใช้ AI เป็นเครื่องมือเสริม

IUX Frontend Team — Git Workflow & Code Structure Guide

อัปเดตล่าสุด: กรกฎาคม 2026