Enhance project member invitation feature with new localization and UI updates

- Added new localization strings for "invite member" and "also invite to project" across multiple languages (Albanian, German, English, Spanish, Portuguese, Chinese).
- Updated the project member invite drawer to conditionally display UI elements based on the context of the invitation (from assigner or not).
- Introduced a new state management feature to track if the invitation is initiated from the assignee selector, improving user experience.
This commit is contained in:
shancds
2025-07-22 16:21:18 +05:30
parent 3373dccc58
commit da791e2cb7
9 changed files with 41 additions and 14 deletions

View File

@@ -11,7 +11,7 @@ import { useAuthService } from '@/hooks/useAuth';
import { Avatar, Button, Checkbox } from '@/components';
import { sortTeamMembers } from '@/utils/sort-team-members';
import { useAppDispatch } from '@/hooks/useAppDispatch';
import { toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
import { setIsFromAssigner, toggleProjectMemberDrawer } from '@/features/projects/singleProject/members/projectMembersSlice';
import { updateEnhancedKanbanTaskAssignees } from '@/features/enhanced-kanban/enhanced-kanban.slice';
interface AssigneeSelectorProps {
@@ -206,6 +206,7 @@ const AssigneeSelector: React.FC<AssigneeSelectorProps> = ({
const handleInviteProjectMemberDrawer = () => {
setIsOpen(false); // Close the assignee dropdown first
dispatch(setIsFromAssigner(true));
dispatch(toggleProjectMemberDrawer()); // Then open the invite drawer
};

View File

@@ -22,7 +22,7 @@ import { teamMembersApiService } from '@/api/team-members/teamMembers.api.servic
const ProjectMemberDrawer = () => {
const { t } = useTranslation('project-view/project-member-drawer');
const { isDrawerOpen, currentMembersList, isLoading } = useAppSelector(
const { isDrawerOpen, currentMembersList, isLoading, isFromAssigner } = useAppSelector(
state => state.projectMemberReducer
);
const { projectId } = useAppSelector(state => state.projectReducer);
@@ -176,8 +176,9 @@ const ProjectMemberDrawer = () => {
);
const renderNotFoundContent = () => (
<Flex>
<Flex style={{ display: 'block'}}>
<Button
className='mb-2'
block
type="primary"
onClick={sendInviteToProject}
@@ -189,19 +190,23 @@ const ProjectMemberDrawer = () => {
{validateEmail(searchTerm) ? t('inviteAsAMember') : t('inviteNewMemberByEmail')}
</span>
</Button>
{isFromAssigner && <Flex>
<input className='mr-2' type="checkbox" checked={true} name={t('alsoInviteToProject')} id="AlsoInviteToProject" />
<label htmlFor={t('alsoInviteToProject')}>{t('alsoInviteToProject')}</label>
</Flex>}
</Flex>
);
return (
<Modal
title={
<Typography.Text style={{ fontWeight: 500, fontSize: 16 }}>{t('title')}</Typography.Text>
<Typography.Text style={{ fontWeight: 500, fontSize: 16 }}>{isFromAssigner ? t('inviteMember') : t('title')}</Typography.Text>
}
open={isDrawerOpen}
onCancel={() => dispatch(toggleProjectMemberDrawer())}
afterOpenChange={handleOpenChange}
footer={
<Button
!isFromAssigner && <Button
style={{ width: 140, fontSize: 12 }}
block
icon={<LinkOutlined />}
@@ -232,7 +237,7 @@ const ProjectMemberDrawer = () => {
/>
</Form.Item>
</Form>
<div style={{ fontSize: 14, fontWeight: 500, marginBottom: 8 }}>{t('members')}</div>
{!isFromAssigner && <><div style={{ fontSize: 14, fontWeight: 500, marginBottom: 8 }}>{t('members')}</div>
<div style={{ maxHeight: 360, minHeight: 120, overflowY: 'auto', marginBottom: 16 }}>
<List
loading={isLoading}
@@ -248,7 +253,8 @@ const ProjectMemberDrawer = () => {
</List.Item>
)}
/>
</div>
</div></>
}
</Modal>
);
};

View File

@@ -8,6 +8,7 @@ interface ProjectMembersState {
currentMembersList: IMentionMemberViewModel[];
isDrawerOpen: boolean;
isLoading: boolean;
isFromAssigner: boolean;
error: string | null;
}
@@ -16,6 +17,7 @@ const initialState: ProjectMembersState = {
currentMembersList: [],
isDrawerOpen: false,
isLoading: false,
isFromAssigner: false,
error: null,
};
@@ -89,6 +91,12 @@ const projectMembersSlice = createSlice({
reducers: {
toggleProjectMemberDrawer: state => {
state.isDrawerOpen = !state.isDrawerOpen;
if (state.isDrawerOpen === false) {
state.isFromAssigner = false;
}
},
setIsFromAssigner: (state, action: PayloadAction<boolean>) => {
state.isFromAssigner = action.payload;
},
},
extraReducers: builder => {
@@ -139,7 +147,7 @@ const projectMembersSlice = createSlice({
},
});
export const { toggleProjectMemberDrawer } = projectMembersSlice.actions;
export const { toggleProjectMemberDrawer, setIsFromAssigner } = projectMembersSlice.actions;
export {
getProjectMembers,
getAllProjectMembers,