npm package: @ignitech/modules
Description: Ignitech Frontend Modules Library - Reusable components for Ignitech websites
Author: Ignitech
Latest version: 1.0.5

# Ignitech Frontend Modules Library

Thư viện modules frontend tái sử dụng cho các website Ignitech.

## Phiên bản 1.0.0

Phiên bản đầu tiên bao gồm 3 modules:
- **Contact Form Module** - Form liên hệ với validation và tích hợp API
- **Payment Method Module** - Xử lý thanh toán, giỏ hàng và chuyển hướng đến cổng thanh toán
- **SEO Module** - Xử lý SEO (meta tags, structured data, social media tags)

## Cài đặt

```bash
npm install @ignitech/modules
# hoặc
yarn add @ignitech/modules
```

## Import Modules

### Import tất cả modules (không khuyến nghị nếu chỉ dùng một vài module)

```tsx
import { ContactForm, PaymentMethod } from '@ignitech/modules';
```

### Import riêng lẻ từng module (khuyến nghị - tree-shaking tốt hơn)

```tsx
// Chỉ import Contact Form module
import { ContactForm, useContactForm } from '@ignitech/modules/contact';

// Chỉ import Payment module
import { PaymentMethod, usePayment } from '@ignitech/modules/payment';

// Chỉ import utilities
import { apiFetch, getApiBaseUrl } from '@ignitech/modules/utils';
```

**Lợi ích của import riêng lẻ:**
- Bundle size nhỏ hơn (chỉ bundle code cần thiết)
- Tree-shaking tốt hơn
- Load time nhanh hơn
- Phù hợp khi website chỉ cần 1-2 module

## Modules

### 1. Contact Form Module

Module xử lý form liên hệ với validation và gửi dữ liệu đến API backend.

#### Sử dụng Component

```tsx
// Cách 1: Import từ subpath (khuyến nghị)
import { ContactForm } from '@ignitech/modules/contact';

// Cách 2: Import từ main entry
import { ContactForm } from '@ignitech/modules';

function App() {
  return (
    <ContactForm
      title="Liên hệ với chúng tôi"
      description="Điền thông tin để chúng tôi có thể liên hệ lại"
      apiBaseUrl="https://api.example.com"
      onSuccess={(data) => console.log('Success:', data)}
      onError={(error) => console.error('Error:', error)}
    />
  );
}
```

#### Sử dụng Hook

```tsx
// Cách 1: Import từ subpath (khuyến nghị)
import { useContactForm } from '@ignitech/modules/contact';

// Cách 2: Import từ main entry
import { useContactForm } from '@ignitech/modules';

function CustomContactForm() {
  const { submit, isLoading, error, success } = useContactForm({
    apiBaseUrl: 'https://api.example.com',
    onSuccess: (data) => console.log('Success:', data),
  });

  const handleSubmit = async () => {
    await submit({
      name: 'Nguyễn Văn A',
      phone: '0912345678',
      email: 'example@email.com',
      content: 'Nội dung tin nhắn',
    });
  };

  return (
    <div>
      {/* Your custom form UI */}
      <button onClick={handleSubmit} disabled={isLoading}>
        {isLoading ? 'Đang gửi...' : 'Gửi'}
      </button>
      {error && <p>{error}</p>}
      {success && <p>Gửi thành công!</p>}
    </div>
  );
}
```

#### Props

| Prop | Type | Default | Mô tả |
|------|------|---------|-------|
| `title` | `string` | `"Liên hệ với chúng tôi"` | Tiêu đề form |
| `description` | `string` | - | Mô tả form |
| `submitButtonText` | `string` | `"Gửi tin nhắn"` | Text nút submit |
| `apiBaseUrl` | `string` | - | URL base của API backend |
| `onSuccess` | `(data: ContactFormData) => void` | - | Callback khi gửi thành công |
| `onError` | `(error: string) => void` | - | Callback khi có lỗi |
| `showLabels` | `boolean` | `true` | Hiển thị labels cho các input |
| `placeholder` | `object` | - | Custom placeholder cho các field |
| `className` | `string` | - | CSS class tùy chỉnh |

