Add team activity dashboard

feat/team-dashboard
Kamran Ahmed 5 months ago
parent 0e787b49c6
commit d3b20b1277
  1. 7
      src/components/Dashboard/DashboardTeamRoadmaps.tsx
  2. 12
      src/components/Dashboard/TeamDashboard.tsx
  3. 2
      src/components/TeamActivity/TeamActivityItem.tsx
  4. 53
      src/components/TeamActivity/TeamActivityPage.tsx

@ -13,6 +13,7 @@ import { useToast } from '../../hooks/use-toast';
import type { TeamResourceConfig } from '../CreateTeam/RoadmapSelector'; import type { TeamResourceConfig } from '../CreateTeam/RoadmapSelector';
import { pageProgressMessage } from '../../stores/page'; import { pageProgressMessage } from '../../stores/page';
import type { BuiltInRoadmap } from './PersonalDashboard'; import type { BuiltInRoadmap } from './PersonalDashboard';
import { MapIcon, Users2 } from 'lucide-react';
type DashboardTeamRoadmapsProps = { type DashboardTeamRoadmapsProps = {
isLoading: boolean; isLoading: boolean;
@ -205,12 +206,14 @@ export function DashboardTeamRoadmaps(props: DashboardTeamRoadmapsProps) {
const roadmapHeading = ( const roadmapHeading = (
<div className="mb-3 flex h-[20px] items-center justify-between gap-2 text-xs"> <div className="mb-3 flex h-[20px] items-center justify-between gap-2 text-xs">
<h2 className="uppercase text-gray-400">Roadmaps</h2> <h2 className="uppercase text-gray-400">Roadmaps</h2>
<span className="mx-3 h-[1px] flex-grow bg-gray-200" />
{canManageCurrentTeam && ( {canManageCurrentTeam && (
<a <a
href={`/team/roadmaps?t=${teamId}`} href={`/team/roadmaps?t=${teamId}`}
className="rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black" className="flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black"
> >
Manage Roadmaps <MapIcon className="mr-1.5 size-3" strokeWidth={2.5} />
Roadmaps
</a> </a>
)} )}
</div> </div>

@ -9,6 +9,7 @@ import { Tooltip } from '../Tooltip';
import { DashboardTeamRoadmaps } from './DashboardTeamRoadmaps'; import { DashboardTeamRoadmaps } from './DashboardTeamRoadmaps';
import type { BuiltInRoadmap } from './PersonalDashboard'; import type { BuiltInRoadmap } from './PersonalDashboard';
import { InviteMemberPopup } from '../TeamMembers/InviteMemberPopup'; import { InviteMemberPopup } from '../TeamMembers/InviteMemberPopup';
import { Users, Users2 } from 'lucide-react';
type TeamDashboardProps = { type TeamDashboardProps = {
builtInRoleRoadmaps: BuiltInRoadmap[]; builtInRoleRoadmaps: BuiltInRoadmap[];
@ -110,12 +111,14 @@ export function TeamDashboard(props: TeamDashboardProps) {
<h2 className="mb-3 mt-6 flex h-[20px] items-center justify-between text-xs uppercase text-gray-400"> <h2 className="mb-3 mt-6 flex h-[20px] items-center justify-between text-xs uppercase text-gray-400">
Team Members Team Members
<span className="flex-grow h-[1px] bg-gray-200 mx-3" />
{canManageCurrentTeam && ( {canManageCurrentTeam && (
<a <a
href={`/team/members?t=${teamId}`} href={`/team/members?t=${teamId}`}
className="rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black" className="flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black"
> >
Manage Members <Users2 className="mr-1.5 size-3" strokeWidth={2.5} />
Members
</a> </a>
)} )}
</h2> </h2>
@ -162,7 +165,10 @@ export function TeamDashboard(props: TeamDashboardProps) {
</div> </div>
)} )}
<TeamActivityPage teamId={teamId} /> <TeamActivityPage
teamId={teamId}
canManageCurrentTeam={canManageCurrentTeam}
/>
</section> </section>
); );
} }

@ -158,7 +158,7 @@ export function TeamActivityItem(props: TeamActivityItemProps) {
const activityLimit = showAll ? activities.length : 5; const activityLimit = showAll ? activities.length : 5;
return ( return (
<li key={user._id} className="overflow-hidden rounded-md border"> <li key={user._id} className="overflow-hidden bg-white rounded-md border">
<h3 className="flex flex-wrap items-center gap-1 bg-gray-100 px-2 py-2.5 text-sm"> <h3 className="flex flex-wrap items-center gap-1 bg-gray-100 px-2 py-2.5 text-sm">
{username} has {activities.length} updates in {uniqueResourcesCount} {username} has {activities.length} updates in {uniqueResourcesCount}
&nbsp;resource(s) &nbsp;resource(s)

@ -9,6 +9,12 @@ import { TeamActivityItem } from './TeamActivityItem';
import { TeamActivityTopicsModal } from './TeamActivityTopicsModal'; import { TeamActivityTopicsModal } from './TeamActivityTopicsModal';
import { TeamEmptyStream } from './TeamEmptyStream'; import { TeamEmptyStream } from './TeamEmptyStream';
import { Pagination } from '../Pagination/Pagination'; import { Pagination } from '../Pagination/Pagination';
import {
ChartNoAxesGantt,
CircleDashed,
Flag,
LoaderCircle,
} from 'lucide-react';
export type TeamStreamActivity = { export type TeamStreamActivity = {
_id?: string; _id?: string;
@ -51,10 +57,11 @@ type GetTeamActivityResponse = {
type TeamActivityPageProps = { type TeamActivityPageProps = {
teamId?: string; teamId?: string;
canManageCurrentTeam?: boolean;
}; };
export function TeamActivityPage(props: TeamActivityPageProps) { export function TeamActivityPage(props: TeamActivityPageProps) {
const { teamId: defaultTeamId } = props; const { teamId: defaultTeamId, canManageCurrentTeam = false } = props;
const { t: teamId = defaultTeamId } = getUrlParams(); const { t: teamId = defaultTeamId } = getUrlParams();
const toast = useToast(); const toast = useToast();
@ -182,6 +189,38 @@ export function TeamActivityPage(props: TeamActivityPageProps) {
return enrichedUsers; return enrichedUsers;
}, [users, activities]); }, [users, activities]);
const sectionHeading = (
<h3 className="mb-3 flex h-[20px] w-full items-center justify-between text-xs uppercase text-gray-400">
Team Activity
<span className="mx-3 h-[1px] flex-grow bg-gray-200" />
{canManageCurrentTeam && (
<a
href={`/team/progress?t=${teamId}`}
className="flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black"
>
<ChartNoAxesGantt className="mr-1.5 size-3" strokeWidth={2.5} />
Progresses
</a>
)}
</h3>
);
if (isLoading) {
return (
<>
{sectionHeading}
<div className="flex flex-col gap-2">
{Array.from({ length: 4 }).map((_, index) => (
<div
key={index}
className="h-[70px] w-full animate-pulse rounded-lg border bg-gray-100"
/>
))}
</div>
</>
);
}
if (!teamId) { if (!teamId) {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.location.href = '/'; window.location.href = '/';
@ -190,10 +229,6 @@ export function TeamActivityPage(props: TeamActivityPageProps) {
} }
} }
if (isLoading) {
return null;
}
return ( return (
<> <>
{selectedActivity && ( {selectedActivity && (
@ -205,9 +240,7 @@ export function TeamActivityPage(props: TeamActivityPageProps) {
{usersWithActivities.length > 0 ? ( {usersWithActivities.length > 0 ? (
<> <>
<h3 className="mb-4 flex w-full items-center justify-between text-xs uppercase text-gray-400"> {sectionHeading}
Team Activity
</h3>
<ul className="mb-4 mt-2 flex flex-col gap-3"> <ul className="mb-4 mt-2 flex flex-col gap-3">
{usersWithActivities.map((user, index) => { {usersWithActivities.map((user, index) => {
return ( return (
@ -237,9 +270,7 @@ export function TeamActivityPage(props: TeamActivityPageProps) {
</> </>
) : ( ) : (
<> <>
<h3 className="mb-4 flex w-full items-center justify-between text-xs uppercase text-gray-400"> {sectionHeading}
Team Activity
</h3>
<div className="rounded-lg border bg-white p-4"> <div className="rounded-lg border bg-white p-4">
<TeamEmptyStream teamId={teamId} /> <TeamEmptyStream teamId={teamId} />
</div> </div>

Loading…
Cancel
Save