Skip to content

vtrc-mobile — Repository map

บทนี้เป็นแผนที่ไฟล์ของ vtrc-mobile (branch: master, 1055 tracked files, ~610 ไฟล์ใต้ src/) — React Native 0.63 ESS app ของพนักงานสภากาชาดไทย

ชื่อ package คือ rn_redcross (vtrc-mobile/package.json:2) — ไม่ตรงกับชื่อโฟลเดอร์ repo


แผนที่โฟลเดอร์ระดับ repo

vtrc-mobile/                         (branch: master)
├── index.js                         # AppRegistry + notification init
├── App.js                           # 1071 บรรทัด — Provider + PersistGate + Router/Scene ทั้งหมด
├── app.json                         # name/displayName = rn_redcross
├── package.json / yarn.lock
├── polyfills.js / performanceShim.js / shim.js
├── babel.config.js / metro.config.js / react-native.config.js
├── firebase.json
├── __tests__/App-test.js            # template smoke test เดียว
├── __mocks__/
├── android/                         # applicationId com.redcross.vtrc
│   └── app/
│       ├── build.gradle             # versionName 1.9.12, signingConfigs.release hardcode
│       └── src/main/assets/
│           └── digicert2025.cer     # SSL pinning cert
├── ios/
│   ├── Podfile                      # platform ios 12.0, target rn_redcross
│   └── rn_redcross.xcworkspace
├── assets/fonts/
├── scripts/
└── src/
    ├── actions/                     # 6 ไฟล์ — async helpers (ชื่อ *Slice แต่ไม่ใช่ createSlice)
    ├── app/                         # store + sensitive-storage adapter
    ├── assets/                      # ~150 ไฟล์ (font/json/image)
    ├── components/                  # 218 ไฟล์ ใน 27 โฟลเดอร์ domain
    ├── config/                      # Config.API / MEETING_API
    ├── constants/                   # 19 ไฟล์ รวม HostApi / Authen / PrivateKey
    ├── containers/                  # 141 ไฟล์ (120 top-level + meeting-management/)
    ├── features/                    # 14 createSlice จริง
    ├── gql/                         # client + query/ + mutation/
    ├── services/                    # meetingService.js
    ├── themes/                      # Colors Fonts Metrics Images Svg
    └── utils/                       # fetch login setting hostUrl …

ไม่มี App.js / index.js ใน src/ — อยู่ที่ root ตาม RN CLI convention


นับไฟล์ตามชั้น (ยืนยันจาก filesystem บน branch master)

