# AGENT.md

## Purpose

- This file defines repository-specific instructions for coding agents.
- Scope is the full repo unless a deeper `AGENT.md` overrides it.

## Stack Context

- Frontend: Angular 20 standalone app.
- Package manager: `pnpm`.
- Deployment: Docker / Docker Compose with tenant-specific services.
- Current service mapping expectation:
  - `app_default` on host port `8090`
  - `app_tis` on host port `8091`

## Tenant Build Rules

- `default` tenant currently builds via `ng build` and outputs to `dist/production`.
- `tis` tenant builds via `ng build --configuration tis` and outputs to `dist/tis`.
- `prebuild:tis` is tenant-scoped and should keep using scripts under `scripts/tis/*`.
- Keep Docker `DIST_DIR` aligned with actual Angular output path.
- Do not assume `default` Angular configuration is usable unless verified (it may reference missing replacements).
- Do not use Angular `fileReplacements` for static assets (`.png`, `.jpg`, etc.); use tenant public assets or prebuild copy scripts.

## Tenant PWA Rules

- Keep tenant manifest files under tenant public assets (e.g. `public-tis/favicon/site.webmanifest`).
- Ensure `manifest` `id`, `start_url`, and `scope` match actual deployment path:
  - root deploy: `/`
  - subpath deploy example: `/tis/`
- Keep `<link rel="manifest">` path and branding config `manifestPath` aligned.

## Input Component Rules

- File: `src/app/shared/components/input/input.component.ts`
- For `type === 'number'` or `type === 'price'`:
  - Normalize Persian/Arabic digits to English digits.
  - Allow only digits and `.`.
  - Support `fixed` precision formatting when provided.
- Keep behavior for identifier fields (`mobile`, `phone`, `postalCode`, `nationalId`) string-safe.

## Change Policy

- Keep changes minimal and scoped to user request.
- Prefer root-cause fixes over temporary workarounds.
- Avoid unrelated refactors.
- Reuse existing patterns and naming conventions.

## Do / Don't

- Do follow existing field wrapper style in `src/app/shared/components/fields/*.component.ts`.
- Do reuse `app-input` and set only required props (`type`, `label`, `name`, constraints).
- Do register every new field in:
  - `src/app/shared/components/fields/index.ts`
  - `src/app/shared/constants/fields/index.ts`
- Do keep control keys consistent across form group, field component `name`, and `fieldControl` key.
- Don't add one-off field patterns when an existing field component can be reused.
- Don't use invalid Angular file replacements for directories or empty paths.
- Don't change tenant output directories without updating Docker `DIST_DIR`.

## How To Create Form Fields

- Create a wrapper component in `src/app/shared/components/fields`.
- Use the same pattern as existing files like:
  - `src/app/shared/components/fields/name.component.ts`
  - `src/app/shared/components/fields/unit_price.component.ts`
- Minimal wrapper shape:
  - `selector`: `field-<field-name>`
  - template: `<app-input ... />`
  - inputs: `control` (required), optional `name`, optional `label`

Example pattern:

```ts
@Component({
  selector: 'field-example',
  template: `<app-input [label]="label" [control]="control" [name]="name" type="simple" />`,
  imports: [ReactiveFormsModule, InputComponent],
})
export class ExampleComponent {
  @Input({ required: true }) control = new FormControl<string>('');
  @Input() name = 'example';
  @Input() label = 'Example';
}
```

## Register New Fields

- Export the component from:
  - `src/app/shared/components/fields/index.ts`
- Add its form control factory in:
  - `src/app/shared/constants/fields/index.ts`
- `fieldControl` entry shape:
  - key must match form control name
  - return tuple: `[defaultValue, validators]`

Example:

```ts
example: (value = '', isRequired = true): ControlConfig => [
  value,
  isRequired ? [Validators.required] : [],
],
```

## Using Fields In Forms

- In form group builders, use `fieldControl.<key>(initialValue, isRequired)` for consistency.
- In templates, render matching wrapper component and pass the matching control:
  - `<field-example [control]="form.controls.example" />`
- For numeric/price behavior, use `app-input` `type="number"` or `type="price"` and optional `[fixed]`.

## List Component Configs

- Centralized list metadata is stored in `src/app/shared/constants/list-configs/` — **never** in domain modules.
- Structure by data type, not domain (e.g. `good-list.const.ts`, `sku-list.const.ts`, `category-list.const.ts`).
- Each config implements `IListConfig` (defined in `list-config.model.ts`):
  - `pageTitle`: display title for the list page
  - `addNewCtaLabel`: call-to-action button label
  - `emptyPlaceholderTitle` and `emptyPlaceholderDescription`: empty state messaging
  - `columns`: array of `IColumn[]` definitions
- Usage in list components:
  ```ts
  @Input() header: IColumn[] = goodListConfig.columns;
  listConfig = goodListConfig;
  ```
- Any domain needing a list config imports from `@/shared/constants/list-configs` — no cross-domain dependencies.
- **Do not** define configs inside domains or duplicate them across modules.

## Breadcrumb Usage in Stores & Views

- Entity stores expose `breadcrumbItems` as a computed signal.
- Call `store.breadcrumbItems()` in view components and extend with current page:
  ```ts
  setBreadcrumb() {
    this.breadcrumbService.setItems([
      ...this.store.breadcrumbItems(),
      { title: 'Current Page' },
    ]);
  }
  ```
- Root page breadcrumbs are set in the store's `getData()` method once entity is loaded.

## Validation Checklist

- For TypeScript-only changes, run:
  - `pnpm -s exec tsc -p tsconfig.app.json --noEmit`
- For Docker/build changes, verify with:
  - `docker compose build app_default`
  - `docker compose build app_tis`
- Start with targeted validation, then broader checks only if needed.

## Communication Expectations

- Report exactly which files changed and why.
- Call out any assumptions or discovered config mismatches.
- If validation is blocked (permissions, missing dependencies), state it clearly and provide next command.
