Add initial Portal version
This commit is contained in:
5
src/app/[locale]/admin/page.tsx
Normal file
5
src/app/[locale]/admin/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import AdminTenantsClient from "@/components/admin/AdminTenantsClient";
|
||||
|
||||
export default function AdminPage() {
|
||||
return <AdminTenantsClient />;
|
||||
}
|
||||
5
src/app/[locale]/dashboard/page.tsx
Normal file
5
src/app/[locale]/dashboard/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import DashboardClient from "@/components/dashboard/DashboardClient";
|
||||
|
||||
export default function DashboardPage() {
|
||||
return <DashboardClient />;
|
||||
}
|
||||
43
src/app/[locale]/layout.tsx
Normal file
43
src/app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { getMessages } from "next-intl/server";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import { notFound } from "next/navigation";
|
||||
import { NavShell } from "@/components/layout/nav-shell";
|
||||
|
||||
export function generateStaticParams() {
|
||||
return routing.locales.map((locale) => ({ locale }));
|
||||
}
|
||||
|
||||
export default async function LocaleLayout({
|
||||
children,
|
||||
params,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
params: Promise<{ locale: string }>;
|
||||
}) {
|
||||
const { locale } = await params;
|
||||
|
||||
if (!routing.locales.includes(locale as any)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const messages = await getMessages();
|
||||
|
||||
return (
|
||||
<html lang={locale} className="dark">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>PieCed Portal</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="PieCed IT — Multi-tenant AI assistant platform"
|
||||
/>
|
||||
</head>
|
||||
<body className="min-h-screen bg-surface-0 text-text-primary antialiased">
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<NavShell>{children}</NavShell>
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
60
src/app/[locale]/login/page.tsx
Normal file
60
src/app/[locale]/login/page.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
"use client";
|
||||
|
||||
import { signIn } from "next-auth/react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function LoginPage() {
|
||||
const t = useTranslations("login");
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-surface-0">
|
||||
{/* Background grid pattern */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-[0.04]"
|
||||
style={{
|
||||
backgroundImage: `
|
||||
linear-gradient(var(--color-accent) 1px, transparent 1px),
|
||||
linear-gradient(90deg, var(--color-accent) 1px, transparent 1px)
|
||||
`,
|
||||
backgroundSize: "60px 60px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="relative z-10 w-full max-w-sm px-5 animate-in">
|
||||
{/* Logo mark */}
|
||||
<div className="flex justify-center mb-8">
|
||||
<div className="relative h-12 w-12">
|
||||
<div className="absolute inset-0 rounded-lg bg-accent/15" />
|
||||
<div className="absolute inset-[5px] rounded-md bg-accent" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-surface-1 rounded-2xl border border-border p-8 shadow-2xl shadow-black/40">
|
||||
<h1 className="font-display text-xl font-semibold text-center mb-1">
|
||||
{t("title")}
|
||||
</h1>
|
||||
<p className="text-text-secondary text-sm text-center mb-8">
|
||||
{t("subtitle")}
|
||||
</p>
|
||||
|
||||
<button
|
||||
onClick={() => signIn("zitadel", { callbackUrl: "/dashboard" })}
|
||||
className="
|
||||
w-full py-3 px-4 rounded-lg font-medium text-sm
|
||||
bg-accent text-surface-0 cursor-pointer
|
||||
hover:bg-accent-dim active:scale-[0.98]
|
||||
transition-all duration-150
|
||||
shadow-lg shadow-accent/20
|
||||
"
|
||||
>
|
||||
{t("button")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-center text-text-muted text-[11px] mt-6 tracking-wide uppercase">
|
||||
{t("footer")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
5
src/app/[locale]/page.tsx
Normal file
5
src/app/[locale]/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function RootPage() {
|
||||
redirect("/dashboard");
|
||||
}
|
||||
5
src/app/[locale]/tenants/[name]/page.tsx
Normal file
5
src/app/[locale]/tenants/[name]/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import TenantDetailClient from "@/components/tenants/TenantDetailClient";
|
||||
|
||||
export default function TenantDetailPage() {
|
||||
return <TenantDetailClient />;
|
||||
}
|
||||
Reference in New Issue
Block a user