Xem hướng dẫn chi tiết: [Contact Module README](./src/contact/README.md)

### 2. Payment Method Module

Module xử lý tạo đơn hàng và chuyển hướng đến cổng thanh toán.

#### Sử dụng Component

```tsx
// Cách 1: Import từ subpath (khuyến nghị)
import { PaymentMethod } from '@ignitech/modules/payment';

// Cách 2: Import từ main entry
import { PaymentMethod } from '@ignitech/modules';

function App() {
  return (
    <PaymentMethod
      title="Thanh toán đơn hàng"
      amount={100000}
      availableMethods={['momo', 'zalopay', 'vnpay']}
      apiBaseUrl="https://api.example.com"
      onSuccess={(orderId) => console.log('Order created:', orderId)}
      autoRedirect={true}
    />
  );
}
```

#### Sử dụng Hook

```tsx
// Cách 1: Import từ subpath (khuyến nghị)
import { usePayment } from '@ignitech/modules/payment';

// Cách 2: Import từ main entry
import { usePayment } from '@ignitech/modules';

function CustomPayment() {
  const { createOrder, isLoading, error, orderData } = usePayment({
    apiBaseUrl: 'https://api.example.com',
    autoRedirect: true,
  });

  const handlePayment = async () => {
    await createOrder({
      amount: 100000,
      method: 'momo',
    });
  };

  return (
    <div>
      {/* Your custom payment UI */}
      <button onClick={handlePayment} disabled={isLoading}>
        {isLoading ? 'Đang xử lý...' : 'Thanh toán'}
      </button>
      {error && <p>{error}</p>}
    </div>
  );
}
```

#### Props

| Prop | Type | Default | Mô tả |
|------|------|---------|-------|
| `title` | `string` | `"Thanh toán"` | Tiêu đề form |
| `description` | `string` | - | Mô tả form |
| `amount` | `number` | - | Số tiền thanh toán |
| `defaultMethod` | `PaymentMethod` | `"momo"` | Phương thức thanh toán mặc định |
| `availableMethods` | `PaymentMethod[]` | `['momo', 'zalopay', 'vnpay']` | Danh sách phương thức thanh toán |
| `submitButtonText` | `string` | `"Thanh toán"` | Text nút submit |
| `apiBaseUrl` | `string` | - | URL base của API backend |
| `onSuccess` | `(orderId: string) => void` | - | Callback khi tạo đơn thành công |
| `onError` | `(error: string) => void` | - | Callback khi có lỗi |
| `autoRedirect` | `boolean` | `true` | Tự động chuyển hướng đến cổng thanh toán |
| `showAmountInput` | `boolean` | `false` | Hiển thị input để nhập số tiền |
| `className` | `string` | - | CSS class tùy chỉnh |

Xem hướng dẫn chi tiết: [Payment Module README](./src/payment/README.md)

### 3. SEO Module

Module xử lý SEO (Search Engine Optimization) cho website, bao gồm meta tags, structured data, và social media tags.

#### Sử dụng Component

```tsx
// Cách 1: Import từ subpath (khuyến nghị)
import { MetaTags, useSEO, StructuredData } from '@ignitech/modules/seo';

// Cách 2: Import từ main entry
import { MetaTags, useSEO } from '@ignitech/modules';

function ContactPage() {
  const { seoData } = useSEO({
    title: 'Liên hệ với chúng tôi',
    description: 'Điền form để liên hệ với chúng tôi',
    keywords: ['liên hệ', 'contact'],
    siteName: 'Tên Website',
    siteUrl: 'https://example.com',
  });

  return (
    <>
      <MetaTags seo={seoData} />
      <StructuredData
        type="ContactPage"
        data={{
          name: 'Tên công ty',
          url: 'https://example.com/contact',
        }}
      />
      {/* Your page content */}
    </>
  );
}
```

