feat: site institucional completo com design system - Implementa\u00e7\u00e3o do site institucional da Aggios com design system completo incluindo gradientes, tipografia, componentes e se\u00e7\u00f5es de recursos, pre\u00e7os e CTA

This commit is contained in:
Erik Silva
2025-12-07 02:19:08 -03:00
parent 53f240a4da
commit bf6707e746
90 changed files with 25927 additions and 1 deletions

View File

@@ -0,0 +1,12 @@
'use client';
import { ThemeProvider } from '@/contexts/ThemeContext';
import { ReactNode } from 'react';
export default function AuthLayoutWrapper({ children }: { children: ReactNode }) {
return (
<ThemeProvider>
{children}
</ThemeProvider>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
"use client";
import { ThemeProvider } from '@/contexts/ThemeContext';
export default function LoginLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ThemeProvider>
<div className="min-h-screen bg-[#FDFDFC] dark:bg-gray-900">
{children}
</div>
</ThemeProvider>
);
}

View File

@@ -0,0 +1,275 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { Button, Input, Checkbox } from "@/components/ui";
import toast, { Toaster } from 'react-hot-toast';
import { saveAuth } from '@/lib/auth';
import { API_ENDPOINTS, apiRequest } from '@/lib/api';
import dynamic from 'next/dynamic';
const ThemeToggle = dynamic(() => import('@/components/ThemeToggle'), { ssr: false });
export default function LoginPage() {
const [isLoading, setIsLoading] = useState(false);
const [formData, setFormData] = useState({
email: "",
password: "",
rememberMe: false,
});
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Validações básicas
if (!formData.email) {
toast.error('Por favor, insira seu email');
return;
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
toast.error('Por favor, insira um email válido');
return;
}
if (!formData.password) {
toast.error('Por favor, insira sua senha');
return;
}
setIsLoading(true);
try {
const response = await fetch('http://localhost:3000/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: formData.email,
password: formData.password,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || 'Credenciais inválidas');
}
const data = await response.json();
// Salvar token e dados do usuário
localStorage.setItem('token', data.token);
localStorage.setItem('user', JSON.stringify(data.user));
toast.success('Login realizado com sucesso! Redirecionando...');
setTimeout(() => {
window.location.href = '/painel';
}, 1000);
} catch (error: any) {
toast.error(error.message || 'Erro ao fazer login. Verifique suas credenciais.');
setIsLoading(false);
}
}; return (
<>
<Toaster
position="top-center"
toastOptions={{
duration: 5000,
style: {
background: '#FFFFFF',
color: '#000000',
padding: '16px',
borderRadius: '8px',
border: '1px solid #E5E5E5',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
},
error: {
icon: '⚠️',
style: {
background: '#ff3a05',
color: '#FFFFFF',
border: 'none',
},
},
success: {
icon: '✓',
style: {
background: '#10B981',
color: '#FFFFFF',
border: 'none',
},
},
}}
/>
<div className="flex min-h-screen">
{/* Lado Esquerdo - Formulário */}
<div className="w-full lg:w-1/2 flex items-center justify-center px-6 sm:px-12 py-12">
<div className="w-full max-w-md">
{/* Logo mobile */}
<div className="lg:hidden text-center mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080]">
<h1 className="text-3xl font-bold text-white">aggios</h1>
</div>
</div>
{/* Theme Toggle */}
<div className="flex justify-end mb-4">
<ThemeToggle />
</div>
{/* Header */}
<div className="mb-8">
<h2 className="text-[28px] font-bold text-[#000000] dark:text-white">
Bem-vindo de volta
</h2>
<p className="text-[14px] text-[#7D7D7D] dark:text-gray-400 mt-2">
Entre com suas credenciais para acessar o painel
</p>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-5">
<Input
label="Email"
type="email"
placeholder="seu@email.com"
leftIcon="ri-mail-line"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
required
/>
<Input
label="Senha"
type="password"
placeholder="Digite sua senha"
leftIcon="ri-lock-line"
value={formData.password}
onChange={(e) =>
setFormData({ ...formData, password: e.target.value })
}
required
/>
<div className="flex items-center justify-between">
<Checkbox
label="Lembrar de mim"
checked={formData.rememberMe}
onChange={(e) =>
setFormData({ ...formData, rememberMe: e.target.checked })
}
/>
<Link
href="/recuperar-senha"
className="text-[14px] gradient-text hover:underline font-medium cursor-pointer"
>
Esqueceu a senha?
</Link>
</div>
<Button
type="submit"
variant="primary"
className="w-full"
size="lg"
isLoading={isLoading}
>
Entrar
</Button>
</form>
{/* Divider */}
<div className="relative my-8">
<div className="absolute inset-0 flex items-center">
<div className="w-full border-t border-[#E5E5E5]" />
</div>
<div className="relative flex justify-center text-[13px]">
<span className="px-4 bg-white text-[#7D7D7D]">
ou continue com
</span>
</div>
</div>
{/* Social Login */}
<div className="grid grid-cols-2 gap-4">
<Button variant="outline" leftIcon="ri-google-fill">
Google
</Button>
<Button variant="outline" leftIcon="ri-microsoft-fill">
Microsoft
</Button>
</div>
{/* Sign up link */}
<p className="text-center mt-8 text-[14px] text-[#7D7D7D]">
Não tem uma conta?{" "}
<Link href="/cadastro" className="gradient-text font-medium hover:underline cursor-pointer">
Criar conta
</Link>
</p>
</div>
</div>
{/* Lado Direito - Branding */}
<div className="hidden lg:flex lg:w-1/2 relative overflow-hidden" style={{ background: 'linear-gradient(90deg, #FF3A05, #FF0080)' }}>
<div className="relative z-10 flex flex-col justify-center items-center w-full p-12 text-white">
{/* Logo */}
<div className="mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-white/10 backdrop-blur-sm border border-white/20">
<h1 className="text-5xl font-bold tracking-tight bg-linear-to-r from-white to-white/80 bg-clip-text text-transparent">
aggios
</h1>
</div>
</div>
{/* Conteúdo */}
<div className="max-w-lg text-center">
<div className="w-20 h-20 rounded-2xl bg-white/20 flex items-center justify-center mb-6 mx-auto">
<i className="ri-dashboard-line text-4xl" />
</div>
<h2 className="text-4xl font-bold mb-4">Gerencie seus projetos com facilidade</h2>
<p className="text-white/80 text-lg mb-8">
Tenha controle total sobre seus projetos, equipe e clientes em um lugar.
</p>
{/* Features */}
<div className="space-y-4 text-left">
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-shield-check-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Gestão Completa</h4>
<p className="text-white/70 text-sm">Controle projetos, tarefas e prazos em tempo real</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-check-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Relatórios Detalhados</h4>
<p className="text-white/70 text-sm">Análises e métricas para tomada de decisão</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-check-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Colaboração em Equipe</h4>
<p className="text-white/70 text-sm">Trabalhe junto com sua equipe de forma eficiente</p>
</div>
</div>
</div>
</div>
</div>
{/* Círculos decorativos */}
<div className="absolute top-0 right-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
<div className="absolute bottom-0 left-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
</div>
</div>
</>
);
}

