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.
115 lines
3.5 KiB
115 lines
3.5 KiB
1 year ago
|
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;
|
||
|
};
|
||
|
|
||
|
export function TransferToTeamList(props: TransferToTeamListProps) {
|
||
|
const { teams, setTeams, selectedTeamId, setSelectedTeamId } = 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',
|
||
|
isSelected && 'border-gray-500 bg-gray-100 text-black'
|
||
|
)}
|
||
|
onClick={() => {
|
||
|
setSelectedTeamId(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>
|
||
|
)}
|
||
|
</>
|
||
|
);
|
||
|
}
|