Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
05abb8c
Удален инлайновый стиль
maximste Mar 9, 2026
1f5ec12
Удален npmrc
maximste Mar 9, 2026
96d8c68
Добавлен шрифт Inter
maximste Mar 9, 2026
03aaa81
Скорректирвоаны sizing стили
maximste Mar 9, 2026
af5439a
Скорректирована верстка окна регистрации
maximste Mar 9, 2026
7d669ba
Добавлено использование стилей кнопок для форм и страниц ошибок, обно…
maximste Mar 9, 2026
0072b1b
Удалено неиспользуемое подключение модуля 'sass:color' в стилях стран…
maximste Mar 9, 2026
4eaf332
Обновлены размеры шрифтов в нескольких компонентах, заменив фиксирова…
maximste Mar 9, 2026
4ddb088
Добавлены пути для алиасов в конфигурации TypeScript и Vite, обновлен…
maximste Mar 9, 2026
41a6053
Обновлены страницы ошибок 404 и 500
maximste Mar 9, 2026
71876d2
Добавлено включение папки 'types' в конфигурацию TypeScript и объявле…
maximste Mar 9, 2026
1ceea59
Обновлена версия пакета 'immutable' до 5.1.5 в package-lock.json
maximste Mar 9, 2026
4cff192
Добавлены новые параметры конфигурации TypeScript: isolatedModules, n…
maximste Mar 13, 2026
ff88898
Добавлен скрипт prebuild
maximste Mar 13, 2026
4990178
Переход на FSD
maximste Mar 14, 2026
459102f
Добавлен prettier
maximste Mar 14, 2026
59a8456
Правки pretier по проекту
maximste Mar 14, 2026
9ddc460
Добавлена конфигурация ESLint
maximste Mar 14, 2026
a759af9
Добавлена конфигурация Stylelint
maximste Mar 14, 2026
cebc967
Добавлена конфигурация для husky и lint-staged, обновлены настройки E…
maximste Mar 14, 2026
4a65814
Добавлены новые расширения для конфигурации Stylelint
maximste Mar 14, 2026
e598ab9
Обновлен скрипт "lint:fix" в package.json для корректного выполнения …
maximste Mar 14, 2026
09f8a14
Обновлена конфигурация ESLint
maximste Mar 15, 2026
5c3d919
Обновлены конфигурации ESLint и Stylelint: добавлено новое правило дл…
maximste Mar 15, 2026
e0f4cca
Упрощены скрипты линтинга в package.json: объединены команды ESLint и…
maximste Mar 15, 2026
dfedd52
Правки линтинга
maximste Mar 15, 2026
bd2fdb2
Добавлен базовый компонент Block
maximste Mar 22, 2026
752443e
Добавлена поддержка добавления/снятия слушателей события в базовом ко…
maximste Mar 22, 2026
60a339d
Добавленf функция registerComponent.ts для регистрации компонентов в …
maximste Mar 22, 2026
e324743
Добавлен базовый элемент Block
maximste Mar 22, 2026
cd078ed
Добавлено наследование компонентов от Block
maximste Mar 22, 2026
a358ade
Перевод форм на использование Block
maximste Mar 22, 2026
5c317f7
Перевод оставшихся страниц на использование Block
maximste Mar 22, 2026
e7dd941
Добавлены правила валидации для различных типов полей ввода
maximste Mar 22, 2026
10b5265
Добавлены валидаторы для различных типов форм
maximste Mar 22, 2026
8ae455c
Добавлен обработчик валидации форм
maximste Mar 22, 2026
5f49fe7
Добавлена валидация формы авторизации
maximste Mar 22, 2026
2952109
Добавлена валидация формы регистрации
maximste Mar 22, 2026
96e0d7a
Добавлена валидация формы редактирования пользователя
maximste Mar 22, 2026
96dedb2
Добавлен stylelint-config-idiomatic-order и stylelint-config-standard…
maximste Mar 22, 2026
ca8f799
Добавлена перемееная для цвета ошибок валидации
maximste Mar 22, 2026
3ed0230
Скорерктированы правила stylelint
maximste Mar 22, 2026
de3d090
Скорректированы стили по правилам stylelint
maximste Mar 22, 2026
8eb9b6f
Реализован базовый компонент Textarea
maximste Mar 22, 2026
4a396b6
Реализован базовый компонент IconButton
maximste Mar 22, 2026
cbf087a
Добавлен индексный файл для textarea
maximste Mar 22, 2026
113ab9c
Переработана заглушка для варианта отсуствия сообщений в чате
maximste Mar 22, 2026
530bffe
Из FormField удалены стили textarea
maximste Mar 22, 2026
7170d09
Добавлена регистрация компонентов IconButton и Textarea
maximste Mar 22, 2026
6ad3dd9
Добавлен базовый компонент Search
maximste Mar 22, 2026
b065878
Доработан компонент Button под выод иконок слева и справа при необход…
maximste Mar 22, 2026
7b1f30c
Реализован компонент MessageComposer
maximste Mar 22, 2026
cd9257c
Реализован компонент Sidebar
maximste Mar 22, 2026
74b7358
Добавлены mock данные
maximste Mar 22, 2026
5ad80eb
Добавлена утилита timelineHasMessages
maximste Mar 22, 2026
38d9c2f
Добавлены типы для элементов ленты чата и обновлен компонент Messenge…
maximste Mar 22, 2026
527bb8d
Добавлено событие выбора чата в компонент Sidebar и соответствующий о…
maximste Mar 22, 2026
21b8e05
Обновлен импорт в компоненте App для использования страницы чата вмес…
maximste Mar 22, 2026
9329ec8
Реализована логика монтирования страницы чата в мессенджере, добавлен…
maximste Mar 22, 2026
cfec0b9
Исправлены стили невалидных полей ввода
maximste Mar 22, 2026
a390f3c
Добавлен компонент SidebarHeader боковой панели мессенджера.
maximste Mar 22, 2026
f2cb54e
Добавлен компонент SidebarAvatar для отображения аватаров пользовател…
maximste Mar 22, 2026
1768096
Добавлен компонент SidebarPrimaryLine для отображения строки с информ…
maximste Mar 22, 2026
799363a
Добавлен компонент SidebarSecondaryLine для отображения дополнительно…
maximste Mar 22, 2026
0f7a42b
Добавлен компонент SidebarChatListItem для отображения элементов спис…
maximste Mar 22, 2026
4e830db
Добавлен компонент SidebarUserPanel для отображения информации о теку…
maximste Mar 22, 2026
69ccf12
Добавлен компонент SidebarUserStatus для отображения статуса пользова…
maximste Mar 22, 2026
7c5922c
Добавлен функционал для рендеринга компонента IconButton как ссылки, …
maximste Mar 22, 2026
d1af90b
Добавлен компонент SidebarChatSection для отображения секции чатов в …
maximste Mar 22, 2026
603aebf
Добавлены новые компоненты боковой панели: SidebarAvatar, SidebarPrim…
maximste Mar 22, 2026
b6209a4
Обновлена боковая панель:
maximste Mar 22, 2026
a5cb20d
Добавлен функционал отправки сообщений в чат с использованием нового …
maximste Mar 22, 2026
bb73247
Добавлен компонент ChatHeader для отображения заголовка чата с кнопка…
maximste Mar 22, 2026
3c69ebb
Добавлен компонент ChatFooter для отображения области ввода сообщений…
maximste Mar 22, 2026
2907725
Добавлены компоненты ChatPage, ChatThread и ChatTimelineRow для отобр…
maximste Mar 22, 2026
c141614
Обновлен README.md и FSD.md
maximste Mar 22, 2026
1e5725a
Обновлен README.md
maximste Mar 22, 2026
b478e40
Удалены комментарии из tsconfig
maximste Mar 22, 2026
78b01f4
Перевод страниц 404 и 500 на работу с Block
maximste Mar 23, 2026
eb9cf6d
Исправлен обработчик события keydown в компонент MessageComposer
maximste Mar 23, 2026
21bf29b
Добавлен обработчик события клика для кнопки отмены в компоненте Edit…
maximste Mar 23, 2026
a2fb7cb
Рефакторинг компонента ProfilePage
maximste Mar 23, 2026
b10dd43
Добавлен обработчик события клика в компонент Sidebar
maximste Mar 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lerna-debug.log*

