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 DateObject from "react-date-object";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import AvatarImage from "../../../../assets/images/avatar_image.png";
|
||||
import UserAvatar from "../UserAvatar";
|
||||
import { formatDateRange } from "./date/utils";
|
||||
import type { TaskLabel } from "./labels/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="flex items-center gap-2 flex-wrap">
|
||||
{selectedUsers.map((user) => (
|
||||
<div
|
||||
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>
|
||||
<UserAvatar key={user.id} src={user.avatar} alt={user.name} className="size-8" />
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -91,19 +91,28 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
|
||||
page.data?.users?.map((user: UserItemType) => ({
|
||||
id: user.id,
|
||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||
avatar: user.profilePic,
|
||||
})) ?? [],
|
||||
) ?? [];
|
||||
const taskUsers: TaskUser[] =
|
||||
taskDetail?.users?.map((user) => ({
|
||||
id: user.id,
|
||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||
avatar: user.profilePic,
|
||||
})) ?? [];
|
||||
const userMap = new Map<string, TaskUser>(apiUsers.map((user) => [user.id, user]));
|
||||
|
||||
taskUsers.forEach((user) => {
|
||||
if (!userMap.has(user.id)) {
|
||||
userMap.set(user.id, user);
|
||||
const existing = userMap.get(user.id);
|
||||
|
||||
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());
|
||||
@@ -115,6 +124,7 @@ const TaskDetailToolbar: FC<Props> = ({ activeTab, onTabChange, taskDetail, task
|
||||
page.data?.users?.map((user: UserItemType) => ({
|
||||
id: user.id,
|
||||
name: `${user.firstName} ${user.lastName}`.trim(),
|
||||
avatar: user.profilePic,
|
||||
})) ?? [],
|
||||
) ?? []
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { type FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Input from "../../../../../components/Input";
|
||||
import UserAvatar from "../../UserAvatar";
|
||||
import TaskDetailLabelCheckbox from "../labels/TaskDetailLabelCheckbox";
|
||||
import type { TaskUser } from "./types";
|
||||
|
||||
@@ -71,7 +72,7 @@ const TaskDetailUsersList: FC<Props> = ({
|
||||
onToggle={() => onToggle(user.id)}
|
||||
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>
|
||||
);
|
||||
|
||||
@@ -135,6 +135,7 @@ const UpdateProject: FC = () => {
|
||||
project.users.map((user) => ({
|
||||
id: user.id,
|
||||
name: `${user.firstName} ${user.lastName}`,
|
||||
profilePic: user.profilePic,
|
||||
})),
|
||||
);
|
||||
} else if (project.userIds?.length) {
|
||||
|
||||
@@ -8,10 +8,12 @@ import { UserItemType } from "../../../users/types/UserTypes";
|
||||
import { useGetWorkspaces } from "../../workspace/hooks/useWorkspaceData";
|
||||
import { WorkspaceItemType } from "../../workspace/types/WorkspaceTypes";
|
||||
import WorkspaceColorPicker from "../../workspace/components/WorkspaceColorPicker";
|
||||
import UserAvatar from "../../components/UserAvatar";
|
||||
|
||||
export type SelectedUser = {
|
||||
id: string;
|
||||
name: string;
|
||||
profilePic?: string;
|
||||
};
|
||||
|
||||
export const BACKGROUND_PRESETS = [
|
||||
@@ -95,7 +97,11 @@ const CreateProjectSidebar: FC<Props> = ({
|
||||
if (user) {
|
||||
onSelectedUsersChange([
|
||||
...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) => (
|
||||
<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>
|
||||
<CloseCircle variant="Bold" className="size-4 cursor-pointer" color="red" onClick={() => handleRemoveUser(user.id)} />
|
||||
</div>
|
||||
|
||||
@@ -12,6 +12,7 @@ export type ProjectUserType = {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
profilePic?: string;
|
||||
};
|
||||
|
||||
export type CreateProjectType = {
|
||||
|
||||
@@ -59,6 +59,7 @@ export type TaskUserType = {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
profilePic?: string;
|
||||
};
|
||||
|
||||
export type TaskChecklistItemType = {
|
||||
|
||||
@@ -89,6 +89,7 @@ const UpdateWorkspace: FC = () => {
|
||||
workspace.users.map((user) => ({
|
||||
id: user.id,
|
||||
name: `${user.firstName} ${user.lastName}`,
|
||||
profilePic: user.profilePic,
|
||||
})),
|
||||
);
|
||||
} else if (workspace.userIds?.length) {
|
||||
|
||||
@@ -6,10 +6,12 @@ import Select from "../../../../components/Select";
|
||||
import { useGetUsers } from "../../../users/hooks/useUserData";
|
||||
import { UserItemType } from "../../../users/types/UserTypes";
|
||||
import WorkspaceColorPicker from "./WorkspaceColorPicker";
|
||||
import UserAvatar from "../../components/UserAvatar";
|
||||
|
||||
export type SelectedUser = {
|
||||
id: string;
|
||||
name: string;
|
||||
profilePic?: string;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
@@ -55,7 +57,11 @@ const CreateWorkspaceSidebar: FC<Props> = ({
|
||||
if (user) {
|
||||
onSelectedUsersChange([
|
||||
...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}
|
||||
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>
|
||||
<CloseCircle
|
||||
variant="Bold"
|
||||
|
||||
@@ -18,6 +18,7 @@ export type WorkspaceUserType = {
|
||||
id: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
profilePic?: string;
|
||||
};
|
||||
|
||||
export type WorkspaceDetailType = WorkspaceItemType & {
|
||||
|
||||
Reference in New Issue
Block a user