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:
12
front-end-dash.aggios.app/app/(auth)/LayoutWrapper.tsx
Normal file
12
front-end-dash.aggios.app/app/(auth)/LayoutWrapper.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
1507
front-end-dash.aggios.app/app/(auth)/cadastro/page.tsx
Normal file
1507
front-end-dash.aggios.app/app/(auth)/cadastro/page.tsx
Normal file
File diff suppressed because it is too large
Load Diff
17
front-end-dash.aggios.app/app/(auth)/layout.tsx
Normal file
17
front-end-dash.aggios.app/app/(auth)/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
275
front-end-dash.aggios.app/app/(auth)/login/page.tsx
Normal file
275
front-end-dash.aggios.app/app/(auth)/login/page.tsx
Normal 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 só 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
250
front-end-dash.aggios.app/app/(auth)/recuperar-senha/page.tsx
Normal file
250
front-end-dash.aggios.app/app/(auth)/recuperar-senha/page.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
12
front-end-dash.aggios.app/app/LayoutWrapper.tsx
Normal file
12
front-end-dash.aggios.app/app/LayoutWrapper.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
BIN
front-end-dash.aggios.app/app/favicon.ico
Normal file
BIN
front-end-dash.aggios.app/app/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
94
front-end-dash.aggios.app/app/globals.css
Normal file
94
front-end-dash.aggios.app/app/globals.css
Normal 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;
|
||||
}
|
||||
63
front-end-dash.aggios.app/app/layout.tsx
Normal file
63
front-end-dash.aggios.app/app/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
146
front-end-dash.aggios.app/app/not-found.tsx
Normal file
146
front-end-dash.aggios.app/app/not-found.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
5
front-end-dash.aggios.app/app/page.tsx
Normal file
5
front-end-dash.aggios.app/app/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function Home() {
|
||||
redirect("/login");
|
||||
}
|
||||
175
front-end-dash.aggios.app/app/painel/page.tsx
Normal file
175
front-end-dash.aggios.app/app/painel/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user