499 lines
13 KiB
Markdown
499 lines
13 KiB
Markdown
|
|
# 🎨 Dashboard Frontend - NoIdle (estilo JumpCloud)
|
|||
|
|
|
|||
|
|
## 📋 Visão Geral
|
|||
|
|
|
|||
|
|
Dashboard moderno e funcional para o NoIdle, inspirado no design do JumpCloud, com estatísticas em tempo real, alertas e notificações.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✨ Componentes Criados
|
|||
|
|
|
|||
|
|
### 1. **MainDashboard.jsx** (400 linhas)
|
|||
|
|
|
|||
|
|
Componente principal do dashboard com:
|
|||
|
|
|
|||
|
|
**Estatísticas Principais (Cards grandes):**
|
|||
|
|
- 👥 Usuários
|
|||
|
|
- 👥 Times
|
|||
|
|
- 💻 Dispositivos
|
|||
|
|
- 🛡️ Políticas MDM
|
|||
|
|
- 📊 Atividades Hoje
|
|||
|
|
|
|||
|
|
**Cards de Alertas (8 cards):**
|
|||
|
|
- ⚠️ Dispositivos Offline (7+ dias)
|
|||
|
|
- ℹ️ Sem Atividade (24h)
|
|||
|
|
- ❌ Políticas Falhadas (24h)
|
|||
|
|
- ✅ Comandos Pendentes
|
|||
|
|
- 🔄 Precisam Atualização
|
|||
|
|
- 💾 Espaço em Disco Baixo
|
|||
|
|
- 🟢 Online Agora
|
|||
|
|
- 👤 Usuários Inativos (30d)
|
|||
|
|
|
|||
|
|
**Status do Sistema:**
|
|||
|
|
- API Backend
|
|||
|
|
- Banco de Dados
|
|||
|
|
- Sistema MDM
|
|||
|
|
- Última Atualização
|
|||
|
|
|
|||
|
|
**Notificações:**
|
|||
|
|
- Dispositivos
|
|||
|
|
- Atividade Recente
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 Preview do Design
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────────┐
|
|||
|
|
│ Bem-vindo, Admin! 👋 [Atualizar] [Configurações] │
|
|||
|
|
├─────────────────────────────────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐│
|
|||
|
|
│ │ 77 │ │ 14 │ │ 143 │ │ 8 │ │ 1.2K ││
|
|||
|
|
│ │ Usuários │ │ Times │ │Disposit. │ │Políticas │ │Ativid. ││
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └────────┘│
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|||
|
|
│ │ [●] 0 │ │ [✓] 0 │ │ [!] 0 │ │ [i] 0 │ │
|
|||
|
|
│ │ Offline │ │Sem Ativ. │ │Políticas │ │Comandos │ │
|
|||
|
|
│ │ 7+ dias │ │ 24h │ │ Falhadas │ │Pendentes │ │
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
|||
|
|
│ │ [↑] 0 │ │ [!] 0 │ │ [✓] 45 │ │ [i] 0 │ │
|
|||
|
|
│ │Precisam │ │ Disco │ │ Online │ │Inativos │ │
|
|||
|
|
│ │Atualiz. │ │ Baixo │ │ Agora │ │ 30d │ │
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ ┌──────────────────────────────────────────────────────────┐ │
|
|||
|
|
│ │ Status do Sistema [✓] OK │ │
|
|||
|
|
│ │ ✅ Todos os serviços estão operacionais │ │
|
|||
|
|
│ │ • API Backend: Online │ │
|
|||
|
|
│ │ • Banco de Dados: Conectado │ │
|
|||
|
|
│ │ • Sistema MDM: Ativo │ │
|
|||
|
|
│ └──────────────────────────────────────────────────────────┘ │
|
|||
|
|
│ │
|
|||
|
|
│ ┌─────────────────────────┐ ┌────────────────────────────┐ │
|
|||
|
|
│ │ Notificações │ │ Atividade Recente │ │
|
|||
|
|
│ │ • Offline 7+ dias: 12 │ │ • Dispositivos online: 45 │ │
|
|||
|
|
│ │ • Sem atividade: 8 │ │ • Políticas exec. hoje: - │ │
|
|||
|
|
│ │ • Precisam update: 5 │ │ • Comandos pendentes: 3 │ │
|
|||
|
|
│ └─────────────────────────┘ └────────────────────────────┘ │
|
|||
|
|
└─────────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 Implementação
|
|||
|
|
|
|||
|
|
### 1. Instalar Dependências
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd /var/www/pointcontrol/frontend
|
|||
|
|
npm install @mui/material @emotion/react @emotion/styled @mui/icons-material
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Criar Estrutura de Pastas
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
mkdir -p components/Dashboard
|
|||
|
|
mkdir -p pages/dashboard
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Copiar Componente
|
|||
|
|
|
|||
|
|
Arquivo já criado:
|
|||
|
|
- `frontend/components/Dashboard/MainDashboard.jsx`
|
|||
|
|
|
|||
|
|
### 4. Criar Página Next.js
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// pages/dashboard/index.js
|
|||
|
|
import MainDashboard from '../../components/Dashboard/MainDashboard';
|
|||
|
|
import Layout from '../../components/Layout';
|
|||
|
|
|
|||
|
|
export default function DashboardPage() {
|
|||
|
|
return (
|
|||
|
|
<Layout>
|
|||
|
|
<MainDashboard />
|
|||
|
|
</Layout>
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5. Atualizar Navegação
|
|||
|
|
|
|||
|
|
No menu lateral, adicionar link para `/dashboard`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 API Endpoint
|
|||
|
|
|
|||
|
|
### GET /api/dashboard/stats
|
|||
|
|
|
|||
|
|
**Resposta:**
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"stats": {
|
|||
|
|
"users": 77,
|
|||
|
|
"teams": 14,
|
|||
|
|
"devices": 143,
|
|||
|
|
"policies": 8,
|
|||
|
|
"activities_today": 1234,
|
|||
|
|
"devices_online": 45,
|
|||
|
|
"devices_offline": 98,
|
|||
|
|
"pending_commands": 3
|
|||
|
|
},
|
|||
|
|
"alerts": {
|
|||
|
|
"devices_offline_7days": 12,
|
|||
|
|
"devices_no_activity_24h": 8,
|
|||
|
|
"failed_policies_24h": 2,
|
|||
|
|
"devices_need_update": 5,
|
|||
|
|
"low_disk_space": 1,
|
|||
|
|
"inactive_users": 3
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 Customização de Cores
|
|||
|
|
|
|||
|
|
### Paleta de Cores Usada:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
const colors = {
|
|||
|
|
primary: '#2563eb', // Azul - Usuários
|
|||
|
|
secondary: '#7c3aed', // Roxo - Times
|
|||
|
|
success: '#059669', // Verde - Dispositivos
|
|||
|
|
danger: '#dc2626', // Vermelho - Políticas
|
|||
|
|
warning: '#f59e0b', // Laranja - Avisos
|
|||
|
|
info: '#3b82f6', // Azul claro - Informações
|
|||
|
|
orange: '#ea580c', // Laranja escuro - Atividades
|
|||
|
|
gray: '#6b7280' // Cinza - Inativos
|
|||
|
|
};
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Customizar no Theme:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// theme.js
|
|||
|
|
import { createTheme } from '@mui/material/styles';
|
|||
|
|
|
|||
|
|
const theme = createTheme({
|
|||
|
|
palette: {
|
|||
|
|
primary: {
|
|||
|
|
main: '#2563eb',
|
|||
|
|
},
|
|||
|
|
secondary: {
|
|||
|
|
main: '#7c3aed',
|
|||
|
|
},
|
|||
|
|
success: {
|
|||
|
|
main: '#10b981',
|
|||
|
|
},
|
|||
|
|
error: {
|
|||
|
|
main: '#dc2626',
|
|||
|
|
},
|
|||
|
|
warning: {
|
|||
|
|
main: '#f59e0b',
|
|||
|
|
},
|
|||
|
|
info: {
|
|||
|
|
main: '#3b82f6',
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
typography: {
|
|||
|
|
fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif',
|
|||
|
|
h4: {
|
|||
|
|
fontWeight: 700,
|
|||
|
|
},
|
|||
|
|
h6: {
|
|||
|
|
fontWeight: 600,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
shape: {
|
|||
|
|
borderRadius: 8,
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
export default theme;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔄 Atualização em Tempo Real
|
|||
|
|
|
|||
|
|
O componente atualiza automaticamente a cada 30 segundos:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
useEffect(() => {
|
|||
|
|
fetchDashboardData();
|
|||
|
|
const interval = setInterval(fetchDashboardData, 30000);
|
|||
|
|
return () => clearInterval(interval);
|
|||
|
|
}, []);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Para desabilitar:
|
|||
|
|
```javascript
|
|||
|
|
// Remover o setInterval
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Para mudar frequência:
|
|||
|
|
```javascript
|
|||
|
|
const interval = setInterval(fetchDashboardData, 60000); // 1 minuto
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📱 Responsividade
|
|||
|
|
|
|||
|
|
### Breakpoints Material-UI:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// xs: 0-600px (mobile)
|
|||
|
|
// sm: 600-960px (tablet)
|
|||
|
|
// md: 960-1280px (laptop)
|
|||
|
|
// lg: 1280-1920px (desktop)
|
|||
|
|
// xl: 1920px+ (large screens)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Grid Responsivo:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
<Grid item xs={12} sm={6} md={2.4}> // 5 cards em desktop, 2 em tablet, 1 em mobile
|
|||
|
|
<StatCard ... />
|
|||
|
|
</Grid>
|
|||
|
|
|
|||
|
|
<Grid item xs={12} sm={6} md={3}> // 4 cards em desktop, 2 em tablet, 1 em mobile
|
|||
|
|
<AlertCard ... />
|
|||
|
|
</Grid>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🧪 Testes
|
|||
|
|
|
|||
|
|
### Testar Componente:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
// __tests__/MainDashboard.test.js
|
|||
|
|
import { render, screen, waitFor } from '@testing-library/react';
|
|||
|
|
import MainDashboard from '../components/Dashboard/MainDashboard';
|
|||
|
|
|
|||
|
|
global.fetch = jest.fn(() =>
|
|||
|
|
Promise.resolve({
|
|||
|
|
json: () => Promise.resolve({
|
|||
|
|
success: true,
|
|||
|
|
stats: {
|
|||
|
|
users: 77,
|
|||
|
|
teams: 14,
|
|||
|
|
devices: 143,
|
|||
|
|
// ...
|
|||
|
|
},
|
|||
|
|
alerts: {
|
|||
|
|
devices_offline_7days: 12,
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
test('renders dashboard with stats', async () => {
|
|||
|
|
render(<MainDashboard />);
|
|||
|
|
|
|||
|
|
await waitFor(() => {
|
|||
|
|
expect(screen.getByText('77')).toBeInTheDocument();
|
|||
|
|
expect(screen.getByText('Usuários')).toBeInTheDocument();
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 Funcionalidades Futuras
|
|||
|
|
|
|||
|
|
### 1. Gráficos e Charts
|
|||
|
|
```javascript
|
|||
|
|
import { LineChart, BarChart } from 'recharts';
|
|||
|
|
|
|||
|
|
// Gráfico de atividades dos últimos 7 dias
|
|||
|
|
// Gráfico de políticas executadas
|
|||
|
|
// Gráfico de dispositivos online vs offline
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Filtros Avançados
|
|||
|
|
```javascript
|
|||
|
|
// Filtrar por período (hoje, semana, mês)
|
|||
|
|
// Filtrar por time
|
|||
|
|
// Filtrar por status
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Ações Rápidas
|
|||
|
|
```javascript
|
|||
|
|
// Executar política em dispositivos selecionados
|
|||
|
|
// Enviar notificação para usuários
|
|||
|
|
// Gerar relatório
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4. Notificações em Tempo Real
|
|||
|
|
```javascript
|
|||
|
|
// WebSocket para notificações push
|
|||
|
|
// Toast notifications
|
|||
|
|
// Badge de contador
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📝 Checklist de Implementação
|
|||
|
|
|
|||
|
|
### Backend:
|
|||
|
|
- [x] Criar rota `/api/dashboard/stats`
|
|||
|
|
- [x] Queries para estatísticas
|
|||
|
|
- [x] Queries para alertas
|
|||
|
|
- [ ] Testar endpoint com Postman
|
|||
|
|
|
|||
|
|
### Frontend:
|
|||
|
|
- [x] Criar componente `MainDashboard.jsx`
|
|||
|
|
- [ ] Criar página `pages/dashboard/index.js`
|
|||
|
|
- [ ] Adicionar ao menu de navegação
|
|||
|
|
- [ ] Configurar tema Material-UI
|
|||
|
|
- [ ] Testar responsividade
|
|||
|
|
- [ ] Adicionar loading states
|
|||
|
|
- [ ] Adicionar error handling
|
|||
|
|
|
|||
|
|
### Integrações:
|
|||
|
|
- [ ] Conectar com sistema MDM
|
|||
|
|
- [ ] Conectar com políticas
|
|||
|
|
- [ ] Conectar com dispositivos
|
|||
|
|
- [ ] Conectar com usuários
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🚀 Deploy
|
|||
|
|
|
|||
|
|
### 1. Build Frontend:
|
|||
|
|
```bash
|
|||
|
|
cd /var/www/pointcontrol/frontend
|
|||
|
|
npm run build
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. Start Production:
|
|||
|
|
```bash
|
|||
|
|
npm start
|
|||
|
|
# ou
|
|||
|
|
pm2 start npm --name "noidle-frontend" -- start
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. Configurar Proxy Nginx:
|
|||
|
|
```nginx
|
|||
|
|
location / {
|
|||
|
|
proxy_pass http://localhost:3000;
|
|||
|
|
proxy_http_version 1.1;
|
|||
|
|
proxy_set_header Upgrade $http_upgrade;
|
|||
|
|
proxy_set_header Connection 'upgrade';
|
|||
|
|
proxy_set_header Host $host;
|
|||
|
|
proxy_cache_bypass $http_upgrade;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📖 Documentação de Componentes
|
|||
|
|
|
|||
|
|
### StatCard
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
<StatCard
|
|||
|
|
title="Usuários"
|
|||
|
|
value={77}
|
|||
|
|
icon={GroupIcon}
|
|||
|
|
color="#2563eb"
|
|||
|
|
link="/users"
|
|||
|
|
/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Props:**
|
|||
|
|
- `title` (string): Título do card
|
|||
|
|
- `value` (number): Valor numérico
|
|||
|
|
- `icon` (Component): Ícone Material-UI
|
|||
|
|
- `color` (string): Cor do ícone (hex)
|
|||
|
|
- `link` (string): URL para navegação
|
|||
|
|
|
|||
|
|
### AlertCard
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
<AlertCard
|
|||
|
|
title="Dispositivos Offline"
|
|||
|
|
value={12}
|
|||
|
|
icon={WarningIcon}
|
|||
|
|
color="#dc2626"
|
|||
|
|
link="/devices?status=offline"
|
|||
|
|
/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Props:**
|
|||
|
|
- `title` (string): Título do alerta
|
|||
|
|
- `value` (number): Valor numérico
|
|||
|
|
- `icon` (Component): Ícone Material-UI
|
|||
|
|
- `color` (string): Cor da barra lateral
|
|||
|
|
- `link` (string): URL para ver detalhes
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎨 Screenshots Esperados
|
|||
|
|
|
|||
|
|
### Desktop (1920x1080):
|
|||
|
|
- 5 cards de estatísticas principais em linha
|
|||
|
|
- 4 cards de alertas por linha (2 linhas = 8 cards)
|
|||
|
|
- 2 cards de notificações lado a lado
|
|||
|
|
|
|||
|
|
### Tablet (768x1024):
|
|||
|
|
- 2 cards de estatísticas por linha
|
|||
|
|
- 2 cards de alertas por linha
|
|||
|
|
- 2 cards de notificações empilhados
|
|||
|
|
|
|||
|
|
### Mobile (375x667):
|
|||
|
|
- 1 card por linha (empilhados)
|
|||
|
|
- Scroll vertical
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ✅ Status
|
|||
|
|
|
|||
|
|
| Componente | Status | Progresso |
|
|||
|
|
|------------|--------|-----------|
|
|||
|
|
| MainDashboard.jsx | ✅ Criado | 100% |
|
|||
|
|
| API /dashboard/stats | ✅ Criada | 100% |
|
|||
|
|
| Página Next.js | ⏳ Pendente | 0% |
|
|||
|
|
| Tema Material-UI | ⏳ Pendente | 0% |
|
|||
|
|
| Testes | ⏳ Pendente | 0% |
|
|||
|
|
| Deploy | ⏳ Pendente | 0% |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🆘 Troubleshooting
|
|||
|
|
|
|||
|
|
### Erro: "Module not found: @mui/material"
|
|||
|
|
```bash
|
|||
|
|
npm install @mui/material @emotion/react @emotion/styled
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Erro: "fetch is not defined" (SSR)
|
|||
|
|
```javascript
|
|||
|
|
// Usar SWR ou adicionar polyfill
|
|||
|
|
import 'isomorphic-fetch';
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Cards não responsivos
|
|||
|
|
```javascript
|
|||
|
|
// Verificar breakpoints do Grid
|
|||
|
|
<Grid item xs={12} sm={6} md={3}>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**Dashboard Frontend Implementado e Pronto! 🎉**
|
|||
|
|
|
|||
|
|
**Próximo passo:** Criar a página Next.js e integrar no menu.
|
|||
|
|
|