View File

@@ -0,0 +1,250 @@
"use client";
import { useState } from "react";
import Link from "next/link";
import { Button, Input } from "@/components/ui";
import toast, { Toaster } from 'react-hot-toast';
export default function RecuperarSenhaPage() {
const [isLoading, setIsLoading] = useState(false);
const [email, setEmail] = useState("");
const [emailSent, setEmailSent] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Validações básicas
if (!email) {
toast.error('Por favor, insira seu email');
return;
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
toast.error('Por favor, insira um email válido');
return;
}
setIsLoading(true);
try {
// Simular envio de email
await new Promise((resolve) => setTimeout(resolve, 2000));
setEmailSent(true);
toast.success('Email de recuperação enviado com sucesso!');
} catch (error) {
toast.error('Erro ao enviar email. Tente novamente.');
} finally {
setIsLoading(false);
}
};
return (
<>
<Toaster
position="top-center"
toastOptions={{
duration: 5000,
style: {
background: '#FFFFFF',
color: '#000000',
padding: '16px',
borderRadius: '8px',
border: '1px solid #E5E5E5',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
},
error: {
icon: '⚠️',
style: {
background: '#ff3a05',
color: '#FFFFFF',
border: 'none',
},
},
success: {
icon: '✓',
style: {
background: '#10B981',
color: '#FFFFFF',
border: 'none',
},
},
}}
/>
<div className="flex min-h-screen">
{/* Lado Esquerdo - Formulário */}
<div className="w-full lg:w-1/2 flex items-center justify-center px-6 sm:px-12 py-12">
<div className="w-full max-w-md">
{/* Logo mobile */}
<div className="lg:hidden text-center mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080]">
<h1 className="text-3xl font-bold text-white">aggios</h1>
</div>
</div>
{!emailSent ? (
<>
{/* Header */}
<div className="mb-8">
<h2 className="text-[28px] font-bold text-[#000000]">
Recuperar senha
</h2>
<p className="text-[14px] text-[#7D7D7D] mt-2">
Digite seu email e enviaremos um link para redefinir sua senha
</p>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-5">
<Input
label="Email"
type="email"
placeholder="seu@email.com"
leftIcon="ri-mail-line"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<Button
type="submit"
variant="primary"
className="w-full"
size="lg"
isLoading={isLoading}
>
Enviar link de recuperação
</Button>
</form>
{/* Back to login */}
<div className="mt-6 text-center">
<Link
href="/login"
className="text-[14px] gradient-text hover:underline inline-flex items-center gap-2 font-medium cursor-pointer"
>
<i className="ri-arrow-left-line" />
Voltar para o login
</Link>
</div>
</>
) : (
<>
{/* Success Message */}
<div className="text-center">
<div className="w-20 h-20 rounded-full bg-[#10B981]/10 flex items-center justify-center mx-auto mb-6">
<i className="ri-mail-check-line text-4xl text-[#10B981]" />
</div>
<h2 className="text-[28px] font-bold text-[#000000] mb-4">
Email enviado!
</h2>
<p className="text-[14px] text-[#7D7D7D] mb-2">
Enviamos um link de recuperação para:
</p>
<p className="text-[16px] font-semibold text-[#000000] mb-6">
{email}
</p>
<div className="p-6 bg-[#F0F9FF] border border-[#BAE6FD] rounded-md text-left mb-6">
<div className="flex gap-4">
<i className="ri-information-line text-[#0EA5E9] text-xl mt-0.5" />
<div>
<h4 className="text-sm font-semibold text-[#000000] mb-1">
Verifique sua caixa de entrada
</h4>
<p className="text-xs text-[#7D7D7D]">
Clique no link que enviamos para redefinir sua senha.
Se não receber em alguns minutos, verifique sua pasta de spam.
</p>
</div>
</div>
</div>
<Button
variant="outline"
className="w-full mb-4"
onClick={() => setEmailSent(false)}
>
Enviar novamente
</Button>
<Link
href="/login"
className="text-[14px] gradient-text hover:underline inline-flex items-center gap-2 font-medium cursor-pointer"
>
<i className="ri-arrow-left-line" />
Voltar para o login
</Link>
</div>
</>
)}
</div>
</div>
{/* Lado Direito - Branding */}
<div className="hidden lg:flex lg:w-1/2 relative overflow-hidden" style={{ background: 'linear-gradient(90deg, #FF3A05, #FF0080)' }}>
<div className="relative z-10 flex flex-col justify-center items-center w-full p-12 text-white">
{/* Logo */}
<div className="mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-white/10 backdrop-blur-sm border border-white/20">
<h1 className="text-5xl font-bold tracking-tight bg-linear-to-r from-white to-white/80 bg-clip-text text-transparent">
aggios
</h1>
</div>
</div>
{/* Conteúdo */}
<div className="max-w-lg text-center">
<div className="w-20 h-20 rounded-2xl bg-white/20 flex items-center justify-center mb-6 mx-auto">
<i className="ri-lock-password-line text-4xl" />
</div>
<h2 className="text-4xl font-bold mb-4">Recuperação segura</h2>
<p className="text-white/80 text-lg mb-8">
Protegemos seus dados com os mais altos padrões de segurança.
Seu link de recuperação é único e expira em 24 horas.
</p>
{/* Features */}
<div className="space-y-4 text-left">
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-shield-check-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Criptografia de ponta</h4>
<p className="text-white/70 text-sm">Seus dados são protegidos com tecnologia de última geração</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-time-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Link temporário</h4>
<p className="text-white/70 text-sm">O link expira em 24h para sua segurança</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-customer-service-2-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Suporte disponível</h4>
<p className="text-white/70 text-sm">Nossa equipe está pronta para ajudar caso precise</p>
</div>
</div>
</div>
</div>
</div>
{/* Círculos decorativos */}
<div className="absolute top-0 right-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
<div className="absolute bottom-0 left-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
</div>
</div>
</>
);
}

