v1.4: Segurança multi-tenant, file serving via API e UX humanizada
- Validação cross-tenant no login e rotas protegidas
- File serving via /api/files/{bucket}/{path} (eliminação DNS)
- Mensagens de erro humanizadas inline (sem pop-ups)
- Middleware tenant detection via headers customizados
- Upload de logos retorna URLs via API
- README atualizado com changelog v1.4 completo
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { getUser } from '@/lib/auth';
|
||||
import {
|
||||
RocketLaunchIcon,
|
||||
ChartBarIcon,
|
||||
@@ -16,6 +18,21 @@ import {
|
||||
} from '@heroicons/react/24/outline';
|
||||
|
||||
export default function DashboardPage() {
|
||||
const [userName, setUserName] = useState('');
|
||||
const [greeting, setGreeting] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const user = getUser();
|
||||
if (user) {
|
||||
setUserName(user.name.split(' ')[0]); // Primeiro nome
|
||||
}
|
||||
|
||||
const hour = new Date().getHours();
|
||||
if (hour >= 5 && hour < 12) setGreeting('Bom dia');
|
||||
else if (hour >= 12 && hour < 18) setGreeting('Boa tarde');
|
||||
else setGreeting('Boa noite');
|
||||
}, []);
|
||||
|
||||
const overviewStats = [
|
||||
{ name: 'Receita Total (Mês)', value: 'R$ 124.500', change: '+12%', changeType: 'increase', icon: ChartBarIcon, color: 'green' },
|
||||
{ name: 'Novos Leads', value: '45', change: '+5%', changeType: 'increase', icon: RocketLaunchIcon, color: 'blue' },
|
||||
@@ -89,14 +106,25 @@ export default function DashboardPage() {
|
||||
return (
|
||||
<div className="p-6 h-full overflow-auto">
|
||||
<div className="space-y-8">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
Visão Geral da Agência
|
||||
</h1>
|
||||
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
Acompanhe o desempenho de todos os módulos em tempo real
|
||||
</p>
|
||||
{/* Header Personalizado */}
|
||||
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h1 className="text-2xl font-heading font-bold text-gray-900 dark:text-white">
|
||||
{greeting}, {userName || 'Administrador'}! 👋
|
||||
</h1>
|
||||
<p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
|
||||
Aqui está o resumo da sua agência hoje. Tudo parece estar sob controle.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-xs font-medium px-3 py-1 rounded-full bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400 border border-green-200 dark:border-green-800 flex items-center gap-1">
|
||||
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
|
||||
Sistema Operacional
|
||||
</span>
|
||||
<span className="text-xs text-gray-500 dark:text-gray-400">
|
||||
{new Date().toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long' })}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Top Stats */}
|
||||
|
||||
Reference in New Issue
Block a user