# Conventions Code And Development Guide
Hướng dẫn quy tắc và quy ước phát triển cho dự án.
## 1. Naming Conventions
### Files & Folders
#### Component Files
- **PascalCase** cho tên file component
- **Folder structure**: Mỗi component 1 folder riêng
- Bắt buộc có `[Link]` để export
```
components/
├── atoms/
│ └── AppButton/
│ ├── [Link]
│ ├── [Link]
│ ├── [Link] (optional)
│ └── [Link]
├── molecules/
└── organisms/
```
#### Utility Files
- **Hooks**: `use${Name}.ts`
- `[Link]`, `[Link]`, `[Link]`
- **Services**: `${name}[Link]` hoặc folder structure
- `[Link]`, `[Link]`
- **Utils**: `${name}.ts` hoặc `${name}.[Link]`
- `[Link]`, `[Link]`, `[Link]`
- **Types**: `${name}.[Link]`
- `[Link]`, `[Link]`
- **Constants**: `${name}.ts` (UPPER_SNAKE_CASE variables)
- `constants/[Link]`, `constants/[Link]`
### Variables & Functions
#### Variables
```typescript
const userName = 'John'; // camelCase
const MAX_RETRIES = 3; // UPPER_SNAKE_CASE for constants
const isLoading = false; // is/has/can/should prefix for boolean
const hasError = true;
const canDelete = false;
```
#### Functions
```typescript
function getUserData() {} // Regular: camelCase
const handleClick = () => {} // Event handlers: on* or handle*
const onClick = () => {}
const fetchUserData = async () => {} // Async: fetch*, load*, get*
const loadUsersList = async () => {}
```
#### React Components & Props
```typescript
export const AppButton = () => {} // Component: PascalCase
export const useLoginLogic = () => {} // Hook: use${Name}
interface AppButtonProps { // Props: ${Component}Props
children: string;
onClick?: () => void;
}
```
### Git Branches
**Format**: `<type>/<TICKET-xxx>-<description>`
```bash
# Examples
feat/TICKET-101-add-login-form
fix/TICKET-102-fix-modal-styling
refactor/TICKET-103-extract-hooks
docs/TICKET-104-update-readme
chore/TICKET-105-update-dependencies
# ❌ AVOID
feature/add-login-form # No ticket ID
FEAT/TICKET-101-Add-Form # Uppercase
feat/TICKET_101_add_form # Underscore instead of dash
```
**Types**: `feat`, `fix`, `refactor`, `docs`, `style`, `perf`, `test`, `chore`,
`ci`
---
## 2. Code Rules
### TypeScript & Type Safety
**Luôn sử dụng explicit types:**
```typescript
// ✅ GOOD
const userName: string = 'John';
const users: User[] = [];
const handleClick = (event: [Link]<HTMLButtonElement>) => {}
// ❌ AVOID
const userName = 'John';
const users = [];
const handleClick = (event: any) => {}
```
**Enable strict mode** trong `[Link]`:
```json
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true
}
}
```
### React Components
#### Function Component Pattern
```typescript
import { FC, ReactNode } from 'react';
interface AppButtonProps {
children: ReactNode;
onClick?: () => void;
disabled?: boolean;
}
export const AppButton: FC<AppButtonProps> = ({
children,
onClick,
disabled = false,
}) => {
return (
<button onClick={onClick} disabled={disabled}>
{children}
</button>
);
};
[Link] = 'AppButton';
```
#### Custom Hooks
```typescript
export const useLoginLogic = () => {
const [form] = [Link]();
const { error: notifyError } = useAppNotification();
const navigate = useNavigate();
const handleSubmit = useCallback((values: any) => {
// Handle submit
}, [form, notifyError, navigate]);
return { form, handleSubmit, notifyError };
};
```
### Code Organization
#### Import Order
```typescript
// 1. External libraries
import React, { FC, useCallback } from 'react';
import { Button } from 'antd';
// 2. Internal imports
import { AppButton } from '@components/atoms';
import { useLoginLogic } from '@hooks/useLoginLogic';
import { ROUTE_PATH } from '@constants/app';
import { User } from '@types/[Link]';
// 3. Styles
import styles from './[Link]';
```
#### Component File Structure
```typescript
// 1. Imports
import { FC, useCallback } from 'react';
import { Button } from 'antd';
// 2. Types/Interfaces
interface MyComponentProps {
title: string;
onClick?: () => void;
}
// 3. Component
export const MyComponent: FC<MyComponentProps> = ({ title, onClick }) => {
return <Button onClick={onClick}>{title}</Button>;
};
// 4. Display Name (for debugging)
[Link] = 'MyComponent';
```
### Styling
**SCSS Modules** (recommended):
```typescript
import styles from './[Link]';
export const AppButton = () => {
return <button className={[Link]}>Click</button>;
};
```
**Tailwind CSS**:
```typescript
export const AppButton = () => {
return <button className="px-4 py-2 bg-blue-500 text-white
rounded">Click</button>;
};
```
**Hybrid** (SCSS + Tailwind):
```typescript
import clsx from 'clsx';
import styles from './[Link]';
export const AppButton = ({ variant = 'primary' }) => {
return (
<button
className={clsx(
[Link],
{ [[Link]]: variant === 'primary' }
)}
>
Click
</button>
);
};
```
### Error Handling
```typescript
const handleSubmit = async (values: any) => {
try {
const response = await [Link](values);
navigate(ROUTE_PATH.DASHBOARD);
} catch (error) {
if (error instanceof APIErrorResponse) {
notifyError([Link]);
} else {
notifyError('An unexpected error occurred');
}
}
};
```
### Comments & Documentation
**JSDoc Format:**
```typescript
/**
* Formats a date to readable format
* @param date - The date to format
* @param format - Format pattern (default: 'YYYY-MM-DD')
* @returns Formatted date string
*/
export const formatDate = (date: Date, format = 'YYYY-MM-DD'): string => {
// Implementation
};
```
**Inline Comments** - Explain WHY, not WHAT:
```typescript
// Timeout needed to ensure animation completes before unmounting
setTimeout(() => {
setIsVisible(false);
}, 300);
```
### Linting
Dự án sử dụng **ESLint** với TypeScript support:
```bash
npm run lint # Check for errors
npm run lint:fix # Auto-fix errors
```
---
## 3. Git Workflow
### Setup & Checkout Branch
**Luôn checkout từ develop:**
```bash
# 1. Switch to develop & update
git checkout develop
git pull origin develop
# 2. Create & checkout new branch
git checkout -b feat/TICKET-101-add-login-form
# Hoặc tạo rồi checkout
git branch feat/TICKET-101-add-login-form
git checkout feat/TICKET-101-add-login-form
# 3. Verify
git branch # Show local branches
git branch -a # Show all branches
```
### Commit Message
**Format** - Conventional Commits:
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
**Examples:**
```
feat(auth): add login form validation
- Add email format validation
- Add password strength check
- Add error message display
Closes #123
```
**Best Practices:**
- ✅ Commit thường xuyên (1 feature = 1 commit)
- ✅ Meaningful messages với ticket reference
- ✅ Atomic commits (1 logic change per commit)
- ❌ Avoid generic messages: "fix", "update", "changes"
- ❌ Avoid large commits với nhiều unrelated changes
### Push & Pull Request
```bash
# 1. Push branch to remote
git push -u origin feat/TICKET-123-add-user-dashboard
# 2. Create Pull Request
# - Source: feat/TICKET-123-add-user-dashboard
# - Target: develop
# - Add description & link ticket
# - Wait for code review & tests to pass
# 3. After merge, cleanup
git branch -d feat/TICKET-123-add-user-dashboard # Delete local
git push origin --delete feat/TICKET-123-add-user-dashboard # Delete remote
```
### Git Hooks (Husky)
Dự án sử dụng **Husky** để tự động validate commits:
```bash
# Setup git hooks (chạy 1 lần)
npm run prepare
# Hooks tự chạy trước khi commit:
# - pre-commit: Lint & format code
# - commit-msg: Validate commit message format
```
---
## 4. Setup & Development
### Prerequisites
- **[Link]**: >= 18.x (LTS recommended)
- **Yarn**: >= 1.22.0 hoặc **npm**: >= 9.0.0
- **Git**: >= 2.40.0
### Initial Setup
```bash
# Clone repository
git clone <repository-url>
cd medix-hitowa-doctor-web
# Install dependencies
yarn install
# Setup git hooks
npm run prepare
```
### Environment Configuration
Tạo file `app/.[Link]`:
```bash
VITE_API_BASE_URL=[Link]
```
### Development Commands
```bash
# Start development server (default client)
yarn dev
# Development server cho client cụ thể
yarn dev hitowa
yarn dev medix
# TypeScript checking
yarn typecheck
# Linting
yarn lint # Check for errors
yarn lint:fix # Auto-fix errors
# Preview production build
yarn preview
```
**Development Server**: [Link]
### Building
```bash
# Build default client
yarn build
# Build specific client
yarn build hitowa
yarn build medix
# Build all clients
yarn build
# Output: customize/[client]/dist/
```
### Project Structure
```
medix-hitowa-doctor-web/
├── app/src/
│ ├── components/ # React components
│ │ ├── atoms/ # Basic components
│ │ ├── molecules/ # Composed components
│ │ ├── organisms/ # Complex components
│ │ └── templates/ # Page templates
│ ├── constants/ # Constants & configuration
│ ├── hooks/ # Custom React hooks
│ ├── pages/ # Page components
│ ├── router/ # Routing configuration
│ ├── services/ # API services
│ ├── store/ # Redux store
│ ├── types/ # TypeScript types
│ ├── utils/ # Utility functions
│ └── scss/ # Global styles
│
├── customize/ # Multi-client customization
│ ├── default/ # Default client
│ ├── hitowa/ # Hitowa client
│ └── medix/ # Medix client
│
└── scripts/ # Build & dev scripts
```
### Multi-Client Structure
Mỗi client có cấu trúc tương tự:
```
customize/hitowa/
├── [Link] # Client entry point
├── [Link] # Client metadata
├── public/fonts/ # Client-specific fonts
└── src/
├── components/ # Custom components
└── pages/ # Custom pages
```
**Select Client**: Set `VITE_CLIENT` environment variable
### Path Aliases
Dự án sử dụng path aliases (định nghĩa trong `[Link]`):
```typescript
@/* → app/src/*
@components/* → app/src/components/*
@hooks/* → app/src/hooks/*
@constants/* → app/src/constants/*
@types/* → app/src/types/*
@utils/* → app/src/utils/*
```
**Usage:**
```typescript
import { AppButton } from '@components/atoms/AppButton';
import { useLoginLogic } from '@hooks/useLoginLogic';
import { ROUTE_PATH } from '@constants/app';
```
---
## 5. Project Structure
```
medix-hitowa-doctor-web/
├── app/src/
│ ├── components/ # React components
│ │ ├── atoms/ # Basic components
│ │ ├── molecules/ # Composed components
│ │ ├── organisms/ # Complex components
│ │ └── templates/ # Page templates
│ ├── constants/ # Constants & configuration
│ ├── hooks/ # Custom React hooks
│ ├── pages/ # Page components
│ ├── router/ # Routing configuration
│ ├── services/ # API services
│ ├── store/ # Redux store
│ ├── types/ # TypeScript types
│ ├── utils/ # Utility functions
│ └── scss/ # Global styles
│
├── customize/ # Multi-client customization
│ ├── default/
│ ├── hitowa/
│ └── medix/
│
└── scripts/ # Build & dev scripts
```
---
## 6. Troubleshooting
### Node Modules Issues
```bash
# Clear and reinstall
rm -rf node_modules [Link]
yarn install
# Or with npm
rm -rf node_modules [Link]
npm install
```
### Port Already in Use
```bash
# Dev server uses port 5173
# Change in [Link] if needed:
# server: { port: 3000 }
```
### TypeScript/Cache Issues
```bash
# Clear Vite cache
rm -rf app/.vite
# Full clean
yarn clean
npm install
yarn dev
```
### Common Errors
| Error | Solution |
|-------|----------|
| `VITE_CLIENT not found` | Check customize folder or use 'default' |
| `Cannot find module '@/*'` | Verify [Link] paths |
| `Lint errors block commit` | Run `yarn lint:fix` before commit |
| `Port 5173 in use` | Kill process or change port |
---
## 7. Best Practices
### Code Quality ✅
- Use TypeScript strictly (no `any`)
- Commit frequently & meaningfully
- Reference tickets in commits
- Use path aliases (not relative imports)
- Code review before merging
- Run lint before committing
### Git Workflow ✅
- Always checkout from `develop`
- Use proper branch naming
- Create PR from feature branch to develop
- Squash commits if needed
- Delete branch after merge
### DO NOT ❌
- Push directly to develop
- Use generic commit messages
- Force push without discussion
- Commit large files or secrets
- Ignore linting errors
- Use relative imports (../../)
---
## 8. Additional Resources
- [TypeScript Documentation]([Link]
- [React Documentation]([Link]
- [Vite Documentation]([Link]
- [Tailwind CSS]([Link]
- [Ant Design]([Link]
- [Conventional Commits]([Link]
---
**Last Updated**: January 7, 2026