View File

@@ -0,0 +1,12 @@
'use client';
import { ThemeProvider } from '@/contexts/ThemeContext';
import { ReactNode } from 'react';
export default function LayoutWrapper({ children }: { children: ReactNode }) {
return (
<ThemeProvider>
{children}
</ThemeProvider>
);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,94 @@
@import "tailwindcss";
@import "remixicon/fonts/remixicon.css";
:root {
/* Cores do Design System Aggios */
--primary: #FF3A05;
--secondary: #FF0080;
--background: #FDFDFC;
--foreground: #000000;
--text-secondary: #7D7D7D;
--border: #E5E5E5;
--white: #FFFFFF;
/* Gradiente */
--gradient: linear-gradient(90deg, #FF3A05, #FF0080);
--gradient-text: linear-gradient(to right, #FF3A05, #FF0080);
/* Espaçamentos */
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 32px;
--space-2xl: 48px;
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-text-secondary: var(--text-secondary);
--color-border: var(--border);
--font-sans: var(--font-inter);
--font-heading: var(--font-open-sans);
--font-mono: var(--font-fira-code);
}
body {
background: var(--background);
color: var(--foreground);
font-family: var(--font-sans), Arial, Helvetica, sans-serif;
line-height: 1.5;
}
/* Estilos base dos inputs */
input,
select,
textarea {
font-size: 14px;
box-shadow: none !important;
}
input:focus,
select:focus,
textarea:focus {
box-shadow: none !important;
outline: none !important;
}
/* Focus visible para acessibilidade */
*:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
/* Hero section gradient text */
.gradient-text {
background: var(--gradient-text);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Hover gradient text */
.hover\:gradient-text:hover {
background: var(--gradient-text);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* Group hover para remover gradiente e usar cor sólida */
.group:hover .group-hover\:text-white {
background: none !important;
-webkit-background-clip: unset !important;
-webkit-text-fill-color: unset !important;
background-clip: unset !important;
color: white !important;
}
/* Smooth scroll */
html {
scroll-behavior: smooth;
}

View File

@@ -0,0 +1,63 @@
import type { Metadata } from "next";
import { Inter, Open_Sans, Fira_Code } from "next/font/google";
import "./globals.css";
import LayoutWrapper from "./LayoutWrapper";
const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
weight: ["400", "500", "600"],
});
const openSans = Open_Sans({
variable: "--font-open-sans",
subsets: ["latin"],
weight: ["700"],
});
const firaCode = Fira_Code({
variable: "--font-fira-code",
subsets: ["latin"],
weight: ["400", "600"],
});
export const metadata: Metadata = {
title: "Aggios - Dashboard",
description: "Plataforma SaaS para agências digitais",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="pt-BR">
<head>
<script
dangerouslySetInnerHTML={{
__html: `
(function() {
const theme = localStorage.getItem('theme');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const isDark = theme === 'dark' || (!theme && prefersDark);
if (isDark) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
})();
`,
}}
/>
</head>
<body
className={`${inter.variable} ${openSans.variable} ${firaCode.variable} antialiased bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors`}
>
<LayoutWrapper>
{children}
</LayoutWrapper>
</body>
</html>
);
}

View File

@@ -0,0 +1,146 @@
"use client";
import Link from "next/link";
import { Button } from "@/components/ui";
export default function NotFound() {
return (
<div className="flex min-h-screen">
{/* Lado Esquerdo - Conteúdo 404 */}
<div className="w-full lg:w-1/2 flex items-center justify-center px-6 sm:px-12 py-12">
<div className="w-full max-w-md text-center">
{/* Logo mobile */}
<div className="lg:hidden mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080]">
<h1 className="text-3xl font-bold text-white">aggios</h1>
</div>
</div>
{/* 404 Number */}
<div className="mb-6">
<h1 className="text-[120px] font-bold leading-none gradient-text">
404
</h1>
</div>
{/* Message */}
<div className="mb-6">
<h2 className="text-[28px] font-bold text-[#000000] mb-2">
Página não encontrada
</h2>
<p className="text-[14px] text-[#7D7D7D] leading-relaxed">
Desculpe, a página que você está procurando não existe ou foi movida.
Verifique a URL ou volte para a página inicial.
</p>
</div>
{/* Actions */}
<div className="space-y-3">
<Button
variant="primary"
className="w-full"
size="lg"
leftIcon="ri-login-box-line"
onClick={() => window.location.href = '/login'}
>
Fazer login
</Button>
<Button
variant="outline"
className="w-full"
size="lg"
leftIcon="ri-user-add-line"
onClick={() => window.location.href = '/cadastro'}
>
Criar conta
</Button>
</div>
{/* Help Section */}
<div className="mt-8 p-5 bg-[#F5F5F5] rounded-lg text-left">
<h4 className="text-[13px] font-semibold text-[#000000] mb-3 flex items-center gap-2">
<i className="ri-questionnaire-line text-[16px] gradient-text" />
Precisa de ajuda?
</h4>
<ul className="text-[13px] text-[#7D7D7D] space-y-2">
<li className="flex items-start gap-2">
<i className="ri-arrow-right-s-line text-[16px] gradient-text mt-0.5" />
<span>Verifique se a URL está correta</span>
</li>
<li className="flex items-start gap-2">
<i className="ri-arrow-right-s-line text-[16px] gradient-text mt-0.5" />
<span>Tente buscar no menu principal</span>
</li>
<li className="flex items-start gap-2">
<i className="ri-arrow-right-s-line text-[16px] gradient-text mt-0.5" />
<span>Entre em contato com o suporte se o problema persistir</span>
</li>
</ul>
</div>
</div>
</div>
{/* Lado Direito - Branding */}
<div className="hidden lg:flex lg:w-1/2 relative overflow-hidden" style={{ background: 'linear-gradient(90deg, #FF3A05, #FF0080)' }}>
<div className="relative z-10 flex flex-col justify-center items-center w-full p-12 text-white">
{/* Logo */}
<div className="mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-white/10 backdrop-blur-sm border border-white/20">
<h1 className="text-5xl font-bold tracking-tight bg-linear-to-r from-white to-white/80 bg-clip-text text-transparent">
aggios
</h1>
</div>
</div>
{/* Conteúdo */}
<div className="max-w-lg text-center">
<div className="w-20 h-20 rounded-2xl bg-white/20 flex items-center justify-center mb-6 mx-auto">
<i className="ri-compass-3-line text-4xl" />
</div>
<h2 className="text-4xl font-bold mb-4">Perdido? Estamos aqui!</h2>
<p className="text-white/80 text-lg mb-8">
Mesmo que esta página não exista, temos muitas outras funcionalidades incríveis
esperando por você no Aggios.
</p>
{/* Features */}
<div className="space-y-4 text-left">
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-dashboard-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Dashboard Completo</h4>
<p className="text-white/70 text-sm">Visualize todos os seus projetos e métricas</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-team-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Gestão de Equipe</h4>
<p className="text-white/70 text-sm">Organize e acompanhe sua equipe</p>
</div>
</div>
<div className="flex items-start gap-3">
<div className="w-6 h-6 rounded-full bg-white/20 flex items-center justify-center shrink-0 mt-0.5">
<i className="ri-customer-service-line text-sm" />
</div>
<div>
<h4 className="font-semibold mb-1">Suporte 24/7</h4>
<p className="text-white/70 text-sm">Estamos sempre disponíveis para ajudar</p>
</div>
</div>
</div>
</div>
</div>
{/* Círculos decorativos */}
<div className="absolute top-0 right-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
<div className="absolute bottom-0 left-0 w-96 h-96 bg-white/5 rounded-full blur-3xl" />
</div>
</div>
);
}

View File

@@ -0,0 +1,5 @@
import { redirect } from "next/navigation";
export default function Home() {
redirect("/login");
}

View File

@@ -0,0 +1,175 @@
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { isAuthenticated, getUser, clearAuth } from '@/lib/auth';
export default function PainelPage() {
const router = useRouter();
const [userData, setUserData] = useState<any>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Verificar se usuário está logado
if (!isAuthenticated()) {
router.push('/login');
return;
}
const user = getUser();
if (user) {
setUserData(user);
setLoading(false);
} else {
router.push('/login');
}
}, [router]);
if (loading) {
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#FF3A05] mx-auto mb-4"></div>
<p className="text-gray-600">Carregando...</p>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-50">
{/* Header */}
<header className="bg-white border-b border-gray-200 shadow-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<div className="flex items-center justify-center w-10 h-10 bg-gradient-to-r from-[#FF3A05] to-[#FF0080] rounded-lg">
<span className="text-white font-bold text-lg">A</span>
</div>
<div>
<h1 className="text-xl font-bold text-gray-900">Aggios</h1>
<p className="text-sm text-gray-500">{userData?.company}</p>
</div>
</div>
<div className="flex items-center gap-4">
<div className="text-right">
<p className="text-sm font-medium text-gray-900">{userData?.name}</p>
<p className="text-xs text-gray-500">{userData?.email}</p>
</div>
<button
onClick={() => {
clearAuth();
router.push('/login');
}}
className="px-4 py-2 text-sm font-medium text-gray-700 hover:text-gray-900"
>
Sair
</button>
</div>
</div>
</div>
</header>
{/* Main Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* Welcome Card */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6 mb-6">
<div className="flex items-center gap-4 mb-4">
<div className="flex-shrink-0">
<div className="w-16 h-16 bg-gradient-to-br from-[#FF3A05] to-[#FF0080] rounded-full flex items-center justify-center">
<span className="text-2xl">🎉</span>
</div>
</div>
<div>
<h2 className="text-2xl font-bold text-gray-900">
Bem-vindo ao Aggios, {userData?.name}!
</h2>
<p className="text-gray-600 mt-1">
Sua conta foi criada com sucesso. Este é o seu painel administrativo.
</p>
</div>
</div>
</div>
{/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-6">
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Projetos</p>
<p className="text-3xl font-bold text-gray-900 mt-2">0</p>
</div>
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center">
<svg className="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
</svg>
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Clientes</p>
<p className="text-3xl font-bold text-gray-900 mt-2">0</p>
</div>
<div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center">
<svg className="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">Receita</p>
<p className="text-3xl font-bold text-gray-900 mt-2">R$ 0</p>
</div>
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center">
<svg className="w-6 h-6 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
</div>
</div>
</div>
{/* Next Steps */}
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<h3 className="text-lg font-semibold text-gray-900 mb-4">Próximos Passos</h3>
<div className="space-y-3">
<div className="flex items-start gap-3 p-4 bg-gray-50 rounded-lg">
<div className="flex-shrink-0 w-6 h-6 bg-[#FF3A05] rounded-full flex items-center justify-center text-white text-sm font-bold">
1
</div>
<div>
<h4 className="font-medium text-gray-900">Complete seu perfil</h4>
<p className="text-sm text-gray-600 mt-1">Adicione mais informações sobre sua empresa</p>
</div>
</div>
<div className="flex items-start gap-3 p-4 bg-gray-50 rounded-lg">
<div className="flex-shrink-0 w-6 h-6 bg-[#FF3A05] rounded-full flex items-center justify-center text-white text-sm font-bold">
2
</div>
<div>
<h4 className="font-medium text-gray-900">Adicione seu primeiro cliente</h4>
<p className="text-sm text-gray-600 mt-1">Comece a gerenciar seus clientes</p>
</div>
</div>
<div className="flex items-start gap-3 p-4 bg-gray-50 rounded-lg">
<div className="flex-shrink-0 w-6 h-6 bg-[#FF3A05] rounded-full flex items-center justify-center text-white text-sm font-bold">
3
</div>
<div>
<h4 className="font-medium text-gray-900">Crie seu primeiro projeto</h4>
<p className="text-sm text-gray-600 mt-1">Organize seu trabalho em projetos</p>
</div>
</div>
</div>
</div>
</main>
</div>
);
}