Skip to main content

๐Ÿ“‹ PREXITION

Aplikasi: Premix Intelligent Formulation (PREXITION)
Perusahaan: PT Global Vita Nutritech Indonesia
Tipe Project: Frontend React Web Application
Versi: 3.9.3
Tim Product Terkait: Debby Tantika Ardi
Tanggal Dokumentasi: Januari 2026


๐Ÿ“‘ Daftar Isiโ€‹

  1. Overview Project
  2. Tech Stack & Dependencies
  3. Struktur Folder Project
  4. Setup & Running Project
  5. Environment Variables
  6. Architecture & Pattern
  7. Key Components & Features
  8. API Integration
  9. State Management
  10. Routing & Navigation
  11. Authentication & Authorization
  12. Build & Deployment
  13. Development Guidelines
  14. Common Issues & Troubleshooting
  15. Dokumentasi & Resources

๐Ÿ”— Akses Aplikasiโ€‹

Berikut adalah alamat akses cepat untuk environment aplikasi:

EnvironmentURL AksesDeskripsi
๐Ÿš€ Productionhttps://prexition.gvn.co.idEnvironment utama pengguna
๐Ÿงช Developmenthttps://prexitiondev.gvn.co.idTesting & staging area
โš™๏ธ Hangfirehttps://prexitionapi.gvn.co.id/hangfireDashboard Background Jobs

Overview Projectโ€‹

Deskripsiโ€‹

PREXITION adalah aplikasi web frontend yang dibangun dengan React + TypeScript untuk mengelola Premix Intelligent Formulation. Aplikasi ini menangani:

  • ๐Ÿ“Š Dashboard & Reporting
  • ๐Ÿญ Master Data Management (Items, Formula, Nutrition, dll)
  • ๐Ÿ’ผ Transaksi Bisnis (Product Costing, Scale Up Formula, dll)
  • ๐Ÿ”ง Sistem Konfigurasi & Parameter
  • ๐Ÿ‘ฅ User Management & Role-Based Access Control

Target Usersโ€‹

  • Product Formulation Specialists
  • Supply Chain Managers
  • System Administrators
  • Finance/Cost Management Teams

Lifecycle Statusโ€‹

  • Status: Production (v3.9.3)
  • Browser Support: Modern browsers (Chrome, Firefox, Safari, Edge)
  • Responsive: Mobile-friendly dengan PWA support

Tech Stack & Dependenciesโ€‹

Framework & Languageโ€‹

โ”œโ”€โ”€ React 18.2.0          โ†’ UI Library
โ”œโ”€โ”€ TypeScript 5.2.2 โ†’ Type-safe JavaScript
โ”œโ”€โ”€ Vite 7.2.2 โ†’ Build tool & Dev server
โ””โ”€โ”€ React Router 7.9.6 โ†’ Client-side routing

UI & Stylingโ€‹

โ”œโ”€โ”€ Material-UI (MUI) 7.3.5      โ†’ Component library
โ”œโ”€โ”€ Styled Components 6.1.17 โ†’ CSS-in-JS styling
โ”œโ”€โ”€ Emotion 11.14.0 โ†’ CSS-in-JS framework
โ”œโ”€โ”€ Bootstrap 5.3.2 โ†’ Utility classes
โ”œโ”€โ”€ SASS 1.94.0 โ†’ CSS preprocessing
โ””โ”€โ”€ Iconify 4.1.1 โ†’ Icon library

State Management & Dataโ€‹

โ”œโ”€โ”€ MobX 6.12.0           โ†’ Reactive state management
โ”œโ”€โ”€ MobX-React-Lite 4.0.5 โ†’ React bindings untuk MobX
โ”œโ”€โ”€ MobX-Cookie 4.0.5 โ†’ Cookie integration
โ””โ”€โ”€ LocalForage 1.10.0 โ†’ Local storage management

Form & Validationโ€‹

โ”œโ”€โ”€ Formik 2.4.5          โ†’ Form state management
โ”œโ”€โ”€ Yup 1.3.3 โ†’ Schema validation
โ””โ”€โ”€ React Number Format โ†’ Number formatting

API & HTTPโ€‹

โ”œโ”€โ”€ Axios 1.6.7           โ†’ HTTP client
โ””โ”€โ”€ Crypto-JS 4.2.0 โ†’ Encryption utilities

Utility Librariesโ€‹

โ”œโ”€โ”€ React-PDF 10.2.0      โ†’ PDF rendering
โ”œโ”€โ”€ Date-FNS 3.3.1 โ†’ Date utilities
โ”œโ”€โ”€ Moment 2.30.1 โ†’ Date manipulation
โ”œโ”€โ”€ i18next 23.8.2 โ†’ Internationalization
โ”œโ”€โ”€ UUID 9.0.1 โ†’ ID generation
โ”œโ”€โ”€ SweetAlert2 11.6.13 โ†’ Alert dialogs
โ””โ”€โ”€ React-Toastify 10.0.4 โ†’ Toast notifications

