aethex-forge/client/components/TeamWidget.tsx
2025-11-15 16:38:40 +00:00

184 lines
6 KiB
TypeScript

import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Users, MessageCircle, ExternalLink } from "lucide-react";
export interface TeamMember {
id: string;
name: string;
role: string;
title?: string;
avatar_url?: string;
status?: "online" | "offline" | "away";
bio?: string;
links?: Array<{ title: string; url: string }>;
}
interface TeamWidgetProps {
members: TeamMember[];
title?: string;
description?: string;
type?: "sprint" | "org" | "company";
onViewProfile?: (memberId: string) => void;
onMessage?: (memberId: string) => void;
accentColor?: "green" | "blue" | "purple" | "cyan";
}
const colorMap = {
green: {
bg: "bg-gradient-to-br from-green-950/40 to-green-900/20",
border: "border-green-500/20",
},
blue: {
bg: "bg-gradient-to-br from-blue-950/40 to-blue-900/20",
border: "border-blue-500/20",
},
purple: {
bg: "bg-gradient-to-br from-purple-950/40 to-purple-900/20",
border: "border-purple-500/20",
},
cyan: {
bg: "bg-gradient-to-br from-cyan-950/40 to-cyan-900/20",
border: "border-cyan-500/20",
},
};
const statusColors = {
online: "bg-green-500",
offline: "bg-gray-500",
away: "bg-yellow-500",
};
export function TeamWidget({
members,
title = "Team Members",
description = "Sprint team and collaborators",
type = "sprint",
onViewProfile,
onMessage,
accentColor = "green",
}: TeamWidgetProps) {
const colors = colorMap[accentColor];
return (
<Card className={`${colors.bg} border ${colors.border}`}>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Users className="h-5 w-5" />
{title}
</CardTitle>
<CardDescription>{description}</CardDescription>
</CardHeader>
<CardContent>
{members.length === 0 ? (
<div className="text-center py-12">
<Users className="h-12 w-12 mx-auto text-gray-500 opacity-50 mb-4" />
<p className="text-gray-400">No team members</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
{members.map((member) => (
<div
key={member.id}
className="p-4 bg-black/30 rounded-lg border border-gray-500/10 hover:border-gray-500/30 transition space-y-3"
>
{/* Member Header */}
<div className="flex items-start gap-3">
<div className="relative flex-shrink-0">
{member.avatar_url ? (
<img
src={member.avatar_url}
alt={member.name}
className="w-10 h-10 rounded-lg object-cover"
/>
) : (
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-gray-600 to-gray-700 flex items-center justify-center">
<span className="text-sm font-bold text-gray-200">
{member.name.charAt(0).toUpperCase()}
</span>
</div>
)}
{member.status && (
<div
className={`absolute bottom-0 right-0 w-3 h-3 rounded-full border-2 border-black ${
statusColors[member.status]
}`}
/>
)}
</div>
<div className="flex-1 min-w-0">
<h4 className="font-semibold text-white truncate">
{member.name}
</h4>
<p className="text-xs text-gray-400">{member.role}</p>
{member.title && (
<p className="text-xs text-gray-500">{member.title}</p>
)}
</div>
</div>
{/* Bio */}
{member.bio && (
<p className="text-xs text-gray-400 line-clamp-2">
{member.bio}
</p>
)}
{/* Links */}
{member.links && member.links.length > 0 && (
<div className="flex gap-1 flex-wrap pt-2 border-t border-gray-500/10">
{member.links.map((link) => (
<a
key={link.url}
href={link.url}
target="_blank"
rel="noopener noreferrer"
className="text-xs px-2 py-1 bg-gray-600/30 text-gray-300 rounded hover:bg-gray-600/50 transition inline-flex items-center gap-1"
>
{link.title}
<ExternalLink className="h-3 w-3" />
</a>
))}
</div>
)}
{/* Actions */}
<div className="grid grid-cols-2 gap-2 pt-2 border-t border-gray-500/10">
{onViewProfile && (
<Button
size="sm"
variant="outline"
className="border-gray-500/20 text-gray-300 hover:bg-gray-500/10 text-xs"
onClick={() => onViewProfile(member.id)}
>
Profile
</Button>
)}
{onMessage && (
<Button
size="sm"
className="bg-gray-600 hover:bg-gray-700 text-xs"
onClick={() => onMessage(member.id)}
>
<MessageCircle className="h-3 w-3 mr-1" />
Message
</Button>
)}
</div>
</div>
))}
</div>
)}
</CardContent>
</Card>
);
}
export default TeamWidget;