feat: Send progress reminder

chore/team-member
Arik Chakma 1 year ago
parent 8a16de9a70
commit 78941763e6
  1. 6
      src/components/TeamMembers/RoleBadge.tsx
  2. 84
      src/components/TeamMembers/TeamMemberItem.tsx
  3. 142
      src/components/TeamMembers/TeamMembersPage.tsx

@ -3,9 +3,9 @@ import type { AllowedRoles } from '../CreateTeam/RoleDropdown';
export function MemberRoleBadge({ role }: { role: AllowedRoles }) {
return (
<span
className={`rounded-full px-2 py-0.5 text-xs flex items-center capitalize ${['admin'].includes(role)
? 'bg-blue-100 text-blue-700 '
: 'bg-gray-100 text-gray-700 '
className={`rounded-full px-2 py-0.5 text-xs sm:flex items-center capitalize ${['admin'].includes(role)
? 'bg-blue-100 text-blue-700 '
: 'bg-gray-100 text-gray-700 '
} ${['manager'].includes(role) ? 'bg-green-100 text-green-700' : ''}`}
>
{role}

@ -1,7 +1,7 @@
import { MailIcon } from "../ReactIcons/MailIcon";
import { MemberActionDropdown } from "./MemberActionDropdown";
import { MemberRoleBadge } from "./RoleBadge";
import type { TeamMemberItem } from "./TeamMembersPage";
import { MailIcon } from '../ReactIcons/MailIcon';
import { MemberActionDropdown } from './MemberActionDropdown';
import { MemberRoleBadge } from './RoleBadge';
import type { TeamMemberItem } from './TeamMembersPage';
type TeamMemberProps = {
member: TeamMemberItem;
@ -11,42 +11,59 @@ type TeamMemberProps = {
canManageCurrentTeam: boolean;
handleDeleteMember: () => void;
onUpdateMember: () => void;
handleSendReminder: () => void;
};
export function TeamMemberItem(props: TeamMemberProps) {
const { member, index, teamId, onUpdateMember, canManageCurrentTeam, userId, handleDeleteMember } = props;
const showNoProgress = member.progress.length === 0 && member.status === 'joined';
const {
member,
index,
teamId,
onUpdateMember,
canManageCurrentTeam,
userId,
handleDeleteMember,
handleSendReminder,
} = props;
const showNoProgress =
member.progress.length === 0 && member.status === 'joined';
const showReminder =
member.progress.length === 0 &&
member.status === 'joined' &&
!(member.userId === userId);
return (
<div
className={`flex items-center justify-between gap-2 p-3 ${index === 0 ? '' : 'border-t'
}`}
className={`flex items-center justify-between gap-2 p-3 ${
index === 0 ? '' : 'border-t'
}`}
>
<div className="flex items-center gap-3">
<img
src={
member.avatar
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${member.avatar
}`
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${member.avatar}`
: '/images/default-avatar.png'
}
alt={member.name || ''}
className="hidden h-10 w-10 rounded-full sm:block"
/>
<div>
<span class={'mb-1 block sm:hidden'}>
<div className="mb-1 flex items-center gap-2 sm:hidden">
<MemberRoleBadge role={member.role} />
</span>
{showReminder && (
<SendProgressReminder handleSendReminder={handleSendReminder} />
)}
</div>
<div className="flex items-center">
<h3 className="inline-grid grid-cols-[auto_auto_auto] items-center font-medium">
<span className="truncate">{member.name}</span>
{
showNoProgress && (
<span className="ml-2 text-xs font-normal bg-gray-600 text-white rounded-full sm:inline px-2 py-0.5">
No Progress
</span>
)
}
{showNoProgress && (
<span className="ml-2 rounded-full bg-gray-600 px-2 py-0.5 text-xs font-normal text-white sm:inline">
No Progress
</span>
)}
{member.userId === userId && (
<span className="ml-2 hidden text-xs font-normal text-blue-500 sm:inline">
You
@ -66,14 +83,18 @@ export function TeamMemberItem(props: TeamMemberProps) {
)}
</div>
</div>
<p className="text-sm text-gray-500">
<p className="truncate text-sm text-gray-500">
{member.invitedEmail}
</p>
</div>
</div>
<div className="flex items-center text-sm">
{/* <SendProgressReminder /> */}
<div className="flex shrink-0 items-center text-sm">
{showReminder && (
<span className="hidden sm:block">
<SendProgressReminder handleSendReminder={handleSendReminder} />
</span>
)}
<span class={'hidden sm:block'}>
<MemberRoleBadge role={member.role} />
</span>
@ -87,14 +108,23 @@ export function TeamMemberItem(props: TeamMemberProps) {
)}
</div>
</div>
)
);
}
function SendProgressReminder() {
type SendProgressReminderProps = {
handleSendReminder: () => void;
};
function SendProgressReminder(props: SendProgressReminderProps) {
const { handleSendReminder } = props;
return (
<button className="rounded-full whitespace-nowrap px-2 py-0.5 text-xs bg-orange-100 text-orange-700 flex items-center gap-1.5 mr-2">
<button
onClick={handleSendReminder}
className="mr-2 flex items-center gap-1.5 whitespace-nowrap rounded-full bg-orange-100 px-2 py-0.5 text-xs text-orange-700"
>
<MailIcon className="h-3 w-3" />
Send Reminder
<span>Reminder</span>
</button>
)
);
}

@ -1,5 +1,5 @@
import { useEffect, useState } from 'preact/hooks';
import { httpDelete, httpGet } from '../../lib/http';
import { httpDelete, httpGet, httpPatch } from '../../lib/http';
import { MemberActionDropdown } from './MemberActionDropdown';
import { useAuth } from '../../hooks/use-auth';
import { pageProgressMessage } from '../../stores/page';
@ -94,11 +94,11 @@ export function TeamMembersPage() {
pageProgressMessage.set('');
});
}, [teamId]);
async function deleteMember(teamId: string, memberId: string) {
pageProgressMessage.set('Deleting member');
const { response, error } = await httpDelete(
`${import.meta.env.PUBLIC_API_URL
`${
import.meta.env.PUBLIC_API_URL
}/v1-delete-member/${teamId}/${memberId}`,
{}
);
@ -112,6 +112,23 @@ export function TeamMembersPage() {
await getTeamMemberList();
}
async function handleSendReminder(teamId: string, memberId: string) {
pageProgressMessage.set('Sending Reminder');
const { response, error } = await httpPatch(
`${
import.meta.env.PUBLIC_API_URL
}/v1-send-progress-reminder/${teamId}/${memberId}`,
{}
);
if (error || !response) {
toast.error(error?.message || 'Something went wrong');
return;
}
toast.success('Reminder has been sent');
}
const joinedMembers = teamMembers.filter(
(member) => member.status === 'joined'
);
@ -180,66 +197,81 @@ export function TeamMembersPage() {
onUpdateMember={() => {
setMemberToUpdate(member);
}}
handleSendReminder={() => {
handleSendReminder(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
/>
);
})}
</div>
{invitedMembers.length > 0 && (<div className="mt-6">
<h3 className="font-medium text-xl">Invited Members</h3>
<div className="rounded-b-sm rounded-t-md border mt-2">
{invitedMembers.map((member, index) => {
return (
<TeamMemberItem
key={index}
member={member}
index={index}
teamId={teamId}
userId={user?.id!}
canManageCurrentTeam={canManageCurrentTeam}
handleDeleteMember={() => {
deleteMember(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
onUpdateMember={() => {
setMemberToUpdate(member);
}}
/>
);
})}
{invitedMembers.length > 0 && (
<div className="mt-6">
<h3 className="text-xl font-medium">Invited Members</h3>
<div className="mt-2 rounded-b-sm rounded-t-md border">
{invitedMembers.map((member, index) => {
return (
<TeamMemberItem
key={index}
member={member}
index={index}
teamId={teamId}
userId={user?.id!}
canManageCurrentTeam={canManageCurrentTeam}
handleDeleteMember={() => {
deleteMember(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
onUpdateMember={() => {
setMemberToUpdate(member);
}}
handleSendReminder={() => {
handleSendReminder(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
/>
);
})}
</div>
</div>
</div>)}
)}
{
rejectedMembers.length > 0 && (
<div className="mt-6">
<h3 className="font-medium text-xl">Rejected Members</h3>
<div className="rounded-b-sm rounded-t-md border mt-2">
{rejectedMembers.map((member, index) => {
return (
<TeamMemberItem
key={index}
member={member}
index={index}
teamId={teamId}
userId={user?.id!}
canManageCurrentTeam={canManageCurrentTeam}
handleDeleteMember={() => {
deleteMember(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
onUpdateMember={() => {
setMemberToUpdate(member);
}}
/>
);
})}
</div>
{rejectedMembers.length > 0 && (
<div className="mt-6">
<h3 className="text-xl font-medium">Rejected Members</h3>
<div className="mt-2 rounded-b-sm rounded-t-md border">
{rejectedMembers.map((member, index) => {
return (
<TeamMemberItem
key={index}
member={member}
index={index}
teamId={teamId}
userId={user?.id!}
canManageCurrentTeam={canManageCurrentTeam}
handleDeleteMember={() => {
deleteMember(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
onUpdateMember={() => {
setMemberToUpdate(member);
}}
handleSendReminder={() => {
handleSendReminder(teamId, member._id!).finally(() => {
pageProgressMessage.set('');
});
}}
/>
);
})}
</div>
)
}
</div>
)}
</div>
{canManageCurrentTeam && (

Loading…
Cancel
Save