PWA & Performanceโ€‹

โ”œโ”€โ”€ vite-plugin-pwa 1.1.0 โ†’ Progressive Web App
โ””โ”€โ”€ NProgress 0.2.0 โ†’ Progress bar

Struktur Folder Projectโ€‹

prexitionfrontend/
โ”‚
โ”œโ”€โ”€ ๐Ÿ“„ Konfigurasi Project
โ”‚ โ”œโ”€โ”€ package.json โ†’ Dependencies & scripts
โ”‚ โ”œโ”€โ”€ tsconfig.json โ†’ TypeScript config
โ”‚ โ”œโ”€โ”€ tsconfig.node.json โ†’ Node TS config
โ”‚ โ”œโ”€โ”€ vite.config.ts โ†’ Vite configuration
โ”‚ โ”œโ”€โ”€ index.html โ†’ Entry HTML
โ”‚ โ”œโ”€โ”€ Dockerfile โ†’ Docker config
โ”‚ โ”œโ”€โ”€ Jenkinsfile โ†’ CI/CD pipeline
โ”‚ โ””โ”€โ”€ README.md โ†’ Basic readme
โ”‚
โ”œโ”€โ”€ ๐Ÿ“‚ public/ โ†’ Static assets
โ”‚ โ”œโ”€โ”€ pdf.worker.mjs โ†’ PDF worker
โ”‚ โ”œโ”€โ”€ Fonts/ โ†’ Custom fonts
โ”‚ โ”œโ”€โ”€ icons/ โ†’ App icons (Android, iOS, Windows)
โ”‚ โ””โ”€โ”€ images/ โ†’ Static images
โ”‚ โ”œโ”€โ”€ avatars/ โ†’ User avatars
โ”‚ โ”œโ”€โ”€ captcha/ โ†’ Captcha images
โ”‚ โ”œโ”€โ”€ customizer/ โ†’ Theme customizer
โ”‚ โ”œโ”€โ”€ pages/ โ†’ Page backgrounds
โ”‚ โ””โ”€โ”€ screenshots/ โ†’ Screenshots
โ”‚
โ””โ”€โ”€ ๐Ÿ“‚ src/ โ†’ SOURCE CODE
โ”‚
โ”œโ”€โ”€ ๐Ÿ“„ main.tsx โ†’ React entry point
โ”œโ”€โ”€ ๐Ÿ“„ env.d.ts โ†’ Environment type definitions
โ”œโ”€โ”€ ๐Ÿ“„ vite-env.d.ts โ†’ Vite type definitions
โ”‚
โ”œโ”€โ”€ ๐Ÿ“‚ app/ โ†’ Application core
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ api/
โ”‚ โ”‚ โ””โ”€โ”€ agent.ts โ†’ API client & requests
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ common/ โ†’ Shared utilities
โ”‚ โ”‚ โ”œโ”€โ”€ Constant.ts โ†’ App constants
โ”‚ โ”‚ โ”œโ”€โ”€ config/
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ pdfConfig.ts โ†’ PDF configuration
โ”‚ โ”‚ โ”œโ”€โ”€ helpers/ โ†’ Utility functions
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ BatchName.ts โ†’ Format Batching Name
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ Crypto.ts โ†’ Encryption/decryption
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ Currency.ts โ†’ Currency formatting
โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ ErrorHandler.ts โ†’ Form BE Error Handler
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ UomConversion.ts โ†’ UOM Conversion
โ”‚ โ”‚ โ””โ”€โ”€ Lov/ โ†’ List of Values
โ”‚ โ”‚ โ””โ”€โ”€ types.ts
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ components/ โ†’ Reusable components
โ”‚ โ”‚ โ”œโ”€โ”€ Captcha/ โ†’ Captcha component
โ”‚ โ”‚ โ”œโ”€โ”€ dashboard/ โ†’ Dashboard components
โ”‚ โ”‚ โ”œโ”€โ”€ Form/ โ†’ Form-related components
โ”‚ โ”‚ โ”œโ”€โ”€ Master/ โ†’ Master data components
โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ Formula/
โ”‚ โ”‚ โ”œโ”€โ”€ PDFTemplate/ โ†’ PDF templates
โ”‚ โ”‚ โ”œโ”€โ”€ shared/ โ†’ Shared components
โ”‚ โ”‚ โ””โ”€โ”€ Transaction/ โ†’ Transaction components
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ core/ โ†’ Core functionality
โ”‚ โ”‚ โ”œโ”€โ”€ components/ โ†’ Layout components
โ”‚ โ”‚ โ”œโ”€โ”€ configs/ โ†’ App configurations
โ”‚ โ”‚ โ”œโ”€โ”€ context/ โ†’ React Context providers
โ”‚ โ”‚ โ”œโ”€โ”€ hooks/ โ†’ Custom React hooks
โ”‚ โ”‚ โ”œโ”€โ”€ layouts/ โ†’ Layout wrappers
โ”‚ โ”‚ โ”œโ”€โ”€ theme/ โ†’ MUI theme configuration
โ”‚ โ”‚ โ””โ”€โ”€ utils/ โ†’ Core utilities
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ hooks/ โ†’ Custom hooks
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ layout/ โ†’ Main layouts
โ”‚ โ”‚ โ”œโ”€โ”€ App.tsx โ†’ Root layout
โ”‚ โ”‚ โ”œโ”€โ”€ BlankLayout.tsx โ†’ Blank/Minimal layout
โ”‚ โ”‚ โ”œโ”€โ”€ UserLayout.tsx โ†’ User dashboard layout
โ”‚ โ”‚ โ”œโ”€โ”€ UserThemeOptions.ts
โ”‚ โ”‚ โ””โ”€โ”€ components/ โ†’ Layout sub-components
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ models/ โ†’ TypeScript types/interfaces
โ”‚ โ”‚ โ”œโ”€โ”€ clsGlobalAPIModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ DatatableModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ ErrorModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ GeneralModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ menuModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ ParameterModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ ProgramModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ roleModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ systemAPIModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ userModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ ValidityRuleModel.ts
โ”‚ โ”‚ โ”œโ”€โ”€ Dashboard/
โ”‚ โ”‚ โ”œโ”€โ”€ master/ โ†’ Master data models
โ”‚ โ”‚ โ”œโ”€โ”€ Oracle/ โ†’ Oracle-specific models
โ”‚ โ”‚ โ””โ”€โ”€ Transaction/ โ†’ Transaction models
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ router/ โ†’ Route definitions
โ”‚ โ”‚ โ”œโ”€โ”€ AuthRoute.tsx โ†’ Protected routes
โ”‚ โ”‚ โ””โ”€โ”€ Routes.tsx โ†’ Route configuration
โ”‚ โ”‚
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ stores/ โ†’ MobX stores (State Management)
โ”‚ โ”‚ โ”œโ”€โ”€ authStore.ts โ†’ Authentication state
โ”‚ โ”‚ โ”œโ”€โ”€ CommonStore.ts โ†’ Shared state
โ”‚ โ”‚ โ”œโ”€โ”€ DashboardStore.ts
โ”‚ โ”‚ โ”œโ”€โ”€ GeneralStore.ts
โ”‚ โ”‚ โ”œโ”€โ”€ LovStore.ts โ†’ List of Values store
โ”‚ โ”‚ โ”œโ”€โ”€ store.ts โ†’ Root store
โ”‚ โ”‚ โ”œโ”€โ”€ ValidityRuleStore.ts
โ”‚ โ”‚ โ”œโ”€โ”€ master/ โ†’ Master data stores
โ”‚ โ”‚ โ”œโ”€โ”€ oracle/ โ†’ Oracle stores
โ”‚ โ”‚ โ”œโ”€โ”€ system/ โ†’ System stores
โ”‚ โ”‚ โ””โ”€โ”€ transaction/ โ†’ Transaction stores
โ”‚
โ”œโ”€โ”€ ๐Ÿ“‚ assets/ โ†’ Asset files (images, icons)
โ”‚
โ”œโ”€โ”€ ๐Ÿ“‚ features/ โ†’ Feature pages
โ”‚ โ”œโ”€โ”€ Home.tsx โ†’ Home page
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ authentication/ โ†’ Login & role selection
โ”‚ โ”‚ โ”œโ”€โ”€ ChoseRole.tsx
โ”‚ โ”‚ โ””โ”€โ”€ login.tsx
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ errors/ โ†’ Error pages
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ master/ โ†’ Master data features
โ”‚ โ”‚ โ”œโ”€โ”€ Approval/
โ”‚ โ”‚ โ”œโ”€โ”€ Customer/
โ”‚ โ”‚ โ”œโ”€โ”€ Distributor/
โ”‚ โ”‚ โ”œโ”€โ”€ Formula/
โ”‚ โ”‚ โ”œโ”€โ”€ Items/
โ”‚ โ”‚ โ”œโ”€โ”€ MaterialPrice/
โ”‚ โ”‚ โ”œโ”€โ”€ Nutrition/
โ”‚ โ”‚ โ”œโ”€โ”€ NutritionItem/
โ”‚ โ”‚ โ”œโ”€โ”€ NutritionType/
โ”‚ โ”‚ โ”œโ”€โ”€ OtherVarCost/
โ”‚ โ”‚ โ”œโ”€โ”€ ParameterConversion/
โ”‚ โ”‚ โ””โ”€โ”€ ProductionType/
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ misc/ โ†’ Miscellaneous pages
โ”‚ โ”‚ โ”œโ”€โ”€ 404.tsx
โ”‚ โ”‚ โ”œโ”€โ”€ BadGatewayPage.tsx
โ”‚ โ”‚ โ””โ”€โ”€ NotAuthorizedPage.tsx
โ”‚ โ”œโ”€โ”€ ๐Ÿ“‚ system/ โ†’ System configuration
โ”‚ โ”‚ โ”œโ”€โ”€ systemConfig.tsx
โ”‚ โ”‚ โ””โ”€โ”€ Parameter/
โ”‚ โ””โ”€โ”€ ๐Ÿ“‚ transaction/ โ†’ Transaction features
โ”‚ โ”œโ”€โ”€ inquiry/
โ”‚ โ”œโ”€โ”€ ProductCosting/
โ”‚ โ”œโ”€โ”€ ProductDataSheet/
โ”‚ โ”œโ”€โ”€ ScaleUpFormula/
โ”‚ โ””โ”€โ”€ Spec/
โ”‚
โ”œโ”€โ”€ ๐Ÿ“‚ styles/ โ†’ Global styles
โ”‚ โ”œโ”€โ”€ fonts.css โ†’ Font definitions
โ”‚ โ””โ”€โ”€ globals.css โ†’ Global CSS
โ”‚
โ””โ”€โ”€ ๐Ÿ“‚ dev-dist/ โ†’ Build output (generated)
โ””โ”€โ”€ Service Worker files


