import { useState, useEffect } from "react"; import { isAxiosError } from "axios"; import { useTranslation } from "react-i18next"; import { Stack, Text, Button, Table, ActionIcon, Badge, Loader, Group, Modal, Select, CloseButton, Tooltip, Menu, Avatar, Box, } from "@mantine/core"; import LocalIcon from "@app/components/shared/LocalIcon"; import { alert } from "@app/components/toast"; import { teamService, Team } from "@app/services/teamService"; import { User, userManagementService } from "@app/services/userManagementService"; import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex"; import ChangeUserPasswordModal from "@app/components/shared/ChangeUserPasswordModal"; interface TeamDetailsSectionProps { teamId: number; onBack: () => void; } export default function TeamDetailsSection({ teamId, onBack }: TeamDetailsSectionProps) { const { t } = useTranslation(); const [loading, setLoading] = useState(true); const [team, setTeam] = useState(null); const [teamUsers, setTeamUsers] = useState([]); const [availableUsers, setAvailableUsers] = useState([]); const [allTeams, setAllTeams] = useState([]); const [userLastRequest, setUserLastRequest] = useState>({}); const [addMemberModalOpened, setAddMemberModalOpened] = useState(false); const [changeTeamModalOpened, setChangeTeamModalOpened] = useState(false); const [changePasswordModalOpened, setChangePasswordModalOpened] = useState(false); const [passwordUser, setPasswordUser] = useState(null); const [selectedUser, setSelectedUser] = useState(null); const [selectedUserId, setSelectedUserId] = useState(""); const [selectedTeamId, setSelectedTeamId] = useState(""); const [processing, setProcessing] = useState(false); // License information const [licenseInfo, setLicenseInfo] = useState<{ availableSlots: number; } | null>(null); const [mailEnabled, setMailEnabled] = useState(false); const [lockedUsers, setLockedUsers] = useState([]); const isLockedUser = (user: User) => lockedUsers.includes(user.username); useEffect(() => { fetchTeamDetails(); fetchAllTeams(); }, [teamId]); const fetchTeamDetails = async () => { try { setLoading(true); const [data, adminData] = await Promise.all([teamService.getTeamDetails(teamId), userManagementService.getUsers()]); console.log("[TeamDetailsSection] Raw data:", data); setTeam(data.team); setTeamUsers(Array.isArray(data.teamUsers) ? data.teamUsers : []); setAvailableUsers(Array.isArray(data.availableUsers) ? data.availableUsers : []); setUserLastRequest(data.userLastRequest || {}); // Store license information setLicenseInfo({ availableSlots: adminData.availableSlots, }); setMailEnabled(adminData.mailEnabled); setLockedUsers(adminData.lockedUsers || []); } catch (error) { console.error("Failed to fetch team details:", error); alert({ alertType: "error", title: t("workspace.teams.loadError", "Failed to load team details") }); onBack(); } finally { setLoading(false); } }; const fetchAllTeams = async () => { try { const teams = await teamService.getTeams(); setAllTeams(teams); } catch (error) { console.error("Failed to fetch teams:", error); } }; const handleAddMember = async () => { if (!selectedUserId) { alert({ alertType: "error", title: t("workspace.teams.addMemberToTeam.selectUserRequired", "Please select a user") }); return; } try { setProcessing(true); await teamService.addUserToTeam(teamId, parseInt(selectedUserId)); alert({ alertType: "success", title: t("workspace.teams.addMemberToTeam.success", "User added to team successfully") }); setAddMemberModalOpened(false); setSelectedUserId(""); fetchTeamDetails(); } catch (error: unknown) { console.error("Failed to add member:", error); const errorMessage = isAxiosError(error) ? error.response?.data?.message || error.response?.data?.error || error.message : (error instanceof Error ? error.message : undefined) || t("workspace.teams.addMemberToTeam.error", "Failed to add user to team"); alert({ alertType: "error", title: errorMessage }); } finally { setProcessing(false); } }; const handleRemoveMember = async (user: User) => { if (!window.confirm(t("workspace.teams.confirmRemove", `Remove ${user.username} from this team?`))) { return; } try { setProcessing(true); // Find the Default team ID const defaultTeam = allTeams.find((t) => t.name === "Default"); if (!defaultTeam) { throw new Error("Default team not found"); } // Move user to Default team by updating their role with the Default team ID await teamService.moveUserToTeam(user.username, user.rolesAsString || "ROLE_USER", defaultTeam.id); alert({ alertType: "success", title: t("workspace.teams.removeMemberSuccess", "User removed from team") }); fetchTeamDetails(); } catch (error: unknown) { console.error("Failed to remove member:", error); const errorMessage = isAxiosError(error) ? error.response?.data?.message || error.response?.data?.error || error.message : (error instanceof Error ? error.message : undefined) || t("workspace.teams.removeMemberError", "Failed to remove user from team"); alert({ alertType: "error", title: errorMessage }); } finally { setProcessing(false); } }; const handleDeleteUser = async (user: User) => { const confirmMessage = t( "workspace.people.confirmDelete", "Are you sure you want to delete this user? This action cannot be undone.", ); if (!window.confirm(`${confirmMessage}\n\nUser: ${user.username}`)) { return; } try { setProcessing(true); await userManagementService.deleteUser(user.username); alert({ alertType: "success", title: t("workspace.people.deleteUserSuccess", "User deleted successfully") }); fetchTeamDetails(); } catch (error: unknown) { console.error("Failed to delete user:", error); const errorMessage = isAxiosError(error) ? error.response?.data?.message || error.response?.data?.error || error.message : (error instanceof Error ? error.message : undefined) || t("workspace.people.deleteUserError", "Failed to delete user"); alert({ alertType: "error", title: errorMessage }); } finally { setProcessing(false); } }; const handleUnlockUser = async (user: User) => { const confirmMessage = t("workspace.people.confirmUnlock", "Are you sure you want to unlock this user account?"); if (!window.confirm(`${confirmMessage}\n\nUser: ${user.username}`)) { return; } try { await userManagementService.unlockUser(user.username); alert({ alertType: "success", title: t("workspace.people.unlockUserSuccess", "User account unlocked successfully") }); fetchTeamDetails(); } catch (error: unknown) { console.error("[TeamDetailsSection] Failed to unlock user:", error); const errorMessage = isAxiosError(error) ? error.response?.data?.message || error.response?.data?.error || error.message : (error instanceof Error ? error.message : undefined) || t("workspace.people.unlockUserError", "Failed to unlock user account"); alert({ alertType: "error", title: errorMessage }); } }; const openChangeTeamModal = (user: User) => { setSelectedUser(user); setSelectedTeamId(user.team?.id?.toString() || ""); setChangeTeamModalOpened(true); }; const openChangePasswordModal = (user: User) => { setPasswordUser(user); setChangePasswordModalOpened(true); }; const closeChangePasswordModal = () => { setChangePasswordModalOpened(false); setPasswordUser(null); }; const handleChangeTeam = async () => { if (!selectedUser || !selectedTeamId) { alert({ alertType: "error", title: t("workspace.teams.changeTeam.selectTeamRequired", "Please select a team") }); return; } try { setProcessing(true); await teamService.moveUserToTeam( selectedUser.username, selectedUser.rolesAsString || "ROLE_USER", parseInt(selectedTeamId), ); alert({ alertType: "success", title: t("workspace.teams.changeTeam.success", "Team changed successfully") }); setChangeTeamModalOpened(false); setSelectedUser(null); setSelectedTeamId(""); fetchTeamDetails(); } catch (error: unknown) { console.error("Failed to change team:", error); const errorMessage = isAxiosError(error) ? error.response?.data?.message || error.response?.data?.error || error.message : (error instanceof Error ? error.message : undefined) || t("workspace.teams.changeTeam.error", "Failed to change team"); alert({ alertType: "error", title: errorMessage }); } finally { setProcessing(false); } }; if (loading) { return ( {t("workspace.teams.loadingDetails", "Loading team details...")} ); } if (!team) { return ( {t("workspace.teams.teamNotFound", "Team not found")} ); } return ( {/* Header with back button */}
{team.name} {t("workspace.teams.memberCount", { count: teamUsers.length })} {teamUsers.length === 1 ? "member" : "members"}
{/* Add Member Button */} 0} position="bottom" withArrow zIndex={Z_INDEX_OVER_CONFIG_MODAL} > {/* Members Table */} {t("workspace.people.user")} {t("workspace.people.role")} {teamUsers.length === 0 ? ( {t("workspace.teams.noMembers", "No members in this team")} ) : ( teamUsers.map((user) => { const isActive = userLastRequest[user.username] && Date.now() - userLastRequest[user.username] < 5 * 60 * 1000; // Active within last 5 minutes return ( {user.username.charAt(0).toUpperCase()} {user.username} {isLockedUser(user) && ( {t("workspace.people.lockedBadge", "Locked")} )} {user.email && ( {user.email} )} {(user.rolesAsString || "").includes("ROLE_ADMIN") ? t("workspace.people.admin") : t("workspace.people.member")} {/* Info icon with tooltip */} Authentication: {user.authenticationType || "Unknown"} Last Activity:{" "} {userLastRequest[user.username] ? new Date(userLastRequest[user.username]).toLocaleString() : "Never"} } multiline w={220} position="left" withArrow zIndex={Z_INDEX_OVER_CONFIG_MODAL + 10} > {/* Actions menu */} } onClick={() => openChangeTeamModal(user)} disabled={processing || team.name === "Internal"} > {t("workspace.teams.changeTeam.label", "Change Team")} } onClick={() => openChangePasswordModal(user)} disabled={processing} > {t("workspace.people.changePassword.action", "Change password")} {isLockedUser(user) && ( } onClick={() => handleUnlockUser(user)} disabled={processing} > {t("workspace.people.unlockAccount", "Unlock Account")} )} {team.name !== "Internal" && team.name !== "Default" && ( } onClick={() => handleRemoveMember(user)} disabled={processing} > {t("workspace.teams.removeMember", "Remove from team")} )} } onClick={() => handleDeleteUser(user)} disabled={processing || team.name === "Internal"} > {t("workspace.people.deleteUser", "Delete User")} ); }) )}
{/* Add Member Modal */} setAddMemberModalOpened(false)} size="md" zIndex={Z_INDEX_OVER_CONFIG_MODAL} centered padding="xl" withCloseButton={false} >
setAddMemberModalOpened(false)} size="lg" style={{ position: "absolute", top: -8, right: -8, zIndex: 1, }} /> {/* Header with Icon */} {t("workspace.teams.addMemberToTeam.title")} {t("workspace.teams.addMemberToTeam.addingTo")} {team.name} t.name !== "Internal") .map((team) => ({ value: team.id.toString(), label: team.name, }))} value={selectedTeamId} onChange={(value) => setSelectedTeamId(value || "")} searchable comboboxProps={{ withinPortal: true, zIndex: Z_INDEX_OVER_CONFIG_MODAL }} />
); }