using System;
using Ban.Sdaid.Notation.Documents;
using Ban.Sdaid.Icd;
namespace Ban.Sdaid.Icd.Arch.Tech.Angular
{
/// <summary>
/// ADR-UI-003: Физическая структура проекта src-ui — тематические папки верхнего уровня,
/// плоские фичи, самодостаточный переносимый набор ui/ с дизайн-токенами, TS-алиасы.
/// </summary>
public class ADR_UI_003_ProjectStructure : IAdrDocument, IFolder<ArchAngularFolder>
{
public string Name => "ADR-UI-003. Структура проекта src-ui";
public string Description =>
@"Каркас `src-ui`, созданный `ng new`, минимален. По мере роста (страницы, сервисы, компоненты,
модели, гарды) нужен предсказуемый **физический** layout: чтобы человек и ИИ одинаково находили место
для нового кода, а генераторы опирались на стабильные пути. Учитываем переносимость набора `ui/` и
отсутствие внешнего UI-kit.";
public string Version => "1.0";
public string Status => "accepted";
public string[] Comments => new[]
{
"2026-08-11. Принято следом за ADR-UI-002.",
};
public Type? Supersedes => null;
public static string S1_Context = """
## Контекст и постановка задачи
Нужен предсказуемый физический layout `src-ui`, чтобы:
- человек и ИИ-ассистент одинаково находили место для нового кода;
- генераторы/skills опирались на стабильные пути;
- структура не разъезжалась при добавлении фич.
Две особенности ICD, отличающие раскладку от типовой: собственный **переносимый** набор
компонентов `ui/` (должен быть самодостаточным, включая дизайн-токены) и **отсутствие**
внешнего UI-kit (нет `antd-overrides` и подобного).
""";
public static string S2_DecisionDrivers = """
## Драйверы решения
1. **Единственная ответственность папок** — каждая папка верхнего уровня имеет понятное
назначение, новый код легко классифицировать.
2. **Плоские модули** — никакой группировки `modules/<group>/<feature>/`; навигационная
группировка живёт в меню, не в файловой системе.
3. **Lazy loading** — каждая фича `modules/<feature>/` подключается ленивыми маршрутами.
4. **Стабильные пути** — для автоматизации и предсказуемого ревью.
5. **Самодостаточность `ui/`** — набор с токенами переносится в другой проект целиком, без
внешних стилевых зависимостей.
""";
public static string S3_ConsideredOptions = """
## Рассмотренные варианты
- **A. Тематические папки верхнего уровня + плоские фичи** — `app/{consts, directives, guards,
models, modules, pipes, services, ui, utils}`, фичи рядом в `modules/`.
- **B. Двухуровневые модули** — `modules/<group>/<feature>/`; навигационная группировка
дублируется в файловой системе.
- **C. Feature-first** — каждая фича со своими `services/components/models` обособленно, без
общих тематических папок.
""";
public static string S4_DecisionOutcome = """
## Решение
Выбран **Вариант A**. Папки создаются **по мере надобности** (не заводим пустые заранее);
назначение каждой зафиксировано ниже. Именование файлов — по стилю Angular 22 без суффиксов
(см. ADR-UI-002).
### Дерево верхнего уровня (целевое)
```
src-ui/
└── src/
├── app/
│ ├── consts/ # Глобальные константы
│ ├── directives/ # Атрибутивные/структурные директивы
│ ├── guards/ # CanActivate-гарды
│ ├── models/ # Общие модели (Option, Pagination, Sorting, …)
│ ├── modules/ # Фичи (плоско, см. ниже)
│ ├── pipes/ # Глобальные pipe-ы
│ ├── services/ # Singleton-сервисы (root)
│ │ ├── api-clients/ # Клиенты к backend (генерируемые; см. ADR про API)
│ │ └── router/ # Реестры маршрутов
│ ├── ui/ # Собственный переносимый набор компонентов (см. ниже)
│ ├── utils/ # Чистые функции
│ ├── app.ts
│ ├── app.config.ts
│ ├── app.routes.ts
│ └── app.const.ts
├── styles/
│ └── theme/ # Переопределения токенов набора под проект (тема)
├── styles.scss # Точка входа стилей (подключает токены ui/ и styles/theme/)
├── index.html
└── main.ts
```
### Набор `ui/` — самодостаточный и переносимый
```
app/ui/
├── tokens/ # Дизайн-токены (CSS custom properties): палитра, отступы, типографика.
│ # Едут ВМЕСТЕ с набором — часть его контракта.
├── <component>/ # Папка на компонент (button/, table/, …): <name>.ts|html|scss + index.ts
└── index.ts # Общий barrel набора
```
Набор зависит только «вниз» (Angular, `@angular/cdk`, свои токены) и не импортирует доменный
код (см. ADR-UI-002, принципы переносимости).
### Структура папки фичи (`modules/<feature>/`)
```
modules/<feature>/
├── components/ # Под-компоненты страниц
├── models/ # Доменные UI-модели фичи
├── pages/
│ └── <page>/
│ ├── <page>.ts
│ ├── <page>.html
│ └── <page>.scss
├── services/ # Per-page сервисы (регистрируются в providers страницы)
└── <feature>.routes.ts # Ленивые маршруты фичи
```
### Принципы организации
1. **Модули — плоско.** Никакого `modules/<group>/<feature>/`; группировка — только в меню.
2. **`ui/` — переиспользуемые виджеты**, не привязанные к фиче; самодостаточны (с токенами).
3. **`services/` (app) — только глобальные** singleton + `api-clients/` и `router/`. Per-page
сервисы — в `modules/<feature>/services/`.
4. **`models/` (app) — только общие**; доменные — в фиче.
5. **Без `store/`** — глобального store нет (ADR-UI-001).
### Стили и кастомизация набора
- Стили — SCSS; дизайн-токены — CSS custom properties в `app/ui/tokens/` (переносятся с набором).
- **Кастомизация под проект — переопределением значений токенов** в `src/styles/theme/`: меняет
тему глобально, компоненты не трогаются (чистая замена подхода «antd-overrides»).
- **Точечная кастомизация** — через component-scoped переменные, которые компонент осознанно
экспонирует (`--icd-<component>-<prop>`). Инкапсулированные стили компонентов снаружи не
«ломаем» (ViewEncapsulation) — только предусмотренные переменные.
### TS-алиасы (`tsconfig.json`)
```jsonc
{
"compilerOptions": {
"paths": {
"@app/*": ["src/app/*"],
"@api/*": ["src/app/services/api-clients/*"],
"@ui/*": ["src/app/ui/*"]
}
}
}
```
Алиасы обязательны для всего, что вне текущей папки фичи — импорты устойчивы к рефакторингу
путей. Для набора `ui/` алиас `@ui/*` дополнительно облегчает будущий вынос в библиотеку.
### API-клиенты
Место — `app/services/api-clients/<context>/`. Список контекстов и способ генерации клиента из
backend-контракта уточняются отдельным ADR при появлении API; сейчас фиксируется только место.
""";
public static string S5_PositiveConsequences = """
## Положительные следствия
- Плоские `modules/` исключают споры «куда положить фичу»; тематические папки дают однозначное
место каждой роли кода.
- Набор `ui/` самодостаточен (компоненты + токены) — переносится и кастомизируется без правки
компонентов.
- Алиасы делают импорты независимыми от глубины фичи и устойчивыми к рефакторингу.
""";
public static string S6_NegativeConsequences = """
## Отрицательные следствия и компромиссы
- При росте числа фич `modules/` содержит много одноуровневых каталогов — решается навигацией
IDE, не структурой.
- Доменные модели рассыпаны по `modules/*/models/` — цена изоляции фич.
- Кастомизация только через токены и предусмотренные переменные требует, чтобы компоненты
заранее экспонировали нужные «хуки» — дисциплина при дизайне API компонента.
""";
public static string S7_Validation = """
## Проверка
- Новая фича добавляется как `modules/<feature>/{components, models, pages, services,
<feature>.routes.ts}` без правки верхнего уровня.
- Любой виджет из `ui/` используется из любой фичи без циклических зависимостей и без импорта
доменного кода.
- Смена палитры/отступов выполняется правкой `src/styles/theme/`, без изменения компонентов.
""";
public static string S8_OpenQuestions = """
## Открытые вопросы / отложено
- **API-контексты** и способ генерации клиентов из backend-контракта — отдельным ADR при
появлении эндпоинтов.
- **`validators/`** — пока не заводим; появится с первыми формами (на Signal Forms).
""";
public static string S99_Related = $"""
## Связанные артефакты
- {nameof(Ban.Sdaid.Icd.Arch.Tech.Angular.ADR_UI_001_Stack)} — Технологический стек фронтенда.
- {nameof(Ban.Sdaid.Icd.Arch.Tech.Angular.ADR_UI_002_NamingAndConventions)} — Именование и конвенции.
""";
}
}