computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.0 KiB
132 lines
4.0 KiB
import { useEffect, useState } from 'react'; |
|
import { useToast } from '../../hooks/use-toast'; |
|
import { Users2 } from 'lucide-react'; |
|
import { httpGet } from '../../lib/http'; |
|
import { cn } from '../../lib/classname'; |
|
import type { UserTeamItem } from '../TeamDropdown/TeamDropdown'; |
|
|
|
type TransferToTeamListProps = { |
|
teams: UserTeamItem[]; |
|
setTeams: (teams: UserTeamItem[]) => void; |
|
|
|
selectedTeamId: string | null; |
|
setSelectedTeamId: (teamId: string | null) => void; |
|
|
|
isTeamMembersLoading: boolean; |
|
setIsTeamMembersLoading: (isLoading: boolean) => void; |
|
onTeamChange: (teamId: string | null) => void; |
|
}; |
|
|
|
export function TransferToTeamList(props: TransferToTeamListProps) { |
|
const { |
|
teams, |
|
setTeams, |
|
selectedTeamId, |
|
setSelectedTeamId, |
|
isTeamMembersLoading, |
|
setIsTeamMembersLoading, |
|
onTeamChange, |
|
} = props; |
|
|
|
const toast = useToast(); |
|
|
|
const [isLoading, setIsLoading] = useState(true); |
|
|
|
async function getAllTeams() { |
|
if (teams.length > 0) { |
|
return; |
|
} |
|
|
|
const { response, error } = await httpGet<UserTeamItem[]>( |
|
`${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams` |
|
); |
|
if (error || !response) { |
|
toast.error(error?.message || 'Something went wrong'); |
|
return; |
|
} |
|
|
|
setTeams( |
|
response.filter((team) => ['admin', 'manager'].includes(team.role)) |
|
); |
|
} |
|
|
|
useEffect(() => { |
|
getAllTeams().finally(() => setIsLoading(false)); |
|
}, []); |
|
|
|
const loadingTeams = isLoading && ( |
|
<ul className="mt-2 grid grid-cols-3 gap-1.5"> |
|
{[...Array(3)].map((_, index) => ( |
|
<li key={index}> |
|
<div className="relative flex w-full items-center gap-2 rounded-md border p-2"> |
|
<div className="h-6 w-6 shrink-0 animate-pulse rounded-full bg-gray-200" /> |
|
<div className="inline-grid w-full"> |
|
<div className="h-4 animate-pulse rounded bg-gray-200" /> |
|
</div> |
|
</div> |
|
</li> |
|
))} |
|
</ul> |
|
); |
|
|
|
return ( |
|
<> |
|
{(teams.length > 0 || isLoading) && ( |
|
<p className="text-sm">Select a team to transfer this roadmap to</p> |
|
)} |
|
|
|
{loadingTeams} |
|
{teams.length > 0 && !isLoading && ( |
|
<ul className="mt-2 grid grid-cols-3 gap-1.5"> |
|
{teams.map((team) => { |
|
const isSelected = team._id === selectedTeamId; |
|
|
|
return ( |
|
<li key={team._id}> |
|
<button |
|
className={cn( |
|
'relative flex w-full items-center gap-2.5 rounded-lg border p-2.5 disabled:cursor-not-allowed disabled:opacity-70', |
|
isSelected && 'border-gray-500 bg-gray-100 text-black' |
|
)} |
|
disabled={isTeamMembersLoading} |
|
onClick={() => { |
|
if (isSelected) { |
|
setSelectedTeamId(null); |
|
} else { |
|
setSelectedTeamId(team._id); |
|
} |
|
onTeamChange(team._id); |
|
}} |
|
> |
|
<img |
|
src={ |
|
team.avatar |
|
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${ |
|
team.avatar |
|
}` |
|
: '/images/default-avatar.png' |
|
} |
|
alt={team.name || ''} |
|
className="h-6 w-6 shrink-0 rounded-full" |
|
/> |
|
<div className="inline-grid w-full"> |
|
<h3 className="truncate text-left font-normal"> |
|
{team.name} |
|
</h3> |
|
</div> |
|
</button> |
|
</li> |
|
); |
|
})} |
|
</ul> |
|
)} |
|
|
|
{teams.length === 0 && !isLoading && ( |
|
<div className="flex grow flex-col items-center justify-center gap-2"> |
|
<Users2 className="h-12 w-12 text-gray-500" /> |
|
<p className="text-gray-500">You are not a member of any team.</p> |
|
</div> |
|
)} |
|
</> |
|
); |
|
}
|
|
|