feat: move public portal to root and admin login to /login

This commit is contained in:
Erik Silva
2026-01-21 19:15:10 -03:00
parent 0da0a4534b
commit 1b7a12ba9a
18 changed files with 96 additions and 84 deletions

View File

@@ -41,7 +41,7 @@ export default function NotFoundClient({ primaryColor, orgName }: NotFoundClient
<div className="flex flex-col gap-3">
<Link
href="/dashboard"
href="/"
className="flex items-center justify-center gap-2 group px-6 py-3 rounded-xl text-white font-semibold transition-all shadow-lg active:scale-95 hover:opacity-90"
style={{
backgroundColor: primaryColor,

View File

@@ -56,7 +56,7 @@ export async function login(email: string, password: string) {
// Logout
export async function logout() {
(await cookies()).delete("auth-token");
redirect("/");
redirect("/login");
}
// Verificar sessão

View File

@@ -75,7 +75,15 @@ export default function DashboardClient({
</p>
</div>
<div className="flex items-center">
<div className="flex flex-wrap items-center gap-3">
<a
href="/"
target="_blank"
className="w-full sm:w-auto h-11 sm:h-10 px-4 sm:px-6 rounded-xl sm:rounded-lg font-bold text-xs bg-slate-100 hover:bg-slate-200 text-slate-600 transition-all flex items-center justify-center gap-2"
>
<Eye size={16} />
Ver Portal Público
</a>
<a
href="/dashboard/documentos?upload=true"
style={{ backgroundColor: primaryColor }}

View File

@@ -8,7 +8,7 @@ export default async function ConfiguracoesPage() {
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const organization = await getOrganization();

View File

@@ -12,7 +12,7 @@ export default async function DocumentDetailPage({
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const { id } = await params;

View File

@@ -11,7 +11,7 @@ export default async function NewDocumentPage({
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const params = await searchParams;

View File

@@ -12,7 +12,7 @@ export default async function DocumentsPage({
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const params = await searchParams;

View File

@@ -7,7 +7,7 @@ export default async function DashboardPage() {
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const stats = await getDashboardStats();

View File

@@ -6,7 +6,7 @@ export default async function ProfilePage() {
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
return (

View File

@@ -8,7 +8,7 @@ export default async function UsuariosPage() {
const session = await getSession();
if (!session) {
redirect("/");
redirect("/login");
}
const users = await getUsers();

View File

@@ -175,7 +175,7 @@ export default function DocumentViewClient({
style={{ backgroundColor: primaryColor }}
>
<div className="max-w-5xl mx-auto flex items-center justify-between">
<a href="/portal" className="flex items-center gap-2 md:gap-3 hover:opacity-80 transition-opacity">
<a href="/" className="flex items-center gap-2 md:gap-3 hover:opacity-80 transition-opacity">
{organization.logoUrl ? (
<img
src={organization.logoUrl}
@@ -204,7 +204,7 @@ export default function DocumentViewClient({
</a>
) : null}
<a
href="/portal"
href="/"
className="text-white/80 hover:text-white flex items-center gap-1 md:gap-2 text-xs md:text-sm bg-white/10 hover:bg-white/20 px-2.5 py-1.5 rounded-lg transition-colors"
>
<Home size={14} />

26
src/app/login/page.tsx Normal file
View File

@@ -0,0 +1,26 @@
import React from "react";
import { prisma } from "@/lib/db";
import { redirect } from "next/navigation";
import LoginClient from "@/components/LoginClient";
import { getSession } from "@/app/actions/auth";
// Force dynamic rendering - this page needs database access
export const dynamic = 'force-dynamic';
export default async function Page() {
// Verifica se o usuário já está logado
const session = await getSession();
if (session) {
redirect("/dashboard");
}
// Verifica se existe alguma organização cadastrada
const organization = await prisma.organization.findFirst();
// Se não houver organização, redireciona para o setup inicial (Instalação)
if (!organization) {
redirect("/setup");
}
return <LoginClient organization={organization} />;
}

View File

@@ -1,28 +1,57 @@
import React from "react";
import { prisma } from "@/lib/db";
import { redirect } from "next/navigation";
import LoginClient from "@/components/LoginClient";
import { getSession } from "@/app/actions/auth";
import PortalClient from "./portal/PortalClient";
// Force dynamic rendering - this page needs database access
export const dynamic = 'force-dynamic';
export default async function Page() {
// Verifica se o usuário já está logado
const session = await getSession();
if (session) {
redirect("/dashboard");
}
// Verifica se existe alguma organização cadastrada
export default async function PortalPage() {
const organization = await prisma.organization.findFirst();
// Se não houver organização, redireciona para o setup inicial (Instalação)
if (!organization) {
redirect("/setup");
}
return <LoginClient organization={organization} />;
// Get all public root folders (projects)
const publicFolders = await prisma.folder.findMany({
where: {
organizationId: organization.id,
parentId: null,
isPublished: true,
},
orderBy: { createdAt: "desc" },
include: {
_count: {
select: {
documents: {
where: { isPublished: true }
},
children: {
where: { isPublished: true }
}
}
}
}
});
return (
<PortalClient
organization={{
name: organization.name,
logoUrl: organization.logoUrl,
primaryColor: organization.primaryColor,
}}
folders={publicFolders.map((f: any) => ({
id: f.id,
name: f.name,
description: f.description,
color: f.color,
imageUrl: f.imageUrl,
documentsCount: f._count.documents,
foldersCount: f._count.children,
createdAt: f.createdAt,
}))}
/>
);
}

View File

@@ -63,7 +63,7 @@ export default function PortalClient({
{/* Header */}
<header className="bg-white border-b border-slate-100 sticky top-0 z-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 sm:h-20 flex items-center justify-between">
<a href="/portal" className="flex items-center gap-3 sm:gap-4 min-w-0 hover:opacity-80 transition-opacity">
<a href="/" className="flex items-center gap-3 sm:gap-4 min-w-0 hover:opacity-80 transition-opacity">
{organization.logoUrl ? (
<img src={organization.logoUrl} alt={organization.name} className="h-8 sm:h-10 object-contain shrink-0" />
) : (

View File

@@ -1,56 +1,5 @@
import { prisma } from "@/lib/db";
import { redirect } from "next/navigation";
import PortalClient from "./PortalClient";
// Force dynamic rendering - this page needs database access
export const dynamic = 'force-dynamic';
export default async function PortalPage() {
const organization = await prisma.organization.findFirst();
if (!organization) {
redirect("/setup");
}
// Get all public root folders (projects)
const publicFolders = await prisma.folder.findMany({
where: {
organizationId: organization.id,
parentId: null,
isPublished: true,
},
orderBy: { createdAt: "desc" },
include: {
_count: {
select: {
documents: {
where: { isPublished: true }
},
children: {
where: { isPublished: true }
}
}
}
}
});
return (
<PortalClient
organization={{
name: organization.name,
logoUrl: organization.logoUrl,
primaryColor: organization.primaryColor,
}}
folders={publicFolders.map((f: any) => ({
id: f.id,
name: f.name,
description: f.description,
color: f.color,
imageUrl: f.imageUrl,
documentsCount: f._count.documents,
foldersCount: f._count.children,
createdAt: f.createdAt,
}))}
/>
);
export default function PortalRedirect() {
redirect("/");
}

View File

@@ -11,7 +11,7 @@ export default async function SetupPage() {
// Se já existe, redireciona para o login (setup já foi feito)
if (existingOrg) {
redirect("/");
redirect("/login");
}
// Se não existe, mostra o setup

View File

@@ -61,7 +61,7 @@ export default function UnauthorizedClient({ primaryColor, orgName }: Unauthoriz
</Link>
<Link
href="/"
href="/login"
className="px-6 py-3 rounded-xl font-semibold text-slate-500 hover:bg-slate-100 transition-all"
>
Fazer Login com outra conta

View File

@@ -105,7 +105,7 @@ export default function FolderViewClient({
{/* Header */}
<header className="bg-white border-b border-slate-100 sticky top-0 z-10">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 sm:h-20 flex items-center justify-between">
<a href="/portal" className="flex items-center gap-3 sm:gap-4 min-w-0 hover:opacity-80 transition-opacity">
<a href="/" className="flex items-center gap-3 sm:gap-4 min-w-0 hover:opacity-80 transition-opacity">
{organization.logoUrl ? (
<img src={organization.logoUrl} alt={organization.name} className="h-8 sm:h-10 object-contain shrink-0" />
) : (
@@ -120,7 +120,7 @@ export default function FolderViewClient({
</a>
<div className="flex items-center gap-2 sm:gap-3">
<a
href="/portal"
href="/"
className="flex items-center gap-1.5 px-2.5 sm:px-3 py-1.5 sm:py-2 rounded-lg bg-slate-100 hover:bg-slate-200 text-slate-600 hover:text-slate-900 transition-colors text-[10px] sm:text-xs font-bold uppercase tracking-wide"
>
<Home size={14} />