#### Sử dụng Hook

```tsx
import { useSEO } from '@ignitech/modules/seo';

function Page() {
  const {
    seoData,
    fullTitle,
    validation,
  } = useSEO({
    title: 'Page Title',
    description: 'Page description',
    siteName: 'Site Name',
  });

  // Use seoData to update document head
  useEffect(() => {
    if (seoData.title) {
      document.title = seoData.title;
    }
  }, [seoData]);

  return <div>{/* Your content */}</div>;
}
```

#### Props

| Prop | Type | Default | Mô tả |
|------|------|---------|-------|
| `title` | `string` | - | Tiêu đề trang |
| `description` | `string` | - | Mô tả trang |
| `keywords` | `string \| string[]` | - | Keywords |
| `siteName` | `string` | - | Tên website |
| `siteUrl` | `string` | - | URL website |
| `ogImage` | `string` | - | Open Graph image |
| `canonical` | `string` | - | Canonical URL |

Xem hướng dẫn chi tiết: [SEO Module README](./src/seo/README.md)

## Kiến trúc

Mỗi module được tổ chức theo 3 lớp:

1. **Service Layer** - Xử lý API communication
2. **Hook Layer** - Quản lý state và logic
3. **Component Layer** - UI components

```
src/
  contact/
    ContactForm.tsx       # Component
    useContactForm.ts     # Hook
    contact.service.ts    # Service
    index.ts
  payment/
    PaymentMethod.tsx     # Component
    usePayment.ts         # Hook
    payment.service.ts   # Service
    index.ts
  seo/
    components/           # SEO Components
    hooks/               # SEO Hooks
    utils/               # SEO Utilities
    index.ts
  utils/
    types.ts
    fetch.ts
    validators.ts
```

## Cấu hình API

Module tự động lấy API base URL theo thứ tự ưu tiên:

1. Prop `apiBaseUrl` (nếu được truyền vào)
2. `window.IGNITECH_API_BASE_URL` (global variable)
3. `process.env.REACT_APP_API_BASE_URL` hoặc `process.env.NEXT_PUBLIC_API_BASE_URL`

### Ví dụ cấu hình

```tsx
// Option 1: Truyền qua props
<ContactForm apiBaseUrl="https://api.example.com" />

// Option 2: Set global variable
window.IGNITECH_API_BASE_URL = 'https://api.example.com';

// Option 3: Environment variable
// .env
REACT_APP_API_BASE_URL=https://api.example.com
```

## API Endpoints

### Contact Form

- **POST** `/api/contact` - Gửi form liên hệ

Request body:
```json
{
  "name": "Nguyễn Văn A",
  "phone": "0912345678",
  "email": "example@email.com",
  "content": "Nội dung tin nhắn"
}
```

### Payment

- **POST** `/api/payment/orders` - Tạo đơn hàng

Request body:
```json
{
  "amount": 100000,
  "method": "momo",
  "description": "Mô tả đơn hàng"
}
```

Response:
```json
{
  "success": true,
  "data": {
    "orderId": "order_123",
    "paymentUrl": "https://payment-gateway.com/...",
    "qrCode": "data:image/png;base64,...",
    "amount": 100000,
    "method": "momo",
    "status": "pending"
  }
}
```

- **GET** `/api/payment/orders/:orderId/status` - Kiểm tra trạng thái thanh toán

## Styling

Components sử dụng **CSS Variables (CSS Custom Properties)** để cho phép website tùy biến hoàn toàn màu sắc, font chữ và styling.

### Customize Colors và Font

Tạo file CSS để override CSS variables:

```css
/* styles/ignitech-theme.css */
:root {
  /* Brand colors */
  --ignitech-primary: #ff6b6b;
  --ignitech-primary-hover: #ee5a5a;
  --ignitech-error: #c92a2a;
  --ignitech-success: #51cf66;
  
  /* Typography */
  --ignitech-font-family: 'Inter', sans-serif;
  --ignitech-font-size-base: 1rem;
  
  /* Spacing & Border */
  --ignitech-border-radius: 0.5rem;
}
```

Import vào website:

```tsx
// Next.js
import './styles/ignitech-theme.css';

// Hoặc import CSS variables mặc định (optional)
import '@ignitech/modules/styles/variables.css';
```

Xem hướng dẫn chi tiết: [STYLING.md](./STYLING.md)

### Sử dụng với className

Bạn cũng có thể thêm custom CSS classes:

```tsx
<ContactForm
  className="max-w-md mx-auto p-6 bg-white rounded-lg shadow-lg"
/>
```

## Tích hợp vào Website

Xem hướng dẫn tích hợp: [INTEGRATION.md](./INTEGRATION.md)

## Next.js Support

Modules hoàn toàn tương thích với **Next.js** (cả Pages Router và App Router).

Xem hướng dẫn chi tiết: [NEXTJS.md](./NEXTJS.md)

### Quick Start với Next.js

```tsx
// app/contact/page.tsx
'use client';

import { ContactForm } from '@ignitech/modules/contact';

export default function ContactPage() {
  return (
    <ContactForm
      apiBaseUrl={process.env.NEXT_PUBLIC_API_BASE_URL}
      onSuccess={(data) => console.log('Success:', data)}
    />
  );
}
```

## Validation

Module sử dụng **Zod** để validate dữ liệu:

- **Email**: Format email hợp lệ
- **Phone**: 10-11 chữ số hoặc format +84
- **Name**: 2-100 ký tự
- **Content**: 10-1000 ký tự
- **Amount**: Số dương

## Build

```bash
npm run build
```

Output sẽ được tạo trong thư mục `dist/` với:
- CommonJS (`dist/index.js`)
- ES Modules (`dist/index.esm.js`)
- TypeScript definitions (`dist/index.d.ts`)

## Development

```bash
npm run dev  # Watch mode
npm run type-check  # Type checking
npm run lint  # Linting
```

## License

MIT

## Đóng góp

Module này được thiết kế để dễ dàng mở rộng. Khi thêm module mới:

1. Tạo thư mục module trong `src/`
2. Tổ chức theo cấu trúc: Service → Hook → Component
3. Export từ `src/index.ts`
4. Cập nhật README

## Best Practices

### Khi nào nên import từ subpath?

**Nên dùng subpath import** khi:
- Website chỉ sử dụng 1-2 module
- Muốn tối ưu bundle size
- Quan tâm đến performance

```tsx
// Tốt - chỉ bundle Contact module
import { ContactForm } from '@ignitech/modules/contact';
```

**Có thể dùng main import** khi:
- Website sử dụng nhiều module (3+)
- Không quan tâm bundle size
- Muốn code ngắn gọn hơn

```tsx
// OK nhưng bundle lớn hơn
import { ContactForm, PaymentMethod, BlogModule } from '@ignitech/modules';
```

### Thêm module mới

Khi thêm module mới (ví dụ: Blog), cần:

1. Tạo module trong `src/blog/`
2. Export từ `src/blog/index.ts`
3. Thêm vào `src/index.ts` (optional - để hỗ trợ main import)
4. Thêm subpath export vào `package.json`:
```json
"./blog": {
  "types": "./dist/blog/index.d.ts",
  "import": "./dist/blog/index.esm.js",
  "require": "./dist/blog/index.js"
}
```
5. Thêm entry point vào `tsup.config.ts`

## Roadmap

- [ ] Blog Module
- [ ] Gallery Module
- [ ] FAQ Module
- [ ] Testimonials Module
- [ ] Widget Engine
- [ ] Template System
- [ ] UI Builder