feat: implement portal shell layout with user authentication, sidebar navigation, and progress tracking

This commit is contained in:
Poyraz Avsever
2026-06-08 13:56:06 +03:00
parent 47b9f728e6
commit d41267c29b
17 changed files with 582 additions and 130 deletions
+19
View File
@@ -39,6 +39,24 @@ export default async function PortalLayout({
.join("")
.slice(0, 2) || "MS";
const { data: clientData } = await supabase
.from("clients")
.select("id")
.eq("client_auth_id", user.id)
.maybeSingle();
let avgProgress = 0;
if (clientData) {
const { data: projectsData } = await supabase
.from("projects")
.select("progress")
.eq("client_id", clientData.id)
.eq("status", "active");
if (projectsData && projectsData.length > 0) {
avgProgress = Math.round(projectsData.reduce((sum, p) => sum + p.progress, 0) / projectsData.length);
}
}
return (
<PortalShell
user={{
@@ -47,6 +65,7 @@ export default async function PortalLayout({
shortName,
avatarUrl: profile?.avatar_url || null,
}}
progress={avgProgress}
>
{children}
</PortalShell>
+1 -1
View File
@@ -42,7 +42,7 @@ export default async function PortalDashboardPage() {
const completedProjects = projects.filter(p => p.status === 'completed');
return (
<div className="flex flex-col gap-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="mx-auto flex max-w-7xl flex-col gap-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight">Hoş Geldiniz, {clientData.name}</h1>
<p className="text-muted-foreground">İş süreçlerinizi ve aktif projelerinizi buradan takip edebilirsiniz.</p>
@@ -32,7 +32,7 @@ export function PortalProjectClient({ project, sections, tasks, revisions, clien
const pendingRevisions = revisions.filter((r: any) => r.status === 'pending' || r.status === 'in_progress').length;
return (
<div className="mx-auto flex max-w-5xl flex-col gap-6 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="mx-auto flex max-w-7xl flex-col gap-6 animate-in fade-in slide-in-from-bottom-4 duration-500">
{/* Header Info */}
<div className="flex flex-col gap-4 md:flex-row md:items-start justify-between">
<div className="space-y-1">
+26
View File
@@ -0,0 +1,26 @@
import { MessageSquareDiff } from "lucide-react";
import Link from "next/link";
export default function PortalRevisionsPage() {
return (
<div className="mx-auto flex max-w-7xl flex-col gap-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight">Revizyon Taleplerim</h1>
<p className="text-muted-foreground">İlettiğiniz tüm revizyon taleplerinin durumunu buradan takip edebilirsiniz.</p>
</div>
<div className="flex min-h-72 flex-col items-center justify-center rounded-sm border border-dashed border-border bg-muted/20 p-8 text-center">
<MessageSquareDiff className="h-10 w-10 text-muted-foreground" />
<h3 className="mt-4 text-lg font-semibold text-foreground">
Revizyon modülü yapım aşamasında
</h3>
<p className="mt-2 max-w-md text-sm text-muted-foreground">
Yakında tüm revizyon taleplerinizi buradan yönetebileceksiniz. Şimdilik proje detay sayfasından revizyon talep edebilirsiniz.
</p>
<Link href="/portal" className="mt-4 text-primary hover:underline text-sm font-medium">
Dashboard'a dön
</Link>
</div>
</div>
);
}
+26
View File
@@ -0,0 +1,26 @@
import { FolderKanban } from "lucide-react";
import Link from "next/link";
export default function PortalTasksPage() {
return (
<div className="mx-auto flex max-w-7xl flex-col gap-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
<div className="flex flex-col gap-2">
<h1 className="text-3xl font-semibold tracking-tight">Görevlerim</h1>
<p className="text-muted-foreground">Size atanan ve herkese açık olan proje görevleri.</p>
</div>
<div className="flex min-h-72 flex-col items-center justify-center rounded-sm border border-dashed border-border bg-muted/20 p-8 text-center">
<FolderKanban className="h-10 w-10 text-muted-foreground" />
<h3 className="mt-4 text-lg font-semibold text-foreground">
Görev modülü yapım aşamasında
</h3>
<p className="mt-2 max-w-md text-sm text-muted-foreground">
Yakında tüm görevlerinizi buradan takip edebileceksiniz. Şimdilik proje detay sayfasından görevlere ulaşabilirsiniz.
</p>
<Link href="/portal" className="mt-4 text-primary hover:underline text-sm font-medium">
Dashboard'a dön
</Link>
</div>
</div>
);
}