recruitment-web
recruitment-web (default branch: master, canonical branch: prod, 200 tracked files บน prod) เป็นเว็บสมัครงานสาธารณะของสภากาชาดไทย — ผู้สมัครภายนอก (ไม่ใช่พนักงาน) กรอกใบสมัครงาน (application profile), แนบไฟล์เอกสาร, และสมัครตำแหน่งงานที่เปิดรับผ่านหน้านี้ เชื่อมกับ backend ชื่อ recruitment-api (อยู่ใน Domain Microservices group — นอก scope ลึกของเล่มนี้ ยกเว้น endpoint ที่ frontend เรียก)
ชื่อ package คือ recruitment-web (recruitment-web/package.json:2) — ตรงกับชื่อ repo
Stack และเวอร์ชัน
| Dependency | เวอร์ชัน | หลักฐาน |
|---|---|---|
| react / react-dom | ^18.2.0 | recruitment-web/package.json:21-22 |
| react-scripts (CRA) | 5.0.1 | recruitment-web/package.json:31 |
| antd | 5.18.0 | recruitment-web/package.json:13 |
| react-router-dom | ^6.8.1 | recruitment-web/package.json:30 |
| recoil | ^0.7.6 | recruitment-web/package.json:33 |
| axios | ^1.4.0 | recruitment-web/package.json:14 |
| crypto-js | ^4.1.1 | recruitment-web/package.json:15 |
| react-google-recaptcha | ^3.1.0 | recruitment-web/package.json:26 |
| react-pdf | ^9.1.0 | recruitment-web/package.json:29 |
| react-ga4 | ^2.1.0 | recruitment-web/package.json:25 |
| moment | ^2.29.4 | recruitment-web/package.json:19 |
| sass | ^1.58.3 | recruitment-web/package.json:34 |
| tailwindcss (dev) | ^3.2.7 | recruitment-web/package.json:67 |
Stack เป็น Create React App (CRA) มาตรฐาน — ไม่ใช่ Next.js ควรอ้างอิงจาก react-scripts ใน package.json เป็นหลัก
Package manager ที่ Dockerfile ใช้คือ yarn (recruitment-web/Dockerfile:7-9) แม้ repo จะมีทั้ง package-lock.json และอาจมี yarn.lock ตาม context build — ตรวจ lockfile จริงก่อนรัน CI
Entrypoint และพอร์ต
src/index.js คือ entrypoint ของ CRA — wrap ด้วย RecoilRoot แล้ว BrowserRouter แล้ว render <App /> (recruitment-web/src/index.js:13-19)
Dev server รันที่พอร์ต 3006 ตาม script "start": "PORT=3006 react-scripts start" (recruitment-web/package.json:40)
App.js ทำหน้าที่:
- ปิด
console.log/warn/errorนอก hostname ที่เป็นuat-jobsหรือlocalhost(recruitment-web/src/App.js:29-32) - initialize Google Analytics ด้วย
REACT_APP_GA_ID(recruitment-web/src/App.js:34) - ตั้ง CSS variables ของ theme จาก Recoil + localStorage (
recruitment-web/src/App.js:36-47) - route gate — ถ้าไม่มี
checkLogin.isOtpที่ decrypt ได้ จะ redirect ออกจาก/myJobและ/applicantProfileกลับ/(recruitment-web/src/App.js:49-62) - ส่ง GA pageview ตาม pathname (
recruitment-web/src/App.js:64-74)
Deploy artifact
Dockerfile แบบ multi-stage:
| Stage | Base image | ทำอะไร | Citation |
|---|---|---|---|
| stage-1 | node:20-alpine | yarn แล้ว yarn build | recruitment-web/Dockerfile:1-9 |
| stage-2 | nginx:1.30.2 | copy build/ ไป /usr/share/nginx/html/build/ + default.conf | recruitment-web/Dockerfile:11-25 |
nginx SPA fallback: try_files $uri $uri/ /index.html (recruitment-web/default.conf:7-11) listen port 80
ข้อสังเกตสำคัญ — Dockerfile ประกาศ ENV REACT_APP_SECRET_KEY=... และ endpoint อื่น ๆ ไว้ที่ stage 2 (nginx) (Dockerfile:15-21) แต่ CRA inline ค่า REACT_APP_* ทั้งหมดเข้า JS bundle ตอน yarn build ที่ stage 1 เท่านั้น — ค่า ENV ที่ประกาศใน stage 2 จึงไม่มีผลต่อ bundle ที่ deploy จริง ค่าที่ถูก bake เข้า bundle มาจากไฟล์ .env / .env.uat / .env.dev ที่อยู่ใน build context ตอนรัน yarn build (ดู 04-scorecard CORR-RCWEB-01)
Backend ที่เชื่อมต่อ (พิสูจน์จากโค้ด)
| ปลายทาง | ผ่าน env var | ใช้ทำอะไร | หลักฐาน |
|---|---|---|---|
recruitment-api | REACT_APP_END_POINT_RECRUITMENT_API | CRUD ใบสมัคร, login/OTP, สมัครตำแหน่ง | recruitment-web/src/config.js:11, axios-rc.js:11 |
recruitment-api (path แนบไฟล์) | REACT_APP_END_POINT_RECRUITMENT_API_ATTACHFILE | preview ไฟล์แนบที่ upload แล้ว | config.js:12, axios-rc.js:5-7 |
"common API" (คาด vtrc-common) | REACT_APP_END_POINT_COMMON_API | ประกาศใน axios-common.js — ไม่พบ caller ใน component | axios-common.js:6, grep ไม่พบ import |
| "workflow / workforce API" | REACT_APP_END_POINT_WF_API_ATTACHFILE | ประกาศใน config — ไม่พบจุดใช้งาน | config.js:13 — UNVERIFIED |
Endpoint hosts ตาม env file (branch: prod)
| ไฟล์ | REACT_APP_NODE_ENV | Recruitment API host |
|---|---|---|
.env | 'prod' | https://vtrcapi.redcross.or.th/recruitment-api/api/v1 |
.env.uat | 'uat' | https://uat-vtrcapi.redcross.or.th/recruitment-api/api/v1 |
.env.dev | 'dev' | http://localhost:9330/recruitment-api/api/v1 |
(อ่านจากไฟล์ env ที่ track ใน git บน branch prod — ไม่ paste ค่า secret)
ธีมหลักของเล่มนี้
- OTP login ทางอีเมล —
sent_otp→validate_otpผ่าน GET query string (email + OTP รั่วใน access log / browser history) - AES ฝั่ง client —
crypto-jsAES ด้วยREACT_APP_SECRET_KEY/REACT_APP_PRIVATE_KEYที่ bake ใน bundle - PII ใน localStorage — เก็บหลัง decrypt ใต้ key
user-loginโดยไม่มี expiry จริง - ไฟล์แนบเป็น base64 ใน JSON payload ไม่ใช่ multipart
- ทุกหน้าและทุก HTTP call ที่ frontend ยิง — ดู 03-pages-and-endpoints
สารบัญ
| บท | หัวข้อ |
|---|---|
| 01 | Repository map — โฟลเดอร์, env, axios clients, Recoil |
| 02 | Core pipeline — OTP, AES/localStorage, submit profile, apply job |
| 03 | Every page + HTTP endpoint catalog |
| 04 | Scorecard |
ดูภาพรวมกลุ่ม OCR & Auxiliary ที่ Volume 9 index.