Skip to content

Commit 373c379

Browse files
committed
catch all dashboard route
1 parent b4593d4 commit 373c379

10 files changed

Lines changed: 6337 additions & 308 deletions

File tree

app/dashboard/[[...path]]/page.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import DashboardClient from "@/components/dashboard/dashboard-client";
2+
3+
export function generateStaticParams() {
4+
// This satisfies the static export requirement
5+
return [{ path: [] }];
6+
}
7+
8+
export default function DashboardPage() {
9+
return <DashboardClient />;
10+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import { useRouter, usePathname } from "next/navigation";
5+
import { supabase } from "@/lib/supabase";
6+
import type { User } from "@supabase/supabase-js";
7+
import DashboardHome from "@/components/dashboard/dashboard-home";
8+
import PostsList from "@/components/dashboard/posts-list";
9+
import PostEditor from "@/components/dashboard/post-editor";
10+
import NewPost from "@/components/dashboard/new-post";
11+
import ProfileView from "@/components/dashboard/profile-view";
12+
import ProfileEditor from "@/components/dashboard/profile-editor";
13+
import NewProfile from "@/components/dashboard/new-profile";
14+
15+
export default function DashboardClient() {
16+
const router = useRouter();
17+
const pathname = usePathname();
18+
const [user, setUser] = useState<User | null>(null);
19+
const [loading, setLoading] = useState(true);
20+
21+
useEffect(() => {
22+
const checkAuth = async () => {
23+
const {
24+
data: { session },
25+
} = await supabase.auth.getSession();
26+
27+
if (!session) {
28+
router.push("/login");
29+
return;
30+
}
31+
32+
setUser(session.user);
33+
setLoading(false);
34+
};
35+
36+
checkAuth();
37+
38+
const {
39+
data: { subscription },
40+
} = supabase.auth.onAuthStateChange((event, session) => {
41+
if (event === "SIGNED_OUT") {
42+
router.push("/");
43+
}
44+
setUser(session?.user ?? null);
45+
setLoading(false);
46+
});
47+
48+
return () => {
49+
subscription.unsubscribe();
50+
};
51+
}, [router]);
52+
53+
if (loading) {
54+
return (
55+
<div className="flex justify-center items-center min-h-[400px]">
56+
<p>Loading...</p>
57+
</div>
58+
);
59+
}
60+
61+
// Client-side routing based on pathname
62+
if (!user) {
63+
return null;
64+
}
65+
66+
// Extract the path parts after /dashboard/
67+
const pathParts = pathname.split("/").slice(2);
68+
const section = pathParts[0] || "";
69+
const action = pathParts[1] || "";
70+
const id = pathParts[2] || "";
71+
72+
// Render the appropriate component based on the path
73+
if (section === "posts") {
74+
if (action === "new") {
75+
return <NewPost user={user} />;
76+
}
77+
if (action === "edit" && id) {
78+
return <PostEditor user={user} postId={id} />;
79+
}
80+
return <PostsList user={user} />;
81+
}
82+
83+
if (section === "profile") {
84+
if (action === "new") {
85+
return <NewProfile user={user} />;
86+
}
87+
if (action === "edit" && id) {
88+
return <ProfileEditor user={user} profileId={id} />;
89+
}
90+
return <ProfileView user={user} />;
91+
}
92+
93+
// Default to dashboard home
94+
return <DashboardHome user={user} />;
95+
}
Lines changed: 42 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
"use client"
1+
"use client";
22

3-
import { useEffect, useState } from "react"
4-
import { useRouter } from "next/navigation"
5-
import Link from "next/link"
6-
import { supabase } from "@/lib/supabase"
7-
import type { User } from "@supabase/supabase-js"
8-
import type { Author, Post } from "@/types/supabase"
9-
import { Button } from "@/components/ui/button"
10-
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
11-
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
12-
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
13-
import { Skeleton } from "@/components/ui/skeleton"
14-
import { Edit, Plus, Trash2 } from "lucide-react"
3+
import { useState, useEffect } from "react";
4+
import Link from "next/link";
5+
import { useRouter } from "next/navigation";
6+
import { supabase } from "@/lib/supabase";
7+
import type { User } from "@supabase/supabase-js";
8+
import type { Author, Post } from "@/types/supabase";
9+
import { Button } from "@/components/ui/button";
10+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
11+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
12+
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
13+
import { Skeleton } from "@/components/ui/skeleton";
14+
import { Edit, Plus, Trash2 } from "lucide-react";
1515
import {
1616
AlertDialog,
1717
AlertDialogAction,
@@ -22,70 +22,62 @@ import {
2222
AlertDialogHeader,
2323
AlertDialogTitle,
2424
AlertDialogTrigger,
25-
} from "@/components/ui/alert-dialog"
25+
} from "@/components/ui/alert-dialog";
2626

27-
export default function Dashboard() {
28-
const router = useRouter()
29-
const [user, setUser] = useState<User | null>(null)
30-
const [author, setAuthor] = useState<Author | null>(null)
31-
const [posts, setPosts] = useState<Post[]>([])
32-
const [loading, setLoading] = useState(true)
33-
34-
useEffect(() => {
35-
async function getUser() {
36-
const {
37-
data: { session },
38-
} = await supabase.auth.getSession()
39-
40-
if (!session) {
41-
router.push("/login")
42-
return
43-
}
27+
interface DashboardHomeProps {
28+
user: User;
29+
}
4430

45-
setUser(session.user)
31+
export default function DashboardHome({ user }: DashboardHomeProps) {
32+
const router = useRouter();
33+
const [author, setAuthor] = useState<Author | null>(null);
34+
const [posts, setPosts] = useState<Post[]>([]);
35+
const [loading, setLoading] = useState(true);
4636

37+
useEffect(() => {
38+
async function fetchData() {
4739
try {
4840
// Check if user has an author profile
49-
const { data: authorData } = await supabase.from("authors").select("*").eq("user_id", session.user.id).single()
41+
const { data: authorData } = await supabase.from("authors").select("*").eq("user_id", user.id).single();
5042

51-
setAuthor(authorData)
43+
setAuthor(authorData);
5244

5345
if (authorData) {
5446
// Fetch user's posts
5547
const { data: postsData } = await supabase
5648
.from("posts")
5749
.select("*")
5850
.eq("author_id", authorData.id)
59-
.order("created_at", { ascending: false })
51+
.order("created_at", { ascending: false });
6052

61-
setPosts(postsData || [])
53+
setPosts(postsData || []);
6254
}
6355
} catch (error) {
64-
console.error("Error fetching user data:", error)
56+
console.error("Error fetching user data:", error);
6557
} finally {
66-
setLoading(false)
58+
setLoading(false);
6759
}
6860
}
6961

70-
getUser()
71-
}, [router])
62+
fetchData();
63+
}, [user]);
7264

7365
const handleSignOut = async () => {
74-
await supabase.auth.signOut()
75-
router.push("/")
76-
}
66+
await supabase.auth.signOut();
67+
router.push("/");
68+
};
7769

7870
const handleDeletePost = async (postId: string) => {
7971
try {
80-
const { error } = await supabase.from("posts").delete().eq("id", postId)
72+
const { error } = await supabase.from("posts").delete().eq("id", postId);
8173

82-
if (error) throw error
74+
if (error) throw error;
8375

84-
setPosts(posts.filter((post) => post.id !== postId))
76+
setPosts(posts.filter((post) => post.id !== postId));
8577
} catch (error) {
86-
console.error("Error deleting post:", error)
78+
console.error("Error deleting post:", error);
8779
}
88-
}
80+
};
8981

9082
if (loading) {
9183
return (
@@ -96,7 +88,7 @@ export default function Dashboard() {
9688
</div>
9789
<Skeleton className="h-[500px] w-full" />
9890
</div>
99-
)
91+
);
10092
}
10193

10294
return (
@@ -277,6 +269,5 @@ export default function Dashboard() {
277269
</Tabs>
278270
)}
279271
</div>
280-
)
272+
);
281273
}
282-

0 commit comments

Comments
 (0)