mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-08-11 19:53:59 +02:00
Updating personal progress from popup
This commit is contained in:
@@ -1,37 +1,25 @@
|
|||||||
import { useState } from 'preact/hooks';
|
import { useState } from 'preact/hooks';
|
||||||
import type { GroupByRoadmap, TeamMember } from './TeamProgressPage';
|
import type { GroupByRoadmap, TeamMember } from './TeamProgressPage';
|
||||||
import { MemberProgressModal } from './MemberProgressModal';
|
|
||||||
import { getUrlParams } from '../../lib/browser';
|
import { getUrlParams } from '../../lib/browser';
|
||||||
import ExternalLinkIcon from '../../icons/external-link.svg';
|
import ExternalLinkIcon from '../../icons/external-link.svg';
|
||||||
import { useAuth } from '../../hooks/use-auth';
|
import { useAuth } from '../../hooks/use-auth';
|
||||||
|
|
||||||
type GroupRoadmapItemProps = {
|
type GroupRoadmapItemProps = {
|
||||||
roadmap: GroupByRoadmap;
|
roadmap: GroupByRoadmap;
|
||||||
|
onShowResourceProgress: (member: TeamMember, resourceId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
|
export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
|
||||||
|
const { onShowResourceProgress } = props;
|
||||||
const { members, resourceTitle, resourceId } = props.roadmap;
|
const { members, resourceTitle, resourceId } = props.roadmap;
|
||||||
|
|
||||||
const { t: teamId } = getUrlParams();
|
const { t: teamId } = getUrlParams();
|
||||||
const user = useAuth();
|
const user = useAuth();
|
||||||
|
|
||||||
const [showAll, setShowAll] = useState(false);
|
const [showAll, setShowAll] = useState(false);
|
||||||
const [detailResourceId, setDetailResourceId] = useState<string | null>(null);
|
|
||||||
const [selectedMember, setSelectedMember] = useState<TeamMember | null>(null);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{detailResourceId && (
|
|
||||||
<MemberProgressModal
|
|
||||||
member={selectedMember!}
|
|
||||||
teamId={teamId}
|
|
||||||
resourceId={detailResourceId}
|
|
||||||
resourceType={'roadmap'}
|
|
||||||
onClose={() => {
|
|
||||||
setDetailResourceId(null);
|
|
||||||
setSelectedMember(null);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<div className="flex h-full min-h-[270px] flex-col rounded-md border">
|
<div className="flex h-full min-h-[270px] flex-col rounded-md border">
|
||||||
<div className="flex items-center gap-3 border-b p-3">
|
<div className="flex items-center gap-3 border-b p-3">
|
||||||
<div className="flex min-w-0 flex-grow items-center justify-between">
|
<div className="flex min-w-0 flex-grow items-center justify-between">
|
||||||
@@ -59,11 +47,15 @@ export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`group relative w-full overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none ${isMyProgress ? 'border-green-500 hover:border-green-600' : ''}`}
|
className={`group relative w-full overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none ${
|
||||||
|
isMyProgress ? 'border-green-500 hover:border-green-600' : ''
|
||||||
|
}`}
|
||||||
key={member?.member._id}
|
key={member?.member._id}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDetailResourceId(member?.progress?.resourceId!);
|
onShowResourceProgress(
|
||||||
setSelectedMember(member.member);
|
member.member,
|
||||||
|
member.progress?.resourceId!
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="relative z-10 flex items-center justify-between gap-1 text-sm">
|
<span className="relative z-10 flex items-center justify-between gap-1 text-sm">
|
||||||
@@ -80,7 +72,9 @@ export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
|
|||||||
className="h-5 w-5 shrink-0 rounded-full"
|
className="h-5 w-5 shrink-0 rounded-full"
|
||||||
/>
|
/>
|
||||||
<span className="inline-grid grid-cols-[auto,32px] items-center">
|
<span className="inline-grid grid-cols-[auto,32px] items-center">
|
||||||
<span className="truncate mr-[5px]">{member?.member?.name}</span>
|
<span className="mr-[5px] truncate">
|
||||||
|
{member?.member?.name}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="shrink-0 text-xs text-gray-400">
|
<span className="shrink-0 text-xs text-gray-400">
|
||||||
@@ -88,7 +82,11 @@ export function GroupRoadmapItem(props: GroupRoadmapItemProps) {
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className={`absolute inset-0 ${isMyProgress ? 'bg-green-100 group-hover:bg-green-200' : 'bg-gray-100 group-hover:bg-gray-200'}`}
|
className={`absolute inset-0 ${
|
||||||
|
isMyProgress
|
||||||
|
? 'bg-green-100 group-hover:bg-green-200'
|
||||||
|
: 'bg-gray-100 group-hover:bg-gray-200'
|
||||||
|
}`}
|
||||||
style={{
|
style={{
|
||||||
width: `${
|
width: `${
|
||||||
(member?.progress?.done / member?.progress?.total) * 100
|
(member?.progress?.done / member?.progress?.total) * 100
|
||||||
|
@@ -1,36 +1,22 @@
|
|||||||
import type { TeamMember } from './TeamProgressPage';
|
import type { TeamMember } from './TeamProgressPage';
|
||||||
import { useState } from 'preact/hooks';
|
import { useState } from 'preact/hooks';
|
||||||
import { MemberProgressModal } from './MemberProgressModal';
|
|
||||||
|
|
||||||
type MemberProgressItemProps = {
|
type MemberProgressItemProps = {
|
||||||
teamId: string;
|
|
||||||
member: TeamMember;
|
member: TeamMember;
|
||||||
|
onShowResourceProgress: (resourceId: string) => void;
|
||||||
isMyProgress?: boolean;
|
isMyProgress?: boolean;
|
||||||
};
|
};
|
||||||
export function MemberProgressItem(props: MemberProgressItemProps) {
|
export function MemberProgressItem(props: MemberProgressItemProps) {
|
||||||
const { member, teamId, isMyProgress = false } = props;
|
const { member, onShowResourceProgress, isMyProgress = false } = props;
|
||||||
|
|
||||||
const memberProgress = member?.progress?.sort((a, b) => {
|
const memberProgress = member?.progress?.sort((a, b) => {
|
||||||
return b.done - a.done;
|
return b.done - a.done;
|
||||||
});
|
});
|
||||||
|
|
||||||
const [detailResourceId, setDetailResourceId] = useState<string | null>(null);
|
|
||||||
const [showAll, setShowAll] = useState(false);
|
const [showAll, setShowAll] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{detailResourceId && (
|
|
||||||
<MemberProgressModal
|
|
||||||
member={member}
|
|
||||||
teamId={teamId}
|
|
||||||
resourceId={detailResourceId}
|
|
||||||
resourceType={'roadmap'}
|
|
||||||
onClose={() => {
|
|
||||||
setDetailResourceId(null);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className={`flex h-full min-h-[270px] flex-col overflow-hidden rounded-md border`}
|
className={`flex h-full min-h-[270px] flex-col overflow-hidden rounded-md border`}
|
||||||
key={member._id}
|
key={member._id}
|
||||||
@@ -52,7 +38,7 @@ export function MemberProgressItem(props: MemberProgressItemProps) {
|
|||||||
{isMyProgress && (
|
{isMyProgress && (
|
||||||
<div className="inline-grid grid-cols-[auto,32px] items-center gap-1.5">
|
<div className="inline-grid grid-cols-[auto,32px] items-center gap-1.5">
|
||||||
<h3 className="truncate font-medium">{member.name}</h3>
|
<h3 className="truncate font-medium">{member.name}</h3>
|
||||||
<span className="rounded-md bg-red-500 py-0.5 px-1 text-xs text-white">
|
<span className="rounded-md bg-red-500 px-1 py-0.5 text-xs text-white">
|
||||||
You
|
You
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,7 +51,7 @@ export function MemberProgressItem(props: MemberProgressItemProps) {
|
|||||||
(progress) => {
|
(progress) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={() => setDetailResourceId(progress.resourceId)}
|
onClick={() => onShowResourceProgress(progress.resourceId)}
|
||||||
className="group relative overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none"
|
className="group relative overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-none"
|
||||||
key={progress.resourceId}
|
key={progress.resourceId}
|
||||||
>
|
>
|
||||||
|
@@ -7,9 +7,9 @@ import { useKeydown } from '../../hooks/use-keydown';
|
|||||||
import type { TeamMember } from './TeamProgressPage';
|
import type { TeamMember } from './TeamProgressPage';
|
||||||
import { httpGet } from '../../lib/http';
|
import { httpGet } from '../../lib/http';
|
||||||
import {
|
import {
|
||||||
|
renderTopicProgress,
|
||||||
ResourceProgressType,
|
ResourceProgressType,
|
||||||
ResourceType,
|
ResourceType,
|
||||||
renderTopicProgress,
|
|
||||||
updateResourceProgress,
|
updateResourceProgress,
|
||||||
} from '../../lib/resource-progress';
|
} from '../../lib/resource-progress';
|
||||||
import CloseIcon from '../../icons/close.svg';
|
import CloseIcon from '../../icons/close.svg';
|
||||||
@@ -17,8 +17,6 @@ import { useToast } from '../../hooks/use-toast';
|
|||||||
import { useAuth } from '../../hooks/use-auth';
|
import { useAuth } from '../../hooks/use-auth';
|
||||||
import { pageProgressMessage } from '../../stores/page';
|
import { pageProgressMessage } from '../../stores/page';
|
||||||
import { ProgressHint } from './ProgressHint';
|
import { ProgressHint } from './ProgressHint';
|
||||||
import QuestionIcon from '../../icons/question.svg';
|
|
||||||
import { InfoIcon } from '../ReactIcons/InfoIcon';
|
|
||||||
|
|
||||||
export type ProgressMapProps = {
|
export type ProgressMapProps = {
|
||||||
member: TeamMember;
|
member: TeamMember;
|
||||||
@@ -26,6 +24,7 @@ export type ProgressMapProps = {
|
|||||||
resourceId: string;
|
resourceId: string;
|
||||||
resourceType: 'roadmap' | 'best-practice';
|
resourceType: 'roadmap' | 'best-practice';
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
onShowMyProgress: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MemberProgressResponse = {
|
type MemberProgressResponse = {
|
||||||
@@ -36,7 +35,14 @@ type MemberProgressResponse = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function MemberProgressModal(props: ProgressMapProps) {
|
export function MemberProgressModal(props: ProgressMapProps) {
|
||||||
const { resourceId, member, resourceType, teamId, onClose } = props;
|
const {
|
||||||
|
resourceId,
|
||||||
|
member,
|
||||||
|
resourceType,
|
||||||
|
onShowMyProgress,
|
||||||
|
teamId,
|
||||||
|
onClose,
|
||||||
|
} = props;
|
||||||
const user = useAuth();
|
const user = useAuth();
|
||||||
const isCurrentUser = user?.email === member.email;
|
const isCurrentUser = user?.email === member.email;
|
||||||
|
|
||||||
@@ -112,6 +118,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setIsLoading(true);
|
||||||
Promise.all([
|
Promise.all([
|
||||||
renderResource(resourceJsonUrl),
|
renderResource(resourceJsonUrl),
|
||||||
getMemberProgress(teamId, member._id, resourceType, resourceId),
|
getMemberProgress(teamId, member._id, resourceType, resourceId),
|
||||||
@@ -136,7 +143,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
.finally(() => {
|
.finally(() => {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
}, []);
|
}, [member]);
|
||||||
|
|
||||||
function updateTopicStatus(topicId: string, newStatus: ResourceProgressType) {
|
function updateTopicStatus(topicId: string, newStatus: ResourceProgressType) {
|
||||||
if (!resourceId || !resourceType || !isCurrentUser) {
|
if (!resourceId || !resourceType || !isCurrentUser) {
|
||||||
@@ -176,18 +183,21 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
if (!targetGroup) {
|
if (!targetGroup) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';
|
const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';
|
||||||
if (!groupId) {
|
if (!groupId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetGroup.classList.contains('removed')) {
|
if (targetGroup.classList.contains('removed')) {
|
||||||
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const isCurrentStatusDone = targetGroup.classList.contains('done');
|
const isCurrentStatusDone = targetGroup.classList.contains('done');
|
||||||
const normalizedGroupId = groupId.replace(/^\d+-/, '');
|
const normalizedGroupId = groupId.replace(/^\d+-/, '');
|
||||||
|
|
||||||
updateTopicStatus(
|
updateTopicStatus(
|
||||||
normalizedGroupId,
|
normalizedGroupId,
|
||||||
!isCurrentStatusDone ? 'done' : 'pending'
|
!isCurrentStatusDone ? 'done' : 'pending'
|
||||||
@@ -235,7 +245,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isCurrentUser || !containerEl.current) {
|
if (!member || !containerEl.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +256,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
containerEl.current?.removeEventListener('contextmenu', handleRightClick);
|
containerEl.current?.removeEventListener('contextmenu', handleRightClick);
|
||||||
containerEl.current?.removeEventListener('click', handleClick);
|
containerEl.current?.removeEventListener('click', handleClick);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [member]);
|
||||||
|
|
||||||
const removedTopics = memberProgress?.removed || [];
|
const removedTopics = memberProgress?.removed || [];
|
||||||
const memberDone =
|
const memberDone =
|
||||||
@@ -282,19 +292,18 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
{isCurrentUser ? (
|
{isCurrentUser ? (
|
||||||
<div className="mb-5 mt-0 text-left md:mt-4 md:text-center">
|
<div className="mb-5 mt-0 text-left md:mt-4 md:text-center">
|
||||||
<h2 className={'mb-1 text-lg font-bold md:text-2xl'}>
|
<h2 className={'mb-1 text-lg font-bold md:text-2xl'}>
|
||||||
Your Progress
|
Update Your Progress
|
||||||
</h2>
|
</h2>
|
||||||
<p className={'text-gray-500'}>
|
<p className={'text-gray-500'}>
|
||||||
You can{' '}
|
Follow the{' '}
|
||||||
<button
|
<button
|
||||||
className="inline-flex items-center text-blue-600 underline"
|
className="inline-flex items-center text-blue-600 underline"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setShowProgressHint(true);
|
setShowProgressHint(true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
follow these instructions
|
instructions to update your progress
|
||||||
</button>{' '}
|
</button>{' '}
|
||||||
to update your progress below.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -308,28 +317,29 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
You are looking at {member.name}'s progress.{' '}
|
You are looking at {member.name}'s progress.{' '}
|
||||||
<a
|
<button
|
||||||
target={'_blank'}
|
|
||||||
href={`/${resourceId}?t=${teamId}`}
|
|
||||||
className="text-blue-600 underline"
|
className="text-blue-600 underline"
|
||||||
|
onClick={onShowMyProgress}
|
||||||
>
|
>
|
||||||
View your progress
|
View your progress
|
||||||
</a>
|
</button>
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
||||||
<p className={'block text-gray-500 md:hidden'}>
|
<p className={'block text-gray-500 md:hidden'}>
|
||||||
View your progress
|
<button
|
||||||
<a
|
|
||||||
target={'_blank'}
|
|
||||||
href={`/${resourceId}?t=${teamId}`}
|
|
||||||
className="text-blue-600 underline"
|
className="text-blue-600 underline"
|
||||||
|
onClick={onShowMyProgress}
|
||||||
>
|
>
|
||||||
on the roadmap page.
|
View your progress.
|
||||||
</a>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p class="-mx-4 mb-3 flex items-center justify-start border-b border-t px-4 py-2 text-sm sm:hidden">
|
<p
|
||||||
|
class={`-mx-4 mb-3 flex items-center justify-start border-b border-t px-4 py-2 text-sm sm:hidden ${
|
||||||
|
isLoading ? 'striped-loader' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<span class="mr-2.5 block rounded-sm bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900">
|
<span class="mr-2.5 block rounded-sm bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900">
|
||||||
<span>{progressPercentage}</span>% Done
|
<span>{progressPercentage}</span>% Done
|
||||||
</span>
|
</span>
|
||||||
@@ -338,7 +348,11 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
<span>{memberDone}</span> of <span>{memberTotal}</span> done
|
<span>{memberDone}</span> of <span>{memberTotal}</span> done
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="-mx-4 mb-3 hidden items-center justify-center border-b border-t py-2 text-sm sm:flex">
|
<p
|
||||||
|
class={`-mx-4 mb-3 hidden items-center justify-center border-b border-t py-2 text-sm sm:flex ${
|
||||||
|
isLoading ? 'striped-loader' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
<span class="mr-2.5 block rounded-sm bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900">
|
<span class="mr-2.5 block rounded-sm bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900">
|
||||||
<span>{progressPercentage}</span>% Done
|
<span>{progressPercentage}</span>% Done
|
||||||
</span>
|
</span>
|
||||||
@@ -385,7 +399,7 @@ export function MemberProgressModal(props: ProgressMapProps) {
|
|||||||
className="popup-close absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 sm:hidden"
|
className="popup-close absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 sm:hidden"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
>
|
>
|
||||||
<img src={CloseIcon} className="h-4 w-4" />
|
<img alt={'close'} src={CloseIcon} className="h-4 w-4" />
|
||||||
<span class="sr-only">Close modal</span>
|
<span class="sr-only">Close modal</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -15,11 +15,12 @@ export function ProgressHint(props: ProgressHintProps) {
|
|||||||
useKeydown('Escape', () => {
|
useKeydown('Escape', () => {
|
||||||
onClose();
|
onClose();
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed left-0 right-0 top-0 z-50 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50">
|
<div className="fixed left-0 right-0 top-0 z-50 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50">
|
||||||
<div className="relative flex h-full w-full items-center justify-center">
|
<div className="relative flex h-full w-full items-center justify-center">
|
||||||
<div
|
<div
|
||||||
className="relative w-full max-w-lg rounded-md border border-yellow-300 bg-yellow-50 px-3 py-3 text-gray-500"
|
className="relative w-full max-w-lg rounded-md bg-yellow-50 px-3 py-3 text-gray-500"
|
||||||
ref={containerEl}
|
ref={containerEl}
|
||||||
>
|
>
|
||||||
<span className="mb-1.5 block text-xs font-medium uppercase text-green-600">
|
<span className="mb-1.5 block text-xs font-medium uppercase text-green-600">
|
||||||
|
@@ -9,6 +9,7 @@ import { $currentTeam } from '../../stores/team';
|
|||||||
import { GroupRoadmapItem } from './GroupRoadmapItem';
|
import { GroupRoadmapItem } from './GroupRoadmapItem';
|
||||||
import { getUrlParams, setUrlParams } from '../../lib/browser';
|
import { getUrlParams, setUrlParams } from '../../lib/browser';
|
||||||
import { useAuth } from '../../hooks/use-auth';
|
import { useAuth } from '../../hooks/use-auth';
|
||||||
|
import { MemberProgressModal } from './MemberProgressModal';
|
||||||
|
|
||||||
export type UserProgress = {
|
export type UserProgress = {
|
||||||
resourceTitle: string;
|
resourceTitle: string;
|
||||||
@@ -56,6 +57,11 @@ export function TeamProgressPage() {
|
|||||||
const currentTeam = useStore($currentTeam);
|
const currentTeam = useStore($currentTeam);
|
||||||
const user = useAuth();
|
const user = useAuth();
|
||||||
|
|
||||||
|
const [showMemberProgress, setShowMemberProgress] = useState<{
|
||||||
|
resourceId: string;
|
||||||
|
member: TeamMember;
|
||||||
|
}>();
|
||||||
|
|
||||||
const [teamMembers, setTeamMembers] = useState<TeamMember[]>([]);
|
const [teamMembers, setTeamMembers] = useState<TeamMember[]>([]);
|
||||||
const [selectedGrouping, setSelectedGrouping] = useState<
|
const [selectedGrouping, setSelectedGrouping] = useState<
|
||||||
'roadmap' | 'member'
|
'roadmap' | 'member'
|
||||||
@@ -88,12 +94,10 @@ export function TeamProgressPage() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getTeamProgress().then(
|
getTeamProgress().then(() => {
|
||||||
() => {
|
pageProgressMessage.set('');
|
||||||
pageProgressMessage.set('');
|
setIsLoading(false);
|
||||||
setIsLoading(false);
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}, [teamId]);
|
}, [teamId]);
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
@@ -143,13 +147,34 @@ export function TeamProgressPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
{showMemberProgress && (
|
||||||
|
<MemberProgressModal
|
||||||
|
member={showMemberProgress.member}
|
||||||
|
teamId={teamId}
|
||||||
|
resourceId={showMemberProgress.resourceId}
|
||||||
|
resourceType={'roadmap'}
|
||||||
|
onClose={() => {
|
||||||
|
setShowMemberProgress(undefined);
|
||||||
|
}}
|
||||||
|
onShowMyProgress={() => {
|
||||||
|
setShowMemberProgress({
|
||||||
|
resourceId: showMemberProgress.resourceId,
|
||||||
|
member: teamMembers.find(
|
||||||
|
(member) => member.email === user?.email
|
||||||
|
)!,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{groupingTypes.map((grouping) => (
|
{groupingTypes.map((grouping) => (
|
||||||
<button
|
<button
|
||||||
className={`rounded-md border p-1 px-2 text-sm ${selectedGrouping === grouping.value
|
className={`rounded-md border p-1 px-2 text-sm ${
|
||||||
? ' border-gray-400 bg-gray-200 '
|
selectedGrouping === grouping.value
|
||||||
: ''
|
? ' border-gray-400 bg-gray-200 '
|
||||||
}`}
|
: ''
|
||||||
|
}`}
|
||||||
onClick={() => setSelectedGrouping(grouping.value)}
|
onClick={() => setSelectedGrouping(grouping.value)}
|
||||||
>
|
>
|
||||||
{grouping.label}
|
{grouping.label}
|
||||||
@@ -162,7 +187,16 @@ export function TeamProgressPage() {
|
|||||||
<div className="grid gap-4 sm:grid-cols-2">
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
{groupByRoadmap.map((roadmap) => {
|
{groupByRoadmap.map((roadmap) => {
|
||||||
return (
|
return (
|
||||||
<GroupRoadmapItem key={roadmap.resourceId} roadmap={roadmap} />
|
<GroupRoadmapItem
|
||||||
|
key={roadmap.resourceId}
|
||||||
|
roadmap={roadmap}
|
||||||
|
onShowResourceProgress={(member, resourceId) => {
|
||||||
|
setShowMemberProgress({
|
||||||
|
resourceId,
|
||||||
|
member,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
@@ -171,9 +205,14 @@ export function TeamProgressPage() {
|
|||||||
<div className="grid gap-4 sm:grid-cols-2">
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
{teamMembers.map((member) => (
|
{teamMembers.map((member) => (
|
||||||
<MemberProgressItem
|
<MemberProgressItem
|
||||||
teamId={teamId}
|
|
||||||
member={member}
|
member={member}
|
||||||
isMyProgress={member?.email === user?.email}
|
isMyProgress={member?.email === user?.email}
|
||||||
|
onShowResourceProgress={(resourceId) => {
|
||||||
|
setShowMemberProgress({
|
||||||
|
resourceId,
|
||||||
|
member,
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user