feat: move public portal to root and admin login to /login
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -8,7 +8,7 @@ export default async function ConfiguracoesPage() {
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const organization = await getOrganization();
|
||||
|
||||
@@ -12,7 +12,7 @@ export default async function DocumentDetailPage({
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const { id } = await params;
|
||||
|
||||
@@ -11,7 +11,7 @@ export default async function NewDocumentPage({
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const params = await searchParams;
|
||||
|
||||
@@ -12,7 +12,7 @@ export default async function DocumentsPage({
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const params = await searchParams;
|
||||
|
||||
@@ -7,7 +7,7 @@ export default async function DashboardPage() {
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const stats = await getDashboardStats();
|
||||
|
||||
@@ -6,7 +6,7 @@ export default async function ProfilePage() {
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -8,7 +8,7 @@ export default async function UsuariosPage() {
|
||||
const session = await getSession();
|
||||
|
||||
if (!session) {
|
||||
redirect("/");
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
const users = await getUsers();
|
||||
|
||||
@@ -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
26
src/app/login/page.tsx
Normal 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} />;
|
||||
}
|
||||
@@ -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,
|
||||
}))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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" />
|
||||
) : (
|
||||
|
||||
@@ -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("/");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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} />
|
||||
|
||||
Reference in New Issue
Block a user