Setup & Running Projectโ€‹

Prerequisitesโ€‹

  • Node.js: v16+ (recommended v18 LTS)
  • yarn v1.22+
  • Git: untuk version control

Installationโ€‹

# Clone repository
git clone <repository-url>
cd prexitionfrontend

# Install dependencies
yarn install

# Jalankan Development Server
yarn dev

# Build untuk Production
yarn build

# Preview hasil Build secara lokal
yarn preview

# Server akan running di: http://localhost:3002

Available Scriptsโ€‹

CommandDeskripsi
yarn devJalankan dev server (port 3002)
yarn dev:productionDev mode dengan NODE_ENV=production
yarn buildBuild untuk production
yarn lintESLint checking
yarn previewPreview production build

Environment Variablesโ€‹

File Konfigurasiโ€‹

Buat file .env di root project dengan variabel berikut:

# ===== API & WSO Configuration =====
VITE_USERNAME=<username-untuk-wso>
VITE_PASSWORD=<password-untuk-wso>
VITE_WSO_URL=https://prexition-wso.example.com
VITE_API_URL=https://prexitionapidev.gvn.co.id
VITE_SECRET=<secret-key-untuk-encryption>

# ===== Parameter IDs (untuk LOV) =====
VITE_ID_ITEM_TEMPLATE=<id>
VITE_ID_TYPE=<id>
VITE_ID_STATUS=<id>
VITE_ID_UOM=<id>
VITE_ID_LIST_STATUS=<id>
VITE_ID_CONTEXT=<id>
VITE_ID_ORGANIZATIO=<id>
VITE_ID_COSTTYPE=<id>
VITE_ID_LOVSHPNONSHP=<id>
VITE_ID_LOVFLUSHING=<id>

