profile picture

This commit is contained in:
hamid zarghami
2026-07-20 10:11:43 +03:30
parent bd65d28ea3
commit 94639858f2
11 changed files with 53 additions and 16 deletions
@@ -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>
);
+1
View File
@@ -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 & {