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

<Meta title='@dxtmisha/en/functional-basic/Classes/Formatters - Data Formatting Utility'/>

# Formatters Class

A specialized class for formatting data lists based on a provided configuration. It serves as a bridge between raw data and localized, human-readable strings, utilizing the `GeoIntl` singleton for consistent formatting across different locales.

## Key Features

- **Declarative Configuration** — Define formatting rules once and apply them to the entire dataset.
- **Support for Multiple Types** — Built-in support for currencies, dates, names, numbers, plurals, and units.
- **Custom Transformations** — The ability to provide your own functions for unique formatting needs.
- **Typing** — Full TypeScript support for items, parameters, and resulting formatted lists.
- **Automatic Key Generation** — Automatically adds formatted values to items with the `Format` suffix (e.g., `price` becomes `priceFormat`).

## Initialization

To initialize the object, call the constructor `Formatters(options, list)`.

### Generic Constraints

- `Options extends FormattersOptionsList` — type of formatting parameters.
- `List extends FormattersListProp` — type of input data (array or single item).
- `Item extends FormattersItemProp<List>` — type of a single item in the list.

**Parameters:**
- `options: Options` — formatting parameters for each column/property.
- `list?: List` — initial data list for formatting.

```typescript
import { Formatters } from '@dxtmisha/functional-basic'

// 1. Defining formatting parameters
const options = {
  price: { 
    type: 'currency', 
    options: { currencyPropName: 'currency' } 
  },
  created: { 
    type: 'date', 
    options: { type: 'datetime' } 
  },
  user: {
    type: 'name',
    options: { lastPropName: 'surname', firstPropName: 'name' }
  }
}

// 2. Raw data
const data = [
  {
    price: 100,
    currency: 'USD',
    created: '2024-03-07T12:00:00',
    name: 'John',
    surname: 'Doe'
  }
]

// 3. Initialization
const formatter = new Formatters(options, data)
```

## Methods

### Processing
- `to(): FormattersReturn<List, Options>` — Processes the data and returns the result. If the input was an array, returns a new array of enriched items. If it was a single item — a single object. Adds properties with the `Format` suffix.

### Configuration
- `setList(list?: List): this` — Updates the data for formatting. Supports chaining.

### Information
- `is(): boolean` — Checks if data is set for processing.
- `isArray(): boolean` — Whether the current data is an array.
- `length(): number` — Returns the count of records in the list.
- `getList(): FormattersList<Item>` — Returns the current list as an array.
- `getOptions(): Options` — Returns the current formatting configuration.

## Formatting Types and Parameters

The `FormattersOptionsList` configuration is a dictionary where keys correspond to property names in the data (dot notation `path.to.prop` is supported), and values are `FormattersOptionsItem` objects.

### General Structure of `FormattersOptionsItem`
- `type?: FormattersType` — Formatter type.
- `transformation?: (value, item, options) => string` — Custom transformation function.
- `options?: Options` — Parameter object, the structure of which depends on the selected `type`.

### Detailed Type Description

#### 1. Currency (`currency`)
Used for localized display of monetary values.
- `currencyPropName?: string` — Property name in the item from which the currency code is taken (default is `currency`).
- `options?: string | Intl.NumberFormatOptions` — You can pass a fixed code (e.g., `'USD'`) or an `Intl.NumberFormat` settings object.
- `numberOnly?: boolean` — If `true`, returns only the formatted number without the currency symbol.

#### 2. Date (`date`)
Formatting dates and times via `GeoIntl`.
- `type?: GeoDate` — Preset format:
    - `full` — Full date and time.
    - `datetime` — Date and time (without seconds).
    - `date` — Date only.
    - `time` — Time only.
    - `year-month`, `year`, `month`, `day`, `day-month`, `hour-minute`.
- `options?: Intl.DateTimeFormatOptions` — Standard `Intl` parameters (e.g., `month: 'long'`).
- `hour24?: boolean` — If `true`, forces 24-hour mode.

#### 3. Name (`name`)
Combines full name parts in the correct order.
- `lastPropName?: string` — Field for the last name (default is `lastName`).
- `firstPropName?: string` — Field for the first name (default is `firstName`).
- `surname?: string` — Field for the middle name/surname (default is `surname`).
- `short?: boolean` — If `true`, outputs the last name and initials (e.g., "Doe J.").

#### 4. Number (`number`)
Standard number formatting with digit separation.
- `options?: Intl.NumberFormatOptions` — `Intl` parameters (number of decimal places, style, etc.).

#### 5. Plural (`plural`)
Choosing the correct word form depending on the number.
- `words: string` — Word forms via the `|` separator.
    - For English: `"apple|apples"`.
    - For Russian: `"яблоко|яблока|яблок"`.
- `options?: Intl.PluralRulesOptions` — Pluralization rule settings.
- `optionsNumber?: Intl.NumberFormatOptions` — Settings for formatting the number itself that is output before the word.

#### 6. Unit (`unit`)
Adding units of measurement (km, kg, l).
- `unit: string` — Unit of measurement code (e.g., `'kilometer'`, `'kilogram'`, `'liter'`).
- `options?: Intl.NumberFormatOptions` — Formatting parameters for the numeric part.

## Examples

### Using Dot Notation
```typescript
const options = {
  'user.profile.age': { type: 'number' }
}
const data = { user: { profile: { age: 25 } } }
const formatter = new Formatters(options, data)

const result = formatter.to()
// result.userProfileAgeFormat === "25"
```

### Custom Transformation
```typescript
const options = {
  status: {
    // Custom function takes precedence over type
    transformation: (value, item) => {
       return value === 'active' ? `✅ ${item.name} is online` : '❌ Offline'
    }
  }
}
```
