profile picture
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
import { type FC } from "react";
|
||||||
|
import AvatarImage from "../../../assets/images/avatar_image.png";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
src?: string | null;
|
||||||
|
alt?: string;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserAvatar: FC<Props> = ({ src, alt = "", className = "size-6" }) => (
|
||||||
|
<div className={`${className} rounded-full overflow-hidden shrink-0 bg-[#D0D0D0]`}>
|
||||||
|
<img src={src || AvatarImage} alt={alt} className="size-full object-cover" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default UserAvatar;
|
||||||
@@ -2,7 +2,7 @@ import { Add } from "iconsax-react";
|
|||||||
import { type FC } from "react";
|
import { type FC } from "react";
|
||||||
import type DateObject from "react-date-object";
|
import type DateObject from "react-date-object";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import AvatarImage from "../../../../assets/images/avatar_image.png";
|
import UserAvatar from "../UserAvatar";
|
||||||
import { formatDateRange } from "./date/utils";
|
import { formatDateRange } from "./date/utils";
|
||||||
import type { TaskLabel } from "./labels/types";
|
import type { TaskLabel } from "./labels/types";
|
||||||
import type { TaskUser } from "./users/types";
|
import type { TaskUser } from "./users/types";
|
||||||
@@ -52,16 +52,7 @@ const TaskDetailMetadataPreview: FC<Props> = ({ selectedLabels, selectedUsers, s
|
|||||||
<div className="text-xs font-medium mb-2">{t("taskmanager.users")}</div>
|
<div className="text-xs font-medium mb-2">{t("taskmanager.users")}</div>
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
{selectedUsers.map((user) => (
|
{selectedUsers.map((user) => (
|
||||||
<div
|
<UserAvatar key={user.id} src={user.avatar} alt={user.name} className="size-8" />
|
||||||
key={user.id}
|
|
||||||
className="size-8 rounded-full bg-[#D0D0D0] overflow-hidden shrink-0"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={user.avatar ?? AvatarImage}
|
|
||||||
alt={user.name}
|
|
||||||
className="size-full object-cover"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -91,19 +91,28 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
|
|||||||
page.data?.users?.map((user: UserItemType) => ({
|
page.data?.users?.map((user: UserItemType) => ({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||||
|
avatar: user.profilePic,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
) ?? [];
|
) ?? [];
|
||||||
const taskUsers: TaskUser[] =
|
const taskUsers: TaskUser[] =
|
||||||
taskDetail?.users?.map((user) => ({
|
taskDetail?.users?.map((user) => ({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||||
|
avatar: user.profilePic,
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
const userMap = new Map<string, TaskUser>(apiUsers.map((user) => [user.id, user]));
|
const userMap = new Map<string, TaskUser>(apiUsers.map((user) => [user.id, user]));
|
||||||
|
|
||||||
taskUsers.forEach((user) => {
|
taskUsers.forEach((user) => {
|
||||||
if (!userMap.has(user.id)) {
|
const existing = userMap.get(user.id);
|
||||||
userMap.set(user.id, user);
|
|
||||||
|
if (existing) {
|
||||||
|
if (!existing.avatar && user.avatar) {
|
||||||
|
userMap.set(user.id, { ...existing, avatar: user.avatar });
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userMap.set(user.id, user);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Array.from(userMap.values());
|
return Array.from(userMap.values());
|
||||||
@@ -115,6 +124,7 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
|
|||||||
page.data?.users?.map((user: UserItemType) => ({
|
page.data?.users?.map((user: UserItemType) => ({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||||
|
avatar: user.profilePic,
|
||||||
})) ?? [],
|
})) ?? [],
|
||||||
) ?? []
|
) ?? []
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { type FC } from "react";
|
import { type FC } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import Input from "../../../../../components/Input";
|
import Input from "../../../../../components/Input";
|
||||||
|
import UserAvatar from "../../UserAvatar";
|
||||||
import TaskDetailLabelCheckbox from "../labels/TaskDetailLabelCheckbox";
|
import TaskDetailLabelCheckbox from "../labels/TaskDetailLabelCheckbox";
|
||||||
import type { TaskUser } from "./types";
|
import type { TaskUser } from "./types";
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ const TaskDetailUsersList: FC<Props> = ({
|
|||||||
onToggle={() => onToggle(user.id)}
|
onToggle={() => onToggle(user.id)}
|
||||||
ariaLabel={user.name}
|
ariaLabel={user.name}
|
||||||
/>
|
/>
|
||||||
<div className="size-6 rounded-full bg-gray-400 shrink-0"></div>
|
<UserAvatar src={user.avatar} alt={user.name} />
|
||||||
<div className="text-[10px]">{user.name}</div>
|
<div className="text-[10px]">{user.name}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ const UpdateProject: FC = () => {
|
|||||||
project.users.map((user) => ({
|
project.users.map((user) => ({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: `${user.firstName} ${user.lastName}`,
|
name: `${user.firstName} ${user.lastName}`,
|
||||||
|
profilePic: user.profilePic,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
} else if (project.userIds?.length) {
|
} else if (project.userIds?.length) {
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ import { UserItemType } from "../../../users/types/UserTypes";
|
|||||||
import { useGetWorkspaces } from "../../workspace/hooks/useWorkspaceData";
|
import { useGetWorkspaces } from "../../workspace/hooks/useWorkspaceData";
|
||||||
import { WorkspaceItemType } from "../../workspace/types/WorkspaceTypes";
|
import { WorkspaceItemType } from "../../workspace/types/WorkspaceTypes";
|
||||||
import WorkspaceColorPicker from "../../workspace/components/WorkspaceColorPicker";
|
import WorkspaceColorPicker from "../../workspace/components/WorkspaceColorPicker";
|
||||||
|
import UserAvatar from "../../components/UserAvatar";
|
||||||
|
|
||||||
export type SelectedUser = {
|
export type SelectedUser = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BACKGROUND_PRESETS = [
|
export const BACKGROUND_PRESETS = [
|
||||||
@@ -95,7 +97,11 @@ const CreateProjectSidebar: FC<Props> = ({
|
|||||||
if (user) {
|
if (user) {
|
||||||
onSelectedUsersChange([
|
onSelectedUsersChange([
|
||||||
...selectedUsers,
|
...selectedUsers,
|
||||||
{ id: user.id, name: `${user.firstName} ${user.lastName}` },
|
{
|
||||||
|
id: user.id,
|
||||||
|
name: `${user.firstName} ${user.lastName}`,
|
||||||
|
profilePic: user.profilePic,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +148,7 @@ const CreateProjectSidebar: FC<Props> = ({
|
|||||||
) : (
|
) : (
|
||||||
selectedUsers.map((user) => (
|
selectedUsers.map((user) => (
|
||||||
<div key={user.id} className="bg-[#EBEEF5] flex gap-2 text-xs items-center px-2 py-2 rounded-lg">
|
<div key={user.id} className="bg-[#EBEEF5] flex gap-2 text-xs items-center px-2 py-2 rounded-lg">
|
||||||
|
<UserAvatar src={user.profilePic} alt={user.name} />
|
||||||
<div>{user.name}</div>
|
<div>{user.name}</div>
|
||||||
<CloseCircle variant="Bold" className="size-4 cursor-pointer" color="red" onClick={() => handleRemoveUser(user.id)} />
|
<CloseCircle variant="Bold" className="size-4 cursor-pointer" color="red" onClick={() => handleRemoveUser(user.id)} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export type ProjectUserType = {
|
|||||||
id: string;
|
id: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CreateProjectType = {
|
export type CreateProjectType = {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export type TaskUserType = {
|
|||||||
id: string;
|
id: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TaskChecklistItemType = {
|
export type TaskChecklistItemType = {
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ const UpdateWorkspace: FC = () => {
|
|||||||
workspace.users.map((user) => ({
|
workspace.users.map((user) => ({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
name: `${user.firstName} ${user.lastName}`,
|
name: `${user.firstName} ${user.lastName}`,
|
||||||
|
profilePic: user.profilePic,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
} else if (workspace.userIds?.length) {
|
} else if (workspace.userIds?.length) {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import Select from "../../../../components/Select";
|
|||||||
import { useGetUsers } from "../../../users/hooks/useUserData";
|
import { useGetUsers } from "../../../users/hooks/useUserData";
|
||||||
import { UserItemType } from "../../../users/types/UserTypes";
|
import { UserItemType } from "../../../users/types/UserTypes";
|
||||||
import WorkspaceColorPicker from "./WorkspaceColorPicker";
|
import WorkspaceColorPicker from "./WorkspaceColorPicker";
|
||||||
|
import UserAvatar from "../../components/UserAvatar";
|
||||||
|
|
||||||
export type SelectedUser = {
|
export type SelectedUser = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -55,7 +57,11 @@ const CreateWorkspaceSidebar: FC<Props> = ({
|
|||||||
if (user) {
|
if (user) {
|
||||||
onSelectedUsersChange([
|
onSelectedUsersChange([
|
||||||
...selectedUsers,
|
...selectedUsers,
|
||||||
{ id: user.id, name: `${user.firstName} ${user.lastName}` },
|
{
|
||||||
|
id: user.id,
|
||||||
|
name: `${user.firstName} ${user.lastName}`,
|
||||||
|
profilePic: user.profilePic,
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +113,7 @@ const CreateWorkspaceSidebar: FC<Props> = ({
|
|||||||
key={user.id}
|
key={user.id}
|
||||||
className="bg-[#EBEEF5] flex gap-2 text-xs items-center px-2 py-2 rounded-lg"
|
className="bg-[#EBEEF5] flex gap-2 text-xs items-center px-2 py-2 rounded-lg"
|
||||||
>
|
>
|
||||||
|
<UserAvatar src={user.profilePic} alt={user.name} />
|
||||||
<div>{user.name}</div>
|
<div>{user.name}</div>
|
||||||
<CloseCircle
|
<CloseCircle
|
||||||
variant="Bold"
|
variant="Bold"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type WorkspaceUserType = {
|
|||||||
id: string;
|
id: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
profilePic?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WorkspaceDetailType = WorkspaceItemType & {
|
export type WorkspaceDetailType = WorkspaceItemType & {
|
||||||
|
|||||||
Reference in New Issue
Block a user