---
name: ui-component
description: Sử dụng khi tạo mới hoặc sửa đổi React Components trong thư mục frontend/src/components/ hoặc frontend/src/pages/.
---

# Skill: UI Component Engineer

## Phạm vi áp dụng
Skill này áp dụng cho mọi thay đổi trong:
- `frontend/src/components/` — Shared components (Navbar, Sidebar, DbCard, ConnectionPanel, ConnectedList, SemanticLayer...)
- `frontend/src/pages/` — Page components (ChatPage, DataSourcesPage, LoginPage, RegisterPage, SemanticLayerPage, SettingsPage, LandingPage)

## 1. Tech Stack

| Package | Phiên bản | Mục đích |
|---------|-----------|---------|
| React | 19 | UI framework |
| TypeScript | 5.x | Type safety |
| Vite | 7 | Dev server / bundler |
| lucide-react | latest | Icon library duy nhất |
| CSS Modules | built-in | Scoped styling |

**Tuyệt đối không dùng:** Tailwind CSS, styled-components, emotion, inline styles.

## 2. Cấu trúc File Component

Mỗi component **phải** có cấu trúc thư mục riêng:
```
ComponentName/
├── ComponentName.tsx         ← Logic + JSX
├── ComponentName.module.css  ← Styles (CSS Modules)
└── index.ts                  ← Re-export (optional nhưng nên có)
```

**`index.ts` mẫu:**
```ts
export { default } from './ComponentName';
// hoặc nếu có named export:
export { ComponentName } from './ComponentName';
```

## 3. Design Tokens (CSS Variables)

Tất cả giá trị màu sắc được lấy từ `src/index.css` — luôn dùng CSS variables, không hardcode giá trị:

| Token | Giá trị | Dùng khi |
|-------|---------|---------|
| `var(--bg-base)` | `#0F172A` | Nền trang chính |
| `var(--bg-card)` | `#1E293B` | Nền card, panel, container |
| `var(--bg-panel)` | `#161E2E` | Nền slide-in panel (ConnectionPanel) |
| `var(--bg-input)` | `#0F172A` | Nền input field |
| `var(--border)` | `#334155` | Viền mặc định |
| `var(--purple)` | `#7C3AED` | Màu accent chính — nút primary, highlight |
| `var(--purple-lt)` | `#A855F7` | Hover state, gradient accent |
| `var(--green)` | `#10B981` | Trạng thái connected/success |
| `var(--red)` | `#EF4444` | Trạng thái error/danger |
| `var(--text)` | `#F1F5F9` | Text chính |
| `var(--text-muted)` | `#94A3B8` | Text phụ, placeholder, label |
| `var(--radius)` | `12px` | Border radius mặc định |

## 4. Component Boilerplate

### Functional Component chuẩn:
```tsx
import styles from './ComponentName.module.css';
import { SomeIcon } from 'lucide-react';

interface ComponentNameProps {
  // Khai báo props rõ ràng với TypeScript
  title: string;
  onAction: () => void;
  isActive?: boolean;
}

export default function ComponentName({ title, onAction, isActive = false }: ComponentNameProps) {
  return (
    <div className={`${styles.container} ${isActive ? styles.active : ''}`}>
      <SomeIcon size={18} />
      <span>{title}</span>
      <button className={styles.actionBtn} onClick={onAction}>
        Click
      </button>
    </div>
  );
}
```

### CSS Module chuẩn:
```css
.container {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1rem;
}

.container.active {
  border-color: var(--purple);
}

.actionBtn {
  background: var(--purple);
  color: var(--text);
  border: none;
  border-radius: 8px;
  padding: 0.5rem 1rem;
  cursor: pointer;
  transition: background 0.2s;
}

.actionBtn:hover {
  background: var(--purple-lt);
}
```

## 5. Hooks và Context

### `useAuth()` — Auth context:
```tsx
import { useAuth } from '@/hooks/useAuth';

const { user, isAuthenticated, isLoading, login, logout, getValidToken } = useAuth();
```
- `user`: `{ id, username, email, role }` hoặc `null`
- `getValidToken()`: Trả về access token hợp lệ (auto-refresh nếu gần hết hạn). **Luôn dùng cái này** khi gọi API cần auth.

### `useSettings()` — Settings context:
```tsx
import { useSettings } from '@/contexts/SettingsContext';

const { language, theme, setLanguage, setTheme } = useSettings();
```

### `useTranslation()` — i18n:
```tsx
import { useTranslation } from 'react-i18next';

const { t } = useTranslation();
// Dùng: t('key.subkey')
```

## 6. Gọi API từ Component

**Luôn dùng các service file có sẵn**, không fetch trực tiếp trong component:

```ts
// Auth
import { authApi } from '@/services/authApi';
// Connections
import { connectionApi } from '@/services/connectionApi';
// Chat
import { chatApi } from '@/services/chatApi';
```

**Pattern gọi API với auth:**
```tsx
const { getValidToken } = useAuth();

async function fetchData() {
  const token = await getValidToken();
  const result = await connectionApi.getAll(token);
  setConnections(result);
}

useEffect(() => {
  fetchData();
}, []);
```

## 7. Danh sách Components Hiện có

### `src/components/`
| Component | Mô tả |
|-----------|-------|
| `Navbar/` | Top navigation bar, hiện user info + logout |
| `Sidebar/` | Left sidebar menu (Menu + Hệ thống groups) |
| `DbCard/` | Card chọn DB engine (PostgreSQL, MySQL...) |
| `ConnectionPanel/` | Slide-in drawer cấu hình kết nối |
| `ConnectedList/` | Danh sách kết nối đang active |
| `SemanticLayer/` | React Flow diagram cho semantic layer |
| `ProtectedRoute/` | Route guard (auth check) |

### `src/pages/`
| Page | Route | Mô tả |
|------|-------|-------|
| `LandingPage/` | `/landing` | Landing page marketing |
| `LoginPage/` | auth gate | Đăng nhập |
| `RegisterPage/` | auth gate | Đăng ký tài khoản |
| `DataSourcesPage/` | main | Quản lý data source |
| `SemanticLayerPage/` | main | Chỉnh sửa semantic layer |
| `ChatPage/` | main | Chat với AI agent |
| `SettingsPage/` | main | Cài đặt theme/ngôn ngữ |

## 8. Icon Usage

Luôn import từ `lucide-react`. Size mặc định cho icon trong UI:
- Nút/action: `size={16}` hoặc `size={18}`  
- Header/heading: `size={20}` hoặc `size={24}`
- Decorative: `size={32}` hoặc `size={48}`

```tsx
import { Database, Settings, LogOut, ChevronRight } from 'lucide-react';
```

## 9. Sidebar Navigation Items

Sidebar hiện có menu structure (dùng `activePage` prop để highlight):
- **Menu group:** `datasources`, `semantic`, `chat`
- **Hệ thống group:** `settings`, `account`

Khi thêm page mới → cập nhật cả:
1. `Sidebar/Sidebar.tsx` — thêm menu item
2. `App.tsx` — thêm vào `PAGE_MAP`

## 10. Responsive & Animation

- Luôn thêm `transition` cho hover effects (0.2s ease)
- Slide-in panels dùng `translateX` animation
- Status indicators (connected/error) dùng `@keyframes pulse`
- Không dùng `!important` trong CSS — nếu cần override, tăng specificity bằng cách nest class