900 lines
30 KiB
Markdown
900 lines
30 KiB
Markdown
# 🚀 План реализации нового Frontend (Material UI 3 + Next.js 16)
|
||
|
||
**Дата создания:** 26 января 2026
|
||
**Проект:** Uchill Platform - Frontend Material
|
||
**Цель:** Создать новый frontend с Material UI 3, iOS 24+ дизайном и панелью управления снизу
|
||
|
||
---
|
||
|
||
## 📋 Общая информация
|
||
|
||
### Технологический стек:
|
||
- **Framework:** Next.js 16.1+ (с Turbopack)
|
||
- **UI Library:** Material Web Components 3 (`@material/web`) - **ТОЛЬКО Material компоненты!**
|
||
- **Layout System:** Material Design 3 Grid System
|
||
- **Styling:** CSS Variables (Material Theme)
|
||
- **TypeScript:** Да
|
||
- **State Management:** React Context API
|
||
- **API Client:** Axios
|
||
- **Real-time:** WebSocket (чат, доска), WebRTC (видеозвонки)
|
||
- **Icons:** Material Symbols (Google Fonts)
|
||
|
||
### Дизайн-система:
|
||
- **Цвета:** Из `landing_site` (см. ниже)
|
||
- **Стиль:** iOS 24+ (rounded corners, blur effects, glassmorphism)
|
||
- **Навигация:** Bottom Navigation Bar (iOS-style, Material Navigation)
|
||
- **Компоненты:** **ТОЛЬКО Material Web Components 3** (`@material/web`)
|
||
- **Layout:** Material Design 3 Grid System
|
||
- **Styling:** Чистый CSS с CSS Variables (БЕЗ Tailwind CSS)
|
||
|
||
---
|
||
|
||
## 🎨 Цветовая палитра из landing_site
|
||
|
||
```css
|
||
:root {
|
||
--theme: #7444FD; /* Основной фиолетовый */
|
||
--theme2: #F9F3EF; /* Бежевый фон */
|
||
--theme3: #FAF8FF; /* Светло-фиолетовый фон */
|
||
--title: #282C32; /* Темно-серый для заголовков */
|
||
--text: #858585; /* Серый для текста */
|
||
--text2: #cbcbcb; /* Светло-серый */
|
||
--border: #E6E6E6; /* Границы */
|
||
--border-2: #F1F1F1; /* Светлые границы */
|
||
--bg-1: #161921; /* Темный фон */
|
||
--bg-2: #F6F7FF; /* Светлый фон */
|
||
--white: #fff;
|
||
--black: #000;
|
||
--orange: #e78c45;
|
||
}
|
||
```
|
||
|
||
### Адаптация для iOS 24+ стиля:
|
||
- Использовать blur effects (backdrop-filter)
|
||
- Rounded corners (16px, 20px, 24px)
|
||
- Glassmorphism для панелей
|
||
- Soft shadows
|
||
- Smooth animations
|
||
|
||
---
|
||
|
||
## 📦 Этап 1: Подготовка проекта и инфраструктуры
|
||
|
||
### Задача 1.1: Инициализация Next.js 16 проекта
|
||
- [ ] Создать новый Next.js проект в `front_material/`
|
||
- [ ] Настроить TypeScript конфигурацию
|
||
- [ ] Настроить ESLint и Prettier
|
||
- [ ] Настроить пути импортов (`@/components`, `@/utils`, и т.д.)
|
||
- [ ] Создать базовую структуру папок
|
||
|
||
**Команды:**
|
||
```bash
|
||
cd front_material
|
||
npx create-next-app@latest . --typescript --no-tailwind --app --no-src-dir
|
||
npm install @material/web
|
||
npm install axios date-fns livekit-client
|
||
npm install -D @types/node @types/react @types/react-dom
|
||
```
|
||
|
||
**⚠️ Важно:** Создаем проект **БЕЗ Tailwind CSS** (`--no-tailwind`)!
|
||
|
||
### Задача 1.2: Настройка Docker
|
||
- [ ] Создать `Dockerfile` для Next.js 16
|
||
- [ ] Создать `.dockerignore`
|
||
- [ ] Настроить multi-stage build (development, production)
|
||
- [ ] Обновить `docker-compose.yml` (отключить старый frontend, добавить новый)
|
||
- [ ] Настроить hot reload в Docker
|
||
|
||
**Dockerfile структура:**
|
||
```dockerfile
|
||
# Development stage
|
||
FROM node:20-alpine AS development
|
||
WORKDIR /app
|
||
COPY package*.json ./
|
||
RUN npm install
|
||
COPY . .
|
||
EXPOSE 3000
|
||
CMD ["npm", "run", "dev"]
|
||
|
||
# Production stage
|
||
FROM node:20-alpine AS production
|
||
WORKDIR /app
|
||
COPY package*.json ./
|
||
RUN npm ci --only=production
|
||
COPY . .
|
||
RUN npm run build
|
||
EXPOSE 3000
|
||
CMD ["npm", "start"]
|
||
```
|
||
|
||
### Задача 1.3: Настройка переменных окружения
|
||
- [ ] Создать `.env.example`
|
||
- [ ] Настроить `NEXT_PUBLIC_API_URL`
|
||
- [ ] Настроить `NEXT_PUBLIC_WS_URL`
|
||
- [ ] Настроить другие переменные окружения
|
||
|
||
**Файл `.env.example`:**
|
||
```env
|
||
NEXT_PUBLIC_API_URL=http://localhost:8123/api
|
||
NEXT_PUBLIC_WS_URL=ws://localhost:8123/ws
|
||
NEXT_PUBLIC_LIVEKIT_URL=ws://localhost:7880
|
||
NODE_ENV=development
|
||
```
|
||
|
||
### Задача 1.4: Настройка Material Web Components
|
||
- [ ] Установить `@material/web`
|
||
- [ ] Настроить импорт компонентов
|
||
- [ ] Создать wrapper компоненты для React
|
||
- [ ] Настроить темизацию (цвета из landing_site)
|
||
- [ ] Создать базовые стили
|
||
|
||
**Структура:**
|
||
```
|
||
front_material/
|
||
├── src/
|
||
│ ├── components/
|
||
│ │ ├── material/ # Wrapper компоненты для Material UI
|
||
│ │ │ ├── Button.tsx
|
||
│ │ │ ├── TextField.tsx
|
||
│ │ │ ├── Card.tsx
|
||
│ │ │ └── ...
|
||
│ │ └── ...
|
||
│ ├── styles/
|
||
│ │ ├── material-theme.css # Кастомная тема Material UI
|
||
│ │ └── globals.css # Глобальные стили
|
||
```
|
||
|
||
---
|
||
|
||
## 🎨 Этап 2: Дизайн-система и базовые компоненты
|
||
|
||
### Задача 2.1: Создание цветовой темы
|
||
- [ ] Создать CSS переменные на основе цветов landing_site
|
||
- [ ] Адаптировать цвета для iOS 24+ стиля
|
||
- [ ] Создать темную тему (dark mode)
|
||
- [ ] Настроить Material UI тему с кастомными цветами
|
||
|
||
**Файл `src/styles/theme.css`:**
|
||
```css
|
||
:root {
|
||
/* Основные цвета из landing_site */
|
||
--md-sys-color-primary: #7444FD;
|
||
--md-sys-color-on-primary: #FFFFFF;
|
||
--md-sys-color-primary-container: #FAF8FF;
|
||
--md-sys-color-on-primary-container: #282C32;
|
||
|
||
/* iOS 24+ адаптация */
|
||
--ios-blur-background: rgba(255, 255, 255, 0.8);
|
||
--ios-blur-background-dark: rgba(0, 0, 0, 0.6);
|
||
--ios-border-radius: 20px;
|
||
--ios-border-radius-small: 16px;
|
||
--ios-border-radius-large: 24px;
|
||
--ios-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] {
|
||
--md-sys-color-primary: #9D6AFF;
|
||
--ios-blur-background: rgba(0, 0, 0, 0.8);
|
||
}
|
||
```
|
||
|
||
### Задача 2.2: Использование Material Web Components (напрямую)
|
||
- [ ] Импортировать все нужные Material компоненты
|
||
- [ ] Настроить типизацию для Web Components в TypeScript
|
||
- [ ] Создать глобальный импорт всех Material компонентов
|
||
|
||
**Важно:** Используем Material Web Components напрямую в JSX/TSX, без wrapper компонентов!
|
||
|
||
**Файл `src/lib/material-components.ts`:**
|
||
```typescript
|
||
// Импортируем все нужные Material компоненты
|
||
import '@material/web/button/filled-button.js';
|
||
import '@material/web/button/outlined-button.js';
|
||
import '@material/web/button/text-button.js';
|
||
import '@material/web/button/elevated-button.js';
|
||
import '@material/web/button/tonal-button.js';
|
||
|
||
import '@material/web/textfield/filled-text-field.js';
|
||
import '@material/web/textfield/outlined-text-field.js';
|
||
|
||
import '@material/web/card/filled-card.js';
|
||
import '@material/web/card/elevated-card.js';
|
||
import '@material/web/card/outlined-card.js';
|
||
|
||
import '@material/web/list/list.js';
|
||
import '@material/web/list/list-item.js';
|
||
|
||
import '@material/web/dialog/dialog.js';
|
||
import '@material/web/chip/chip-set.js';
|
||
import '@material/web/chip/assist-chip.js';
|
||
import '@material/web/chip/filter-chip.js';
|
||
|
||
import '@material/web/icon/icon.js';
|
||
import '@material/web/iconbutton/icon-button.js';
|
||
|
||
import '@material/web/checkbox/checkbox.js';
|
||
import '@material/web/radio/radio.js';
|
||
import '@material/web/switch/switch.js';
|
||
import '@material/web/select/filled-select.js';
|
||
import '@material/web/select/outlined-select.js';
|
||
|
||
// И другие по необходимости
|
||
```
|
||
|
||
**Использование в компонентах:**
|
||
```typescript
|
||
'use client';
|
||
|
||
export default function LoginPage() {
|
||
return (
|
||
<div>
|
||
<md-outlined-text-field
|
||
label="Email"
|
||
type="email"
|
||
></md-outlined-text-field>
|
||
|
||
<md-filled-button>Войти</md-filled-button>
|
||
</div>
|
||
);
|
||
}
|
||
```
|
||
|
||
### Задача 2.3: Настройка TypeScript для Web Components
|
||
- [ ] Создать типы для Material Web Components
|
||
- [ ] Настроить JSX для использования Web Components
|
||
|
||
**Файл `src/types/material-web.d.ts`:**
|
||
```typescript
|
||
declare namespace JSX {
|
||
interface IntrinsicElements {
|
||
'md-filled-button': any;
|
||
'md-outlined-button': any;
|
||
'md-text-button': any;
|
||
'md-elevated-button': any;
|
||
'md-tonal-button': any;
|
||
'md-filled-text-field': any;
|
||
'md-outlined-text-field': any;
|
||
'md-filled-card': any;
|
||
'md-elevated-card': any;
|
||
'md-outlined-card': any;
|
||
'md-list': any;
|
||
'md-list-item': any;
|
||
'md-dialog': any;
|
||
'md-chip-set': any;
|
||
'md-assist-chip': any;
|
||
'md-filter-chip': any;
|
||
'md-icon': any;
|
||
'md-icon-button': any;
|
||
'md-checkbox': any;
|
||
'md-radio': any;
|
||
'md-switch': any;
|
||
'md-filled-select': any;
|
||
'md-outlined-select': any;
|
||
// ... другие компоненты
|
||
}
|
||
}
|
||
```
|
||
|
||
### Задача 2.4: Настройка Material Grid System
|
||
- [ ] Использовать CSS Grid из Material Design 3
|
||
- [ ] Настроить responsive breakpoints
|
||
- [ ] Создать Layout Grid компоненты
|
||
|
||
**Material Design 3 Grid:**
|
||
```css
|
||
/* src/styles/material-grid.css */
|
||
|
||
/* Material Design 3 Grid System */
|
||
.md-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(12, 1fr);
|
||
gap: 16px;
|
||
padding: 0 16px;
|
||
}
|
||
|
||
/* Responsive breakpoints (Material Design 3) */
|
||
@media (min-width: 600px) { /* Tablet */
|
||
.md-grid {
|
||
gap: 24px;
|
||
padding: 0 24px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 840px) { /* Desktop */
|
||
.md-grid {
|
||
gap: 24px;
|
||
padding: 0 24px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 1240px) { /* Large Desktop */
|
||
.md-grid {
|
||
gap: 24px;
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
}
|
||
}
|
||
|
||
/* Grid column classes */
|
||
.md-col-1 { grid-column: span 1; }
|
||
.md-col-2 { grid-column: span 2; }
|
||
.md-col-3 { grid-column: span 3; }
|
||
.md-col-4 { grid-column: span 4; }
|
||
.md-col-6 { grid-column: span 6; }
|
||
.md-col-8 { grid-column: span 8; }
|
||
.md-col-12 { grid-column: span 12; }
|
||
|
||
/* Responsive columns */
|
||
@media (max-width: 599px) {
|
||
.md-col-sm-12 { grid-column: span 12; }
|
||
}
|
||
|
||
@media (min-width: 600px) and (max-width: 839px) {
|
||
.md-col-md-6 { grid-column: span 6; }
|
||
.md-col-md-12 { grid-column: span 12; }
|
||
}
|
||
|
||
@media (min-width: 840px) {
|
||
.md-col-lg-4 { grid-column: span 4; }
|
||
.md-col-lg-6 { grid-column: span 6; }
|
||
.md-col-lg-8 { grid-column: span 8; }
|
||
}
|
||
```
|
||
|
||
### Задача 2.5: Создание Bottom Navigation Bar (iOS-style + Material)
|
||
- [ ] Компонент `BottomNavigationBar` с использованием Material компонентов
|
||
- [ ] Использовать `md-navigation-bar` и `md-navigation-tab`
|
||
- [ ] Кастомизация под iOS 24+ стиль
|
||
- [ ] Badge для уведомлений (Material Badge)
|
||
- [ ] Адаптация под разные роли (mentor, client, parent)
|
||
|
||
**Использование Material Navigation:**
|
||
```typescript
|
||
'use client';
|
||
|
||
import '@material/web/labs/navigationbar/navigation-bar.js';
|
||
import '@material/web/labs/navigationtab/navigation-tab.js';
|
||
import '@material/web/icon/icon.js';
|
||
import '@material/web/badge/badge.js';
|
||
|
||
export function BottomNavigationBar({ userRole }: { userRole: string }) {
|
||
return (
|
||
<md-navigation-bar className="ios-bottom-bar">
|
||
<md-navigation-tab label="Главная" active>
|
||
<md-icon slot="inactive-icon">home</md-icon>
|
||
<md-icon slot="active-icon">home</md-icon>
|
||
</md-navigation-tab>
|
||
|
||
<md-navigation-tab label="Расписание">
|
||
<md-icon slot="inactive-icon">calendar_month</md-icon>
|
||
<md-icon slot="active-icon">calendar_month</md-icon>
|
||
</md-navigation-tab>
|
||
|
||
<md-navigation-tab label="Чат">
|
||
<md-icon slot="inactive-icon">chat</md-icon>
|
||
<md-icon slot="active-icon">chat</md-icon>
|
||
<md-badge value="3"></md-badge>
|
||
</md-navigation-tab>
|
||
|
||
{userRole === 'mentor' && (
|
||
<md-navigation-tab label="Студенты">
|
||
<md-icon slot="inactive-icon">group</md-icon>
|
||
<md-icon slot="active-icon">group</md-icon>
|
||
</md-navigation-tab>
|
||
)}
|
||
</md-navigation-bar>
|
||
);
|
||
}
|
||
```
|
||
|
||
**Кастомизация под iOS стиль:**
|
||
```css
|
||
/* src/styles/ios-navigation.css */
|
||
md-navigation-bar.ios-bottom-bar {
|
||
--md-navigation-bar-container-color: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(20px);
|
||
-webkit-backdrop-filter: blur(20px);
|
||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.05);
|
||
border-radius: 24px 24px 0 0;
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 1000;
|
||
}
|
||
|
||
[data-theme="dark"] md-navigation-bar.ios-bottom-bar {
|
||
--md-navigation-bar-container-color: rgba(0, 0, 0, 0.8);
|
||
border-top-color: rgba(255, 255, 255, 0.1);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🏗️ Этап 3: Архитектура и структура приложения
|
||
|
||
### Задача 3.1: Настройка роутинга Next.js App Router
|
||
- [ ] Создать структуру папок для маршрутов
|
||
- [ ] Настроить Route Groups: `(auth)`, `(protected)`
|
||
- [ ] Создать layout для защищенных страниц
|
||
- [ ] Создать layout для публичных страниц
|
||
- [ ] Настроить middleware для проверки авторизации
|
||
|
||
**Структура:**
|
||
```
|
||
src/app/
|
||
├── (auth)/
|
||
│ ├── login/
|
||
│ ├── register/
|
||
│ └── layout.tsx
|
||
├── (protected)/
|
||
│ ├── dashboard/
|
||
│ ├── schedule/
|
||
│ ├── chat/
|
||
│ └── layout.tsx
|
||
├── layout.tsx
|
||
└── page.tsx
|
||
```
|
||
|
||
### Задача 3.2: Создание системы аутентификации
|
||
- [ ] Context для хранения пользователя (`AuthContext`)
|
||
- [ ] Хуки для работы с API (`useAuth`, `useLogin`, `useLogout`)
|
||
- [ ] Хранение токенов (localStorage)
|
||
- [ ] Автоматическое обновление токенов
|
||
- [ ] Защита маршрутов через middleware
|
||
|
||
**Файл `src/contexts/AuthContext.tsx`:**
|
||
```typescript
|
||
'use client';
|
||
|
||
import { createContext, useContext, useState, useEffect } from 'react';
|
||
import { getCurrentUser } from '@/api/auth';
|
||
|
||
interface User {
|
||
id: number;
|
||
email: string;
|
||
role: 'mentor' | 'client' | 'parent';
|
||
// ...
|
||
}
|
||
|
||
interface AuthContextType {
|
||
user: User | null;
|
||
loading: boolean;
|
||
login: (token: string) => Promise<void>;
|
||
logout: () => void;
|
||
}
|
||
|
||
const AuthContext = createContext<AuthContextType | null>(null);
|
||
|
||
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||
const [user, setUser] = useState<User | null>(null);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
// Загрузка пользователя при монтировании
|
||
useEffect(() => {
|
||
loadUser();
|
||
}, []);
|
||
|
||
const loadUser = async () => {
|
||
try {
|
||
const token = localStorage.getItem('access_token');
|
||
if (token) {
|
||
const userData = await getCurrentUser();
|
||
setUser(userData);
|
||
}
|
||
} catch (error) {
|
||
localStorage.removeItem('access_token');
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const login = async (token: string) => {
|
||
localStorage.setItem('access_token', token);
|
||
await loadUser();
|
||
};
|
||
|
||
const logout = () => {
|
||
localStorage.removeItem('access_token');
|
||
setUser(null);
|
||
};
|
||
|
||
return (
|
||
<AuthContext.Provider value={{ user, loading, login, logout }}>
|
||
{children}
|
||
</AuthContext.Provider>
|
||
);
|
||
}
|
||
|
||
export function useAuth() {
|
||
const context = useContext(AuthContext);
|
||
if (!context) throw new Error('useAuth must be used within AuthProvider');
|
||
return context;
|
||
}
|
||
```
|
||
|
||
### Задача 3.3: Создание API клиента
|
||
- [ ] Настроить Axios с базовым URL
|
||
- [ ] Добавить interceptors для токенов
|
||
- [ ] Обработка ошибок
|
||
- [ ] Типизация API ответов
|
||
- [ ] Создать модули API (auth, schedule, chat, и т.д.)
|
||
|
||
**Файл `src/lib/api-client.ts`:**
|
||
```typescript
|
||
import axios from 'axios';
|
||
|
||
const apiClient = axios.create({
|
||
baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8123/api',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
});
|
||
|
||
// Добавление токена к запросам
|
||
apiClient.interceptors.request.use((config) => {
|
||
const token = localStorage.getItem('access_token');
|
||
if (token) {
|
||
config.headers.Authorization = `Bearer ${token}`;
|
||
}
|
||
return config;
|
||
});
|
||
|
||
// Обработка ошибок
|
||
apiClient.interceptors.response.use(
|
||
(response) => response,
|
||
(error) => {
|
||
if (error.response?.status === 401) {
|
||
localStorage.removeItem('access_token');
|
||
window.location.href = '/login';
|
||
}
|
||
return Promise.reject(error);
|
||
}
|
||
);
|
||
|
||
export default apiClient;
|
||
```
|
||
|
||
### Задача 3.4: Создание системы управления состоянием
|
||
- [ ] Настроить React Context для глобального состояния
|
||
- [ ] Опционально: добавить Zustand для сложного состояния
|
||
- [ ] Создать stores (userStore, notificationStore, и т.д.)
|
||
|
||
---
|
||
|
||
## 📱 Этап 4: Основные страницы и компоненты
|
||
|
||
### Задача 4.1: Страницы аутентификации
|
||
- [ ] `/login` - страница входа
|
||
- Material UI TextField для email/password
|
||
- Material UI Button
|
||
- iOS-стиль дизайн
|
||
- Валидация форм
|
||
- [ ] `/register` - страница регистрации
|
||
- Форма с выбором роли
|
||
- Material UI компоненты
|
||
- Валидация
|
||
- [ ] `/forgot-password` - восстановление пароля
|
||
- [ ] `/verify-email` - подтверждение email
|
||
|
||
### Задача 4.2: Главный Layout (защищенные страницы)
|
||
- [ ] Создать `ProtectedLayout`
|
||
- [ ] Верхняя панель навигации (iOS-style)
|
||
- [ ] Нижняя панель навигации (Bottom Navigation Bar)
|
||
- [ ] Контентная область с padding
|
||
- [ ] Обработка разных ролей
|
||
|
||
**Компонент `ProtectedLayout.tsx`:**
|
||
```typescript
|
||
'use client';
|
||
|
||
import { useAuth } from '@/contexts/AuthContext';
|
||
import { BottomNavigationBar } from '@/components/navigation/BottomNavigationBar';
|
||
import { TopNavigationBar } from '@/components/navigation/TopNavigationBar';
|
||
import { useRouter } from 'next/navigation';
|
||
import { useEffect } from 'react';
|
||
|
||
export default function ProtectedLayout({ children }: { children: React.ReactNode }) {
|
||
const { user, loading } = useAuth();
|
||
const router = useRouter();
|
||
|
||
useEffect(() => {
|
||
if (!loading && !user) {
|
||
router.push('/login');
|
||
}
|
||
}, [user, loading, router]);
|
||
|
||
if (loading) {
|
||
return <LoadingScreen />;
|
||
}
|
||
|
||
if (!user) {
|
||
return null;
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col h-screen bg-gray-50 dark:bg-gray-900">
|
||
<TopNavigationBar user={user} />
|
||
<main className="flex-1 overflow-y-auto pb-20">
|
||
{children}
|
||
</main>
|
||
<BottomNavigationBar user={user} />
|
||
</div>
|
||
);
|
||
}
|
||
```
|
||
|
||
### Задача 4.3: Дашборды для каждой роли
|
||
- [ ] `/dashboard/mentor` - дашборд ментора
|
||
- Статистика студентов
|
||
- Ближайшие занятия
|
||
- Графики доходов
|
||
- Material UI Cards
|
||
- [ ] `/dashboard/client` - дашборд клиента
|
||
- Календарь занятий
|
||
- Прогресс обучения
|
||
- Статистика
|
||
- [ ] `/dashboard/parent` - дашборд родителя
|
||
- Выбор ребенка
|
||
- Статистика детей
|
||
|
||
### Задача 4.4: Страница расписания
|
||
- [ ] Календарь (Material UI или кастомный)
|
||
- [ ] Создание занятия
|
||
- [ ] Редактирование занятия
|
||
- [ ] Список занятий
|
||
- [ ] Фильтры
|
||
|
||
### Задача 4.5: Страница чата
|
||
- [ ] Список чатов (Material UI List)
|
||
- [ ] Окно чата
|
||
- [ ] WebSocket интеграция
|
||
- [ ] Отправка сообщений
|
||
- [ ] Файлы и медиа
|
||
|
||
### Задача 4.6: Страница видеозвонков
|
||
- [ ] Интеграция с LiveKit
|
||
- [ ] Видео компоненты
|
||
- [ ] Управление микрофоном/камерой
|
||
- [ ] Интерактивная доска
|
||
- [ ] Чат во время звонка
|
||
|
||
---
|
||
|
||
## 🎨 Этап 5: Стилизация и анимации
|
||
|
||
### Задача 5.1: Настройка стилей (только CSS, без Tailwind)
|
||
- [ ] Создать CSS переменные для всей платформы
|
||
- [ ] Использовать Material Design 3 Grid System
|
||
- [ ] Настроить iOS 24+ эффекты (blur, rounded corners)
|
||
- [ ] Настроить dark mode через CSS
|
||
|
||
**⚠️ Важно:** НЕ используем Tailwind CSS! Только чистый CSS и CSS Variables.
|
||
|
||
**Файл `src/styles/globals.css`:**
|
||
```css
|
||
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
|
||
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200');
|
||
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: 'Roboto', -apple-system, BlinkMacSystemFont, sans-serif;
|
||
color: var(--md-sys-color-on-surface);
|
||
background-color: var(--md-sys-color-surface);
|
||
}
|
||
|
||
/* iOS 24+ эффекты */
|
||
.ios-blur {
|
||
backdrop-filter: blur(20px);
|
||
-webkit-backdrop-filter: blur(20px);
|
||
}
|
||
|
||
.ios-card {
|
||
border-radius: 20px;
|
||
background: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(20px);
|
||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] .ios-card {
|
||
background: rgba(0, 0, 0, 0.6);
|
||
}
|
||
```
|
||
|
||
### Задача 5.2: Создание анимаций
|
||
- [ ] Переходы между страницами
|
||
- [ ] Анимация Bottom Navigation Bar
|
||
- [ ] Анимация модальных окон
|
||
- [ ] Skeleton loaders
|
||
- [ ] Pull-to-refresh (опционально)
|
||
|
||
### Задача 5.3: Адаптивный дизайн
|
||
- [ ] Mobile-first подход
|
||
- [ ] Breakpoints для планшетов и десктопов
|
||
- [ ] Адаптация Bottom Navigation Bar для разных экранов
|
||
- [ ] Оптимизация для touch устройств
|
||
|
||
---
|
||
|
||
## 🔌 Этап 6: Интеграция с Backend
|
||
|
||
### Задача 6.1: Интеграция API
|
||
- [ ] Модуль `src/api/auth.ts` - аутентификация
|
||
- [ ] Модуль `src/api/schedule.ts` - расписание
|
||
- [ ] Модуль `src/api/chat.ts` - чат
|
||
- [ ] Модуль `src/api/materials.ts` - материалы
|
||
- [ ] Модуль `src/api/homework.ts` - домашние задания
|
||
- [ ] Модуль `src/api/students.ts` - студенты
|
||
- [ ] Модуль `src/api/payment.ts` - оплата
|
||
- [ ] И другие модули по необходимости
|
||
|
||
### Задача 6.2: WebSocket интеграция
|
||
- [ ] Хук `useChatWebSocket` для чата
|
||
- [ ] Хук `useBoardWebSocket` для доски
|
||
- [ ] Хук `useVideoWebSocket` для видеозвонков
|
||
- [ ] Обработка переподключений
|
||
- [ ] Обработка ошибок
|
||
|
||
### Задача 6.3: Интеграция видеозвонков
|
||
- [ ] LiveKit клиент
|
||
- [ ] Компоненты видео
|
||
- [ ] Управление медиа
|
||
- [ ] Screen sharing
|
||
- [ ] Интерактивная доска во время звонка
|
||
|
||
---
|
||
|
||
## 🐳 Этап 7: Docker и деплой
|
||
|
||
### Задача 7.1: Обновление docker-compose.yml
|
||
- [ ] Отключить старый frontend сервис
|
||
- [ ] Добавить новый `front_material` сервис
|
||
- [ ] Настроить порты
|
||
- [ ] Настроить volumes
|
||
- [ ] Настроить environment variables
|
||
|
||
**Изменения в `docker-compose.yml`:**
|
||
```yaml
|
||
# Старый frontend - закомментировать или удалить
|
||
# frontend:
|
||
# ...
|
||
|
||
# Новый frontend
|
||
front_material:
|
||
build:
|
||
context: ./front_material
|
||
dockerfile: Dockerfile
|
||
target: development
|
||
container_name: platform_front_material
|
||
restart: unless-stopped
|
||
command: npm run dev
|
||
environment:
|
||
- NODE_ENV=development
|
||
- NEXT_PUBLIC_API_URL=http://web:8000/api
|
||
- NEXT_PUBLIC_WS_URL=ws://web:8000/ws
|
||
ports:
|
||
- "3000:3000"
|
||
volumes:
|
||
- ./front_material:/app
|
||
- /app/node_modules
|
||
- /app/.next
|
||
networks:
|
||
- app_network
|
||
depends_on:
|
||
- web
|
||
```
|
||
|
||
### Задача 7.2: Production сборка
|
||
- [ ] Настроить production Dockerfile
|
||
- [ ] Оптимизация bundle size
|
||
- [ ] Настройка кеширования
|
||
- [ ] Настройка статических файлов
|
||
|
||
---
|
||
|
||
## 📝 Этап 8: Документация и тестирование
|
||
|
||
### Задача 8.1: Документация
|
||
- [ ] README.md с инструкциями по установке
|
||
- [ ] Документация компонентов
|
||
- [ ] Документация API интеграции
|
||
- [ ] Документация стилей и темизации
|
||
|
||
### Задача 8.2: Тестирование
|
||
- [ ] Unit тесты для утилит
|
||
- [ ] Integration тесты для API
|
||
- [ ] E2E тесты для критичных flow
|
||
- [ ] Тестирование на разных устройствах
|
||
|
||
---
|
||
|
||
## ✅ Чеклист миграции со старого frontend
|
||
|
||
### Подготовка:
|
||
- [ ] Создать backup старого frontend
|
||
- [ ] Экспортировать важные данные/конфигурации
|
||
- [ ] Документировать текущие API endpoints
|
||
|
||
### Миграция:
|
||
- [ ] Постепенно переносить функциональность
|
||
- [ ] Тестировать каждую страницу
|
||
- [ ] Проверять интеграцию с backend
|
||
- [ ] Проверять WebSocket соединения
|
||
|
||
### Завершение:
|
||
- [ ] Отключить старый frontend в docker-compose.yml
|
||
- [ ] Обновить документацию
|
||
- [ ] Обновить CI/CD (если есть)
|
||
- [ ] Уведомить команду о изменениях
|
||
|
||
---
|
||
|
||
## 🎯 Приоритеты реализации
|
||
|
||
### Фаза 1 (MVP - 2-3 недели):
|
||
1. ✅ Этап 1: Подготовка проекта
|
||
2. ✅ Этап 2: Базовые компоненты
|
||
3. ✅ Этап 3: Архитектура
|
||
4. ✅ Этап 4.1-4.3: Аутентификация и дашборды
|
||
|
||
### Фаза 2 (Основной функционал - 3-4 недели):
|
||
5. ✅ Этап 4.4-4.6: Основные страницы
|
||
6. ✅ Этап 5: Стилизация
|
||
7. ✅ Этап 6: Интеграция с Backend
|
||
|
||
### Фаза 3 (Полировка - 1-2 недели):
|
||
8. ✅ Этап 7: Docker и деплой
|
||
9. ✅ Этап 8: Документация и тестирование
|
||
|
||
---
|
||
|
||
## 📚 Полезные ресурсы
|
||
|
||
### Material Web Components:
|
||
- [Документация](https://github.com/material-components/material-web)
|
||
- [Примеры использования](https://material-web.dev/)
|
||
- [Material Symbols Icons](https://fonts.google.com/icons)
|
||
|
||
### Next.js 16:
|
||
- [Документация](https://nextjs.org/docs)
|
||
- [Turbopack](https://nextjs.org/docs/app/api-reference/next-config-js/turbopack)
|
||
- [App Router](https://nextjs.org/docs/app)
|
||
|
||
### iOS 24+ Design Guidelines:
|
||
- [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/)
|
||
- [iOS Design Patterns](https://developer.apple.com/design/resources/)
|
||
|
||
---
|
||
|
||
## ⚠️ Важные замечания
|
||
|
||
1. **Vite vs Turbopack:**
|
||
- Next.js 16 уже использует Turbopack, который быстрее Vite
|
||
- Рекомендуется использовать Turbopack (встроен в Next.js)
|
||
- Если нужен чистый Vite, можно использовать Vite + React, но потеряете SSR
|
||
|
||
2. **Material UI 3 Web Components:**
|
||
- Это Web Components, не React компоненты
|
||
- Нужны wrapper компоненты для использования в React
|
||
- Альтернатива: использовать React версию Material UI, но она не Material 3
|
||
|
||
3. **Bottom Navigation:**
|
||
- На десктопе можно показывать sidebar вместо bottom bar
|
||
- Адаптация под разные экраны обязательна
|
||
|
||
4. **Цвета:**
|
||
- Использовать цвета из landing_site как основу
|
||
- Адаптировать под iOS 24+ стиль (blur, rounded corners)
|
||
|
||
---
|
||
|
||
**Дата начала:** _______________
|
||
**Ожидаемая дата завершения:** _______________
|
||
**Ответственный:** _______________
|