import React, { useState, useEffect } from "react"; import { Card, Title, Text, Tab, TabList, TabGroup, TabPanel, TabPanels, Grid, Badge, Button as TremorButton, TableRow, TableCell, TableHead, TableHeaderCell, TableBody, Table, Icon } from "@tremor/react"; import { teamInfoCall, teamMemberDeleteCall, teamMemberAddCall, teamMemberUpdateCall, Member } from "@/components/networking"; import { Button, Modal, Form, Input, Select as AntSelect, message } from "antd"; import { PencilAltIcon, PlusIcon, TrashIcon } from "@heroicons/react/outline"; import TeamMemberModal from "./edit_membership"; import UserSearchModal from "@/components/common_components/user_search_modal"; interface TeamData { team_id: string; team_info: { team_alias: string; team_id: string; organization_id: string | null; admins: string[]; members: string[]; members_with_roles: Member[]; metadata: Record; tpm_limit: number | null; rpm_limit: number | null; max_budget: number | null; budget_duration: string | null; models: string[]; blocked: boolean; spend: number; max_parallel_requests: number | null; budget_reset_at: string | null; model_id: string | null; litellm_model_table: string | null; created_at: string; }; keys: any[]; team_memberships: any[]; } interface TeamInfoProps { teamId: string; onClose: () => void; accessToken: string | null; is_team_admin: boolean; is_proxy_admin: boolean; } const TeamInfoView: React.FC = ({ teamId, onClose, accessToken, is_team_admin, is_proxy_admin }) => { const [teamData, setTeamData] = useState(null); const [loading, setLoading] = useState(true); const [isAddMemberModalVisible, setIsAddMemberModalVisible] = useState(false); const [form] = Form.useForm(); const [isEditMemberModalVisible, setIsEditMemberModalVisible] = useState(false); const [selectedEditMember, setSelectedEditMember] = useState(null); const canManageMembers = is_team_admin || is_proxy_admin; const fetchTeamInfo = async () => { try { setLoading(true); if (!accessToken) return; const response = await teamInfoCall(accessToken, teamId); setTeamData(response); } catch (error) { message.error("Failed to load team information"); console.error("Error fetching team info:", error); } finally { setLoading(false); } }; useEffect(() => { fetchTeamInfo(); }, [teamId, accessToken]); const handleMemberCreate = async (values: any) => { try { if (accessToken == null) { return; } const member: Member = { user_email: values.user_email, user_id: values.user_id, role: values.role, } const response = await teamMemberAddCall(accessToken, teamId, member); message.success("Team member added successfully"); setIsAddMemberModalVisible(false); form.resetFields(); fetchTeamInfo(); } catch (error) { message.error("Failed to add team member"); console.error("Error adding team member:", error); } }; const handleMemberDelete = async (member: Member) => { try { if (accessToken == null) { return; } const response = await teamMemberDeleteCall(accessToken, teamId, member); message.success("Team member removed successfully"); fetchTeamInfo(); } catch (error) { message.error("Failed to remove team member"); console.error("Error removing team member:", error); } }; const handleMemberUpdate = async (values: any) => { try { if (accessToken == null) { return; } const member: Member = { user_email: values.user_email, user_id: values.user_id, role: values.role, } const response = await teamMemberUpdateCall(accessToken, teamId, member); message.success("Team member updated successfully"); setIsEditMemberModalVisible(false); fetchTeamInfo(); } catch (error) { message.error("Failed to update team member"); console.error("Error updating team member:", error); } } if (loading) { return
Loading...
; } if (!teamData?.team_info) { return
Team not found
; } const { team_info: info } = teamData; const renderMembersPanel = () => (
User ID User Email Role {teamData ? teamData.team_info.members_with_roles.map( (member: any, index: number) => ( {member["user_id"]} {member["user_email"]} {member["role"]} {is_team_admin ? ( <> { setSelectedEditMember(member); setIsEditMemberModalVisible(true); }} /> {handleMemberDelete(member)}} icon={TrashIcon} size="sm" /> ) : null} ) ) : null}
setIsAddMemberModalVisible(true)}>Add Member
); return (
{info.team_alias} {info.team_id}
Overview Members Settings Budget Status
${info.spend.toFixed(6)} of {info.max_budget === null ? "Unlimited" : `$${info.max_budget}`} {info.budget_duration && ( Reset: {info.budget_duration} )}
Rate Limits
TPM: {info.tpm_limit || 'Unlimited'} RPM: {info.rpm_limit || 'Unlimited'} {info.max_parallel_requests && ( Max Parallel Requests: {info.max_parallel_requests} )}
Models
{info.models.map((model, index) => ( {model} ))}
{renderMembersPanel()} Team Settings
Team ID {info.team_id}
Created At {new Date(info.created_at).toLocaleString()}
Status {info.blocked ? 'Blocked' : 'Active'}
setIsEditMemberModalVisible(false)} onSubmit={handleMemberUpdate} initialData={selectedEditMember} mode="edit" />
setIsAddMemberModalVisible(false)} onSubmit={handleMemberCreate} accessToken={accessToken} />
); }; export default TeamInfoView;