import {Meta} from '@storybook/addon-docs/blocks'

<Meta title='@dxtmisha/vi/functional/Classes/DesignAbstract - Lớp cơ sở Constructor'/>

# Lớp DesignAbstract

Một lớp cơ sở trừu tượng được thiết kế để quản lý các thuộc tính constructor và các thay đổi trạng thái. Nó cung cấp một cách có cấu trúc để xử lý các thuộc tính đầu vào, theo dõi thay đổi và thực thi các hàm callback khi cập nhật dữ liệu.

## Các tính năng chính

- **Quản lý thuộc tính** — xử lý có cấu trúc dữ liệu đầu vào (`props`) và lưu trữ sự kiện (`event`).
- **Theo dõi thay đổi** — tích hợp với `DesignChanged` để giám sát và cập nhật hiệu quả các thay đổi thuộc tính.
- **Quản lý vòng đời** — tự động thực thi `makeCallback` và `initEvent` trong quá trình cập nhật dữ liệu.

## Khởi tạo

`DesignAbstract` là một lớp cơ sở trừu tượng và không thể được khởi tạo trực tiếp. Nó phục vụ như một nền tảng để tạo ra các lớp thiết kế quản lý trạng thái dựa trên các thuộc tính đầu vào (`props`).

### Ràng buộc Generic (Generic Constraints)

Lớp này sử dụng hai loại generic để đảm bảo kiểu dữ liệu nghiêm ngặt:
- `T extends Record<string, any>` — Kiểu cho các thuộc tính đầu vào (`props`). Xác định cấu trúc dữ liệu được truyền vào hàm khởi tạo và được sử dụng để theo dõi các thay đổi.
- `C extends Record<string, any>` — Kiểu cho dữ liệu đầu ra hoặc trạng thái (`event`). Xác định cấu trúc của đối tượng được hình thành trong `initEvent` và được truyền vào các hàm gọi lại.

**Tham số hàm khởi tạo:**
- `props: T` — một đối tượng chứa dữ liệu khởi tạo ban đầu.
- `callback?: (event: C) => void` — một hàm gọi lại tùy chọn được thực thi sau mỗi lần cập nhật dữ liệu.
- `changed?: string[]` — danh sách các tên thuộc tính từ `props` để theo dõi. Nếu không được chỉ định, tất cả các khóa của `props` sẽ được theo dõi.

**Phương thức bắt buộc phải triển khai:**
- `protected abstract initEvent(): void` — một phương thức mô tả logic để chuyển đổi hoặc lọc các `props` thành một đối tượng trạng thái `event`.

```typescript
import { DesignAbstract } from '@dxtmisha/functional'

// 1. Xác định cấu trúc
interface MyProps { label: string; value: number }
interface MyState { display: string }

// 2. Triển khai một lớp cụ thể
class MyDesign extends DesignAbstract<MyProps, MyState> {
  protected initEvent(): void {
    this.event.display = `${this.props.label}: ${this.props.value}`
  }
}

// 3. Tạo một thực thể
const design = new MyDesign(
  { label: 'Counter', value: 10 }, 
  (state) => console.log('Trạng thái mới:', state.display)
)
```

## Các phương thức quản lý dữ liệu

### `make`

Bắt đầu quy trình cập nhật callback. Gọi `makeCallback` và trả về instance để thực hiện chuỗi phương thức (method chaining).

**Tham số:**
- `compelled?: boolean` — nếu là `true`, sẽ ép buộc cập nhật dữ liệu bất kể có thay đổi hay không.

**Trả về:** `this`

### `makeCallback`

Logic thực thi chính để cập nhật trạng thái. Kiểm tra các thay đổi hoặc yêu cầu cập nhật bắt buộc, sau đó khởi tạo sự kiện và kích hoạt các hàm callback.

**Tham số:**
- `compelled: boolean` — ép buộc cập nhật dữ liệu. Mặc định: `false`.

**Trả về:** `void`

## Các phương thức được bảo vệ (cho lớp kế thừa)

### `is`

Kiểm tra xem một giá trị có tồn tại trong `props` theo tên hay không.

**Tham số:**
- `name: keyof T` — tên thuộc tính.

**Trả về:** `boolean`

### `isChanged`

Kiểm tra xem giá trị thuộc tính có bị thay đổi hay không. Được sử dụng để ngăn chặn các tính toán dư thừa.

**Tham số:**
- `name: keyof C` — tên thuộc tính trong sự kiện.
- `nameProp?: keyof T | (keyof T)[]` — tên thuộc tính hoặc danh sách tên thuộc tính trong `props` mà giá trị này phụ thuộc vào. Nếu không được chỉ định, `name` sẽ được sử dụng.

**Trả về:** `boolean`

### `makeCallbackItem`

Thực thi hàm callback đã được truyền vào constructor.

**Trả về:** `void`

### `initEvent` (trừu tượng)

Phương thức trừu tượng phải được triển khai trong lớp con. Nó sẽ gán dữ liệu cho `this.event` dựa trên `this.props`.

**Trả về:** `void`