node_modules
dist
.eslintcache
dist-ssr
*.local

Expand Down
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
1 change: 0 additions & 1 deletion .npmrc

This file was deleted.

10 changes: 10 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.hbs
build/
.github/
.vite/
.vscode/
node_modules/
.gitignore
*.toml
tsconfig*
vite.config.*
7 changes: 7 additions & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
.github
.vite
.vscode
docs

159 changes: 88 additions & 71 deletions README.md

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions docs/FSD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Feature-Sliced Design (FSD) в GilgaChat

Проект использует архитектуру [Feature-Sliced Design](https://feature-sliced.design/). Слои и импорты организованы по правилам FSD.

## Слои (снизу вверх)

- **shared** — переиспользуемый код без привязки к бизнесу: UI на базе **Block** (Handlebars + `registerComponent`), стили (`variables`, `global`), типы и утилиты (`shared/lib`).
- Примеры UI: `Button`, `Input`, `Label`, `Link`, `FormField`, `IconButton`, `Textarea`, `Search`, атомы сайдбара (`SidebarAvatar`, `SidebarPrimaryLine`, `SidebarSecondaryLine`, `SidebarUserStatus`). Регистрация общих блоков — `shared/ui/block/registerBlocks.ts`.
- **entities** — бизнес-сущности. Пока слой минимальный (`entities/user`), при росте доменной логики сюда выносят типы и модели.
- **features** — пользовательские сценарии: авторизация (`features/auth`), регистрация (`features/registration`), редактирование профиля (`features/edit-profile`).
- **widgets** — составные блоки: **MainLayout**, **MessengerLayout**, **Sidebar** (шапка, секции чатов, список, панель пользователя), **ChatPage** (оболочка экрана переписки) и её части — **ChatHeader**, **ChatThread**, **ChatTimelineRow**, **ChatFooter**, **MessageComposer**, **NoChatStub**.
- **pages** — композиция страниц: auth, register, profile, messenger, not-found, server-error. Каждая страница экспортирует функцию `render*Page(container, props?)` или setup-функции (например, `setupMessengerChatPage` для правой колонки мессенджера).
- **app** — инициализация приложения, роутинг по hash, подключение глобальных стилей, `registerComponent` для виджетов и блоков чата. Точка входа: `src/app/index.ts`.

## Правило импортов

Импорты разрешены только **вниз** по слоям:

- `app` → pages, при необходимости widgets
- `pages` → widgets, features
- `widgets` → features, shared
- `features` → entities, shared
- `entities` → shared
- `shared` — без импортов из других слоёв

Запрещено: импортировать из вышележащего слоя (например, features не импортируют из widgets или pages).

## Публичный API слайсов

Используются только публичные экспорты через `index.ts`. Внешний код импортирует слой целиком, без указания внутренних файлов:

- `@/shared/ui`, `@/shared/lib/types`, `@/shared/lib/utils` (в т.ч. маппинг ленты чата `chatTimeline`)
- `@/features/auth`, `@/features/registration`, `@/features/edit-profile`
- `@/widgets/mainLayout`, `@/widgets/messengerLayout`, `@/widgets/sidebar`, `@/widgets/chatPage`, `@/widgets/messageComposer`, `@/widgets/noChatStub`
- `@/pages/auth`, `@/pages/register`, `@/pages/profile`, `@/pages/messenger`, `@/pages/not-found`, `@/pages/server-error`
- `@/app` — точка входа и класс App

Внутренние файлы `widgets/chatPage/*` (кроме публичного `ChatPage` из `index.ts`) подключаются через `registerComponent` в `app`, а не импортируются из pages напрямую.

## Точка входа

В `index.html` подключён `src/app/index.ts`. Он подключает глобальные стили (`@/shared/styles/global.scss`), шрифты, `registerBlocks`, регистрирует виджеты мессенджера и чата и создаёт экземпляр `App`, который вешает обработку `hashchange` и по hash вызывает соответствующую `render*Page`.

## Структура каталогов (кратко)

```
src/
├── app/ # Инициализация, роутинг, registerComponent для чата/сайдбара
├── pages/ # Страницы (auth, register, profile, messenger, not-found, server-error)
├── widgets/
│ ├── mainLayout/
│ ├── messengerLayout/
│ ├── sidebar/ # Sidebar, секции, элементы списка, панель пользователя
│ ├── chatPage/ # ChatPage, ChatHeader, ChatThread, ChatTimelineRow, ChatFooter
│ ├── messageComposer/
│ └── noChatStub/
├── features/ # auth, registration, edit-profile
├── entities/ # user (заглушка)
└── shared/
├── ui/ # block, button, input, label, link, formField, iconButton, textarea, search, sidebar/*
├── styles/ # variables, global, _colors, _buttons, …
└── lib/ # types (в т.ч. лента чата), utils, mocks
```
136 changes: 136 additions & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import jseslint from "@eslint/js";
import stylistic from "@stylistic/eslint-plugin";
import { defineConfig, globalIgnores } from "eslint/config";
import pluginImport from "eslint-plugin-import";
import pluginSimpleImportSort from "eslint-plugin-simple-import-sort";
import globals from "globals";
import tseslint from "typescript-eslint";

export default defineConfig([
globalIgnores([
"node_modules",
".next",
"out",
"scripts",
"build",
"public",
"dist",
"**/*.{mjs,cjs}",
"eslint.config.ts",
"vite.config.ts",
]),

// Общие правила для JS/TS файлов
{
files: ["**/*.{js,ts}"],
languageOptions: {
globals: globals.browser,
},
},

// Основные правила для JS/TS файлов
{
files: ["**/*.{js,ts}"],
plugins: {
js: jseslint,
},
extends: [jseslint.configs.recommended],
rules: {
"max-classes-per-file": ["warn", { max: 1 }],
"max-depth": ["warn", { max: 4 }],
"max-nested-callbacks": ["warn", { max: 2 }],
"max-lines": ["warn", { max: 1000 }],
"no-negated-condition": ["warn"],
"no-nested-ternary": ["warn"],
"no-shadow": ["warn"],
"no-useless-return": ["warn"],
},
},

// Дополнительные правила для TS файлов
{
files: ["**/*.ts"],
plugins: {
"@typescript-eslint": tseslint.plugin,
},
languageOptions: {
parser: tseslint.parser,
parserOptions: {
projectService: true,
},
},
extends: [tseslint.configs.recommended],
rules: {
"@typescript-eslint/no-explicit-any": ["off"],
"@typescript-eslint/ban-ts-comment": ["warn"],
"@typescript-eslint/no-empty-object-type": ["off"],
},
},

// Правила для стилистики JS/TS файлов
{
files: ["**/*.{js,ts}"],
plugins: {
"@stylistic": stylistic,
},
rules: {
"@stylistic/padding-line-between-statements": [
"warn",
// Всегда добавлять пустую строку перед return
{ blankLine: "always", prev: "*", next: "return" },

// Всегда добавлять пустую строку после const, let, var
{ blankLine: "always", prev: ["const", "let", "var"], next: "*" },
{
blankLine: "any",
prev: ["const", "let", "var"],
next: ["const", "let", "var"],
},

// Всегда добавлять пустую строку до и после функций
{ blankLine: "always", prev: ["function"], next: "*" },
{ blankLine: "always", prev: "*", next: ["function"] },

// Всегда добавлять пустую строку до и после типов или интерфейсов
{ blankLine: "always", prev: ["type", "interface"], next: "*" },
{ blankLine: "always", prev: "*", next: ["type", "interface"] },
],
"@stylistic/lines-between-class-members": ["warn", "always"],
},
},

// Правила для импортов
{
extends: [pluginImport.flatConfigs.recommended],
rules: {
"import/no-unresolved": "off",
"import/first": ["error"],
"import/newline-after-import": ["warn"],
"import/no-duplicates": ["warn", { "prefer-inline": false }],
},
},

// Правила для сортировки импортов
{
files: ["**/*.{js,ts}"],
plugins: {
"simple-import-sort": pluginSimpleImportSort,
},
rules: {
"simple-import-sort/exports": ["error"],
"simple-import-sort/imports": [
"error",
{
groups: [
["^@?\\w"], // Packages
["^@/\\w"], // App aliases
["^\.\.(?!/?$)", "^\.\./?$"], // Parent imports
["^\./(?=.*/)(?!/?$)", "^\.(?!/?$)", "^\./?$"], // Other relative imports
["^.+\.?(scss|css)$"], // Styles
["^\u0000"], // Side effect imports
],
},
],
},
},
]);
7 changes: 5 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta
http-equiv="Cache-Control"
content="no-cache, no-store, must-revalidate"
/>
<title>GilgaChat</title>
</head>
<body class="body">
<div id="app" class="app">Loading…</div>
<script type="module" src="/src/main.ts"></script>
<script type="module" src="/src/app/index.ts"></script>
</body>
</html>
Loading
Loading