Update src/app/dashboard/page.tsx
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { ThemeProvider } from '@/providers/themeProvider/ThemeProvider';
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
|
||||
import FooterBase from '@/components/sections/footer/FooterBase';
|
||||
import { LogOut, User, Settings } from 'lucide-react';
|
||||
import { LogOut, User, Mail, Zap } from 'lucide-react';
|
||||
|
||||
interface User {
|
||||
interface UserData {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
@@ -15,34 +15,48 @@ interface User {
|
||||
|
||||
export default function DashboardPage() {
|
||||
const router = useRouter();
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [user, setUser] = useState<UserData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
// Check if user is authenticated
|
||||
const token = localStorage.getItem('token');
|
||||
const userData = localStorage.getItem('user');
|
||||
const checkAuth = async () => {
|
||||
const token = localStorage.getItem("authToken");
|
||||
const userData = localStorage.getItem("user");
|
||||
|
||||
if (!token) {
|
||||
router.push('/auth');
|
||||
return;
|
||||
}
|
||||
if (!token || !userData) {
|
||||
router.push("/auth/login");
|
||||
return;
|
||||
}
|
||||
|
||||
if (userData) {
|
||||
setUser(JSON.parse(userData));
|
||||
}
|
||||
setLoading(false);
|
||||
try {
|
||||
const response = await fetch("/api/auth/verify", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
localStorage.removeItem("authToken");
|
||||
localStorage.removeItem("user");
|
||||
router.push("/auth/login");
|
||||
return;
|
||||
}
|
||||
|
||||
setUser(JSON.parse(userData));
|
||||
} catch (err) {
|
||||
setError("Erro ao verificar sessão");
|
||||
console.error(err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkAuth();
|
||||
}, [router]);
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await fetch('/api/auth/logout', { method: 'POST' });
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
router.push('/');
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error);
|
||||
}
|
||||
const handleLogout = () => {
|
||||
localStorage.removeItem("authToken");
|
||||
localStorage.removeItem("user");
|
||||
router.push("/");
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
@@ -59,10 +73,33 @@ export default function DashboardPage() {
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div className="flex items-center justify-center min-h-screen">
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 border-4 border-primary-cta border-t-transparent rounded-full animate-spin mx-auto mb-4" />
|
||||
<p className="text-foreground/60">Carregando...</p>
|
||||
<div className="inline-block animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-primary-cta"></div>
|
||||
<p className="mt-4 text-foreground/60">Carregando...</p>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="elastic-effect"
|
||||
defaultTextAnimation="entrance-slide"
|
||||
borderRadius="pill"
|
||||
contentWidth="smallMedium"
|
||||
sizing="mediumSizeLargeTitles"
|
||||
background="blurBottom"
|
||||
cardStyle="gradient-bordered"
|
||||
primaryButtonStyle="flat"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="extrabold"
|
||||
>
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<p className="text-red-500">{error}</p>
|
||||
</div>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
@@ -91,92 +128,82 @@ export default function DashboardPage() {
|
||||
{ name: "Comunidade", id: "community" },
|
||||
{ name: "Perfil", id: "profile" }
|
||||
]}
|
||||
button={{ text: "Sair", onClick: handleLogout }}
|
||||
button={{ text: "Sair", href: "/" }}
|
||||
brandName="FitFlow Pro"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-background py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div className="min-h-screen px-4 py-20">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
{/* Welcome Section */}
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-extrabold text-foreground mb-2">
|
||||
Bem-vindo de volta, {user?.name}!
|
||||
</h1>
|
||||
<p className="text-foreground/60">Aqui está seu dashboard pessoal de fitness</p>
|
||||
</div>
|
||||
<h1 className="text-4xl font-bold mb-8">Dashboard</h1>
|
||||
|
||||
{/* Quick Stats Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8">
|
||||
{[
|
||||
{ label: 'Treinos', value: '24', icon: '💪' },
|
||||
{ label: 'Calorias', value: '2.4k', icon: '🔥' },
|
||||
{ label: 'Passos', value: '15.2k', icon: '👣' },
|
||||
{ label: 'Sequência', value: '7 dias', icon: '🔥' },
|
||||
].map((stat, idx) => (
|
||||
<div key={idx} className="bg-card rounded-lg p-6 border border-background-accent">
|
||||
<div className="text-3xl mb-2">{stat.icon}</div>
|
||||
<p className="text-foreground/60 text-sm mb-1">{stat.label}</p>
|
||||
<p className="text-2xl font-bold text-foreground">{stat.value}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* User Profile Card */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-card rounded-lg p-6 border border-background-accent">
|
||||
<div className="flex items-center justify-center w-16 h-16 rounded-full bg-primary-cta/10 mb-4">
|
||||
<User className="w-8 h-8 text-primary-cta" />
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-foreground mb-1">{user?.name}</h2>
|
||||
<p className="text-foreground/60 text-sm mb-6">{user?.email}</p>
|
||||
<button className="w-full py-2 px-4 bg-secondary-cta text-foreground rounded-lg hover:opacity-90 transition flex items-center justify-center gap-2">
|
||||
<Settings className="w-4 h-4" />
|
||||
Configurações
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Recent Activity */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-card rounded-lg p-6 border border-background-accent">
|
||||
<h3 className="text-lg font-bold text-foreground mb-4">Atividade Recente</h3>
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{ title: 'Treino de Perna', time: 'Hoje às 10:30', status: '✅' },
|
||||
{ title: 'Corida Matinal', time: 'Ontem às 06:00', status: '✅' },
|
||||
{ title: 'Treino de Costas', time: '2 dias atrás', status: '✅' },
|
||||
].map((activity, idx) => (
|
||||
<div key={idx} className="flex items-center justify-between pb-4 border-b border-background-accent last:border-0 last:pb-0">
|
||||
{user && (
|
||||
<div className="grid gap-6">
|
||||
<div className="bg-card rounded-2xl p-8 shadow-lg border border-foreground/10">
|
||||
<h2 className="text-2xl font-bold mb-6">Bem-vindo, {user.name}!</h2>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<User className="w-6 h-6 text-primary-cta" />
|
||||
<div>
|
||||
<p className="font-medium text-foreground">{activity.title}</p>
|
||||
<p className="text-sm text-foreground/60">{activity.time}</p>
|
||||
<p className="text-sm text-foreground/60">Nome</p>
|
||||
<p className="font-semibold">{user.name}</p>
|
||||
</div>
|
||||
<span className="text-lg">{activity.status}</span>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex items-center space-x-3">
|
||||
<Mail className="w-6 h-6 text-primary-cta" />
|
||||
<div>
|
||||
<p className="text-sm text-foreground/60">Email</p>
|
||||
<p className="font-semibold">{user.email}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="bg-background rounded-lg p-4">
|
||||
<p className="text-sm text-foreground/60 mb-2">Status da Sessão</p>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
||||
<p className="font-semibold text-green-500">Conectado</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-gradient-to-br from-primary-cta/20 to-accent/20 rounded-2xl p-6 border border-primary-cta/20">
|
||||
<Zap className="w-8 h-8 text-primary-cta mb-2" />
|
||||
<h3 className="text-lg font-semibold mb-1">Treinos</h3>
|
||||
<p className="text-3xl font-bold text-primary-cta">0</p>
|
||||
<p className="text-sm text-foreground/60 mt-2">Treinos concluídos</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-br from-accent/20 to-secondary-cta/20 rounded-2xl p-6 border border-accent/20">
|
||||
<Zap className="w-8 h-8 text-accent mb-2" />
|
||||
<h3 className="text-lg font-semibold mb-1">Nutrição</h3>
|
||||
<p className="text-3xl font-bold text-accent">0</p>
|
||||
<p className="text-sm text-foreground/60 mt-2">Refeições rastreadas</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-gradient-to-br from-secondary-cta/20 to-primary-cta/20 rounded-2xl p-6 border border-secondary-cta/20">
|
||||
<Zap className="w-8 h-8 text-secondary-cta mb-2" />
|
||||
<h3 className="text-lg font-semibold mb-1">Cardio</h3>
|
||||
<p className="text-3xl font-bold text-secondary-cta">0 km</p>
|
||||
<p className="text-sm text-foreground/60 mt-2">Distância total</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="mt-8 grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{[
|
||||
{ label: 'Iniciar Treino', color: 'bg-primary-cta' },
|
||||
{ label: 'Registrar Refeição', color: 'bg-accent' },
|
||||
{ label: 'Ver Progresso', color: 'bg-secondary-cta' },
|
||||
].map((btn, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
className={`${btn.color} text-background font-semibold py-3 px-6 rounded-lg hover:opacity-90 transition`}
|
||||
onClick={handleLogout}
|
||||
className="w-full bg-red-500 hover:bg-red-600 text-white py-3 rounded-lg font-semibold transition flex items-center justify-center space-x-2"
|
||||
>
|
||||
{btn.label}
|
||||
<LogOut className="w-5 h-5" />
|
||||
<span>Sair da Conta</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -185,7 +212,7 @@ export default function DashboardPage() {
|
||||
columns={[
|
||||
{
|
||||
title: "Produto", items: [
|
||||
{ label: "Dashboard", href: "dashboard" },
|
||||
{ label: "Dashboard", href: "/dashboard" },
|
||||
{ label: "Treino", href: "training" },
|
||||
{ label: "Nutrição", href: "nutrition" },
|
||||
{ label: "Cardio Hub", href: "cardio" }
|
||||
|
||||
Reference in New Issue
Block a user