ชั้นจำนวนไฟล์หมายเหตุ
src/containers/*.js (ระดับบน)1201 screen ต่อไฟล์โดยประมาณ
src/containers/meeting-management/21รวม index.js
src/components/21827 domain folders
src/features/14createSlice จริง
src/actions/6async helpers — ชื่อไฟล์ลงท้าย Slice ทำให้สับสน
src/gql/query/14string template GraphQL
src/gql/mutation/7string template GraphQL
src/constants/19รวม secrets
src/utils/25fetch / login / setting / …
src/assets/~150static
tracked ทั้ง repo1055git ls-files

Boot sequence — จาก metro ถึง scene แรก

1. metro bundle entry = index.js
       │  `vtrc-mobile/index.js:1-23`

2. polyfill Node globals (crypto, stream, buffer) ผ่าน shim.js
       │  จำเป็นเพราะ login.js ใช้ crypto.createHash / publicEncrypt

3. initializeNotificationHandlers()
       │  `src/components/shared/NotificationEvent.js`
       │  ลงทะเบียน FCM / local notification listener ก่อน UI

4. AppRegistry.registerComponent('rn_redcross', () => App)

5. App mount:
   Provider → PersistGate.onBeforeLift → Router
       │  `App.js:190-225`

6. Scene initial = key "init" → Init container
       `App.js:229-235`

Init เป็นจุดตัดสินใจต่อ — หลัง PersistGate เรียก refreshToken ซึ่งจะ Actions.intro / Actions.decideenter / Actions.mainmenu ตามสถานะ token (src/features/authSlice.js:555-623)


containers/ — screen inventory

ทุกไฟล์ด้านล่างถูก import ใน App.js และผูกเป็น {Scene key=...} — ไม่มี code-splitting

Auth / onboarding

ContainerScene key (App.js)
Init.jsinit (initial)
Intro.jsintro
DecideEnter.jsdecideenter
Login.jslogin
Verify.jsverify
FillProfile.jsfillprofile
Forgot.jsforgot
CheckLogin.jschecklogin
EmpRegistration.jsempregistration
Term.jsterm
ChangePassword.jschangepassword
VerifySSO.jsverifysso
OTPSSO.jsotpsso
ChangePassWordSSO.jschangepasswordsso
SettingSecureSSO.jssettingsecuresso

หลักฐาน scene: vtrc-mobile/App.js:229-261, 379-398, 949-967

Main shell / profile / setting

ContainerScene key
MainMenu.jsmainmenu
AllListMenu.jsalllistmenu
Profile.jsprofile
PersonalInfo.jspersonalinfo
EmployeePersonalInfo.jsemployeepersonalinfo
EditAddress.jseditaddress
EditPhone.jseditphone
Account.jsaccount
Setting.jssetting
SettingNotification.jssettingnotification
UpdateVersion.jsupdateVersion
ScanUpdate.jsscanupdate
Subscribe.jssubscribe
Timeline.jstimeline
Time.jstime

News / notification / org / contact / documents

ContainerScene key
News.js / NewsList.js / NewsListGuest.js / NewsSearch.jsnews / newslist / newslistguest / newsearch
Notification.js / NotificationList.js / NotificationGroup.jsnotification / notificationlist / notificationgroup
OrgInfo.js / OrgInfoList.jsorginfo / orginfolist
Principle*.js (5) + QualityDocument.js / ListDocuments.js / SearchResult.js / Orientation.jsprinciple* / qualitydocument / listdocuments / searchresult / orientation
Contact.js / ContactHR.js / ContactHRDetail.js / ContactOrg.jscontact / contacthr / contacthrdetail / contactorg

Leave

ContainerScene key
Leave.js / LeaveDetail.js / ListAllLeave.jsleave / leavedetail / listallleave (ประกาศซ้ำ 2 ครั้งใน App.js:609-615)
LeaveApprove.js / LeaveListApprove.js / LeaveApproveByNotification.jsleaveapprove / leavelistapprove / leaveapprovebynotification
LeaveCancleListApprove.js / LeaveCancleDocApprove.jsleavecanclelistapprove / leavecancledocapprove
ManualLeave.js / ReportLeave.jsmanualleave / reportleave
StudyLeave.js / StudyLeaveDetail.js / ListStudyLeave.jsstudyleave / studyleavedetail / liststudyleave

หมายเหตุ: คำว่า Cancle / listallleave duplicate เป็น debt naming — ดู 04-scorecard § QUAL-MOBILE-01

Welfare / medical / other benefits

ContainerScene key
Withdraw.js / WithdrawListMenu.jswitchdraw / withdrawlistmenu
MerdicalExpenses.js / CheckStatusMerdical.js / ListAllMerdicalExpenses.jsmedicalexpenses / checkstatusmerdical / listallmerdicalexpenses
MerdicalExpensesApprove.js / MerdicalExpensesListApprove.js / MedicalExpensesView.js / ReportMerdicalExpenses.jsmerdicalexpensesapprove / merdicalexpenseslistapprove / medicalexpensesview / reportmerdicalexpenses
ChildTuition.js / ListChildTuition.js / StatusChildTuition.jschildtuition / listchildtuition / statuschildtuition
Delegate.js / ListDelegate.jsdelegete (typo ใน scene key, ประกาศซ้ำ) / listdelegete
OtherWelfare.js / Disaster.js / TuitionReimbursement.jsotherwelfare / disaster / tuitionreimbursement
ListBenefitForStaff.js / ListBenefitForApprover.js / Benefit.jslistbenefitforstaff / listbenefitforapprover (Benefit ถูก import — ตรวจ scene ใน App.js ตามไฟล์จริง)
ListPersonalDevelopment.jslistpersonaldevelopment
NewsListWithdraw.jsnewslistwithdraw

Payslip / provident / tax

ContainerScene key
PaySlip.js / PaySlipPreview.jspayslip / payslippreview
ProvidentFund.js / PercentProvidentFund.js / EditPercentProvidentFund.jsprovidentfund / percentprovidentfund / editpercentprovidentfund
ReceiverProvidentFund.js / ProvidentFundListMenu.js / NewsListProvidentFund.jsreceiverprovidentfund / providentfundlistmenu / newslistprovidentfund
TaxReductionView.js / TaxReductionEdit.js / TaxReductionGuide.jstaxview / taxedit / taxguide

Meeting management (containers/meeting-management/)

ContainerScene key
MeetingManagement.jsmeetingmanagement
MyCalendar.jsmycalendar
MeetingDetail.jsmeetingdetail
MeetingInviteList.js / MeetingOrganizer.js / MeetingPending.jsmeetinginvitelist / meetingorganizer / meetingpending
PreCreateMeeting.js / CreateMeeting.js / CreateMeetingDocument.jsprecreatemeeting / createmeeting / createmeetingdocument
InviteInternal.js / InviteExternal.jsinviteinternal / inviteexternal
ApproverList.js / ApproverConfirm.jsapproverlist / approverconfirm
ApprovalList.js / ApprovalDetail.jsapprovallist / approvaldetail
Attendees.js / AttendeesList.jsattendees / attendeeslist
ApprovalRequestList.js / ApprovalRequestDetail.jsapprovalrequestlist / approvalrequestdetail
DelegateNote.js(ตรวจ import ใน App.js — อยู่ในโฟลเดอร์เดียวกัน)

Scene block: vtrc-mobile/App.js:730-838

PMS

ContainerScene key
ManualPMS.jsmanualpms
ListEvaluators.js / MenuEvaluator.jslistevaluators / menuevaluators
CheckDataPersonal.jscheckdatapersonal
EvaluationResult.js / ListEvaluationResult.js / ViewPDFEvaluation.jsevaluationresult / listevaluationresult / viewpdfevaluation

Recruitment

ContainerScene key
RecruitmentListMenu.jsrecruitmentlistmenu
RecruitmentAnnounce.js / FormAnnounce.jsrecruitmentannounce / formannounce
RecruitmentSearchResult.js / RecruitmentDetail.jsrecruitmentsearchresult / recruitmentdetail
ApplyWork.js / RecruitmentHistory.js / WorkWithUs.jsapplywork / recruitmenthistory / workwithus

Course / Conicle

ContainerScene key
GuestCourseList.js / GuestCourse.js / GuestCourseId.jsguestcourselist / guestcourse / guestcourseid
CourseConicle.js / Conicle.js / ContentConicle.jscourseconicle / conicle / contentconicle
CheckInConicle.js / NotificationConicle.jscheckinconicle / notificationconicle

components/ — 27 domain folders

src/components/
├── authen/                 # ฟอร์ม login / verify / captcha UI
├── button/
├── childtuition/
├── course/ / courseconicle/
├── delegate/
├── form/                   # UploadImage UploadFile NewUploadFile FileUpload
├── layout/                 # Layout + LinearGradientBackground
├── mainmenu/
├── meeting-management/
├── news/ / notification/
├── org-info/
├── payslip/ / provident/
├── personal-development/
├── picker/
├── profile/
├── recruitment/
├── report/
├── shared/                 # NotificationEvent Spiner …
├── sso/
├── tax/ / tax-reduction/
├── time/ / timeline/
└── witchdraw/              # typo folder name (withdraw)

จำนวนไฟล์รวม 218 — ไม่มี lazy barrel ที่บังคับ; container import ตรงเข้า component ที่ต้องการ

src/components/shared/NotificationEvent.js (353 บรรทัด) เป็นจุดรวม deep-link จาก push — ดู 03-features-map


features/ vs actions/ — สอง pattern ซ้อนกัน

features/ — createSlice จริง (14 ไฟล์)

Sliceหน้าที่โดยย่อ
authSlice.js (1084 บรรทัด)login / logout / verify / refresh / biometric / captcha / FCM
userSlice.jsprofile + tax + address + phone + fund details
withdrawSlice.jsleave + medical welfare queries/mutations state
slipSlice.jspayslip / salary cert (blacklist จาก persist)
newsSlice.js / notificationSlice.jsข่าว + แจ้งเตือน
documentSlice.js / aboutusSlice.js / contactusSlice.jsเอกสาร / องค์กร / ติดต่อ
courseSlice.js / careerSlice.js / consentSlice.js / settingSlice.js / timeSlice.jsLMS / career / consent / app setting / time

ลงทะเบียนใน combineReducers ที่ src/app/store.js:67-82

actions/ — plain async (ชื่อลงท้าย Slice ทำให้เข้าใจผิด)

ไฟล์ใช้จริง
ssoSlice.jsssoCheckEmpLogin${HOST}/SSOService/checkEmpLogin (src/actions/ssoSlice.js:18-19)
recruitment.jsREST ไป HOSTRECRUITMENT หลาย endpoint (src/actions/recruitment.js:7-273)
withdrawSlice.jsmultipart upload ผ่าน ${HOSTGRAHQL}/graphql (src/actions/withdrawSlice.js:271,339)
userSlice.jsworkforce REST
slipSlice.js / estimateProfileSlice.jshelpers เสริม

ดู 04-scorecard § QUAL-MOBILE-05


gql/ — GraphQL operations

src/gql/
├── client.js          # ApolloClient → Config.API, timeout 10s, fetchPolicy no-cache
├── index.js           # re-export query + mutation
├── query/             # 14 ไฟล์
└── mutation/          # 7 ไฟล์

client.js — มีแต่ใช้น้อย

javascript
const timeoutLink = new ApolloLinkTimeout(10000);
const httpLink = createHttpLink({uri: Config.API});
const client = new ApolloClient({
  link: timeoutHttpLink,
  cache: new InMemoryCache(),
  defaultOptions, // watchQuery/query = no-cache
});

หลักฐาน: vtrc-mobile/src/gql/client.js:1-27

ไม่มี authLink / errorLink บน Apollo client — เพราะ path หลักไม่เดินผ่าน Apollo แต่เดินผ่าน utils/fetch.js ที่แปะ header เองและจัดการ TOKEN_EXPIRED เอง

query/ — ไฟล์และขนาดโดยประมาณ

ไฟล์บรรทัด (wc)ตัวอย่าง export
withdraw.js1230leave + medical + child tuition + study leave + PMS master
user.js1023profile / tax / provident / address dropdowns
document.js311principle / KCMH / quality docs
slip.js157slip + salary cert
auth.js156VERIFY / REFRESH_TOKEN / captcha / OTP
course.js123course list + Conicle URL helpers
news.js64NEWS_QUERY
notification.js53list / by id / count
contactus.js51contact list
about.js35org groups
consent.js25consent / policy
setting.js22app setting / check update
career.js17career list
time.js13TIME_ATTENDANCE_BY_DATE_QUERY

mutation/

ไฟล์ตัวอย่าง export
auth.jsLOGIN_MUTATION, LOGIN_BYPASS_MUTATION, LOGOUT_MUTATION, CREATE_AUTHEN_SESSION_MUTATION, UPDATE_DEVICE_TOKEN_MUTATION, LOG_ERROR (src/gql/mutation/auth.js:21-147)
withdraw.jscreate/update leave, medical destroy, delegate, study leave
user.jstax draft, address, phone, fund rate/benefit
notification.js / news.js / course.js / consent.jsread markers / check-in / consent

Operations เป็น string template functions ที่รับ buildQuery(...) จาก utils/fetch.js — ไม่ใช่ gql tagged template ของ Apollo


config/ และ constants/ — จุด config ที่ต้องระวัง

src/config/index.js

javascript
export const Config = {
  // PROD
   API: 'https://vtrcapi.redcross.or.th/api/graphql',
  // UAT / Local — comment อยู่
  MEETING_API: 'https://uat-vtrcapi.redcross.or.th/meeting',
  isDevMode: process.env.NODE_ENV !== 'production',
};

หลักฐาน: vtrc-mobile/src/config/index.js:1-15

ไฟล์อื่นในโฟลเดอร์: locale.js, global-props.js, form.js — UI/form defaults ไม่ใช่ host

src/constants/HostApi.js — host ชุดที่ถูก import ~25 จุด

Exportค่า PROD ปัจจุบัน
HOSThttps://vtrcapi.redcross.or.th
HOSTGRAHQLhttps://vtrcapi.redcross.or.th/api
HOSTWORKFORCE…/workforce-api/api/restful
HOSTRECRUITMENT…/recruitment-api/api/v1
PATH_WORKFORCE / PATH_RECRUITMENTbase path สำหรับ asset/URL

หลักฐาน: vtrc-mobile/src/constants/HostApi.js:21-38

Drift: fetchRestFull.js:3 import HOSTAPIDEV จาก HostApi แต่ HostApi.js ไม่ได้ export HOSTAPIDEV — ดู 04-scorecard § CORR-MOBILE-02

src/utils/hostUrl.js — duplicate ที่ 3

javascript
export const UAT_HOST = 'https://uat-vtrcapi.redcross.or.th'
export const HOST = 'https://vtrcapi.redcross.or.th'

ถูก import แค่ที่ src/containers/Conicle.js:21 — ดู LEG-MOBILE-02

Secrets ใน constants/

ไฟล์เนื้อหา
constants/Authen.js:1-5API_KEY production device key
constants/PrivateKey.js:1RECRUITMENT_KEY
utils/login.js:17-42RSA private PEM (ใช้คู่กับ public สำหรับ makeCsID)
utils/fetch.js:43apiKey ซ้ำอีกรอบ (inline)

ไฟล์ constants อื่น: User.js (USER_QUERY_TYPE), FlowVerify.js, Menu.js, Withdraw.js, Slip.js, Tax.js, Conicle.js, Career.js, News.js, Notification.js, Document.js, Contactus.js, Course.js, Gender.js, ProvidentFund.js, Recruitment.js


app/ — Redux store + persist

src/app/
├── store.js                              # configureStore + persistReducer
└── redux-persist-sensitive-storage.js    # adapter → react-native-sensitive-info

Persist config:

javascript
const storage = createSensitiveStorage({
  keychainService: 'vtrcKeychain',
  sharedPreferencesName: 'vtrcSharedPrefs',
});
const persistConfig = {
  key: 'root',
  storage,
  timeout: 0,
  blacklist: ['slip'],
};

หลักฐาน: vtrc-mobile/src/app/store.js:55-65

PURGE action รีเซ็ตทุก slice กลับ initialState ด้วยมือ (store.js:84-102) — ถูกเรียกตอน firstRun, TOKEN_INVALID, logout

Middleware: default RTK + redux-logger เฉพาะ non-production (store.js:106-113)


utils/ — helper สำคัญ

ไฟล์หน้าที่บรรทัดโดยประมาณ
fetch.jsGraphQL ผ่าน SSL pinning + token refresh inline~249
fetchRestFull.jsaxios GET/POST + refresh บน 401~255
login.jsRSA_KEY + makeCsID() เท่านั้น76
setting.jsAsyncStorage flags (firsttime, FCMToken, ID, Encode, …)~117
axios.jsmeetingAPI baseURL = Config.MEETING_API/secure23
course.js / meeting.js / withdraw.js / profile.jsdomain helpers
hostUrl.jsHOST duplicate สำหรับ Conicle6
downloadPDF.js / permissionAndroid.js / updateVersion.jsnative-ish helpers

services/

src/services/meetingService.js (338 บรรทัด) — ทุกฟังก์ชันยิง meetingAPI หรือ axios ตรงไป Config.MEETING_API:

  • getListMeetingInMonth, getMeetingdetail, addNewMeeting, updateMeeting, …
  • redirectByPass(accessToken)GET ${Config.MEETING_API}/redirectbypass (meetingService.js:327-338) ถูกเรียกหลัง login/refresh สำเร็จ (authSlice.js:409,591)

android/ / ios/ — จุดที่ต้องระวังก่อน release

Android signing (Critical)

release {
    storeFile file('/Users/bosspj/Desktop/Project/react-native/vtrc-mobile/android/I3Keystore')
    storePassword '…'
    keyAlias 'VTRC'
    keyPassword '…'
}

หลักฐาน: vtrc-mobile/android/app/build.gradle:174-179SEC-MOBILE-02

SSL pin asset

android/app/src/main/assets/digicert2025.cer ตรงกับชื่อใน fetch.js:36 (certs: ['digicert2025'])

เมื่อ Config.isDevMode === true จะตั้ง disableAllSecurity: true (fetch.js:33) — ปิด pinning ทั้งก้อนใน dev

iOS

  • Target / workspace ชื่อ rn_redcross (ios/Podfile:6)
  • Permissions pods: Camera, Notifications (Podfile:11-12)
  • pre_install ลบ UIWebView files จาก AFNetworking (Podfile:16-28)

สิ่งที่ไม่มีใน repo นี้

สิ่งที่คาดว่าจะมีในแอปใหม่สถานะใน vtrc-mobile
@react-navigationไม่มี — ใช้ router-flux
runtime env switch / .env สำหรับ API hostไม่มี — comment ในซอร์ส
Sentry / Crashlytics moduleไม่มีใน package.json dependencies (มีแค่ @react-native-firebase/app + messaging)
automated test เกิน templateมีแค่ __tests__/App-test.js
TypeScriptJS ทั้งโปรเจกต์ (มี babel TS plugins ใน devDependencies แต่ซอร์สหลักเป็น .js)

ขั้นตอนถัดไป

ไป 02 · Core pipeline — endpoint drift, auth, token, RSA