# Contributing to Ospab Host 8.1 Спасибо за интерес к проекту! Мы рады любому вкладу в развитие платформы. ## Оглавление 1. [Кодекс поведения](#кодекс-поведения) 2. [Как внести вклад](#как-внести-вклад) 3. [Процесс разработки](#процесс-разработки) 4. [Стандарты кода](#стандарты-кода) 5. [Коммиты и Pull Requests](#коммиты-и-pull-requests) 6. [Тестирование](#тестирование) 7. [Документация](#документация) ## Кодекс поведения ### Наши обязательства Мы стремимся создать открытое и дружелюбное сообщество. Мы обязуемся: - Использовать уважительный и профессиональный язык - Уважать различные точки зрения и опыт - Принимать конструктивную критику - Фокусироваться на лучшем решении для сообщества - Проявлять эмпатию к другим участникам ### Неприемлемое поведение - Оскорбительные комментарии - Домогательства в любой форме - Публикация личной информации без разрешения - Троллинг и провокации - Другое неэтичное поведение ## Как внести вклад ### Сообщение об ошибках Перед созданием issue убедитесь: 1. Ошибка воспроизводится на последней версии 2. Похожего issue еще нет 3. У вас есть вся необходимая информация **Шаблон сообщения об ошибке:** ```markdown ## Описание Краткое описание ошибки ## Шаги воспроизведения 1. Перейти на... 2. Нажать на... 3. Увидеть ошибку... ## Ожидаемое поведение Что должно произойти ## Фактическое поведение Что произошло на самом деле ## Окружение - OS: [e.g. Ubuntu 22.04] - Node.js: [e.g. 18.19.0] - Browser: [e.g. Chrome 120] - Version: [e.g. 8.1.0] ## Скриншоты Если применимо ## Дополнительная информация Логи, stack traces и т.д. ``` ### Предложение улучшений **Шаблон feature request:** ```markdown ## Проблема Какую проблему решает это улучшение? ## Предлагаемое решение Подробное описание решения ## Альтернативы Рассмотренные альтернативные решения ## Дополнительный контекст Скриншоты, примеры, ссылки ``` ### Pull Requests 1. Fork репозитория 2. Создайте feature ветку (`git checkout -b feature/AmazingFeature`) 3. Зафиксируйте изменения (`git commit -m 'Add some AmazingFeature'`) 4. Push в ветку (`git push origin feature/AmazingFeature`) 5. Откройте Pull Request ## Процесс разработки ### Настройка окружения 1. **Установка зависимостей** ```bash # Клонируйте репозиторий git clone https://github.com/Ospab/ospabhost8.1.git cd ospabhost8.1/ospabhost # Backend cd backend npm install npx prisma generate # Frontend cd ../frontend npm install ``` 2. **Настройка окружения** ```bash # Backend .env cd backend cp .env.example .env # Заполните необходимые переменные ``` 3. **Запуск в режиме разработки** ```bash # Terminal 1 - Backend cd backend npm run dev # Terminal 2 - Frontend cd frontend npm run dev ``` ### Структура веток - `main` - стабильная production ветка - `develop` - активная разработка - `feature/*` - новые функции - `bugfix/*` - исправление ошибок - `hotfix/*` - срочные исправления для production ### Git Flow ``` main └─ develop ├─ feature/new-feature ├─ bugfix/fix-something └─ hotfix/urgent-fix ``` ## Стандарты кода ### TypeScript/JavaScript **Основные правила:** - Используйте TypeScript для типобезопасности - Избегайте `any`, используйте конкретные типы - Функции должны быть чистыми где возможно - Один компонент/функция = одна ответственность - Максимальная длина файла - 300 строк **Именование:** ```typescript // Константы - UPPER_SNAKE_CASE const MAX_RETRIES = 3; const API_BASE_URL = 'https://api.example.com'; // Переменные и функции - camelCase const userData = getUserData(); function calculateTotal(items) { } // Классы и компоненты - PascalCase class UserService { } const LoginPage = () => { }; // Приватные поля - с underscore class Example { private _internalState: string; } // Boolean переменные - is/has/should префиксы const isLoading = true; const hasPermission = false; const shouldUpdate = true; ``` **Комментарии:** ```typescript // Плохо - очевидное const price = 100; // Устанавливаем цену // Хорошо - объясняем "почему" // Используем кеш для снижения нагрузки на API const cachedData = getFromCache(); /** * Вычисляет финальную цену с учетом скидок и налогов * @param basePrice Базовая цена товара * @param discountPercent Процент скидки (0-100) * @returns Финальная цена */ function calculateFinalPrice(basePrice: number, discountPercent: number): number { // Реализация } ``` ### React компоненты **Структура компонента:** ```typescript import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; // 1. Типы interface Props { userId: number; onUpdate?: () => void; } // 2. Константы const DEFAULT_TIMEOUT = 5000; // 3. Компонент const UserProfile: React.FC = ({ userId, onUpdate }) => { // 3.1 Hooks const navigate = useNavigate(); const [loading, setLoading] = useState(false); // 3.2 Effects useEffect(() => { fetchUserData(); }, [userId]); // 3.3 Handlers const handleUpdate = async () => { // Логика }; // 3.4 Render helpers if (loading) { return
Loading...
; } // 3.5 Main render return (
{/* JSX */}
); }; // 4. Export export default UserProfile; ``` **Хуки правила:** - Используйте хуки только на верхнем уровне - Создавайте custom hooks для повторяющейся логики - Мемоизируйте тяжелые вычисления (`useMemo`) - Оптимизируйте callbacks (`useCallback`) ### CSS/Tailwind **Tailwind классы:** ```tsx // Плохо - слишком длинный inline
// Хорошо - группировка или extracted component const buttonClasses = "flex items-center justify-between px-4 py-2 bg-blue-500 text-white rounded-lg shadow-md hover:bg-blue-600 transition-colors duration-200";
// Еще лучше - отдельный компонент