### Cara Mengakses di Code
```typescript
// Import dari vite
const apiUrl = import.meta.env.VITE_API_URL;
const secret = import.meta.env.VITE_SECRET;

Architecture & Patternโ€‹

Architecture Overviewโ€‹

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ React Components (UI) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ State Management (MobX Stores) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ API Integration (Axios) โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Backend API (RESTAPI) with .NET Core โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Design Patternsโ€‹

1. Component Patternโ€‹

  • Functional Components: Semua component menggunakan React Hooks
  • Custom Hooks: Diletakkan di src/app/hooks/ dan src/app/core/hooks/
  • Reusable Components: Umum digunakan components di src/app/components/shared/

2. State Management (MobX)โ€‹

// Contoh MobX Store
class AuthStore {
@observable isLoggedIn = false;

@action
async login(username: string, password: string) {
// Login logic
}

@computed
get isAuthenticated() {
return this.isLoggedIn;
}
}

// Usage di component
import { useLocalObservable } from 'mobx-react-lite';

3. Folder Structure per Featureโ€‹

Setiap feature (master, transaction, dll) memiliki struktur:

Feature/
โ”œโ”€โ”€ components/ โ†’ Components spesifik feature
โ”œโ”€โ”€ store.ts โ†’ State management
โ”œโ”€โ”€ models/ โ†’ TypeScript types
โ”œโ”€โ”€ api.ts โ†’ API calls
โ””โ”€โ”€ index.tsx โ†’ Main page/component

4. API Integration Patternโ€‹

// src/app/api/agent.ts
export const api = {
// Master Data
master: {
getItems: () => axiosInstance.get('/api/items'),
createItem: (data) => axiosInstance.post('/api/items', data),
},
// Transactions
transaction: {
getProductCosting: (id) => axiosInstance.get(`/api/costing/${id}`),
},
};

Key Components & Featuresโ€‹

Dashboardโ€‹

  • File: src/features/Home.tsx, src/app/components/dashboard/
  • Deskripsi: Main dashboard dengan statistik dan overview
  • Components: GridStatistic, Charts, KPI cards

Master Data Managementโ€‹

Modules untuk mengelola master data:

ModuleFolderFungsi
Itemsmaster/Items/CRUD item/produk
Formulamaster/Formula/Manajemen formula produk
Nutritionmaster/Nutrition/Data nutrisi
Customermaster/Customer/Data pelanggan
Distributormaster/Distributor/Data distributor
MaterialPricemaster/MaterialPrice/Harga material
Approvalmaster/Approval/Workflow approval

Transaction Modulesโ€‹

Modules untuk transaksi bisnis:

ModuleFolderFungsi
Product Costingtransaction/ProductCosting/Perhitungan cost produk
Scale Up Formulatransaction/ScaleUpFormula/Scale up resep formula
Product Data Sheettransaction/ProductDataSheet/Data sheet produk
Specificationtransaction/Spec/Spesifikasi produk
Inquirytransaction/inquiry/Pencarian data

Form Componentsโ€‹

  • Location: src/app/components/Form/
  • Menggunakan: Formik + Yup validation
  • Pattern: Controlled components dengan validation real-time

PDF Featuresโ€‹

  • Library: @react-pdf/renderer, react-pdf
  • Config: src/app/common/config/pdfConfig.ts
  • Templates: src/app/components/PDFTemplate/

API Integrationโ€‹

API Client Setupโ€‹

File: src/app/api/agent.ts

// Axios instance dengan interceptors
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 30000,
});

// Request interceptor (add auth token, encryption, etc)
axiosInstance.interceptors.request.use(config => {
// Add headers, tokens
return config;
});

// Response interceptor (handle errors)
axiosInstance.interceptors.response.use(
response => response,
error => {
// Handle errors globally
return Promise.reject(error);
}
);

Proxy Configurationโ€‹

File: vite.config.ts

server: {
proxy: {
"/api": {
target: "https://prexitionapidev.gvn.co.id",
changeOrigin: true,
},
"/gateway": "https://apim.kalbenutritionals.com:8243",
}
}

Error Handlingโ€‹

  • Helper: src/app/common/helpers/ErrorHandler.ts
  • Toast Notifications: react-toastify
  • Alert Dialogs: sweetalert2

State Managementโ€‹

MobX Stores Architectureโ€‹

Root Store: src/app/stores/store.ts

export class RootStore {
authStore: AuthStore;
commonStore: CommonStore;
dashboardStore: DashboardStore;
masterStore: MasterStore;
transactionStore: TransactionStore;

constructor() {
// Initialize stores
}
}

Store Usage di Componentsโ€‹

// 1. Create store instance
const rootStore = new RootStore();

// 2. Use di component
const MyComponent = observer(() => {
const { authStore } = rootStore;

return <div>{authStore.userName}</div>;
});

// 3. Actions untuk update state
authStore.setUserData(userData);

Store Filesโ€‹

stores/
โ”œโ”€โ”€ store.ts โ†’ Root store
โ”œโ”€โ”€ authStore.ts โ†’ Authentication state
โ”œโ”€โ”€ CommonStore.ts โ†’ Common/shared state
โ”œโ”€โ”€ DashboardStore.ts โ†’ Dashboard data
โ”œโ”€โ”€ GeneralStore.ts โ†’ General app state
โ”œโ”€โ”€ LovStore.ts โ†’ List of Values
โ”œโ”€โ”€ ValidityRuleStore.ts โ†’ Validation rules
โ”œโ”€โ”€ master/ โ†’ Master data stores
โ”œโ”€โ”€ oracle/ โ†’ Oracle integration
โ”œโ”€โ”€ system/ โ†’ System configuration
โ””โ”€โ”€ transaction/ โ†’ Transaction stores

Routing & Navigationโ€‹

Route Configurationโ€‹

File: src/app/router/Routes.tsx

const routes = [
{
path: '/',
element: <UserLayout />,
children: [
{ path: 'dashboard', element: <Home /> },
{ path: 'master/items', element: <Items /> },
{ path: 'master/formula', element: <Formula /> },
// ... more routes
]
},
{
path: '/login',
element: <BlankLayout />,
children: [
{ path: '', element: <LoginPage /> },
]
},
// ... catch all
];

Protected Routesโ€‹

File: src/app/router/AuthRoute.tsx

// Component yang melindungi akses berdasarkan authentication
<AuthRoute>
<ProtectedPage />
</AuthRoute>
// Menggunakan React Router
import { useNavigate } from 'react-router-dom';

const navigate = useNavigate();
navigate('/dashboard');

Authentication & Authorizationโ€‹

Authentication Flowโ€‹

Login Page
โ†“
Validate Credentials (WSO)
โ†“
Get JWT Token
โ†“
Store Token (Cookie/LocalStorage)
โ†“
Fetch User Data & Roles
โ†“
Select Role (ChoseRole page)
โ†“
Redirect to Dashboard

Authentication Storeโ€‹

File: src/app/stores/authStore.ts

class AuthStore {
@observable
isLoggedIn = false;

@observable
currentUser: User | null = null;

@action
async login(username: string, password: string) {
// Call WSO API
// Store token
}

@action
logout() {
// Clear token & user data
}
}

Permission Checkingโ€‹

// User roles dan permissions disimpan di authStore
// Permission check dilakukan di component atau route level
if (userRole === 'ADMIN') {
// Show admin features
}

Build & Deploymentโ€‹

Development Buildโ€‹

yarn build

Output: dist/ folder dengan production-ready files

Build Optimizationโ€‹

  • Tree-shaking: TypeScript & Vite sudah enable
  • Code Splitting: React Router lazy loading
  • Asset Optimization: Vite automatic optimization

Docker Deploymentโ€‹

File: Dockerfile

FROM node:18-alpine AS builder
# Build stage

FROM nginx:alpine AS runtime
# Runtime dengan nginx

Build & Run:

docker build -t prexition:latest .
docker run -p 3002:80 prexition:latest

CI/CD Pipelineโ€‹

File: Jenkinsfile

Pipeline steps:

  1. Clone repository
  2. Install dependencies
  3. Build application
  4. Run tests & linting
  5. Deploy to staging/production

Environment-specific Configโ€‹

# Development
yarn dev

# Production
yarn dev:production
yarn build

Development Guidelinesโ€‹

Coding Standardsโ€‹

TypeScriptโ€‹

// โœ… DO: Type everything
interface UserProps {
id: string;
name: string;
email: string;
}

const User: React.FC<UserProps> = ({ id, name, email }) => {
return <div>{name}</div>;
};

// โŒ DON'T: Any types
const User = ({ id, name }: any) => {
return <div>{name}</div>;
};

Component Structureโ€‹

// 1. Imports
import React, { useState } from 'react';
import { observer } from 'mobx-react-lite';

// 2. Types/Interfaces
interface Props {
title: string;
onSubmit: (data: any) => void;
}

// 3. Component
const MyComponent = observer(({ title, onSubmit }: Props) => {
// Hooks
const [count, setCount] = useState(0);

// Event handlers
const handleClick = () => {
setCount(count + 1);
};

// Render
return <div onClick={handleClick}>{title}: {count}</div>;
});

export default MyComponent;

Form Components (Formik + Yup)โ€‹

import * as Yup from 'yup';
import { Formik, Form, Field } from 'formik';

const validationSchema = Yup.object({
email: Yup.string().email('Invalid email').required('Required'),
password: Yup.string().min(6).required('Required'),
});

const MyForm = () => (
<Formik
initialValues={{ email: '', password: '' }}
validationSchema={validationSchema}
onSubmit={(values) => {
// Submit logic
}}
>
{({ errors, touched }) => (
<Form>
<Field name="email" type="email" />
{errors.email && touched.email && <span>{errors.email}</span>}
{/* More fields */}
</Form>
)}
</Formik>
);

Naming Conventionsโ€‹

TypeConventionExample
ComponentsPascalCaseUserList.tsx, FormDialog.tsx
FunctionscamelCasefetchUserData(), handleClick()
VariablescamelCaseuserData, isLoading
ConstantsUPPER_SNAKE_CASEAPI_TIMEOUT, MAX_RETRIES
InterfacesPascalCase with IIUser, IApiResponse
Fileskebab-case or PascalCaseuser-list.ts, UserList.tsx

File Organization per Featureโ€‹

Feature/
โ”œโ”€โ”€ index.tsx โ†’ Main component/page
โ”œโ”€โ”€ Feature.tsx โ†’ Main logic
โ”œโ”€โ”€ Feature.styles.ts โ†’ Styled components
โ”œโ”€โ”€ Feature.types.ts โ†’ TypeScript interfaces
โ”œโ”€โ”€ Feature.constants.ts โ†’ Constants
โ”œโ”€โ”€ Feature.utils.ts โ†’ Utility functions
โ”œโ”€โ”€ components/ โ†’ Sub-components
โ”‚ โ””โ”€โ”€ SubComponent.tsx
โ”œโ”€โ”€ hooks/ โ†’ Custom hooks
โ”‚ โ””โ”€โ”€ useFeature.ts
โ””โ”€โ”€ store.ts โ†’ MobX store

Error Handling Best Practicesโ€‹

try {
const response = await api.fetchData();
handleSuccess(response);
} catch (error) {
const errorMessage = error instanceof AxiosError
? error.response?.data?.message
: error.message;

toast.error(errorMessage);
console.error('Error details:', error);
}

Comments & Documentationโ€‹

/**
* Formats currency value to IDR format
* @param value - Numeric value to format
* @param decimals - Number of decimal places (default: 2)
* @returns Formatted currency string
* @example
* formatCurrency(1000000) // "Rp1.000.000,00"
*/
export const formatCurrency = (
value: number,
decimals: number = 2
): string => {
// Implementation
};

๐Ÿ— Menambahkan LOV Baru (Step-by-Step)โ€‹

Ikuti langkah-langkah berikut untuk mengintegrasikan dataset LOV baru ke dalam sistem:

  1. Definisikan API Request Buka src/app/api/agent.ts dan buat fungsi request baru di dalam kategori yang sesuai (misal: Oracle atau Master).

    // src/app/api/agent.ts
    const Oracle = {
    // ... request lainnya
    codeshp: (params: URLSearchParams) => requests.get('/oracle/codeshp', params),
    };
  2. Update LovOfName Type Tambahkan identifier unik untuk LOV baru Anda pada file tipe global agar dikenal oleh sistem TypeScript.

    // src/app/common/lov/types.ts
    export type LovOfName = "codeshp" | "item" | "akasia" | "specApproved";
  3. Konfigurasi LovStore (Fetch Logic) Buka LovStore.ts, cari fungsi fetch, dan tambahkan case baru di dalam blok switch untuk mengarahkan nama LOV ke API request yang telah dibuat di langkah 1.

    // src/app/stores/LovStore.ts
    switch(nameoflov) {
    case "codeshp":
    response = await agent.Oracle.codeshp(param) as DatatableResponse<T[]>;
    break;
    // Tambahkan case lainnya di sini
    }
  4. Registrasi Store di Root Store Daftarkan instance LovStore baru di store.ts dengan menyertakan interface model data yang sesuai agar mendapatkan dukungan type-safety.

    // src/app/stores/store.ts
    export class RootStore {
    // ... store lainnya
    lovStoreAkasia: new LovStore<AkasiaModel>(),
    LOVScaleUpAFGU: new LovStore<ScaleUpFormulaLovDTO>(),
    LOVSpecApproved: new LovStore<SpecApprovedModel>(),
    }
  5. Update Shared Component LOV Langkah terakhir adalah mendaftarkan store baru tersebut ke dalam komponen UI agar bisa digunakan di form. Edit file di src/app/components/shared/Lov/index.tsx.

    a. Ambil store dari context:

    const { lovStoreAkasia, LOVSpecApproved } = useStore();

    b. Mapping Nama ke Store: Tambahkan mapping pada const currentStore di dalam useMemo agar komponen tahu store mana yang harus digunakan berdasarkan properti name.

      const currentStore = useMemo(() => {
    const storeMap: Record<LovOfName, LovStore<any>> = {
    item: lovStoreItems,
    akasia: lovStoreAkasia,
    codeshp: lovStoreCodeShp,
    specApproved: LOVSpecApproved, // Mapping identifier ke instance store
    };
    return storeMap[props.name];
    }, [props.name, ...]);
  6. Contoh Implementasi di UI (Page/Feature) Setelah mendaftarkan LOV di store, gunakan komponen <Lov /> pada file fitur Anda. Komponen ini sudah terintegrasi dengan Material-UI (MUI) DataGrid dan mendukung pencarian otomatis. Contoh Penggunaan:

    <Lov
    // Identifier unik untuk row data (biasanya GUID dari database)
    rowId={(row) => row.txtGUID}
    // State untuk mengontrol buka/tutup modal
    open={state.aliasModal}
    // Handler untuk menutup modal
    setShow={() => setState(prev => ({ ...prev, aliasModal : false }))}
    // Nama LOV yang sudah didaftarkan di LovOfName & LovStore
    lovName="codeshp"
    // Callback saat user memilih item dari tabel
    setSelect={(item: any) => {
    setFieldValue('txtItemCodeAlias', item.ItemCode);
    }}
    // Definisi kolom DataGrid yang akan ditampilkan di dalam modal
    columns={[
    {
    field: 'ItemCode',
    headerName: 'Item Code',
    minWidth: 140,
    },
    {
    field: 'Description',
    headerName: 'Description',
    minWidth: 350,
    },
    {
    field: 'ItemType',
    headerName: 'Type',
    minWidth: 160,
    },
    ]}
    />
    PropTipeDeskripsi
    lovNameLovOfNameKey identifier yang menghubungkan komponen dengan instance store & API terkait.
    rowIdfunctionFungsi untuk menentukan primary key dari data (penting untuk seleksi row DataGrid).
    openbooleanState boolean untuk visibilitas modal (biasanya dipicu dari klik button/input).
    setSelectfunctionLogic yang dijalankan setelah user memilih data (misal: setFieldValue pada Formik).
    columnsarrayKonfigurasi kolom MUI DataGrid (header, field, width).

Common Issues & Troubleshootingโ€‹

Issue 1: Dev Server tidak bisa diaksesโ€‹

Masalah: http://localhost:3002 tidak bisa dibuka
Solusi:
1. Pastikan port 3002 tidak digunakan program lain
2. Ubah port di vite.config.ts jika port sudah digunakan
3. Gunakan --host flag: yarn dev -- --host

Issue 2: API Proxy tidak bekerjaโ€‹

Masalah: API calls return 404 atau CORS error
Solusi:
1. Verifikasi proxy config di vite.config.ts
2. Pastikan target URL benar dan accessible
3. Check environment variables di .env
4. Lihat browser console untuk error details

Issue 3: MobX store tidak terupdateโ€‹

Masalah: Component tidak re-render saat store berubah
Solusi:
1. Pastikan component wrapped dengan observer()
2. Gunakan @observable untuk state
3. Gunakan @action untuk mutations
4. Verifikasi import path dan store initialization

Issue 4: Build fails dengan TypeScript errorsโ€‹

Masalah: npm run build gagal dengan TS errors
Solusi:
1. Run: npm run lint untuk melihat error details
2. Fix type definitions di model files
3. Pastikan semua imports benar
4. Check tsconfig.json settings

Issue 5: Environment variables tidak terbacaโ€‹

Masalah: import.meta.env.VITE_* return undefined
Solusi:
1. Nama variabel harus diawali VITE_
2. Pastikan .env file ada di root folder
3. Restart dev server setelah update .env
4. Check: console.log(import.meta.env) untuk debugging

Issue 6: PWA tidak bisa installโ€‹

Masalah: Service worker registration fails
Solusi:
1. Verifikasi vite-plugin-pwa config
2. Build project: npm run build
3. Check console.log untuk registration errors
4. PWA hanya bekerja di HTTPS (production)

Issue 7: MobX State tidak Re-renderโ€‹

Masalah: Component lupa dibungkus dengan observer.
Solusi:

import { observer } from 'mobx-react-lite';

const MyComponent = observer(() => {
// logic...
});

Debugging Tipsโ€‹

1. Browser DevToolsโ€‹

- F12 atau Ctrl+Shift+I untuk buka DevTools
- Tab Console untuk JS errors
- Tab Network untuk API calls
- Tab Application > Storage untuk cookies/localStorage
- Tab Sources untuk set breakpoints

2. React DevToolsโ€‹

- Install React DevTools extension
- Inspect components dalam component tree
- View props dan state
- Profile component performance

3. MobX DevToolsโ€‹

- Install MobX DevTools extension
- Monitor store changes
- Time-travel debugging

4. Loggingโ€‹

// Console logging
console.log('Debug:', variable);
console.error('Error:', error);
console.table(data); // Pretty print array/object

// Debugger breakpoint
debugger; // Will pause execution

Dokumentasi & Resourcesโ€‹

Internal Documentationโ€‹

External Resourcesโ€‹

React Ecosystemโ€‹

State Managementโ€‹

UI Frameworkโ€‹

Form & Validationโ€‹

Tools & Buildโ€‹

Utility Librariesโ€‹

PWA & Service Workerโ€‹


Migration & Upgrade Guideโ€‹

Updating Dependenciesโ€‹

# Check outdated packages
npm outdated

# Update specific package
npm update package-name@latest

# Update all packages
npm update

# Security audit
npm audit fix

Support & Contactโ€‹

Tim Developmentโ€‹

  • Frontend Lead: Dana Mulyana
  • BackEnd Lead: Ilham Paqi Andriyansah

Issue Trackingโ€‹

  • GitHub
  • Dokumentasikan issue dengan clear steps to reproduce

Knowledge Baseโ€‹

  • Discussion channel (Teams)

Change Logโ€‹

VersiTanggalChanges
3.0.02025Current version
2.x.x-Previous versions

Dokumen ini dibuat untuk memudahkan handover dan memastikan kontinuitas development.
Untuk update atau pertanyaan, silakan contact tim development.


Last Updated: Desember 2025 Dokumentasi Project PREXITION - PT Global Vita Nutritech Indonesia