369 lines
9.9 KiB
Markdown
369 lines
9.9 KiB
Markdown
# 🚀 НАЧНИТЕ ЗДЕСЬ - Новый Frontend Material UI 3
|
||
|
||
## ✅ Что нужно знать
|
||
|
||
### Технологии:
|
||
- ✅ **Next.js 16** (с Turbopack - быстрее Vite)
|
||
- ✅ **Material Web Components 3** - ТОЛЬКО Material компоненты
|
||
- ✅ **Material Design 3 Grid** - для layout
|
||
- ✅ **Чистый CSS** - БЕЗ Tailwind CSS
|
||
- ✅ **iOS 24+ стиль** - blur, rounded corners
|
||
- ✅ **Bottom Navigation** - вместо sidebar
|
||
|
||
### Цвета из landing_site:
|
||
- `#7444FD` - основной фиолетовый
|
||
- `#FAF8FF` - светлый фон
|
||
- `#282C32` - темный текст
|
||
- `#858585` - серый текст
|
||
|
||
---
|
||
|
||
## 📝 Пошаговая инструкция
|
||
|
||
### Шаг 1: Инициализация проекта
|
||
|
||
```bash
|
||
cd front_material
|
||
|
||
# Создать Next.js проект БЕЗ Tailwind CSS
|
||
npx create-next-app@latest . --typescript --no-tailwind --app --no-src-dir --eslint
|
||
|
||
# Ответы на вопросы:
|
||
# ✔ Would you like to use TypeScript? … Yes
|
||
# ✔ Would you like to use ESLint? … Yes
|
||
# ✔ Would you like to use Tailwind CSS? … No (ВАЖНО!)
|
||
# ✔ Would you like to use `src/` directory? … No
|
||
# ✔ Would you like to use App Router? … Yes
|
||
# ✔ Would you like to customize the default import alias (@/*)? … No
|
||
```
|
||
|
||
### Шаг 2: Установка зависимостей
|
||
|
||
```bash
|
||
# Material Web Components
|
||
npm install @material/web
|
||
|
||
# API и утилиты
|
||
npm install axios date-fns
|
||
|
||
# Видеозвонки
|
||
npm install livekit-client
|
||
|
||
# TypeScript типы
|
||
npm install -D @types/node @types/react @types/react-dom
|
||
```
|
||
|
||
### Шаг 3: Создание структуры папок
|
||
|
||
```bash
|
||
# Создать основные папки
|
||
mkdir -p components/navigation
|
||
mkdir -p components/layout
|
||
mkdir -p components/dashboard
|
||
mkdir -p components/chat
|
||
mkdir -p components/video
|
||
mkdir -p components/common
|
||
|
||
mkdir -p contexts
|
||
mkdir -p hooks
|
||
mkdir -p api
|
||
mkdir -p lib
|
||
mkdir -p styles
|
||
mkdir -p types
|
||
|
||
# Создать группы маршрутов
|
||
mkdir -p app/\(auth\)/login
|
||
mkdir -p app/\(auth\)/register
|
||
mkdir -p app/\(protected\)/dashboard/mentor
|
||
mkdir -p app/\(protected\)/dashboard/client
|
||
mkdir -p app/\(protected\)/schedule
|
||
mkdir -p app/\(protected\)/chat
|
||
```
|
||
|
||
### Шаг 4: Создание базовых файлов
|
||
|
||
#### `types/material-web.d.ts`:
|
||
```typescript
|
||
declare namespace JSX {
|
||
interface IntrinsicElements {
|
||
'md-filled-button': any;
|
||
'md-outlined-button': any;
|
||
'md-text-button': any;
|
||
'md-filled-text-field': any;
|
||
'md-outlined-text-field': any;
|
||
'md-elevated-card': any;
|
||
'md-list': any;
|
||
'md-list-item': any;
|
||
'md-navigation-bar': any;
|
||
'md-navigation-tab': any;
|
||
'md-icon': any;
|
||
'md-icon-button': any;
|
||
'md-dialog': any;
|
||
'md-circular-progress': any;
|
||
// ... добавить остальные
|
||
}
|
||
}
|
||
```
|
||
|
||
#### `lib/material-components.ts`:
|
||
```typescript
|
||
// Импортировать все нужные Material компоненты
|
||
import '@material/web/button/filled-button.js';
|
||
import '@material/web/button/outlined-button.js';
|
||
import '@material/web/textfield/outlined-text-field.js';
|
||
import '@material/web/labs/card/elevated-card.js';
|
||
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/list/list.js';
|
||
import '@material/web/list/list-item.js';
|
||
// ... добавить остальные по необходимости
|
||
```
|
||
|
||
#### `styles/material-theme.css`:
|
||
```css
|
||
:root {
|
||
--md-sys-color-primary: #7444FD;
|
||
--md-sys-color-on-primary: #FFFFFF;
|
||
--md-sys-color-primary-container: #FAF8FF;
|
||
--md-sys-color-on-primary-container: #282C32;
|
||
--md-sys-color-surface: #FFFFFF;
|
||
--md-sys-color-on-surface: #282C32;
|
||
--md-sys-color-background: #F6F7FF;
|
||
--md-sys-color-on-background: #282C32;
|
||
}
|
||
|
||
[data-theme="dark"] {
|
||
--md-sys-color-primary: #9D6AFF;
|
||
--md-sys-color-surface: #161921;
|
||
--md-sys-color-on-surface: #FFFFFF;
|
||
--md-sys-color-background: #161921;
|
||
}
|
||
```
|
||
|
||
#### `styles/material-grid.css`:
|
||
```css
|
||
.md-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(4, 1fr);
|
||
gap: 16px;
|
||
padding: 0 16px;
|
||
}
|
||
|
||
@media (min-width: 600px) {
|
||
.md-grid {
|
||
grid-template-columns: repeat(8, 1fr);
|
||
gap: 24px;
|
||
}
|
||
}
|
||
|
||
@media (min-width: 840px) {
|
||
.md-grid {
|
||
grid-template-columns: repeat(12, 1fr);
|
||
}
|
||
}
|
||
|
||
.md-col-4 { grid-column: span 4; }
|
||
.md-col-6 { grid-column: span 6; }
|
||
.md-col-12 { grid-column: span 12; }
|
||
```
|
||
|
||
#### `styles/ios-material.css`:
|
||
```css
|
||
/* iOS 24+ стилизация Material компонентов */
|
||
md-navigation-bar {
|
||
--md-navigation-bar-container-color: rgba(255, 255, 255, 0.8);
|
||
backdrop-filter: blur(20px);
|
||
-webkit-backdrop-filter: blur(20px);
|
||
border-radius: 24px 24px 0 0;
|
||
border-top: 0.5px solid rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
md-elevated-card {
|
||
--md-elevated-card-container-shape: 20px;
|
||
backdrop-filter: blur(20px);
|
||
}
|
||
|
||
md-filled-button {
|
||
--md-filled-button-container-shape: 16px;
|
||
}
|
||
```
|
||
|
||
#### `app/layout.tsx`:
|
||
```typescript
|
||
import '@/lib/material-components';
|
||
import '@/styles/material-theme.css';
|
||
import '@/styles/material-grid.css';
|
||
import '@/styles/ios-material.css';
|
||
import './globals.css';
|
||
|
||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||
return (
|
||
<html lang="ru">
|
||
<head>
|
||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet" />
|
||
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" rel="stylesheet" />
|
||
</head>
|
||
<body>{children}</body>
|
||
</html>
|
||
);
|
||
}
|
||
```
|
||
|
||
### Шаг 5: Создание первой страницы (Login)
|
||
|
||
#### `app/(auth)/login/page.tsx`:
|
||
```tsx
|
||
'use client';
|
||
|
||
export default function LoginPage() {
|
||
return (
|
||
<div className="md-grid" style={{ minHeight: '100vh', alignItems: 'center' }}>
|
||
<div className="md-col-4 md-col-sm-8 md-col-md-6" style={{ margin: '0 auto' }}>
|
||
<md-elevated-card style={{ padding: '32px' }}>
|
||
<h1 className="md-typescale-headline-medium" style={{ marginBottom: '24px', color: 'var(--md-sys-color-on-surface)' }}>
|
||
Вход в систему
|
||
</h1>
|
||
|
||
<form>
|
||
<md-outlined-text-field
|
||
label="Email"
|
||
type="email"
|
||
required
|
||
style={{ width: '100%', marginBottom: '16px' }}
|
||
></md-outlined-text-field>
|
||
|
||
<md-outlined-text-field
|
||
label="Пароль"
|
||
type="password"
|
||
required
|
||
style={{ width: '100%', marginBottom: '24px' }}
|
||
></md-outlined-text-field>
|
||
|
||
<md-filled-button type="submit" style={{ width: '100%' }}>
|
||
Войти
|
||
</md-filled-button>
|
||
</form>
|
||
</md-elevated-card>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
```
|
||
|
||
### Шаг 6: Запуск проекта
|
||
|
||
```bash
|
||
# Локально
|
||
npm run dev
|
||
|
||
# Откройте http://localhost:3000
|
||
```
|
||
|
||
---
|
||
|
||
## 🐳 Docker
|
||
|
||
### Создать `Dockerfile`:
|
||
|
||
```dockerfile
|
||
FROM node:20-alpine AS development
|
||
WORKDIR /app
|
||
COPY package*.json ./
|
||
RUN npm install
|
||
COPY . .
|
||
EXPOSE 3000
|
||
CMD ["npm", "run", "dev"]
|
||
```
|
||
|
||
### Создать `.dockerignore`:
|
||
|
||
```
|
||
node_modules
|
||
.next
|
||
.env.local
|
||
npm-debug.log*
|
||
.DS_Store
|
||
```
|
||
|
||
### Обновить `docker-compose.yml` (в корне проекта):
|
||
|
||
```yaml
|
||
# Закомментировать старый 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
|
||
```
|
||
|
||
### Запуск через Docker:
|
||
|
||
```bash
|
||
# Из корня проекта
|
||
docker compose up front_material
|
||
|
||
# Или все сервисы
|
||
docker compose up
|
||
```
|
||
|
||
---
|
||
|
||
## 📚 Документация
|
||
|
||
1. **START_HERE.md** (этот файл) - Начните отсюда
|
||
2. **QUICK_START.md** - Быстрый старт с командами
|
||
3. **IMPLEMENTATION_PLAN.md** - Полный план реализации (8 этапов)
|
||
4. **TASKS_SUMMARY.md** - Краткое резюме задач
|
||
5. **MATERIAL_COMPONENTS_GUIDE.md** - Примеры использования Material компонентов
|
||
6. **STRUCTURE.md** - Структура проекта
|
||
|
||
---
|
||
|
||
## ⏭️ Следующие шаги
|
||
|
||
После создания базового проекта:
|
||
|
||
1. Создать AuthContext (`contexts/AuthContext.tsx`)
|
||
2. Создать API клиент (`api/client.ts`)
|
||
3. Создать Bottom Navigation Bar (`components/navigation/BottomNavigationBar.tsx`)
|
||
4. Создать Protected Layout (`app/(protected)/layout.tsx`)
|
||
5. Создать дашборды для каждой роли
|
||
|
||
**Следуйте плану из IMPLEMENTATION_PLAN.md!**
|
||
|
||
---
|
||
|
||
## ⚠️ Важно
|
||
|
||
- ❌ **НЕ используем Tailwind CSS**
|
||
- ❌ **НЕ создаем собственные UI компоненты**
|
||
- ✅ **Используем ТОЛЬКО Material Web Components**
|
||
- ✅ **Сетка из Material Design 3 Grid**
|
||
- ✅ **Стилизация через CSS Variables**
|
||
|
||
---
|
||
|
||
**Готовы начать? Следуйте шагам выше!** 🎉
|