191 lines
6.8 KiB
TypeScript
191 lines
6.8 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { auth } from '@/lib/firebase/config';
|
|
import { toast } from 'sonner';
|
|
import { Users, UserPlus, Crown, Mail } from 'lucide-react';
|
|
import { useParams } from 'next/navigation';
|
|
|
|
interface WorkspaceUser {
|
|
id: string;
|
|
email: string;
|
|
displayName: string;
|
|
role: 'owner' | 'admin' | 'member';
|
|
joinedAt: any;
|
|
lastActive: any;
|
|
}
|
|
|
|
export default function UsersPage() {
|
|
const params = useParams();
|
|
const workspace = params.workspace as string;
|
|
const [users, setUsers] = useState<WorkspaceUser[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [currentUser, setCurrentUser] = useState<WorkspaceUser | null>(null);
|
|
|
|
useEffect(() => {
|
|
loadUsers();
|
|
}, []);
|
|
|
|
const loadUsers = async () => {
|
|
try {
|
|
const user = auth.currentUser;
|
|
if (!user) return;
|
|
|
|
const token = await user.getIdToken();
|
|
const response = await fetch(`/api/workspace/${workspace}/users`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
},
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
setUsers(data.users);
|
|
setCurrentUser(data.currentUser);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading users:', error);
|
|
toast.error('Failed to load workspace users');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const getRoleBadgeColor = (role: string) => {
|
|
switch (role) {
|
|
case 'owner':
|
|
return 'bg-purple-500/10 text-purple-600 border-purple-500/20';
|
|
case 'admin':
|
|
return 'bg-blue-500/10 text-blue-600 border-blue-500/20';
|
|
default:
|
|
return 'bg-gray-500/10 text-gray-600 border-gray-500/20';
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-full flex-col overflow-auto">
|
|
<div className="flex-1 p-8 space-y-8 max-w-6xl">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<h1 className="text-4xl font-bold mb-2">Team Members</h1>
|
|
<p className="text-muted-foreground text-lg">
|
|
Manage workspace access and team collaboration
|
|
</p>
|
|
</div>
|
|
<Button disabled>
|
|
<UserPlus className="mr-2 h-4 w-4" />
|
|
Invite User
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Current User Info */}
|
|
{currentUser && (
|
|
<Card className="border-primary/50 bg-primary/5">
|
|
<CardHeader>
|
|
<CardTitle className="text-base flex items-center gap-2">
|
|
<Crown className="h-4 w-4" />
|
|
Your Account
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<p className="font-medium">{currentUser.displayName || 'Unknown'}</p>
|
|
<p className="text-sm text-muted-foreground">{currentUser.email}</p>
|
|
</div>
|
|
<div className={`px-3 py-1 rounded-full text-xs font-medium border ${getRoleBadgeColor(currentUser.role)}`}>
|
|
{currentUser.role}
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Users List */}
|
|
{loading ? (
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<p className="text-center text-muted-foreground">Loading team members...</p>
|
|
</CardContent>
|
|
</Card>
|
|
) : users.length === 0 ? (
|
|
<Card>
|
|
<CardContent className="pt-6 text-center space-y-4">
|
|
<div className="flex justify-center">
|
|
<div className="h-16 w-16 rounded-full bg-muted flex items-center justify-center">
|
|
<Users className="h-8 w-8 text-muted-foreground" />
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-lg font-semibold mb-2">No team members yet</h3>
|
|
<p className="text-sm text-muted-foreground mb-4">
|
|
Invite team members to collaborate on projects in this workspace
|
|
</p>
|
|
<Button disabled>
|
|
<UserPlus className="mr-2 h-4 w-4" />
|
|
Invite Your First Team Member
|
|
</Button>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
) : (
|
|
<div className="space-y-3">
|
|
{users.map((user) => (
|
|
<Card key={user.id}>
|
|
<CardContent className="pt-6">
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-4">
|
|
<div className="h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center">
|
|
<Mail className="h-5 w-5 text-primary" />
|
|
</div>
|
|
<div>
|
|
<p className="font-medium">{user.displayName || 'Unknown'}</p>
|
|
<p className="text-sm text-muted-foreground">{user.email}</p>
|
|
{user.lastActive && (
|
|
<p className="text-xs text-muted-foreground mt-1">
|
|
Last active: {new Date(user.lastActive._seconds * 1000).toLocaleDateString()}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center gap-3">
|
|
<div className={`px-3 py-1 rounded-full text-xs font-medium border ${getRoleBadgeColor(user.role)}`}>
|
|
{user.role}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{/* Info Card */}
|
|
<Card className="border-blue-500/20 bg-blue-500/5">
|
|
<CardHeader>
|
|
<CardTitle className="text-base">Team Collaboration (Coming Soon)</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-2 text-sm text-muted-foreground">
|
|
<p>
|
|
<strong>👥 Team Workspaces:</strong> Invite team members to collaborate on projects together.
|
|
</p>
|
|
<p>
|
|
<strong>🔐 Role-Based Access:</strong> Control what team members can see and do with flexible permissions.
|
|
</p>
|
|
<p>
|
|
<strong>💬 Shared Context:</strong> All team members can access shared AI chat history and project documentation.
|
|
</p>
|
|
<p className="text-xs italic pt-2">
|
|
This feature is currently in development. Check back soon!
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|