Project

General

Profile

Manual ICO Web » History » Version 1

prin methirattanasophon, 03/17/2026 08:43 AM

1 1 prin methirattanasophon
# Manual ICO Web
2
3
ICO Web — Project Migration Document
4
5
> **Note:** This project was originally scaffolded using [Vite](https://vitejs.dev/) (`create-vite` with the React/TypeScript template).
6
7
---
8
9
## 1. Stack & Prerequisites
10
11
### Tech Stack
12
13
| Category             | Technology           | Version |
14
| -------------------- | -------------------- | ------- |
15
| **Language**         | TypeScript           | ^5.6.3  |
16
| **Framework**        | React                | ^18.3.1 |
17
| **Build Tool**       | Vite                 | ^6.3.5  |
18
| **Styling**          | Tailwind CSS         | ^3.4.11 |
19
| **State Management** | Redux Toolkit        | ^2.2.7  |
20
| **Routing**          | React Router DOM     | ^6.26.2 |
21
| **HTTP Client**      | Axios                | ^1.7.7  |
22
| **Form**             | React Hook Form      | ^7.53.0 |
23
| **Form Validation**  | Zod                  | ^3.23.8 |
24
| **i18n**             | i18next              | ^25.7.4 |
25
| **Testing**          | Jest                 | ^29.7.0 |
26
| **Linting**          | ESLint               | ^8.56.0 |
27
| **Container**        | Docker (multi-stage) | —       |
28
| **Web Server**       | Nginx Alpine         | —       |
29
30
### Prerequisites to Install
31
32
| Tool        | Version       |
33
| ----------- | ------------- |
34
| **Node.js** | LTS (v20/v22) |
35
| **Yarn**    | Berry (v2+)   |
36
| **Docker**  | 20+           |
37
| **Git**     | 2.x           |
38
39
### Verify Installations
40
41
```bash
42
node -v       # v20.x or v22.x
43
yarn -v       # 4.x (Berry)
44
docker -v     # Docker version 20+
45
git --version # git version 2.x
46
```
47
48
---
49
50
## 3. Package Manager
51
52
This project uses **Yarn Berry (v2+)** with classic `node_modules` linker.
53
54
### Configuration
55
56
File: `.yarnrc.yml`
57
58
```yaml
59
nodeLinker: node-modules
60
```
61
62
### Common Commands
63
64
```bash
65
# Install all dependencies
66
yarn install
67
68
# Add a new dependency
69
yarn add <package-name>
70
71
# Add a dev dependency
72
yarn add -D <package-name>
73
74
# Remove a dependency
75
yarn remove <package-name>
76
```
77
78
### Scripts (from package.json)
79
80
```bash
81
yarn dev                    # Start Vite dev server (http://localhost:5173)
82
yarn build                  # TypeScript check + production build → /dist
83
yarn test                   # Run Jest tests
84
```
85
86
---
87
88
## 4. Project Architecture
89
90
### 4.1 Routing (React Router DOM v6)
91
92
**Entry:** `src/app/AppRoutes.tsx`
93
94
All routes are defined in a single file using `<Routes>` and `<Route>`. The app wraps routes in a `<HelmetLayout>` for SEO.
95
96
**Route groups:**
97
98
| Group                 | Path Pattern         | Pages                                                                                      |
99
| --------------------- | -------------------- | ------------------------------------------------------------------------------------------ |
100
| **Landing**           | `/`                  | Landing page, investment campaign                                                          |
101
| **Auth**              | `/login`, `/reset-*` | Login, reset password, Google Authenticator                                                |
102
| **Sign Up (Thai)**    | `/signup/*`          | Type select → corporate/individual → basicinfo → suite test → OTP → ID card → verification |
103
| **Sign Up (Foreign)** | `/foreign/*`         | Fullname → CRS → basicinfo → suite test → doc upload → OTP                                 |
104
| **Re-KYC**            | `/rekyc/*`           | Re-KYC flow, FATCA, suite test, ID card                                                    |
105
| **Portfolio**         | `/portfolio`         | Portfolio management                                                                       |
106
| **Marketplace**       | `/marketplace`       | Marketplace + TOTP confirmation                                                            |
107
| **Order & Trade**     | `/order-trade`       | Order trade + high net worth verification                                                  |
108
| **Subscription**      | `/subscription`      | Subscription page                                                                          |
109
| **Asset Details**     | `/asset-details/*`   | ICO details, white paper, filing                                                           |
110
| **Fraction Exchange** | `/fraction-exchange` | Fraction exchange                                                                          |
111
| **Static Pages**      | `/contact-us`, etc.  | Contact, policy, complaint, about us, terms                                                |
112
| **Error**             | `*`                  | 404 page                                                                                   |
113
114
---
115
116
### 4.2 State Management (Redux Toolkit)
117
118
**Store:** `src/redux/store.tsx`
119
120
```
121
Redux Store
122
└── redux/
123
   ├── store
124
   └── slice/
125
126
```
127
128
---
129
130
### 4.3 API Layer (Axios)
131
132
**File:** `src/api/axios.tsx`
133
134
The project creates multiple Axios instances, all with `baseURL: window.origin` (same-origin proxy):
135
136
| Instance          | Purpose                            | Auth         |
137
| ----------------- | ---------------------------------- | ------------ |
138
| `default export`  | Basic API calls                    | Cookies only |
139
| `axiosCheckToken` | Authenticated calls with refresh   | Auto-refresh |
140
| `axiosMultipart`  | File uploads (multipart/form-data) | Cookies      |
141
| `axiosNoAuth`     | Public API calls                   | None         |
142
143
**Token refresh flow:**
144
145
1. Request interceptor checks if refresh token is expired → redirect to login if so
146
2. If access token is expired, calls `POST /api/v1/authen/customers/refresh`
147
3. Queues failed requests in `failedQueue` while refresh is in-flight
148
4. On success, retries all queued requests with new token
149
5. In dev mode (`isDev()`), token checks are skipped entirely
150
151
**Helper:** `getCustomAxios()` returns `axiosCheckToken` if access token exists, otherwise `axiosNoAuth`.
152
153
---
154
155
### 4.4 Form Handling
156
157
| Library                 | Purpose                            |
158
| ----------------------- | ---------------------------------- |
159
| **React Hook Form**     | Form state, validation, submission |
160
| **Zod**                 | Schema-based validation            |
161
| **@hookform/resolvers** | Connects Zod schemas to RHF        |
162
163
---
164
165
### 4.5 Internationalization (i18n)
166
167
**File:** `src/i18n/config.ts`
168
169
| Setting               | Value                                                          |
170
| --------------------- | -------------------------------------------------------------- |
171
| **Library**           | i18next + react-i18next                                        |
172
| **Languages**         | `en` (English), `th` (Thai)                                    |
173
| **Fallback**          | `en`                                                           |
174
| **Detection**         | localStorage → navigator → htmlTag                             |
175
| **Storage key**       | `i18nextLng` (localStorage)                                    |
176
| **Translation files** | `public/locales/{lng}/{ns}.json`                               |
177
| **Namespaces**        | `common`, `footer`, `navbar`, `landing`, `signup`, `portfolio` |
178
| **Default ns**        | `common`                                                       |
179
180
---
181
182
### 4.6 Styling
183
184
| Tool               | Config File            | Notes                                       |
185
| ------------------ | ---------------------- | ------------------------------------------- |
186
| **Tailwind CSS**   | `tailwind.config.js`   | Custom font: Anuphan, custom colors/screens |
187
| **CSS**            | `src/index.css`        | Global styles                               |
188
| **PostCSS**        | `postcss.config.js`    | Tailwind + Autoprefixer plugins             |
189
| **tailwind-merge** | via `src/lib/utils.ts` | `cn()` helper for conditional classes       |
190
191
---
192
193
### 4.7 Key Libraries
194
195
| Library                 | Purpose                                  |
196
| ----------------------- | ---------------------------------------- |
197
| `crypto-js`             | Encryption/decryption (with pepper keys) |
198
| `jwt-decode`            | Decode JWT tokens (expiry check)         |
199
| `js-cookie`             | Cookie management (access/refresh token) |
200
| `dayjs`                 | Date/time formatting (with UTC/timezone) |
201
| `lodash`                | Utility functions                        |
202
| `react-toastify`        | Toast notifications                      |
203
| `react-helmet-async`    | SEO meta tags                            |
204
| `apexcharts`            | Interactive charts                       |
205
| `chart.js`              | Canvas-based charts                      |
206
| `echarts-for-react`     | ECharts wrapper                          |
207
| `@tanstack/react-table` | Headless table                           |
208
| `swiper`                | Carousel/slider                          |
209
| `leaflet`               | Map component                            |
210
| `filepond`              | File upload widget                       |
211
| `react-webcam`          | Webcam capture (ID card/liveness)        |
212
213
---
214
215
## 5. Environment Variables
216
217
### 5.1 Variable List
218
219
All variables use the `VITE_` prefix (required by Vite to expose to client-side code):
220
221
| Variable              | Required | Description                                  |
222
| --------------------- | -------- | -------------------------------------------- |
223
| `VITE_BASE_URL`       | Yes      | Backend API base URL                         |
224
| `VITE_REKOGNITOR_URL` | Yes      | AWS Rekognition / face liveness service URL  |
225
| `VITE_STATIC_URL`     | Yes      | Static file server URL (images, documents)   |
226
| `VITE_BUCKET_URL`     | Yes      | S3 bucket URL for uploads/downloads          |
227
| `VITE_PEPER`          | Yes      | Encryption pepper (used with crypto-js)      |
228
| `VITE_BACK_REGISTER`  | Yes      | Backend registration endpoint pepper         |
229
| `VITE_CID_PEPER`      | Yes      | CID (citizen ID) encryption pepper           |
230
| `VITE_ENVIRONMENT`    | Yes      | Environment name: `dev`, `uat`, `production` |
231
232
### 5.2 Environment Variable Injection (CI/CD Pipeline)
233
234
**Workflow process:**
235
236
1. **Build Phase:** The React app is built using Vite. During this build use config paceholder `VITE_*` (e.g., the string `"VITE_BASE_URL"` instead of a real URL).
237
2. **Docker Phase:** The `Dockerfile` packages the built static files and an `entrypoint.sh` script into an Nginx image.
238
3. **Environment Fetching:** Before the application spins up in the target AWS environment, the real environment values are fetched from an `.env` file securely stored in an **AWS S3 bucket**.
239
4. **Runtime Injection:** When the Docker container starts, it executes `entrypoint.sh`. This shell script uses `sed` to find all the JS bundles that contain the text placeholders and replaces them with the real environment values fetched from S3.
240
241
This pattern allows the same Docker image to be promoted across Dev, UAT, and Prod environments just by fetching a different `.env` file from S3
242
243
### 5.3 Config File
244
245
**File:** `src/config/config.ts`
246
247
This file maps environment variables to exported constants used throughout the app:
248
249
| Constant              | Source / Env Var      |
250
| --------------------- | --------------------- |
251
| `BASE_URL`            | `VITE_BASE_URL`       |
252
| `BASE_REKOGNITOR_URL` | `VITE_REKOGNITOR_URL` |
253
| `BASE_STATIC_URL`     | `VITE_STATIC_URL`     |
254
| `BASE_BUCKET_URL`     | `VITE_BUCKET_URL`     |
255
| `PEPER`               | `VITE_PEPER`          |
256
| `PEPER_BACK_REGISTER` | `VITE_BACK_REGISTER`  |
257
| `PEPER_CID`           | `VITE_CID_PEPER`      |
258
| `ENVIRONMENT`         | `VITE_ENVIRONMENT`    |