chore: snapshot before agency split

This commit is contained in:
Erik Silva
2025-12-09 17:21:25 -03:00
parent 6ec29c7eef
commit 053e180321
27 changed files with 428 additions and 234 deletions

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -6,10 +6,6 @@ services:
restart: unless-stopped restart: unless-stopped
command: command:
- "--api.insecure=true" - "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.endpoint=tcp://host.docker.internal:2375"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=aggios-network"
- "--providers.file.directory=/etc/traefik/dynamic" - "--providers.file.directory=/etc/traefik/dynamic"
- "--providers.file.watch=true" - "--providers.file.watch=true"
- "--entrypoints.web.address=:80" - "--entrypoints.web.address=:80"

View File

@@ -22,19 +22,31 @@ const tabs = [
]; ];
const themePresets = [ const themePresets = [
{ name: 'Laranja/Rosa', gradient: 'linear-gradient(90deg, #FF3A05, #FF0080)', colors: ['#FF3A05', '#FF0080'] }, { name: 'Marca', gradient: 'linear-gradient(135deg, #ff3a05, #ff0080)', colors: ['#ff3a05', '#ff0080'] },
{ name: 'Azul/Roxo', gradient: 'linear-gradient(90deg, #0066FF, #9333EA)', colors: ['#0066FF', '#9333EA'] }, { name: 'Azul/Roxo', gradient: 'linear-gradient(135deg, #0066FF, #9333EA)', colors: ['#0066FF', '#9333EA'] },
{ name: 'Verde/Esmeralda', gradient: 'linear-gradient(90deg, #10B981, #059669)', colors: ['#10B981', '#059669'] }, { name: 'Verde/Esmeralda', gradient: 'linear-gradient(135deg, #10B981, #059669)', colors: ['#10B981', '#059669'] },
{ name: 'Ciano/Azul', gradient: 'linear-gradient(90deg, #06B6D4, #3B82F6)', colors: ['#06B6D4', '#3B82F6'] }, { name: 'Ciano/Azul', gradient: 'linear-gradient(135deg, #06B6D4, #3B82F6)', colors: ['#06B6D4', '#3B82F6'] },
{ name: 'Rosa/Roxo', gradient: 'linear-gradient(90deg, #EC4899, #A855F7)', colors: ['#EC4899', '#A855F7'] }, { name: 'Rosa/Roxo', gradient: 'linear-gradient(135deg, #EC4899, #A855F7)', colors: ['#EC4899', '#A855F7'] },
{ name: 'Vermelho/Laranja', gradient: 'linear-gradient(90deg, #EF4444, #F97316)', colors: ['#EF4444', '#F97316'] }, { name: 'Vermelho/Laranja', gradient: 'linear-gradient(135deg, #EF4444, #F97316)', colors: ['#EF4444', '#F97316'] },
]; ];
const DEFAULT_GRADIENT = 'linear-gradient(135deg, #ff3a05, #ff0080)';
const THEME_STORAGE_PREFIX = 'agency-theme:';
const setThemeVariables = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient);
document.documentElement.style.setProperty('--gradient', gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right'));
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right'));
};
export default function ConfiguracoesPage() { export default function ConfiguracoesPage() {
const [selectedTab, setSelectedTab] = useState(0); const [selectedTab, setSelectedTab] = useState(0);
const [selectedTheme, setSelectedTheme] = useState(0); const [selectedTheme, setSelectedTheme] = useState(0);
const [customColor1, setCustomColor1] = useState('#FF3A05'); const [activeGradient, setActiveGradient] = useState(DEFAULT_GRADIENT);
const [customColor2, setCustomColor2] = useState('#FF0080'); const [themeKey, setThemeKey] = useState('default');
const [customColor1, setCustomColor1] = useState('#ff3a05');
const [customColor2, setCustomColor2] = useState('#ff0080');
const [showSuccessDialog, setShowSuccessDialog] = useState(false); const [showSuccessDialog, setShowSuccessDialog] = useState(false);
const [successMessage, setSuccessMessage] = useState(''); const [successMessage, setSuccessMessage] = useState('');
const [showSupportDialog, setShowSupportDialog] = useState(false); const [showSupportDialog, setShowSupportDialog] = useState(false);
@@ -64,7 +76,7 @@ export default function ConfiguracoesPage() {
confirmPassword: '', confirmPassword: '',
}); });
// Buscar dados da agência da API // Buscar dados da agência da API e inicializar tema salvo
useEffect(() => { useEffect(() => {
const fetchAgencyData = async () => { const fetchAgencyData = async () => {
try { try {
@@ -78,6 +90,24 @@ export default function ConfiguracoesPage() {
return; return;
} }
const parsedUser = JSON.parse(userData);
const hostname = window.location.hostname;
const hostSubdomain = hostname.split('.')[0] || 'default';
const key = parsedUser?.subdomain || parsedUser?.tenantId || hostSubdomain;
setThemeKey(key);
const savedGradient = localStorage.getItem(`${THEME_STORAGE_PREFIX}${key}`) || DEFAULT_GRADIENT;
setActiveGradient(savedGradient);
setThemeVariables(savedGradient);
const presetIndex = themePresets.findIndex((theme) => theme.gradient === savedGradient);
if (presetIndex >= 0) {
setSelectedTheme(presetIndex);
setCustomColor1(themePresets[presetIndex].colors[0]);
setCustomColor2(themePresets[presetIndex].colors[1]);
}
// Buscar dados da API // Buscar dados da API
const response = await fetch('/api/agency/profile', { const response = await fetch('/api/agency/profile', {
headers: { headers: {
@@ -138,14 +168,13 @@ export default function ConfiguracoesPage() {
}, []); }, []);
const applyTheme = (gradient: string) => { const applyTheme = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient); setActiveGradient(gradient);
document.documentElement.style.setProperty('--gradient', gradient); setThemeVariables(gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right'));
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right'));
}; };
const applyCustomTheme = () => { const applyCustomTheme = () => {
const gradient = `linear-gradient(90deg, ${customColor1}, ${customColor2})`; const gradient = `linear-gradient(90deg, ${customColor1}, ${customColor2})`;
setSelectedTheme(-1);
applyTheme(gradient); applyTheme(gradient);
}; };
@@ -193,9 +222,15 @@ export default function ConfiguracoesPage() {
}; };
const handleSaveTheme = () => { const handleSaveTheme = () => {
// TODO: Integrar com API para salvar no banco const gradientToSave = selectedTheme >= 0
const selectedGradient = themePresets[selectedTheme].gradient; ? themePresets[selectedTheme].gradient
console.log('Salvando tema:', selectedGradient); : activeGradient;
applyTheme(gradientToSave);
if (themeKey) {
localStorage.setItem(`${THEME_STORAGE_PREFIX}${themeKey}`, gradientToSave);
}
setSuccessMessage('Tema salvo com sucesso!'); setSuccessMessage('Tema salvo com sucesso!');
setShowSuccessDialog(true); setShowSuccessDialog(true);
}; };
@@ -283,7 +318,7 @@ export default function ConfiguracoesPage() {
`w-full flex items-center justify-center space-x-2 rounded-lg py-2.5 text-sm font-medium leading-5 transition-all `w-full flex items-center justify-center space-x-2 rounded-lg py-2.5 text-sm font-medium leading-5 transition-all
${selected ${selected
? 'bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow' ? 'bg-white dark:bg-gray-900 text-gray-900 dark:text-white shadow'
: 'text-gray-600 dark:text-gray-400 hover:bg-white/[0.5] dark:hover:bg-gray-700/[0.5] hover:text-gray-900 dark:hover:text-white' : 'text-gray-600 dark:text-gray-400 hover:bg-white/50 dark:hover:bg-gray-700/50 hover:text-gray-900 dark:hover:text-white'
}` }`
} }
> >
@@ -315,7 +350,7 @@ export default function ConfiguracoesPage() {
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 flex items-center justify-between"> <label className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 flex items-center justify-between">
<span>CNPJ</span> <span>CNPJ</span>
<span className="text-xs text-gray-500">Alteração via suporte</span> <span className="text-xs text-gray-500">Alteração via suporte</span>
</label> </label>
@@ -332,7 +367,7 @@ export default function ConfiguracoesPage() {
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 flex items-center justify-between"> <label className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 flex items-center justify-between">
<span>E-mail (acesso)</span> <span>E-mail (acesso)</span>
<span className="text-xs text-gray-500">Alteração via suporte</span> <span className="text-xs text-gray-500">Alteração via suporte</span>
</label> </label>

View File

@@ -48,6 +48,15 @@ import {
const ThemeToggle = dynamic(() => import('@/components/ThemeToggle'), { ssr: false }); const ThemeToggle = dynamic(() => import('@/components/ThemeToggle'), { ssr: false });
const ThemeTester = dynamic(() => import('@/components/ThemeTester'), { ssr: false }); const ThemeTester = dynamic(() => import('@/components/ThemeTester'), { ssr: false });
const DEFAULT_GRADIENT = 'linear-gradient(135deg, #ff3a05, #ff0080)';
const setGradientVariables = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient);
document.documentElement.style.setProperty('--gradient', gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right'));
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right'));
};
export default function AgencyLayout({ export default function AgencyLayout({
children, children,
}: { }: {
@@ -88,8 +97,13 @@ export default function AgencyLayout({
} }
const hostname = window.location.hostname; const hostname = window.location.hostname;
const subdomain = hostname.split('.')[0]; const hostSubdomain = hostname.split('.')[0] || 'default';
setAgencyName(subdomain); const themeKey = parsedUser?.subdomain || parsedUser?.tenantId || hostSubdomain;
setAgencyName(parsedUser?.subdomain || hostSubdomain);
const storedGradient = localStorage.getItem(`agency-theme:${themeKey}`);
setGradientVariables(storedGradient || DEFAULT_GRADIENT);
// Inicializar com "Todos os Clientes" // Inicializar com "Todos os Clientes"
setSelectedClient(clients[0]); setSelectedClient(clients[0]);
@@ -106,7 +120,10 @@ export default function AgencyLayout({
}; };
window.addEventListener('keydown', handleKeyDown); window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown); return () => {
window.removeEventListener('keydown', handleKeyDown);
setGradientVariables(DEFAULT_GRADIENT);
};
}, [router]); }, [router]);
if (!user) { if (!user) {

View File

@@ -31,8 +31,8 @@ export default function CadastroPage() {
const [subdomain, setSubdomain] = useState(""); const [subdomain, setSubdomain] = useState("");
const [domainAvailable, setDomainAvailable] = useState<boolean | null>(null); const [domainAvailable, setDomainAvailable] = useState<boolean | null>(null);
const [checkingDomain, setCheckingDomain] = useState(false); const [checkingDomain, setCheckingDomain] = useState(false);
const [primaryColor, setPrimaryColor] = useState("#FF3A05"); const [primaryColor, setPrimaryColor] = useState("#ff3a05");
const [secondaryColor, setSecondaryColor] = useState("#FF0080"); const [secondaryColor, setSecondaryColor] = useState("#ff0080");
const [logoUrl, setLogoUrl] = useState<string>(""); const [logoUrl, setLogoUrl] = useState<string>("");
const [showPreviewMobile, setShowPreviewMobile] = useState(false); const [showPreviewMobile, setShowPreviewMobile] = useState(false);
@@ -52,8 +52,8 @@ export default function CadastroPage() {
setCepData(data.cepData || { state: "", city: "", neighborhood: "", street: "" }); setCepData(data.cepData || { state: "", city: "", neighborhood: "", street: "" });
setSubdomain(data.subdomain || ""); setSubdomain(data.subdomain || "");
setDomainAvailable(data.domainAvailable ?? null); setDomainAvailable(data.domainAvailable ?? null);
setPrimaryColor(data.primaryColor || "#FF3A05"); setPrimaryColor(data.primaryColor || "#ff3a05");
setSecondaryColor(data.secondaryColor || "#FF0080"); setSecondaryColor(data.secondaryColor || "#ff0080");
setLogoUrl(data.logoUrl || ""); setLogoUrl(data.logoUrl || "");
} catch (error) { } catch (error) {
console.error('Erro ao carregar dados:', error); console.error('Erro ao carregar dados:', error);
@@ -323,7 +323,7 @@ export default function CadastroPage() {
console.log('📤 Enviando cadastro completo:', payload); console.log('📤 Enviando cadastro completo:', payload);
toast.loading('Criando sua conta...', { id: 'register' }); toast.loading('Criando sua conta...', { id: 'register' });
const response = await fetch('/api/admin/agencies', { const response = await fetch(API_ENDPOINTS.adminAgencyRegister, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -332,8 +332,15 @@ export default function CadastroPage() {
}); });
if (!response.ok) { if (!response.ok) {
const error = await response.json(); let errorMessage = 'Erro ao criar conta';
throw new Error(error.message || 'Erro ao criar conta'); try {
const error = await response.json();
errorMessage = error.message || error.error || errorMessage;
} catch (e) {
const text = await response.text();
if (text) errorMessage = text;
}
throw new Error(errorMessage);
} }
const data = await response.json(); const data = await response.json();
@@ -365,9 +372,10 @@ export default function CadastroPage() {
}, },
}); });
// Redirecionar para o painel da agência no subdomínio // Redirecionar para o painel da agência no subdomínio, enviando o gradiente escolhido
setTimeout(() => { setTimeout(() => {
const agencyUrl = `http://${data.subdomain}.localhost/login`; const gradient = `linear-gradient(135deg, ${primaryColor}, ${secondaryColor})`;
const agencyUrl = `http://${data.subdomain}.localhost/login?theme=${encodeURIComponent(gradient)}`;
window.location.href = agencyUrl; window.location.href = agencyUrl;
}, 2000); }, 2000);
@@ -406,8 +414,8 @@ export default function CadastroPage() {
setContacts([{ id: 1, whatsapp: "(11) 98765-4321" }]); setContacts([{ id: 1, whatsapp: "(11) 98765-4321" }]);
setSubdomain("idealpages"); setSubdomain("idealpages");
setDomainAvailable(true); setDomainAvailable(true);
setPrimaryColor("#FF3A05"); setPrimaryColor("#ff3a05");
setSecondaryColor("#FF0080"); setSecondaryColor("#ff0080");
// Marcar todos os steps como completos e ir pro step 5 // Marcar todos os steps como completos e ir pro step 5
setCompletedSteps([1, 2, 3, 4]); setCompletedSteps([1, 2, 3, 4]);
@@ -529,9 +537,9 @@ export default function CadastroPage() {
const getPasswordStrengthColor = () => { const getPasswordStrengthColor = () => {
if (passwordStrength <= 1) return "#EF4444"; if (passwordStrength <= 1) return "#EF4444";
if (passwordStrength === 2) return "#F59E0B"; if (passwordStrength === 2) return "#F59E0B";
if (passwordStrength === 3) return "#3B82F6"; if (passwordStrength === 3) return "#ff3a05";
if (passwordStrength === 4) return "#10B981"; if (passwordStrength === 4) return "#ff3a05";
return "#059669"; return "#ff3a05";
}; };
const fetchCnpjData = async (cnpj: string) => { const fetchCnpjData = async (cnpj: string) => {
@@ -607,7 +615,7 @@ export default function CadastroPage() {
error: { error: {
icon: '⚠️', icon: '⚠️',
style: { style: {
background: '#ff3a05', background: '#ef4444',
color: '#FFFFFF', color: '#FFFFFF',
border: 'none', border: 'none',
}, },
@@ -660,8 +668,8 @@ export default function CadastroPage() {
/> />
<defs> <defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%"> <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#FF3A05" /> <stop offset="0%" stopColor="#ff3a05" />
<stop offset="100%" stopColor="#FF0080" /> <stop offset="100%" stopColor="#ff0080" />
</linearGradient> </linearGradient>
</defs> </defs>
</svg> </svg>
@@ -763,7 +771,11 @@ export default function CadastroPage() {
label={ label={
<span> <span>
Concordo com os{" "} Concordo com os{" "}
<Link href="/termos" className="bg-linear-to-r from-[#FF3A05] to-[#FF0080] bg-clip-text text-transparent hover:underline cursor-pointer font-medium"> <Link
href="/termos"
className="font-medium hover:underline cursor-pointer"
style={{ color: 'var(--brand-color)' }}
>
Termos de Uso Termos de Uso
</Link> </Link>
</span> </span>
@@ -779,7 +791,11 @@ export default function CadastroPage() {
{/* Link para login */} {/* Link para login */}
<p className="text-center mt-6 text-[14px] text-[#7D7D7D]"> <p className="text-center mt-6 text-[14px] text-[#7D7D7D]">
possui uma conta?{" "} possui uma conta?{" "}
<Link href="/login" className="bg-linear-to-r from-[#FF3A05] to-[#FF0080] bg-clip-text text-transparent font-medium hover:underline cursor-pointer"> <Link
href="/login"
className="font-medium hover:underline cursor-pointer"
style={{ color: 'var(--brand-color)' }}
>
Fazer login Fazer login
</Link> </Link>
</p> </p>
@@ -829,13 +845,13 @@ export default function CadastroPage() {
disabled disabled
/> />
<div> <div>
<label className="block text-[13px] font-semibold text-[#000000] mb-2"> <label className="block text-[13px] font-semibold text-zinc-900 mb-2">
Descrição Breve<span className="text-[#FF3A05] ml-1">*</span> Descrição Breve<span className="ml-1" style={{ color: 'var(--brand-color)' }}>*</span>
</label> </label>
<textarea <textarea
name="description" name="description"
placeholder="Apresente sua empresa em poucas palavras (máx 300 caracteres)" placeholder="Apresente sua empresa em poucas palavras (máx 300 caracteres)"
className="w-full px-3.5 py-3 text-[14px] font-normal border rounded-md bg-white placeholder:text-[#7D7D7D] border-[#E5E5E5] focus:border-[#FF3A05] outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none resize-none" className="w-full px-3.5 py-3 text-[14px] font-normal border rounded-md bg-white placeholder:text-zinc-500 border-zinc-200 outline-none ring-0 shadow-none focus:shadow-none resize-none focus:border-[var(--brand-color)]"
rows={4} rows={4}
maxLength={300} maxLength={300}
value={formData.description || ''} value={formData.description || ''}
@@ -989,19 +1005,19 @@ export default function CadastroPage() {
</div> </div>
{/* Contatos da Empresa */} {/* Contatos da Empresa */}
<div className="pt-4 border-t border-[#E5E5E5]"> <div className="pt-4 border-t border-zinc-200">
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-sm font-semibold text-[#000000]">Contatos da Empresa</h3> <h3 className="text-sm font-semibold text-zinc-900">Contatos da Empresa</h3>
</div> </div>
{contacts.map((contact, index) => ( {contacts.map((contact, index) => (
<div key={contact.id} className="space-y-4 p-4 border border-[#E5E5E5] rounded-md bg-white"> <div key={contact.id} className="space-y-4 p-4 border border-zinc-200 rounded-md bg-white">
{contacts.length > 1 && ( {contacts.length > 1 && (
<div className="flex items-center justify-end -mt-2 -mr-2"> <div className="flex items-center justify-end -mt-2 -mr-2">
<button <button
type="button" type="button"
onClick={() => removeContact(contact.id)} onClick={() => removeContact(contact.id)}
className="text-[#7D7D7D] hover:text-[#FF3A05] transition-colors" className="text-zinc-500 transition-colors hover:text-[var(--brand-color)]"
> >
<i className="ri-close-line text-[18px]" /> <i className="ri-close-line text-[18px]" />
</button> </button>
@@ -1044,8 +1060,8 @@ export default function CadastroPage() {
<div className="space-y-6"> <div className="space-y-6">
{/* Subdomínio Aggios */} {/* Subdomínio Aggios */}
<div className="space-y-2"> <div className="space-y-2">
<label className="block text-sm font-medium text-[#000000]"> <label className="block text-sm font-medium text-zinc-900">
Subdomínio Aggios <span className="text-[#FF3A05]">*</span> Subdomínio Aggios <span style={{ color: 'var(--brand-color)' }}>*</span>
</label> </label>
<div className="relative"> <div className="relative">
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
@@ -1061,12 +1077,12 @@ export default function CadastroPage() {
}} }}
onBlur={() => subdomain && checkDomainAvailability(subdomain)} onBlur={() => subdomain && checkDomainAvailability(subdomain)}
placeholder="minhaempresa" placeholder="minhaempresa"
className="w-full pl-10 pr-4 py-2 text-sm border border-[#E5E5E5] rounded-md focus:border-[#FF3A05] transition-colors" className="w-full pl-10 pr-4 py-2 text-sm border border-zinc-200 rounded-md transition-colors focus:border-[var(--brand-color)]"
required required
/> />
{checkingDomain && ( {checkingDomain && (
<div className="absolute inset-y-0 right-0 flex items-center pr-3"> <div className="absolute inset-y-0 right-0 flex items-center pr-3">
<div className="w-4 h-4 border-2 border-[#FF3A05] border-t-transparent rounded-full animate-spin" /> <div className="w-4 h-4 border-2 border-[var(--brand-color)] border-t-transparent rounded-full animate-spin" />
</div> </div>
)} )}
{!checkingDomain && domainAvailable === true && ( {!checkingDomain && domainAvailable === true && (
@@ -1076,13 +1092,13 @@ export default function CadastroPage() {
)} )}
{!checkingDomain && domainAvailable === false && ( {!checkingDomain && domainAvailable === false && (
<div className="absolute inset-y-0 right-0 flex items-center pr-3"> <div className="absolute inset-y-0 right-0 flex items-center pr-3">
<i className="ri-close-circle-fill text-[#FF3A05] text-[20px]" /> <i className="ri-close-circle-fill text-red-500 text-[20px]" />
</div> </div>
)} )}
</div> </div>
<p className="text-xs text-[#7D7D7D] flex items-center gap-1"> <p className="text-xs text-zinc-600 flex items-center gap-1">
<i className="ri-information-line" /> <i className="ri-information-line" />
Seu painel ficará em: <span className="font-medium text-[#000000]">{subdomain || 'seu-dominio'}.aggios.app</span> Seu painel ficará em: <span className="font-medium text-zinc-900">{subdomain || 'seu-dominio'}.aggios.app</span>
</p> </p>
{domainAvailable === true && ( {domainAvailable === true && (
<p className="text-xs text-[#10B981] flex items-center gap-1"> <p className="text-xs text-[#10B981] flex items-center gap-1">
@@ -1091,7 +1107,7 @@ export default function CadastroPage() {
</p> </p>
)} )}
{domainAvailable === false && ( {domainAvailable === false && (
<p className="text-xs text-[#FF3A05] flex items-center gap-1"> <p className="text-xs text-red-500 flex items-center gap-1">
<i className="ri-error-warning-line" /> <i className="ri-error-warning-line" />
Indisponível. Este subdomínio está em uso. Indisponível. Este subdomínio está em uso.
</p> </p>
@@ -1100,11 +1116,11 @@ export default function CadastroPage() {
{/* Informações Adicionais */} {/* Informações Adicionais */}
<div className="p-6 bg-[#F5F5F5] rounded-md space-y-3"> <div className="p-6 bg-[#F5F5F5] rounded-md space-y-3">
<h4 className="text-sm font-semibold text-[#000000] flex items-center gap-2"> <h4 className="text-sm font-semibold text-zinc-900 flex items-center gap-2">
<i className="ri-lightbulb-line text-[#FF3A05]" /> <i className="ri-lightbulb-line" style={{ color: 'var(--brand-color)' }} />
Dicas para escolher seu domínio Dicas para escolher seu domínio
</h4> </h4>
<ul className="text-xs text-[#7D7D7D] space-y-1 ml-6"> <ul className="text-xs text-zinc-600 space-y-1 ml-6">
<li className="list-disc">Use o nome da sua empresa</li> <li className="list-disc">Use o nome da sua empresa</li>
<li className="list-disc">Evite números e hífens quando possível</li> <li className="list-disc">Evite números e hífens quando possível</li>
<li className="list-disc">Escolha algo fácil de lembrar e digitar</li> <li className="list-disc">Escolha algo fácil de lembrar e digitar</li>
@@ -1121,7 +1137,14 @@ export default function CadastroPage() {
<button <button
type="button" type="button"
onClick={() => setShowPreviewMobile(!showPreviewMobile)} onClick={() => setShowPreviewMobile(!showPreviewMobile)}
className="w-full flex items-center justify-center gap-2 px-4 py-3 rounded-lg border-2 border-[#FF3A05] text-[#FF3A05] font-medium hover:bg-[#FF3A05]/5 transition-colors" className="w-full flex items-center justify-center gap-2 px-4 py-3 rounded-lg border-2 font-medium transition-colors"
style={{
borderColor: 'var(--brand-color)',
color: 'var(--brand-color)',
backgroundColor: showPreviewMobile ? 'transparent' : undefined
}}
onMouseEnter={(e) => (e.currentTarget.style.backgroundColor = 'color-mix(in srgb, var(--brand-color) 10%, transparent)')}
onMouseLeave={(e) => (e.currentTarget.style.backgroundColor = 'transparent')}
> >
<i className={`${showPreviewMobile ? 'ri-edit-line' : 'ri-eye-line'} text-xl`} /> <i className={`${showPreviewMobile ? 'ri-edit-line' : 'ri-eye-line'} text-xl`} />
{showPreviewMobile ? 'Voltar ao Formulário' : 'Ver Preview do Painel'} {showPreviewMobile ? 'Voltar ao Formulário' : 'Ver Preview do Painel'}
@@ -1177,7 +1200,7 @@ export default function CadastroPage() {
/> />
<label <label
htmlFor="logo-upload" htmlFor="logo-upload"
className="inline-flex items-center gap-2 px-4 py-2 border border-[#E5E5E5] rounded-md text-sm font-medium text-[#000000] hover:bg-[#F5F5F5] transition-colors cursor-pointer" className="inline-flex items-center gap-2 px-4 py-2 border border-zinc-200 rounded-md text-sm font-medium text-zinc-900 hover:bg-zinc-50 transition-colors cursor-pointer"
> >
<i className="ri-upload-2-line" /> <i className="ri-upload-2-line" />
Escolher arquivo Escolher arquivo
@@ -1186,12 +1209,13 @@ export default function CadastroPage() {
<button <button
type="button" type="button"
onClick={() => setLogoUrl('')} onClick={() => setLogoUrl('')}
className="ml-2 text-sm bg-linear-to-r from-[#FF3A05] to-[#FF0080] bg-clip-text text-transparent hover:underline font-medium" className="ml-2 text-sm hover:underline font-medium"
style={{ color: 'var(--brand-color)' }}
> >
Remover Remover
</button> </button>
)} )}
<p className="text-xs text-[#7D7D7D] mt-2"> <p className="text-xs text-zinc-600 mt-2">
PNG, JPG ou SVG. Tamanho recomendado: 200x200px PNG, JPG ou SVG. Tamanho recomendado: 200x200px
</p> </p>
</div> </div>
@@ -1202,13 +1226,13 @@ export default function CadastroPage() {
<div className="grid grid-cols-1 md:grid-cols-2 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Cor Primária */} {/* Cor Primária */}
<div> <div>
<label className="block text-sm font-medium text-[#000000] mb-3"> <label className="block text-sm font-medium text-zinc-900 mb-3">
Cor Primária <span className="text-[#FF3A05]">*</span> Cor Primária <span style={{ color: 'var(--brand-color)' }}>*</span>
</label> </label>
<div className="flex gap-3"> <div className="flex gap-3">
<div className="relative flex-1"> <div className="relative flex-1">
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i className="ri-palette-line text-[#7D7D7D] text-[18px]" /> <i className="ri-palette-line text-zinc-500 text-[18px]" />
</div> </div>
<input <input
type="text" type="text"
@@ -1219,18 +1243,18 @@ export default function CadastroPage() {
setPrimaryColor(value); setPrimaryColor(value);
} }
}} }}
placeholder="#FF3A05" placeholder="#ff3a05"
className="w-full pl-10 pr-4 py-2 text-sm border border-[#E5E5E5] rounded-md focus:border-[#FF3A05] transition-colors font-mono" className="w-full pl-10 pr-4 py-2 text-sm border border-zinc-200 rounded-md transition-colors font-mono focus:border-[var(--brand-color)]"
/> />
</div> </div>
<input <input
type="color" type="color"
value={primaryColor} value={primaryColor}
onChange={(e) => setPrimaryColor(e.target.value)} onChange={(e) => setPrimaryColor(e.target.value)}
className="w-14 h-10 border-2 border-[#E5E5E5] rounded-md cursor-pointer" className="w-14 h-10 border-2 border-zinc-200 rounded-md cursor-pointer"
/> />
</div> </div>
<p className="text-xs text-[#7D7D7D] mt-1 flex items-center gap-1"> <p className="text-xs text-zinc-600 mt-1 flex items-center gap-1">
<i className="ri-information-line" /> <i className="ri-information-line" />
Usada em menus, botões e destaques Usada em menus, botões e destaques
</p> </p>
@@ -1238,13 +1262,13 @@ export default function CadastroPage() {
{/* Cor Secundária */} {/* Cor Secundária */}
<div> <div>
<label className="block text-sm font-medium text-[#000000] mb-3"> <label className="block text-sm font-medium text-zinc-900 mb-3">
Cor Secundária <span className="text-[#7D7D7D]">(opcional)</span> Cor Secundária <span className="text-zinc-500">(opcional)</span>
</label> </label>
<div className="flex gap-3"> <div className="flex gap-3">
<div className="relative flex-1"> <div className="relative flex-1">
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none"> <div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
<i className="ri-brush-line text-[#7D7D7D] text-[18px]" /> <i className="ri-brush-line text-zinc-500 text-[18px]" />
</div> </div>
<input <input
type="text" type="text"
@@ -1255,18 +1279,18 @@ export default function CadastroPage() {
setSecondaryColor(value); setSecondaryColor(value);
} }
}} }}
placeholder="#FF0080" placeholder="#ff0080"
className="w-full pl-10 pr-4 py-2 text-sm border border-[#E5E5E5] rounded-md focus:border-[#FF3A05] transition-colors font-mono" className="w-full pl-10 pr-4 py-2 text-sm border border-zinc-200 rounded-md transition-colors font-mono focus:border-[var(--brand-color)]"
/> />
</div> </div>
<input <input
type="color" type="color"
value={secondaryColor} value={secondaryColor}
onChange={(e) => setSecondaryColor(e.target.value)} onChange={(e) => setSecondaryColor(e.target.value)}
className="w-14 h-10 border-2 border-[#E5E5E5] rounded-md cursor-pointer" className="w-14 h-10 border-2 border-zinc-200 rounded-md cursor-pointer"
/> />
</div> </div>
<p className="text-xs text-[#7D7D7D] mt-1 flex items-center gap-1"> <p className="text-xs text-zinc-600 mt-1 flex items-center gap-1">
<i className="ri-information-line" /> <i className="ri-information-line" />
Usada em cards e elementos secundários Usada em cards e elementos secundários
</p> </p>
@@ -1275,10 +1299,10 @@ export default function CadastroPage() {
{/* Paletas Sugeridas */} {/* Paletas Sugeridas */}
<div> <div>
<h4 className="text-sm font-semibold text-[#000000] mb-4">Paletas Sugeridas</h4> <h4 className="text-sm font-semibold text-zinc-900 mb-4">Paletas Sugeridas</h4>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{[ {[
{ name: 'Fogo', primary: '#FF3A05', secondary: '#FF0080' }, { name: 'Marca', primary: '#FF3A05', secondary: '#FF0080' },
{ name: 'Oceano', primary: '#0EA5E9', secondary: '#3B82F6' }, { name: 'Oceano', primary: '#0EA5E9', secondary: '#3B82F6' },
{ name: 'Natureza', primary: '#10B981', secondary: '#059669' }, { name: 'Natureza', primary: '#10B981', secondary: '#059669' },
{ name: 'Elegante', primary: '#8B5CF6', secondary: '#A78BFA' }, { name: 'Elegante', primary: '#8B5CF6', secondary: '#A78BFA' },
@@ -1294,7 +1318,8 @@ export default function CadastroPage() {
setPrimaryColor(palette.primary); setPrimaryColor(palette.primary);
setSecondaryColor(palette.secondary); setSecondaryColor(palette.secondary);
}} }}
className="flex items-center gap-2 p-2 rounded-md border border-[#E5E5E5] hover:border-[#FF3A05] transition-colors group cursor-pointer" className="flex items-center gap-2 p-2 rounded-md border border-zinc-200 transition-colors group cursor-pointer"
style={{ borderColor: palette.name === 'Marca' ? 'var(--brand-color)' : undefined }}
> >
<div className="flex gap-1"> <div className="flex gap-1">
<div <div
@@ -1306,7 +1331,7 @@ export default function CadastroPage() {
style={{ backgroundColor: palette.secondary }} style={{ backgroundColor: palette.secondary }}
/> />
</div> </div>
<span className="text-xs font-medium text-[#7D7D7D] group-hover:text-[#000000]"> <span className="text-xs font-medium text-zinc-600 group-hover:text-zinc-900">
{palette.name} {palette.name}
</span> </span>
</button> </button>
@@ -1317,7 +1342,7 @@ export default function CadastroPage() {
{/* Informações */} {/* Informações */}
<div className="p-6 bg-[#F0F9FF] border border-[#BAE6FD] rounded-md"> <div className="p-6 bg-[#F0F9FF] border border-[#BAE6FD] rounded-md">
<div className="flex gap-4"> <div className="flex gap-4">
<i className="ri-information-line text-[#0EA5E9] text-xl mt-0.5" /> <i className="ri-information-line text-[#ff3a05] text-xl mt-0.5" />
<div> <div>
<h4 className="text-sm font-semibold text-[#000000] mb-1"> <h4 className="text-sm font-semibold text-[#000000] mb-1">
Você pode alterar depois Você pode alterar depois
@@ -1337,7 +1362,7 @@ export default function CadastroPage() {
</div> </div>
{/* Rodapé - botão voltar à esquerda, etapas e botão ação à direita */} {/* Rodapé - botão voltar à esquerda, etapas e botão ação à direita */}
<div className="border-t border-[#E5E5E5] bg-white px-4 sm:px-12 py-4"> <div className="border-t border-zinc-200 bg-white px-4 sm:px-12 py-4">
{/* Desktop: Linha única com tudo */} {/* Desktop: Linha única com tudo */}
<div className="hidden md:flex items-center justify-between"> <div className="hidden md:flex items-center justify-between">
{/* Botão voltar à esquerda */} {/* Botão voltar à esquerda */}
@@ -1363,21 +1388,21 @@ export default function CadastroPage() {
? "bg-[#10B981] text-white" ? "bg-[#10B981] text-white"
: currentStep === step.number : currentStep === step.number
? "text-white" ? "text-white"
: "bg-[#E5E5E5] text-[#7D7D7D] group-hover:bg-[#D5D5D5]" : "bg-zinc-200 text-zinc-500 group-hover:bg-zinc-300"
}`} }`}
style={currentStep === step.number ? { background: 'linear-gradient(90deg, #FF3A05, #FF0080)' } : undefined} style={currentStep === step.number ? { background: 'var(--gradient-primary)' } : undefined}
> >
{step.number} {step.number}
</div> </div>
<span className={`text-xs transition-colors ${currentStep === step.number <span className={`text-xs transition-colors ${currentStep === step.number
? "text-[#000000] font-semibold" ? "text-zinc-900 font-semibold"
: "text-[#7D7D7D] group-hover:text-[#000000]" : "text-zinc-500 group-hover:text-zinc-900"
}`}> }`}>
{step.title} {step.title}
</span> </span>
</button> </button>
{index < steps.length - 1 && ( {index < steps.length - 1 && (
<div className="w-12 h-0.5 bg-[#E5E5E5] mb-5" /> <div className="w-12 h-0.5 bg-zinc-200 mb-5" />
)} )}
</div> </div>
))} ))}
@@ -1407,9 +1432,9 @@ export default function CadastroPage() {
? "w-2 bg-[#10B981]" ? "w-2 bg-[#10B981]"
: currentStep === step.number : currentStep === step.number
? "w-8" ? "w-8"
: "w-2 bg-[#E5E5E5] hover:bg-[#D5D5D5]" : "w-2 bg-zinc-200 hover:bg-zinc-300"
}`} }`}
style={currentStep === step.number ? { background: 'linear-gradient(90deg, #FF3A05, #FF0080)' } : undefined} style={currentStep === step.number ? { background: 'var(--gradient-primary)' } : undefined}
aria-label={`Ir para ${step.title}`} aria-label={`Ir para ${step.title}`}
/> />
))} ))}
@@ -1442,7 +1467,7 @@ export default function CadastroPage() {
</div> </div>
{/* Lado Direito - Branding Dinâmico */} {/* Lado Direito - Branding Dinâmico */}
<div className="hidden lg:flex lg:w-[50%] relative overflow-hidden" style={{ background: 'linear-gradient(90deg, #FF3A05, #FF0080)' }}> <div className="hidden lg:flex lg:w-[50%] relative overflow-hidden" style={{ background: 'var(--gradient-primary)' }}>
<DynamicBranding <DynamicBranding
currentStep={currentStep} currentStep={currentStep}
companyName={formData.companyName} companyName={formData.companyName}

View File

@@ -56,7 +56,7 @@ export default function RecuperarSenhaPage() {
error: { error: {
icon: '⚠️', icon: '⚠️',
style: { style: {
background: '#ff3a05', background: '#ef4444',
color: '#FFFFFF', color: '#FFFFFF',
border: 'none', border: 'none',
}, },
@@ -150,7 +150,7 @@ export default function RecuperarSenhaPage() {
<div className="p-6 bg-[#F0F9FF] border border-[#BAE6FD] rounded-md text-left mb-6"> <div className="p-6 bg-[#F0F9FF] border border-[#BAE6FD] rounded-md text-left mb-6">
<div className="flex gap-4"> <div className="flex gap-4">
<i className="ri-information-line text-[#0EA5E9] text-xl mt-0.5" /> <i className="ri-information-line text-[#ff3a05] text-xl mt-0.5" />
<div> <div>
<h4 className="text-sm font-semibold text-zinc-900 dark:text-white mb-1"> <h4 className="text-sm font-semibold text-zinc-900 dark:text-white mb-1">
Verifique sua caixa de entrada Verifique sua caixa de entrada

View File

@@ -1,7 +1,25 @@
'use client'; 'use client';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { useEffect } from 'react';
import { usePathname } from 'next/navigation';
const DEFAULT_GRADIENT = 'linear-gradient(135deg, #ff3a05, #ff0080)';
const setGradientVariables = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient);
document.documentElement.style.setProperty('--gradient', gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right'));
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right'));
};
export default function LayoutWrapper({ children }: { children: ReactNode }) { export default function LayoutWrapper({ children }: { children: ReactNode }) {
const pathname = usePathname();
useEffect(() => {
// Em toda troca de rota, volta para o tema padrão; layouts específicos (ex.: agência) aplicam o próprio na sequência
setGradientVariables(DEFAULT_GRADIENT);
}, [pathname]);
return <>{children}</>; return <>{children}</>;
} }

View File

@@ -61,6 +61,14 @@ html.dark {
color: var(--color-text-inverse); color: var(--color-text-inverse);
} }
/* Seleção em campos de formulário usa o gradiente padrão da marca */
input::selection,
textarea::selection,
select::selection {
background: var(--color-gradient-brand);
color: var(--color-text-inverse);
}
.surface-card { .surface-card {
background-color: var(--color-surface-card); background-color: var(--color-surface-card);
border: 1px solid var(--color-border-strong); border: 1px solid var(--color-border-strong);

View File

@@ -9,6 +9,15 @@ import dynamic from 'next/dynamic';
const ThemeToggle = dynamic(() => import('@/components/ThemeToggle'), { ssr: false }); const ThemeToggle = dynamic(() => import('@/components/ThemeToggle'), { ssr: false });
const DEFAULT_GRADIENT = 'linear-gradient(135deg, #ff3a05, #ff0080)';
const setGradientVariables = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient);
document.documentElement.style.setProperty('--gradient', gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right'));
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right'));
};
export default function LoginPage() { export default function LoginPage() {
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isSuperAdmin, setIsSuperAdmin] = useState(false); const [isSuperAdmin, setIsSuperAdmin] = useState(false);
@@ -27,6 +36,22 @@ export default function LoginPage() {
setSubdomain(sub); setSubdomain(sub);
setIsSuperAdmin(superAdmin); setIsSuperAdmin(superAdmin);
// Aplicar tema: dash sempre padrão; tenants aplicam o salvo ou vindo via query param
const searchParams = new URLSearchParams(window.location.search);
const themeParam = searchParams.get('theme');
if (superAdmin) {
setGradientVariables(DEFAULT_GRADIENT);
} else {
const stored = localStorage.getItem(`agency-theme:${sub}`);
const gradient = themeParam || stored || DEFAULT_GRADIENT;
setGradientVariables(gradient);
if (themeParam) {
localStorage.setItem(`agency-theme:${sub}`, gradient);
}
}
if (isAuthenticated()) { if (isAuthenticated()) {
const target = superAdmin ? '/superadmin' : '/dashboard'; const target = superAdmin ? '/superadmin' : '/dashboard';
window.location.href = target; window.location.href = target;
@@ -106,7 +131,7 @@ export default function LoginPage() {
error: { error: {
icon: '⚠️', icon: '⚠️',
style: { style: {
background: '#ff3a05', background: '#ef4444',
color: '#FFFFFF', color: '#FFFFFF',
border: 'none', border: 'none',
}, },

View File

@@ -11,7 +11,7 @@ export default function NotFound() {
<div className="w-full max-w-md text-center"> <div className="w-full max-w-md text-center">
{/* Logo mobile */} {/* Logo mobile */}
<div className="lg:hidden mb-8"> <div className="lg:hidden mb-8">
<div className="inline-block px-6 py-3 rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080]"> <div className="inline-block px-6 py-3 rounded-2xl bg-linear-to-r from-brand-500 to-brand-700">
<h1 className="text-3xl font-bold text-white">aggios</h1> <h1 className="text-3xl font-bold text-white">aggios</h1>
</div> </div>
</div> </div>
@@ -82,7 +82,7 @@ export default function NotFound() {
</div> </div>
{/* Lado Direito - Branding */} {/* Lado Direito - Branding */}
<div className="hidden lg:flex lg:w-1/2 relative overflow-hidden" style={{ background: 'linear-gradient(90deg, #FF3A05, #FF0080)' }}> <div className="hidden lg:flex lg:w-1/2 relative overflow-hidden" style={{ background: 'var(--gradient-primary)' }}>
<div className="relative z-10 flex flex-col justify-center items-center w-full p-12 text-white"> <div className="relative z-10 flex flex-col justify-center items-center w-full p-12 text-white">
{/* Logo */} {/* Logo */}
<div className="mb-8"> <div className="mb-8">

View File

@@ -165,11 +165,11 @@ export default function PainelPage() {
return ( return (
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900"> <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900">
<div className="text-center"> <div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-[#FF3A05] mx-auto mb-4"></div> <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-brand-500 mx-auto mb-4"></div>
<p className="text-gray-600 dark:text-gray-400">Carregando...</p> <p className="text-gray-600 dark:text-gray-400">Carregando...</p>
</div> </div>
{detailsLoadingId && ( {detailsLoadingId && (
<div className="mt-8 bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-dashed border-[#FF3A05] p-6 text-sm text-gray-600 dark:text-gray-300"> <div className="mt-8 bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-dashed border-brand-500 p-6 text-sm text-gray-600 dark:text-gray-300">
Carregando detalhes da agência selecionada... Carregando detalhes da agência selecionada...
</div> </div>
)} )}
@@ -192,7 +192,7 @@ export default function PainelPage() {
href={selectedDetails.access_url} href={selectedDetails.access_url}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="text-sm text-[#FF3A05] hover:text-[#FF0080]" className="text-sm text-brand-600 hover:text-brand-700"
> >
Abrir painel da agência Abrir painel da agência
</a> </a>
@@ -260,7 +260,7 @@ export default function PainelPage() {
<div> <div>
<p className="text-gray-500 dark:text-gray-400">Website</p> <p className="text-gray-500 dark:text-gray-400">Website</p>
{selectedDetails.tenant.website ? ( {selectedDetails.tenant.website ? (
<a href={selectedDetails.tenant.website} target="_blank" rel="noopener noreferrer" className="text-[#FF3A05] hover:text-[#FF0080]"> <a href={selectedDetails.tenant.website} target="_blank" rel="noopener noreferrer" className="text-brand-600 hover:text-brand-700">
{selectedDetails.tenant.website} {selectedDetails.tenant.website}
</a> </a>
) : ( ) : (
@@ -321,7 +321,7 @@ export default function PainelPage() {
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4"> <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 justify-between">
<div className="flex items-center gap-4"> <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"> <div className="flex items-center justify-center w-10 h-10 bg-gradient-to-r from-brand-500 to-brand-700 rounded-lg">
<span className="text-white font-bold text-lg">A</span> <span className="text-white font-bold text-lg">A</span>
</div> </div>
<div> <div>
@@ -403,7 +403,7 @@ export default function PainelPage() {
{loadingAgencies ? ( {loadingAgencies ? (
<div className="p-8 text-center"> <div className="p-8 text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-[#FF3A05] mx-auto mb-4"></div> <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-brand-500 mx-auto mb-4"></div>
<p className="text-gray-600 dark:text-gray-400">Carregando agências...</p> <p className="text-gray-600 dark:text-gray-400">Carregando agências...</p>
</div> </div>
) : agencies.length === 0 ? ( ) : agencies.length === 0 ? (
@@ -427,11 +427,11 @@ export default function PainelPage() {
{agencies.map((agency) => ( {agencies.map((agency) => (
<tr <tr
key={agency.id} key={agency.id}
className={`hover:bg-gray-50 dark:hover:bg-gray-700 ${selectedAgencyId === agency.id ? 'bg-orange-50/60 dark:bg-gray-700/60' : ''}`} className={`hover:bg-gray-50 dark:hover:bg-gray-700 ${selectedAgencyId === agency.id ? 'bg-brand-50/70 dark:bg-gray-700/60' : ''}`}
> >
<td className="px-6 py-4 whitespace-nowrap"> <td className="px-6 py-4 whitespace-nowrap">
<div className="flex items-center"> <div className="flex items-center">
<div className="flex-shrink-0 h-10 w-10 bg-gradient-to-br from-[#FF3A05] to-[#FF0080] rounded-lg flex items-center justify-center"> <div className="flex-shrink-0 h-10 w-10 bg-gradient-to-br from-brand-500 to-brand-700 rounded-lg flex items-center justify-center">
<span className="text-white font-bold">{agency.name.charAt(0).toUpperCase()}</span> <span className="text-white font-bold">{agency.name.charAt(0).toUpperCase()}</span>
</div> </div>
<div className="ml-4"> <div className="ml-4">
@@ -459,7 +459,7 @@ export default function PainelPage() {
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2"> <td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-2">
<button <button
onClick={() => handleViewDetails(agency.id)} onClick={() => handleViewDetails(agency.id)}
className="inline-flex items-center px-3 py-1.5 rounded-md bg-[#FF3A05] text-white hover:bg-[#FF0080] transition" className="inline-flex items-center px-3 py-1.5 rounded-md bg-gradient-to-r from-brand-500 to-brand-700 text-white hover:opacity-90 transition"
disabled={detailsLoadingId === agency.id || deletingId === agency.id} disabled={detailsLoadingId === agency.id || deletingId === agency.id}
> >
{detailsLoadingId === agency.id ? 'Carregando...' : 'Visualizar'} {detailsLoadingId === agency.id ? 'Carregando...' : 'Visualizar'}

View File

@@ -1,10 +1,14 @@
@layer theme { @layer theme {
:root { :root {
/* Gradientes */ /* Gradientes */
--gradient: linear-gradient(90deg, #FF3A05, #FF0080); --gradient: linear-gradient(135deg, #ff3a05, #ff0080);
--gradient-text: linear-gradient(to right, #FF3A05, #FF0080); --gradient-text: linear-gradient(to right, #ff3a05, #ff0080);
--gradient-primary: linear-gradient(90deg, #FF3A05, #FF0080); --gradient-primary: linear-gradient(135deg, #ff3a05, #ff0080);
--color-gradient-brand: linear-gradient(to right, #FF3A05, #FF0080); --color-gradient-brand: linear-gradient(135deg, #ff3a05, #ff0080);
/* Cores sólidas de marca (usadas em textos/bordas) */
--brand-color: #ff3a05;
--brand-color-strong: #ff0080;
/* Superfícies e tipografia */ /* Superfícies e tipografia */
--color-surface-light: #ffffff; --color-surface-light: #ffffff;

View File

@@ -5,36 +5,36 @@ import { SwatchIcon } from '@heroicons/react/24/outline';
const themePresets = [ const themePresets = [
{ {
name: 'Laranja/Rosa (Padrão)', name: 'Azul (Marca)',
gradient: 'linear-gradient(90deg, #FF3A05, #FF0080)', gradient: 'linear-gradient(135deg, #0ea5e9, #0284c7)',
}, },
{ {
name: 'Azul/Roxo', name: 'Azul/Roxo',
gradient: 'linear-gradient(90deg, #0066FF, #9333EA)', gradient: 'linear-gradient(135deg, #0066FF, #9333EA)',
}, },
{ {
name: 'Verde/Esmeralda', name: 'Verde/Esmeralda',
gradient: 'linear-gradient(90deg, #10B981, #059669)', gradient: 'linear-gradient(135deg, #10B981, #059669)',
}, },
{ {
name: 'Ciano/Azul', name: 'Ciano/Azul',
gradient: 'linear-gradient(90deg, #06B6D4, #3B82F6)', gradient: 'linear-gradient(135deg, #06B6D4, #3B82F6)',
}, },
{ {
name: 'Rosa/Roxo', name: 'Rosa/Roxo',
gradient: 'linear-gradient(90deg, #EC4899, #A855F7)', gradient: 'linear-gradient(135deg, #EC4899, #A855F7)',
}, },
{ {
name: 'Vermelho/Laranja', name: 'Vermelho/Laranja',
gradient: 'linear-gradient(90deg, #EF4444, #F97316)', gradient: 'linear-gradient(135deg, #EF4444, #F97316)',
}, },
{ {
name: 'Índigo/Violeta', name: 'Índigo/Violeta',
gradient: 'linear-gradient(90deg, #6366F1, #8B5CF6)', gradient: 'linear-gradient(135deg, #6366F1, #8B5CF6)',
}, },
{ {
name: 'Âmbar/Amarelo', name: 'Âmbar/Amarelo',
gradient: 'linear-gradient(90deg, #F59E0B, #EAB308)', gradient: 'linear-gradient(135deg, #F59E0B, #EAB308)',
}, },
]; ];
@@ -44,8 +44,8 @@ export default function ThemeTester() {
const applyTheme = (gradient: string) => { const applyTheme = (gradient: string) => {
document.documentElement.style.setProperty('--gradient-primary', gradient); document.documentElement.style.setProperty('--gradient-primary', gradient);
document.documentElement.style.setProperty('--gradient', gradient); document.documentElement.style.setProperty('--gradient', gradient);
document.documentElement.style.setProperty('--gradient-text', gradient.replace('90deg', 'to right')); document.documentElement.style.setProperty('--gradient-text', gradient);
document.documentElement.style.setProperty('--color-gradient-brand', gradient.replace('90deg', 'to right')); document.documentElement.style.setProperty('--color-gradient-brand', gradient);
}; };
return ( return (

View File

@@ -16,8 +16,8 @@ export default function DynamicBranding({
currentStep, currentStep,
companyName = '', companyName = '',
subdomain = '', subdomain = '',
primaryColor = '#FF3A05', primaryColor = '#0ea5e9',
secondaryColor = '#FF0080', secondaryColor = '#0284c7',
logoUrl = '' logoUrl = ''
}: DynamicBrandingProps) { }: DynamicBrandingProps) {
const [activeTestimonial, setActiveTestimonial] = useState(0); const [activeTestimonial, setActiveTestimonial] = useState(0);

View File

@@ -26,7 +26,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>(
ref ref
) => { ) => {
const baseStyles = const baseStyles =
"inline-flex items-center justify-center font-medium rounded-[6px] transition-opacity focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#FF3A05] disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer"; "inline-flex items-center justify-center font-medium rounded-[6px] transition-opacity focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-500 disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer";
const variants = { const variants = {
primary: "text-white hover:opacity-90 active:opacity-80", primary: "text-white hover:opacity-90 active:opacity-80",

View File

@@ -29,9 +29,9 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
type="checkbox" type="checkbox"
className={` className={`
appearance-none w-[18px] h-[18px] border rounded-sm appearance-none w-[18px] h-[18px] border rounded-sm
border-[#E5E5E5] dark:border-gray-600 bg-white dark:bg-gray-700 border-zinc-200 dark:border-gray-600 bg-white dark:bg-gray-700
checked:border-[#FF3A05] checked:border-brand-500
focus:outline-none focus:border-[#FF3A05] focus:outline-none focus:border-brand-500
transition-colors cursor-pointer transition-colors cursor-pointer
${className} ${className}
`} `}
@@ -48,13 +48,13 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
/> />
</div> </div>
{label && ( {label && (
<span className="text-[14px] text-[#000000] dark:text-white select-none"> <span className="text-[14px] text-zinc-900 dark:text-white select-none">
{label} {label}
</span> </span>
)} )}
</label> </label>
{error && ( {error && (
<p className="mt-1 text-[13px] text-[#FF3A05] flex items-center gap-1"> <p className="mt-1 text-[13px] text-red-500 flex items-center gap-1">
<i className="ri-error-warning-line" /> <i className="ri-error-warning-line" />
{error} {error}
</p> </p>

View File

@@ -34,9 +34,9 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
return ( return (
<div className="w-full"> <div className="w-full">
{label && ( {label && (
<label className="block text-[13px] font-semibold text-[#000000] dark:text-white mb-2"> <label className="block text-[13px] font-semibold text-zinc-900 dark:text-white mb-2">
{label} {label}
{props.required && <span className="text-[#FF3A05] ml-1">*</span>} {props.required && <span className="text-brand-500 ml-1">*</span>}
</label> </label>
)} )}
<div className="relative"> <div className="relative">
@@ -51,16 +51,16 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
className={` className={`
w-full px-3.5 py-3 text-[14px] font-normal w-full px-3.5 py-3 text-[14px] font-normal
border rounded-md bg-white dark:bg-gray-700 dark:text-white border rounded-md bg-white dark:bg-gray-700 dark:text-white
placeholder:text-[#7D7D7D] dark:placeholder:text-gray-400 placeholder:text-zinc-500 dark:placeholder:text-gray-400
transition-all transition-all
${leftIcon ? "pl-11" : ""} ${leftIcon ? "pl-11" : ""}
${isPassword || rightIcon ? "pr-11" : ""} ${isPassword || rightIcon ? "pr-11" : ""}
${error ${error
? "border-[#FF3A05]" ? "border-red-500 focus:border-red-500"
: "border-[#E5E5E5] dark:border-gray-600 focus:border-[#FF3A05]" : "border-zinc-200 dark:border-gray-600 focus:border-brand-500"
} }
outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none
disabled:bg-[#E5E5E5]/30 disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:cursor-not-allowed
${className} ${className}
`} `}
{...props} {...props}
@@ -69,7 +69,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
<button <button
type="button" type="button"
onClick={() => setShowPassword(!showPassword)} onClick={() => setShowPassword(!showPassword)}
className="absolute right-3.5 top-1/2 -translate-y-1/2 text-[#7D7D7D] hover:text-[#000000] transition-colors cursor-pointer" className="absolute right-3.5 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-900 transition-colors cursor-pointer"
> >
<i <i
className={`${showPassword ? "ri-eye-off-line" : "ri-eye-line"} text-[20px]`} className={`${showPassword ? "ri-eye-off-line" : "ri-eye-line"} text-[20px]`}
@@ -80,20 +80,20 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
<button <button
type="button" type="button"
onClick={onRightIconClick} onClick={onRightIconClick}
className="absolute right-3.5 top-1/2 -translate-y-1/2 text-[#7D7D7D] hover:text-[#000000] transition-colors cursor-pointer" className="absolute right-3.5 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-900 transition-colors cursor-pointer"
> >
<i className={`${rightIcon} text-[20px]`} /> <i className={`${rightIcon} text-[20px]`} />
</button> </button>
)} )}
</div> </div>
{error && ( {error && (
<p className="mt-1 text-[13px] text-[#FF3A05] flex items-center gap-1"> <p className="mt-1 text-[13px] text-red-500 flex items-center gap-1">
<i className="ri-error-warning-line" /> <i className="ri-error-warning-line" />
{error} {error}
</p> </p>
)} )}
{helperText && !error && ( {helperText && !error && (
<p className="mt-1 text-[13px] text-[#7D7D7D]">{helperText}</p> <p className="mt-1 text-[13px] text-zinc-500">{helperText}</p>
)} )}
</div> </div>
); );

View File

@@ -109,7 +109,7 @@ const SearchableSelect = forwardRef<HTMLSelectElement, SearchableSelectProps>(
{label && ( {label && (
<label className="block text-[13px] font-semibold text-zinc-900 dark:text-white mb-2"> <label className="block text-[13px] font-semibold text-zinc-900 dark:text-white mb-2">
{label} {label}
{required && <span className="text-[#FF3A05] ml-1">*</span>} {required && <span className="text-brand-500 ml-1">*</span>}
</label> </label>
)} )}
@@ -133,8 +133,8 @@ const SearchableSelect = forwardRef<HTMLSelectElement, SearchableSelectProps>(
${leftIcon ? "pl-11" : ""} ${leftIcon ? "pl-11" : ""}
pr-11 pr-11
${error ${error
? "border-[#FF3A05]" ? "border-red-500 focus:border-red-500"
: "border-zinc-200 dark:border-zinc-700 focus:border-[#FF3A05]" : "border-zinc-200 dark:border-zinc-700 focus:border-brand-500"
} }
outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none
${className} ${className}
@@ -160,7 +160,7 @@ const SearchableSelect = forwardRef<HTMLSelectElement, SearchableSelectProps>(
value={searchTerm} value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Buscar..." placeholder="Buscar..."
className="w-full pl-9 pr-3 py-2 text-[14px] border border-zinc-200 dark:border-zinc-700 rounded-md outline-none focus:border-[#FF3A05] shadow-none bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder:text-zinc-500 dark:placeholder:text-zinc-400" className="w-full pl-9 pr-3 py-2 text-[14px] border border-zinc-200 dark:border-zinc-700 rounded-md outline-none focus:border-brand-500 shadow-none bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white placeholder:text-zinc-500 dark:placeholder:text-zinc-400"
/> />
</div> </div>
</div> </div>
@@ -176,7 +176,7 @@ const SearchableSelect = forwardRef<HTMLSelectElement, SearchableSelectProps>(
className={` className={`
w-full px-4 py-2.5 text-left text-[14px] transition-colors w-full px-4 py-2.5 text-left text-[14px] transition-colors
hover:bg-zinc-100 dark:hover:bg-zinc-700 cursor-pointer hover:bg-zinc-100 dark:hover:bg-zinc-700 cursor-pointer
${selectedOption?.value === option.value ? 'bg-[#FF3A05]/10 text-[#FF3A05] font-medium' : 'text-zinc-900 dark:text-white'} ${selectedOption?.value === option.value ? 'bg-brand-500/10 text-brand-600 font-medium' : 'text-zinc-900 dark:text-white'}
`} `}
> >
{option.label} {option.label}
@@ -196,7 +196,7 @@ const SearchableSelect = forwardRef<HTMLSelectElement, SearchableSelectProps>(
<p className="mt-1.5 text-[12px] text-zinc-600 dark:text-zinc-400">{helperText}</p> <p className="mt-1.5 text-[12px] text-zinc-600 dark:text-zinc-400">{helperText}</p>
)} )}
{error && ( {error && (
<p className="mt-1 text-[13px] text-[#FF3A05] flex items-center gap-1"> <p className="mt-1 text-[13px] text-red-500 flex items-center gap-1">
<i className="ri-error-warning-line" /> <i className="ri-error-warning-line" />
{error} {error}
</p> </p>

View File

@@ -33,9 +33,9 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
return ( return (
<div className="w-full"> <div className="w-full">
{label && ( {label && (
<label className="block text-[13px] font-semibold text-[#000000] mb-2"> <label className="block text-[13px] font-semibold text-zinc-900 mb-2">
{label} {label}
{props.required && <span className="text-[#FF3A05] ml-1">*</span>} {props.required && <span className="text-brand-500 ml-1">*</span>}
</label> </label>
)} )}
<div className="relative"> <div className="relative">
@@ -49,17 +49,17 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
className={` className={`
w-full px-3.5 py-3 text-[14px] font-normal w-full px-3.5 py-3 text-[14px] font-normal
border rounded-md bg-white border rounded-md bg-white
text-[#000000] text-zinc-900
transition-all appearance-none transition-all appearance-none
cursor-pointer cursor-pointer
${leftIcon ? "pl-11" : ""} ${leftIcon ? "pl-11" : ""}
pr-11 pr-11
${error ${error
? "border-[#FF3A05]" ? "border-red-500 focus:border-red-500"
: "border-[#E5E5E5] focus:border-[#FF3A05]" : "border-zinc-200 focus:border-brand-500"
} }
outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none outline-none ring-0 focus:ring-0 shadow-none focus:shadow-none
disabled:bg-[#F5F5F5] disabled:cursor-not-allowed disabled:bg-zinc-100 disabled:cursor-not-allowed
${className} ${className}
`} `}
{...props} {...props}
@@ -76,9 +76,9 @@ const Select = forwardRef<HTMLSelectElement, SelectProps>(
<i className="ri-arrow-down-s-line absolute right-3.5 top-1/2 -translate-y-1/2 text-[#7D7D7D] text-[20px] pointer-events-none" /> <i className="ri-arrow-down-s-line absolute right-3.5 top-1/2 -translate-y-1/2 text-[#7D7D7D] text-[20px] pointer-events-none" />
</div> </div>
{helperText && !error && ( {helperText && !error && (
<p className="mt-1.5 text-[12px] text-[#7D7D7D]">{helperText}</p> <p className="mt-1.5 text-[12px] text-zinc-500">{helperText}</p>
)} )}
{error && <p className="mt-1.5 text-[12px] text-[#FF3A05]">{error}</p>} {error && <p className="mt-1.5 text-[12px] text-red-500">{error}</p>}
</div> </div>
); );
} }

View File

@@ -16,6 +16,9 @@ export const API_ENDPOINTS = {
refresh: `${API_BASE_URL}/api/auth/refresh`, refresh: `${API_BASE_URL}/api/auth/refresh`,
me: `${API_BASE_URL}/api/me`, me: `${API_BASE_URL}/api/me`,
// Admin / Agencies
adminAgencyRegister: `${API_BASE_URL}/api/admin/agencies/register`,
// Health // Health
health: `${API_BASE_URL}/health`, health: `${API_BASE_URL}/health`,
apiHealth: `${API_BASE_URL}/api/health`, apiHealth: `${API_BASE_URL}/api/health`,

View File

@@ -1,10 +1,12 @@
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server'; import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) { export async function middleware(request: NextRequest) {
const hostname = request.headers.get('host') || ''; const hostname = request.headers.get('host') || '';
const url = request.nextUrl; const url = request.nextUrl;
const apiBase = process.env.API_INTERNAL_URL || 'http://backend:8080';
// Extrair subdomínio // Extrair subdomínio
const subdomain = hostname.split('.')[0]; const subdomain = hostname.split('.')[0];
@@ -17,9 +19,8 @@ export function middleware(request: NextRequest) {
// Se for agência ({subdomain}.localhost) - validar se existe // Se for agência ({subdomain}.localhost) - validar se existe
if (hostname.includes('.')) { if (hostname.includes('.')) {
try { try {
const res = await fetch(`http://backend:8080/api/tenant/check?subdomain=${subdomain}`); const res = await fetch(`${apiBase}/api/tenant/check?subdomain=${subdomain}`);
if (res.status === 404) { if (!res.ok) {
// Redireciona para o host base (sem subdomínio)
const baseHost = hostname.split('.').slice(1).join('.') || hostname; const baseHost = hostname.split('.').slice(1).join('.') || hostname;
const redirectUrl = new URL(url.toString()); const redirectUrl = new URL(url.toString());
redirectUrl.hostname = baseHost; redirectUrl.hostname = baseHost;
@@ -27,7 +28,11 @@ export function middleware(request: NextRequest) {
return NextResponse.redirect(redirectUrl); return NextResponse.redirect(redirectUrl);
} }
} catch (err) { } catch (err) {
// Em caso de erro de rede, não bloquear const baseHost = hostname.split('.').slice(1).join('.') || hostname;
const redirectUrl = new URL(url.toString());
redirectUrl.hostname = baseHost;
redirectUrl.pathname = '/';
return NextResponse.redirect(redirectUrl);
} }
} }

View File

@@ -10,17 +10,17 @@ module.exports = {
}, },
colors: { colors: {
brand: { brand: {
50: '#f0f9ff', 50: '#fff4ef',
100: '#e0f2fe', 100: '#ffe8df',
200: '#bae6fd', 200: '#ffd0c0',
300: '#7dd3fc', 300: '#ffb093',
400: '#38bdf8', 400: '#ff8a66',
500: '#0ea5e9', 500: '#ff3a05',
600: '#0284c7', 600: '#ff1f45',
700: '#0369a1', 700: '#ff0080',
800: '#075985', 800: '#d10069',
900: '#0c4a6e', 900: '#9e0050',
950: '#082f49', 950: '#4b0028',
}, },
surface: { surface: {
light: '#ffffff', light: '#ffffff',
@@ -28,7 +28,7 @@ module.exports = {
}, },
}, },
boxShadow: { boxShadow: {
glow: '0 0 20px rgba(14, 165, 233, 0.3)', glow: '0 0 20px rgba(255, 58, 5, 0.25)',
}, },
}, },
}, },

View File

@@ -34,4 +34,38 @@ html.dark {
box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.25); box-shadow: 0 25px 50px -12px rgba(15, 23, 42, 0.25);
backdrop-filter: blur(20px); backdrop-filter: blur(20px);
} }
}
@layer utilities {
.bg-brand {
background: var(--color-gradient-brand);
}
.bg-brand-soft {
background: linear-gradient(135deg, var(--color-brand-from-20), var(--color-brand-to-20));
}
.bg-brand-horizontal-soft {
background: linear-gradient(90deg, var(--color-brand-from-20), var(--color-brand-to-20));
}
.hover\:bg-brand:hover {
background: var(--color-gradient-brand);
}
.text-brand-gradient {
background: var(--color-gradient-brand);
-webkit-background-clip: text;
color: transparent;
}
.hover\:text-brand-gradient:hover {
background: var(--color-gradient-brand);
-webkit-background-clip: text;
color: transparent;
}
.shadow-brand-20 {
box-shadow: 0 10px 15px -3px var(--color-brand-shadow-20), 0 4px 6px -4px var(--color-brand-shadow-20);
}
} }

View File

@@ -12,7 +12,7 @@ export default function Home() {
<section className="py-28 bg-white dark:bg-zinc-900 transition-colors"> <section className="py-28 bg-white dark:bg-zinc-900 transition-colors">
<div className="max-w-7xl mx-auto px-6 lg:px-8 grid lg:grid-cols-2 gap-14 items-center"> <div className="max-w-7xl mx-auto px-6 lg:px-8 grid lg:grid-cols-2 gap-14 items-center">
<div> <div>
<div className="inline-flex items-center gap-2 px-4 py-2 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-full text-sm font-semibold text-white shadow-lg shadow-[#FF3A05]/25 mb-8"> <div className="inline-flex items-center gap-2 px-4 py-2 bg-brand rounded-full text-sm font-semibold text-white shadow-lg shadow-brand-20 mb-8">
<i className="ri-rocket-line text-base"></i> <i className="ri-rocket-line text-base"></i>
<span>Plataforma de Gestão Financeira</span> <span>Plataforma de Gestão Financeira</span>
</div> </div>
@@ -26,11 +26,11 @@ export default function Home() {
</p> </p>
<div className="flex flex-col sm:flex-row items-center gap-4"> <div className="flex flex-col sm:flex-row items-center gap-4">
<Link href="http://dash.localhost/cadastro" className="px-8 py-3 bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white font-semibold rounded-xl hover:opacity-90 transition-opacity shadow-lg shadow-[#FF3A05]/30"> <Link href="http://dash.localhost/cadastro" className="px-8 py-3 bg-brand text-white font-semibold rounded-xl hover:opacity-90 transition-opacity shadow-lg shadow-brand-20">
<i className="ri-arrow-right-line mr-2"></i> <i className="ri-arrow-right-line mr-2"></i>
Começar Grátis Começar Grátis
</Link> </Link>
<Link href="#demo" className="px-8 py-3 rounded-xl border border-zinc-300 text-zinc-700 dark:text-white font-semibold hover:border-transparent hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:text-white transition-all"> <Link href="#demo" className="px-8 py-3 rounded-xl border border-zinc-300 text-zinc-700 dark:text-white font-semibold hover:border-transparent hover:bg-brand hover:text-white transition-all">
<i className="ri-play-circle-line mr-2"></i> <i className="ri-play-circle-line mr-2"></i>
Ver Demo Ver Demo
</Link> </Link>
@@ -49,7 +49,7 @@ export default function Home() {
</div> </div>
<div className="relative"> <div className="relative">
<div className="absolute inset-0 blur-3xl bg-linear-to-r from-[#FF3A05]/20 to-[#FF0080]/20 rounded-[40px]"></div> <div className="absolute inset-0 blur-3xl bg-brand-horizontal-soft rounded-[40px]"></div>
<div className="relative rounded-4xl border border-white/30 bg-white/80 dark:bg-zinc-950/80 backdrop-blur-xl shadow-2xl overflow-hidden"> <div className="relative rounded-4xl border border-white/30 bg-white/80 dark:bg-zinc-950/80 backdrop-blur-xl shadow-2xl overflow-hidden">
<div className="flex items-center justify-between px-8 py-6 border-b border-zinc-100 dark:border-zinc-800"> <div className="flex items-center justify-between px-8 py-6 border-b border-zinc-100 dark:border-zinc-800">
<div> <div>
@@ -76,11 +76,11 @@ export default function Home() {
<p className="font-semibold text-zinc-900 dark:text-white">Fluxo de caixa</p> <p className="font-semibold text-zinc-900 dark:text-white">Fluxo de caixa</p>
<span className="text-sm text-emerald-500">+18% este mês</span> <span className="text-sm text-emerald-500">+18% este mês</span>
</div> </div>
<div className="h-40 bg-linear-to-r from-[#FF3A05]/20 via-transparent to-[#FF0080]/20 rounded-xl relative"> <div className="h-40 bg-brand-horizontal-soft rounded-xl relative">
<div className="absolute inset-4 rounded-xl border border-dashed border-zinc-200 dark:border-zinc-800"></div> <div className="absolute inset-4 rounded-xl border border-dashed border-zinc-200 dark:border-zinc-800"></div>
<div className="absolute inset-0 flex items-end gap-2 p-6"> <div className="absolute inset-0 flex items-end gap-2 p-6">
{[40, 60, 80, 50, 90, 70].map((height, index) => ( {[40, 60, 80, 50, 90, 70].map((height, index) => (
<span key={index} className="w-4 rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080]" style={{ height: `${height}%` }}></span> <span key={index} className="w-4 rounded-full bg-brand" style={{ height: `${height}%` }}></span>
))} ))}
</div> </div>
</div> </div>
@@ -116,11 +116,11 @@ export default function Home() {
{ id: "integra", icon: "ri-share-forward-line", title: "Integrações API", desc: "Conecte a Aggios com BI, contabilidade e ferramentas internas via API segura." }, { id: "integra", icon: "ri-share-forward-line", title: "Integrações API", desc: "Conecte a Aggios com BI, contabilidade e ferramentas internas via API segura." },
].map((item) => ( ].map((item) => (
<div id={item.id} key={item.id} className="relative rounded-4xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950/80 backdrop-blur-xl p-8 shadow-lg overflow-hidden"> <div id={item.id} key={item.id} className="relative rounded-4xl border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-950/80 backdrop-blur-xl p-8 shadow-lg overflow-hidden">
<div className="absolute -top-20 -right-10 h-40 w-40 rounded-full bg-linear-to-r from-[#FF3A05]/10 to-[#FF0080]/10 blur-3xl" aria-hidden="true"></div> <div className="absolute -top-20 -right-10 h-40 w-40 rounded-full bg-brand-soft blur-3xl" aria-hidden="true"></div>
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-6 relative z-10"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-6 relative z-10">
<div> <div>
<div className="inline-flex items-center gap-3 mb-4 px-4 py-2 rounded-full border border-zinc-200 dark:border-zinc-800 text-xs uppercase tracking-[0.2em] text-zinc-500"> <div className="inline-flex items-center gap-3 mb-4 px-4 py-2 rounded-full border border-zinc-200 dark:border-zinc-800 text-xs uppercase tracking-[0.2em] text-zinc-500">
<span className="flex h-8 w-8 items-center justify-center rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white text-lg"> <span className="flex h-8 w-8 items-center justify-center rounded-2xl bg-brand text-white text-lg">
<i className={item.icon}></i> <i className={item.icon}></i>
</span> </span>
{item.title} {item.title}
@@ -132,8 +132,8 @@ export default function Home() {
<div className="w-full sm:w-48 h-36 rounded-2xl border border-dashed border-zinc-200 dark:border-zinc-800 p-4 text-sm text-zinc-500 dark:text-zinc-400 bg-white/60 dark:bg-zinc-900/60"> <div className="w-full sm:w-48 h-36 rounded-2xl border border-dashed border-zinc-200 dark:border-zinc-800 p-4 text-sm text-zinc-500 dark:text-zinc-400 bg-white/60 dark:bg-zinc-900/60">
<p className="font-semibold text-zinc-900 dark:text-white mb-2">Módulo em ação</p> <p className="font-semibold text-zinc-900 dark:text-white mb-2">Módulo em ação</p>
<div className="space-y-2"> <div className="space-y-2">
<div className="h-2 rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080]/70"></div> <div className="h-2 rounded-full bg-brand"></div>
<div className="h-2 rounded-full bg-linear-to-r from-[#FF0080] to-[#FF3A05]/70 w-3/4"></div> <div className="h-2 rounded-full bg-brand w-3/4"></div>
<div className="h-2 rounded-full bg-zinc-200 dark:bg-zinc-800 w-2/3"></div> <div className="h-2 rounded-full bg-zinc-200 dark:bg-zinc-800 w-2/3"></div>
</div> </div>
</div> </div>
@@ -157,48 +157,48 @@ export default function Home() {
</div> </div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-dashboard-3-line text-2xl text-white"></i> <i className="ri-dashboard-3-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Dashboard Inteligente</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Dashboard Inteligente</h3>
<p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Visualize todos os seus dados financeiros em tempo real com gráficos e métricas intuitivas.</p> <p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Visualize todos os seus dados financeiros em tempo real com gráficos e métricas intuitivas.</p>
</div> </div>
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-team-line text-2xl text-white"></i> <i className="ri-team-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Gestão de Clientes</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Gestão de Clientes</h3>
<p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Organize e acompanhe todos os seus clientes com informações detalhadas e histórico completo.</p> <p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Organize e acompanhe todos os seus clientes com informações detalhadas e histórico completo.</p>
</div> </div>
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-file-chart-line text-2xl text-white"></i> <i className="ri-file-chart-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Relatórios Avançados</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Relatórios Avançados</h3>
<p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Gere relatórios detalhados e personalizados para tomar decisões mais assertivas.</p> <p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Gere relatórios detalhados e personalizados para tomar decisões mais assertivas.</p>
</div> </div>
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-secure-payment-line text-2xl text-white"></i> <i className="ri-secure-payment-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Segurança Total</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Segurança Total</h3>
<p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Seus dados protegidos com criptografia de ponta e backup automático na nuvem.</p> <p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Seus dados protegidos com criptografia de ponta e backup automático na nuvem.</p>
</div> </div>
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-smartphone-line text-2xl text-white"></i> <i className="ri-smartphone-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Acesso Mobile</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Acesso Mobile</h3>
<p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Gerencie seu negócio de qualquer lugar com nossa plataforma responsiva e intuitiva.</p> <p className="text-zinc-600 dark:text-zinc-400 leading-relaxed transition-colors">Gerencie seu negócio de qualquer lugar com nossa plataforma responsiva e intuitiva.</p>
</div> </div>
<div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-900 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="w-12 h-12 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-xl flex items-center justify-center mb-6"> <div className="w-12 h-12 bg-brand rounded-xl flex items-center justify-center mb-6">
<i className="ri-customer-service-2-line text-2xl text-white"></i> <i className="ri-customer-service-2-line text-2xl text-white"></i>
</div> </div>
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Suporte 24/7</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-4 transition-colors">Suporte 24/7</h3>
@@ -222,7 +222,7 @@ export default function Home() {
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-6xl mx-auto"> <div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-6xl mx-auto">
{/* Plano Básico */} {/* Plano Básico */}
<div className="bg-white dark:bg-zinc-800 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-800 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="text-center mb-8"> <div className="text-center mb-8">
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-2 transition-colors">Básico</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-2 transition-colors">Básico</h3>
<div className="flex items-baseline justify-center gap-1 mb-2"> <div className="flex items-baseline justify-center gap-1 mb-2">
@@ -234,40 +234,40 @@ export default function Home() {
<ul className="space-y-4 mb-8"> <ul className="space-y-4 mb-8">
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Até 10 clientes</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Até 10 clientes</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Dashboard básico</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Dashboard básico</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Relatórios mensais</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Relatórios mensais</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Suporte por email</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Suporte por email</span>
</li> </li>
</ul> </ul>
<Link href="http://dash.localhost/cadastro" className="w-full px-6 py-3 border-2 border-zinc-200 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:text-white transition-all block text-center"> <Link href="http://dash.localhost/cadastro" className="w-full px-6 py-3 border-2 border-zinc-200 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-brand hover:text-white transition-all block text-center">
Começar Grátis Começar Grátis
</Link> </Link>
</div> </div>
{/* Plano Pro */} {/* Plano Pro */}
<div className="bg-linear-to-br from-[#FF3A05] to-[#FF0080] p-8 rounded-2xl text-white shadow-2xl transform scale-105"> <div className="bg-brand p-8 rounded-2xl text-white shadow-2xl transform scale-105">
<div className="text-center mb-8"> <div className="text-center mb-8">
<div className="inline-flex items-center gap-2 px-3 py-1 mb-4 rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-sm font-semibold tracking-tight text-white shadow-lg shadow-black/20"> <div className="inline-flex items-center gap-2 px-3 py-1 mb-4 rounded-full bg-brand text-sm font-semibold tracking-tight text-white shadow-lg shadow-black/20">
<i className="ri-star-line text-xs"></i> <i className="ri-star-line text-xs"></i>
<span>Mais Popular</span> <span>Mais Popular</span>
</div> </div>
@@ -308,7 +308,7 @@ export default function Home() {
</div> </div>
{/* Plano Enterprise */} {/* Plano Enterprise */}
<div className="bg-white dark:bg-zinc-800 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-[#FF3A05]/20 dark:hover:shadow-[#FF3A05]/10 transition-all"> <div className="bg-white dark:bg-zinc-800 p-8 rounded-2xl border border-zinc-200 dark:border-zinc-700 hover:border-transparent hover:shadow-lg hover:shadow-brand-20 transition-all">
<div className="text-center mb-8"> <div className="text-center mb-8">
<h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-2 transition-colors">Enterprise</h3> <h3 className="font-heading font-bold text-xl text-zinc-900 dark:text-white mb-2 transition-colors">Enterprise</h3>
<div className="flex items-baseline justify-center gap-1 mb-2"> <div className="flex items-baseline justify-center gap-1 mb-2">
@@ -320,38 +320,38 @@ export default function Home() {
<ul className="space-y-4 mb-8"> <ul className="space-y-4 mb-8">
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Clientes ilimitados</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Clientes ilimitados</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Dashboard personalizado</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Dashboard personalizado</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Relatórios avançados</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Relatórios avançados</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">Suporte dedicado</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">Suporte dedicado</span>
</li> </li>
<li className="flex items-center gap-3"> <li className="flex items-center gap-3">
<span className="flex h-6 w-6 items-center justify-center rounded-full bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white shadow-sm"> <span className="flex h-6 w-6 items-center justify-center rounded-full bg-brand text-white shadow-sm">
<i className="ri-check-line text-[13px]"></i> <i className="ri-check-line text-[13px]"></i>
</span> </span>
<span className="text-zinc-600 dark:text-zinc-300 transition-colors">White label</span> <span className="text-zinc-600 dark:text-zinc-300 transition-colors">White label</span>
</li> </li>
</ul> </ul>
<Link href="#contact" className="w-full px-6 py-3 border-2 border-zinc-200 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:text-white transition-all block text-center"> <Link href="#contact" className="w-full px-6 py-3 border-2 border-zinc-200 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-brand hover:text-white transition-all block text-center">
Falar com Vendas Falar com Vendas
</Link> </Link>
</div> </div>
@@ -371,11 +371,11 @@ export default function Home() {
</p> </p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4"> <div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<Link href="http://dash.localhost/cadastro" className="px-6 py-3 bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white font-semibold rounded-lg hover:opacity-90 transition-opacity shadow-lg"> <Link href="http://dash.localhost/cadastro" className="px-6 py-3 bg-brand text-white font-semibold rounded-lg hover:opacity-90 transition-opacity shadow-lg">
<i className="ri-rocket-line mr-2"></i> <i className="ri-rocket-line mr-2"></i>
Começar Grátis Agora Começar Grátis Agora
</Link> </Link>
<Link href="#contact" className="px-6 py-3 border-2 border-zinc-300 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:text-white transition-all"> <Link href="#contact" className="px-6 py-3 border-2 border-zinc-300 dark:border-zinc-600 text-zinc-700 dark:text-zinc-300 font-semibold rounded-lg hover:border-transparent hover:bg-brand hover:text-white transition-all">
<i className="ri-phone-line mr-2"></i> <i className="ri-phone-line mr-2"></i>
Falar com Especialista Falar com Especialista
</Link> </Link>
@@ -391,7 +391,7 @@ export default function Home() {
<div className="grid grid-cols-1 md:grid-cols-4 gap-8"> <div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="md:col-span-2"> <div className="md:col-span-2">
<div className="flex items-center gap-2 mb-6"> <div className="flex items-center gap-2 mb-6">
<div className="w-8 h-8 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-lg flex items-center justify-center"> <div className="w-8 h-8 bg-brand rounded-lg flex items-center justify-center">
<span className="text-white font-bold text-sm">A</span> <span className="text-white font-bold text-sm">A</span>
</div> </div>
<span className="font-heading font-bold text-xl">aggios</span> <span className="font-heading font-bold text-xl">aggios</span>
@@ -401,13 +401,13 @@ export default function Home() {
Transforme sua gestão e impulsione seus resultados. Transforme sua gestão e impulsione seus resultados.
</p> </p>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] transition-all group"> <a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-brand transition-all group">
<i className="ri-linkedin-line text-lg group-hover:text-white"></i> <i className="ri-linkedin-line text-lg group-hover:text-white"></i>
</a> </a>
<a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] transition-all group"> <a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-brand transition-all group">
<i className="ri-twitter-line text-lg group-hover:text-white"></i> <i className="ri-twitter-line text-lg group-hover:text-white"></i>
</a> </a>
<a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] transition-all group"> <a href="#" className="w-10 h-10 bg-zinc-800 dark:bg-zinc-700 rounded-lg flex items-center justify-center hover:bg-brand transition-all group">
<i className="ri-instagram-line text-lg group-hover:text-white"></i> <i className="ri-instagram-line text-lg group-hover:text-white"></i>
</a> </a>
</div> </div>
@@ -416,20 +416,20 @@ export default function Home() {
<div> <div>
<h3 className="font-heading font-bold text-lg mb-4">Produto</h3> <h3 className="font-heading font-bold text-lg mb-4">Produto</h3>
<ul className="space-y-3"> <ul className="space-y-3">
<li><a href="#features" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">Recursos</a></li> <li><a href="#features" className="text-zinc-400 hover:text-brand-gradient transition-all">Recursos</a></li>
<li><a href="#pricing" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">Preços</a></li> <li><a href="#pricing" className="text-zinc-400 hover:text-brand-gradient transition-all">Preços</a></li>
<li><a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">API</a></li> <li><a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all">API</a></li>
<li><a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">Integrações</a></li> <li><a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all">Integrações</a></li>
</ul> </ul>
</div> </div>
<div> <div>
<h3 className="font-heading font-bold text-lg mb-4">Suporte</h3> <h3 className="font-heading font-bold text-lg mb-4">Suporte</h3>
<ul className="space-y-3"> <ul className="space-y-3">
<li><a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">Central de Ajuda</a></li> <li><a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all">Central de Ajuda</a></li>
<li><a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">Documentação</a></li> <li><a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all">Documentação</a></li>
<li><a href="mailto:suporte@aggios.app" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">suporte@aggios.app</a></li> <li><a href="mailto:suporte@aggios.app" className="text-zinc-400 hover:text-brand-gradient transition-all">suporte@aggios.app</a></li>
<li><a href="tel:+5511999999999" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all">(11) 99999-9999</a></li> <li><a href="tel:+5511999999999" className="text-zinc-400 hover:text-brand-gradient transition-all">(11) 99999-9999</a></li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -439,9 +439,9 @@ export default function Home() {
© 2025 Aggios. Todos os direitos reservados. © 2025 Aggios. Todos os direitos reservados.
</p> </p>
<div className="flex items-center gap-6 mt-4 md:mt-0"> <div className="flex items-center gap-6 mt-4 md:mt-0">
<a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all text-sm">Privacidade</a> <a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all text-sm">Privacidade</a>
<a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all text-sm">Termos</a> <a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all text-sm">Termos</a>
<a href="#" className="text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all text-sm">Cookies</a> <a href="#" className="text-zinc-400 hover:text-brand-gradient transition-all text-sm">Cookies</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -45,6 +45,14 @@
/* Gradientes */ /* Gradientes */
--gradient-primary: linear-gradient(135deg, var(--color-brand-500) 0%, var(--color-brand-700) 100%); --gradient-primary: linear-gradient(135deg, var(--color-brand-500) 0%, var(--color-brand-700) 100%);
--gradient-accent: linear-gradient(135deg, #6366f1 0%, #a855f7 100%); --gradient-accent: linear-gradient(135deg, #6366f1 0%, #a855f7 100%);
--color-brand-from: #ff3a05;
--color-brand-to: #ff0080;
--color-gradient-brand: linear-gradient(135deg, var(--color-brand-from) 0%, var(--color-brand-to) 100%);
--color-brand-from-10: color-mix(in srgb, var(--color-brand-from) 10%, transparent);
--color-brand-from-20: color-mix(in srgb, var(--color-brand-from) 20%, transparent);
--color-brand-to-10: color-mix(in srgb, var(--color-brand-to) 10%, transparent);
--color-brand-to-20: color-mix(in srgb, var(--color-brand-to) 20%, transparent);
--color-brand-shadow-20: color-mix(in srgb, var(--color-brand-from) 20%, transparent);
/* Focus ring */ /* Focus ring */
--focus-ring: 0 0 0 3px rgba(14, 165, 233, 0.3); --focus-ring: 0 0 0 3px rgba(14, 165, 233, 0.3);

View File

@@ -21,7 +21,7 @@ export default function Header() {
<div className="max-w-7xl mx-auto px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="flex items-center justify-between py-4"> <div className="flex items-center justify-between py-4">
<Link href="#" className="flex items-center gap-2" onClick={closeMobileMenu}> <Link href="#" className="flex items-center gap-2" onClick={closeMobileMenu}>
<div className="w-8 h-8 bg-linear-to-r from-[#FF3A05] to-[#FF0080] rounded-lg flex items-center justify-center"> <div className="w-8 h-8 bg-brand rounded-lg flex items-center justify-center">
<span className="text-white font-bold text-sm">A</span> <span className="text-white font-bold text-sm">A</span>
</div> </div>
<span className="font-heading font-bold text-xl text-zinc-900 dark:text-white transition-colors">aggios</span> <span className="font-heading font-bold text-xl text-zinc-900 dark:text-white transition-colors">aggios</span>
@@ -29,12 +29,12 @@ export default function Header() {
<nav className="hidden md:flex items-center gap-6 lg:gap-8 text-sm font-medium relative"> <nav className="hidden md:flex items-center gap-6 lg:gap-8 text-sm font-medium relative">
{navItems.map((item) => ( {navItems.map((item) => (
<a key={item.href} href={item.href} className="text-zinc-600 dark:text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all"> <a key={item.href} href={item.href} className="text-zinc-600 dark:text-zinc-400 hover:text-brand-gradient transition-all">
{item.label} {item.label}
</a> </a>
))} ))}
<div className="relative group"> <div className="relative group">
<button className="flex items-center gap-1 text-zinc-600 dark:text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all"> <button className="flex items-center gap-1 text-zinc-600 dark:text-zinc-400 hover:text-brand-gradient transition-all">
Soluções Soluções
<i className="ri-arrow-down-s-line text-sm" /> <i className="ri-arrow-down-s-line text-sm" />
</button> </button>
@@ -49,7 +49,7 @@ export default function Header() {
{ href: '#integra', icon: 'ri-share-forward-line', title: 'Integrações API', desc: 'Conexões com BI, contabilidade e apps internos.' }, { href: '#integra', icon: 'ri-share-forward-line', title: 'Integrações API', desc: 'Conexões com BI, contabilidade e apps internos.' },
].map((item) => ( ].map((item) => (
<a key={item.href} href={item.href} className="flex items-start gap-3 rounded-2xl px-4 py-3 text-left text-zinc-700 dark:text-zinc-200 hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors"> <a key={item.href} href={item.href} className="flex items-start gap-3 rounded-2xl px-4 py-3 text-left text-zinc-700 dark:text-zinc-200 hover:bg-zinc-100/70 dark:hover:bg-zinc-800/70 transition-colors">
<span className="mt-1 flex h-10 w-10 items-center justify-center rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white text-xl"> <span className="mt-1 flex h-10 w-10 items-center justify-center rounded-2xl bg-brand text-white text-xl">
<i className={item.icon}></i> <i className={item.icon}></i>
</span> </span>
<span> <span>
@@ -65,10 +65,10 @@ export default function Header() {
<div className="hidden md:flex items-center gap-4"> <div className="hidden md:flex items-center gap-4">
<ThemeToggle /> <ThemeToggle />
<Link href="http://dash.localhost/login" className="text-zinc-600 dark:text-zinc-400 hover:bg-linear-to-r hover:from-[#FF3A05] hover:to-[#FF0080] hover:bg-clip-text hover:text-transparent transition-all font-medium"> <Link href="http://dash.localhost/login" className="text-zinc-600 dark:text-zinc-400 hover:text-brand-gradient transition-all font-medium">
Entrar Entrar
</Link> </Link>
<Link href="http://dash.localhost/cadastro" className="px-6 py-2 bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white font-semibold rounded-lg hover:opacity-90 transition-opacity shadow-lg"> <Link href="http://dash.localhost/cadastro" className="px-6 py-2 bg-brand text-white font-semibold rounded-lg hover:opacity-90 transition-opacity shadow-lg">
Começar Grátis Começar Grátis
</Link> </Link>
</div> </div>
@@ -136,7 +136,7 @@ export default function Header() {
<Link <Link
href="http://dash.localhost/cadastro" href="http://dash.localhost/cadastro"
onClick={closeMobileMenu} onClick={closeMobileMenu}
className="w-full px-5 py-3 rounded-2xl bg-linear-to-r from-[#FF3A05] to-[#FF0080] text-white font-semibold shadow-lg" className="w-full px-5 py-3 rounded-2xl bg-brand text-white font-semibold shadow-lg"
> >
Começar Grátis Começar Grátis
</Link> </Link>

View File

@@ -38,6 +38,16 @@ http:
- security-headers - security-headers
service: dashboard-service service: dashboard-service
# Institucional site (aggios.local and localhost)
institucional-router:
entryPoints:
- web
rule: "Host(`aggios.local`) || Host(`localhost`)"
priority: 3
middlewares:
- security-headers
service: institucional-service
services: services:
api-service: api-service:
loadBalancer: loadBalancer:
@@ -48,3 +58,8 @@ http:
loadBalancer: loadBalancer:
servers: servers:
- url: http://dashboard:3000 - url: http://dashboard:3000
institucional-service:
loadBalancer:
servers:
- url: http://institucional:3000