feat: [US-044] - Project sharing and collaborator management

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Gustavo Henrique Santos Souza de Miranda
2026-01-23 15:36:58 -03:00
co-authored by Claude Opus 4.5
parent 46b681462d
commit 37031c3889
7 changed files with 594 additions and 46 deletions
+36
View File
@@ -1,6 +1,7 @@
import { createClient } from '@/lib/supabase/server'
import NewProjectButton from '@/components/NewProjectButton'
import ProjectList from '@/components/ProjectList'
import ProjectCard from '@/components/ProjectCard'
export default async function DashboardPage() {
const supabase = await createClient()
@@ -19,6 +20,21 @@ export default async function DashboardPage() {
.eq('user_id', user.id)
.order('updated_at', { ascending: false })
// Fetch shared projects (projects where this user is a collaborator)
const { data: collaborations } = await supabase
.from('project_collaborators')
.select('role, projects(id, name, updated_at)')
.eq('user_id', user.id)
const sharedProjects = (collaborations || [])
.filter((c) => c.projects)
.map((c) => ({
...(c.projects as unknown as { id: string; name: string; updated_at: string }),
shared: true,
role: c.role,
}))
.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())
if (error) {
return (
<div className="rounded-lg border border-red-200 bg-red-50 p-4 dark:border-red-800 dark:bg-red-900/20">
@@ -44,6 +60,26 @@ export default async function DashboardPage() {
</div>
<ProjectList initialProjects={projects || []} />
{sharedProjects.length > 0 && (
<div className="mt-10">
<h2 className="mb-4 text-xl font-bold text-zinc-900 dark:text-zinc-50">
Shared with me
</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
{sharedProjects.map((project) => (
<ProjectCard
key={project.id}
id={project.id}
name={project.name}
updatedAt={project.updated_at}
shared
sharedRole={project.role}
/>
))}
</div>
</div>
)}
</div>
)
}