Update custom avatar

This commit is contained in:
Philipinho
2024-06-26 23:20:26 +01:00
parent e476b89d35
commit 7373cbf1b9
15 changed files with 68 additions and 72 deletions

View File

@ -11,7 +11,7 @@ import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import APP_ROUTE from "@/lib/app-route.ts"; import APP_ROUTE from "@/lib/app-route.ts";
import useAuth from "@/features/auth/hooks/use-auth.ts"; import useAuth from "@/features/auth/hooks/use-auth.ts";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
export default function TopMenu() { export default function TopMenu() {
const [currentUser] = useAtom(currentUserAtom); const [currentUser] = useAtom(currentUserAtom);
@ -29,12 +29,11 @@ export default function TopMenu() {
<Menu.Target> <Menu.Target>
<UnstyledButton> <UnstyledButton>
<Group gap={7} wrap={"nowrap"}> <Group gap={7} wrap={"nowrap"}>
<UserAvatar <CustomAvatar
avatarUrl={workspace.logo} avatarUrl={workspace.logo}
name={workspace.name} name={workspace.name}
radius="xl" variant="filled"
color="blue" size="sm"
size={20}
/> />
<Text fw={500} size="sm" lh={1} mr={3}> <Text fw={500} size="sm" lh={1} mr={3}>
{workspace.name} {workspace.name}
@ -80,8 +79,7 @@ export default function TopMenu() {
<Menu.Label>Account</Menu.Label> <Menu.Label>Account</Menu.Label>
<Menu.Item component={Link} to={APP_ROUTE.SETTINGS.ACCOUNT.PROFILE}> <Menu.Item component={Link} to={APP_ROUTE.SETTINGS.ACCOUNT.PROFILE}>
<Group wrap={"nowrap"}> <Group wrap={"nowrap"}>
<UserAvatar <CustomAvatar
radius="xl"
size={"sm"} size={"sm"}
avatarUrl={user.avatarUrl} avatarUrl={user.avatarUrl}
name={user.name} name={user.name}

View File

@ -0,0 +1,32 @@
import React from "react";
import { Avatar } from "@mantine/core";
import { getAvatarUrl } from "@/lib/config.ts";
interface CustomAvatarProps {
avatarUrl: string;
name: string;
color?: string;
size?: string | number;
radius?: string | number;
variant?: string;
style?: any;
component?: any;
}
export const CustomAvatar = React.forwardRef<
HTMLInputElement,
CustomAvatarProps
>(({ avatarUrl, name, ...props }: CustomAvatarProps, ref) => {
const avatarLink = getAvatarUrl(avatarUrl);
return (
<Avatar
ref={ref}
src={avatarLink}
name={name}
alt={name}
color="initials"
{...props}
/>
);
});

View File

@ -1,35 +0,0 @@
import React, { useRef } from "react";
import { Avatar } from "@mantine/core";
import { getAvatarUrl } from "@/lib/config.ts";
interface UserAvatarProps {
avatarUrl: string;
name: string;
color?: string;
size?: string | number;
radius?: string | number;
style?: any;
component?: any;
}
export const UserAvatar = React.forwardRef<HTMLInputElement, UserAvatarProps>(
({ avatarUrl, name, ...props }: UserAvatarProps, ref) => {
const avatar = getAvatarUrl(avatarUrl);
const getInitials = (name: string) => {
const names = name?.split(" ");
return names
?.slice(0, 2)
.map((n) => n[0])
.join("");
};
return avatar ? (
<Avatar ref={ref} src={avatar} alt={name} radius="xl" {...props} />
) : (
<Avatar ref={ref} {...props}>
{getInitials(name)}
</Avatar>
);
},
);

View File

@ -13,7 +13,7 @@ import { currentUserAtom } from "@/features/user/atoms/current-user-atom";
import { useCreateCommentMutation } from "@/features/comment/queries/comment-query"; import { useCreateCommentMutation } from "@/features/comment/queries/comment-query";
import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom"; import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom";
import { useEditor } from "@tiptap/react"; import { useEditor } from "@tiptap/react";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
interface CommentDialogProps { interface CommentDialogProps {
editor: ReturnType<typeof useEditor>; editor: ReturnType<typeof useEditor>;
@ -94,8 +94,7 @@ function CommentDialog({ editor, pageId }: CommentDialogProps) {
> >
<Stack gap={2}> <Stack gap={2}>
<Group> <Group>
<UserAvatar <CustomAvatar
color="blue"
size="sm" size="sm"
avatarUrl={currentUser.user.avatarUrl} avatarUrl={currentUser.user.avatarUrl}
name={currentUser.user.name} name={currentUser.user.name}

View File

@ -13,7 +13,7 @@ import {
useUpdateCommentMutation, useUpdateCommentMutation,
} from "@/features/comment/queries/comment-query"; } from "@/features/comment/queries/comment-query";
import { IComment } from "@/features/comment/types/comment.types"; import { IComment } from "@/features/comment/types/comment.types";
import { UserAvatar } from "@/components/ui/user-avatar"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts"; import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
interface CommentListItemProps { interface CommentListItemProps {
@ -63,8 +63,7 @@ function CommentListItem({ comment }: CommentListItemProps) {
return ( return (
<Box ref={ref} pb="xs"> <Box ref={ref} pb="xs">
<Group> <Group>
<UserAvatar <CustomAvatar
color="blue"
size="sm" size="sm"
avatarUrl={comment.creator.avatarUrl} avatarUrl={comment.creator.avatarUrl}
name={comment.creator.name} name={comment.creator.name}

View File

@ -7,7 +7,7 @@ import { useParams } from "react-router-dom";
import React from "react"; import React from "react";
import { IconDots } from "@tabler/icons-react"; import { IconDots } from "@tabler/icons-react";
import { modals } from "@mantine/modals"; import { modals } from "@mantine/modals";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import useUserRole from "@/hooks/use-user-role.tsx"; import useUserRole from "@/hooks/use-user-role.tsx";
export default function GroupMembersList() { export default function GroupMembersList() {
@ -56,7 +56,7 @@ export default function GroupMembersList() {
<Table.Tr key={index}> <Table.Tr key={index}>
<Table.Td> <Table.Td>
<Group gap="sm"> <Group gap="sm">
<UserAvatar avatarUrl={user.avatarUrl} name={user.name} /> <CustomAvatar avatarUrl={user.avatarUrl} name={user.name} />
<div> <div>
<Text fz="sm" fw={500}> <Text fz="sm" fw={500}>
{user.name} {user.name}

View File

@ -3,7 +3,7 @@ import { useDebouncedValue } from "@mantine/hooks";
import { useWorkspaceMembersQuery } from "@/features/workspace/queries/workspace-query.ts"; import { useWorkspaceMembersQuery } from "@/features/workspace/queries/workspace-query.ts";
import { IUser } from "@/features/user/types/user.types.ts"; import { IUser } from "@/features/user/types/user.types.ts";
import { Group, MultiSelect, MultiSelectProps, Text } from "@mantine/core"; import { Group, MultiSelect, MultiSelectProps, Text } from "@mantine/core";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
interface MultiUserSelectProps { interface MultiUserSelectProps {
onChange: (value: string[]) => void; onChange: (value: string[]) => void;
@ -14,11 +14,10 @@ const renderMultiSelectOption: MultiSelectProps["renderOption"] = ({
option, option,
}) => ( }) => (
<Group gap="sm"> <Group gap="sm">
<UserAvatar <CustomAvatar
avatarUrl={option?.["avatarUrl"]} avatarUrl={option?.["avatarUrl"]}
name={option.label} name={option.label}
size={36} size={36}
radius="xl"
/> />
<div> <div>
<Text size="sm">{option.label}</Text> <Text size="sm">{option.label}</Text>

View File

@ -1,5 +1,5 @@
import { Text, Group, UnstyledButton } from "@mantine/core"; import { Text, Group, UnstyledButton } from "@mantine/core";
import { UserAvatar } from "@/components/ui/user-avatar"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { formattedDate } from "@/lib/time"; import { formattedDate } from "@/lib/time";
import classes from "./history.module.css"; import classes from "./history.module.css";
import clsx from "clsx"; import clsx from "clsx";
@ -25,8 +25,7 @@ function HistoryItem({ historyItem, onSelect, isActive }: HistoryItemProps) {
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<Group gap={4} wrap="nowrap"> <Group gap={4} wrap="nowrap">
<UserAvatar <CustomAvatar
color="blue"
size="sm" size="sm"
avatarUrl={historyItem.lastUpdatedBy.avatarUrl} avatarUrl={historyItem.lastUpdatedBy.avatarUrl}
name={historyItem.lastUpdatedBy.name} name={historyItem.lastUpdatedBy.name}

View File

@ -3,7 +3,7 @@ import { useDebouncedValue } from "@mantine/hooks";
import { Group, MultiSelect, MultiSelectProps, Text } from "@mantine/core"; import { Group, MultiSelect, MultiSelectProps, Text } from "@mantine/core";
import { IGroup } from "@/features/group/types/group.types.ts"; import { IGroup } from "@/features/group/types/group.types.ts";
import { useSearchSuggestionsQuery } from "@/features/search/queries/search-query.ts"; import { useSearchSuggestionsQuery } from "@/features/search/queries/search-query.ts";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { IUser } from "@/features/user/types/user.types.ts"; import { IUser } from "@/features/user/types/user.types.ts";
import { IconGroupCircle } from "@/components/icons/icon-people-circle.tsx"; import { IconGroupCircle } from "@/components/icons/icon-people-circle.tsx";
@ -16,7 +16,7 @@ const renderMultiSelectOption: MultiSelectProps["renderOption"] = ({
}) => ( }) => (
<Group gap="sm"> <Group gap="sm">
{option["type"] === "user" && ( {option["type"] === "user" && (
<UserAvatar <CustomAvatar
avatarUrl={option["avatarUrl"]} avatarUrl={option["avatarUrl"]}
size={20} size={20}
name={option.label} name={option.label}

View File

@ -20,9 +20,13 @@ export default function SpaceGrid() {
withBorder withBorder
> >
<Card.Section className={classes.cardSection} h={40}></Card.Section> <Card.Section className={classes.cardSection} h={40}></Card.Section>
<Avatar variant="filled" size="md" mt={rem(-20)}> <Avatar
{space.name.charAt(0).toUpperCase()} name={space.name}
</Avatar> color="initials"
variant="filled"
size="md"
mt={rem(-20)}
/>
<Text fz="md" fw={500} mt="xs" className={classes.title}> <Text fz="md" fw={500} mt="xs" className={classes.title}>
{space.name} {space.name}

View File

@ -34,9 +34,11 @@ export default function SpaceList() {
> >
<Table.Td> <Table.Td>
<Group gap="sm"> <Group gap="sm">
<Avatar color="gray" radius="xl"> <Avatar
{space.name.charAt(0).toUpperCase()} color="initials"
</Avatar> variant="filled"
name={space.name}
/>
<div> <div>
<Text fz="sm" fw={500}> <Text fz="sm" fw={500}>
{space.name} {space.name}

View File

@ -3,7 +3,7 @@ import { useParams } from "react-router-dom";
import React from "react"; import React from "react";
import { IconDots } from "@tabler/icons-react"; import { IconDots } from "@tabler/icons-react";
import { modals } from "@mantine/modals"; import { modals } from "@mantine/modals";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { import {
useChangeSpaceMemberRoleMutation, useChangeSpaceMemberRoleMutation,
useRemoveSpaceMemberMutation, useRemoveSpaceMemberMutation,
@ -109,7 +109,7 @@ export default function SpaceMembersList({
<Table.Td> <Table.Td>
<Group gap="sm"> <Group gap="sm">
{member.type === "user" && ( {member.type === "user" && (
<UserAvatar <CustomAvatar
avatarUrl={member?.avatarUrl} avatarUrl={member?.avatarUrl}
name={member.name} name={member.name}
/> />

View File

@ -2,7 +2,7 @@ import { focusAtom } from "jotai-optics";
import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts"; import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts";
import { useState } from "react"; import { useState } from "react";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import { FileButton, Tooltip } from "@mantine/core"; import { FileButton, Tooltip } from "@mantine/core";
import { uploadAvatar } from "@/features/user/services/user-service.ts"; import { uploadAvatar } from "@/features/user/services/user-service.ts";
@ -37,10 +37,9 @@ export default function AccountAvatar() {
<FileButton onChange={handleFileChange} accept="image/png,image/jpeg"> <FileButton onChange={handleFileChange} accept="image/png,image/jpeg">
{(props) => ( {(props) => (
<Tooltip label="Change photo" position="bottom"> <Tooltip label="Change photo" position="bottom">
<UserAvatar <CustomAvatar
{...props} {...props}
component="button" component="button"
radius="xl"
size="60px" size="60px"
avatarUrl={currentUser?.user.avatarUrl} avatarUrl={currentUser?.user.avatarUrl}
name={currentUser?.user.name} name={currentUser?.user.name}

View File

@ -35,7 +35,7 @@ export default function WorkspaceInvitesTable() {
<Table.Tr key={index}> <Table.Tr key={index}>
<Table.Td> <Table.Td>
<Group gap="sm"> <Group gap="sm">
<Avatar src={invitation.email} /> <Avatar name={invitation.email} color="initials" />
<div> <div>
<Text fz="sm" fw={500}> <Text fz="sm" fw={500}>
{invitation.email} {invitation.email}

View File

@ -3,7 +3,7 @@ import {
useChangeMemberRoleMutation, useChangeMemberRoleMutation,
useWorkspaceMembersQuery, useWorkspaceMembersQuery,
} from "@/features/workspace/queries/workspace-query.ts"; } from "@/features/workspace/queries/workspace-query.ts";
import { UserAvatar } from "@/components/ui/user-avatar.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
import React from "react"; import React from "react";
import RoleSelectMenu from "@/components/ui/role-select-menu.tsx"; import RoleSelectMenu from "@/components/ui/role-select-menu.tsx";
import { import {
@ -51,7 +51,7 @@ export default function WorkspaceMembersTable() {
<Table.Tr key={index}> <Table.Tr key={index}>
<Table.Td> <Table.Td>
<Group gap="sm"> <Group gap="sm">
<UserAvatar avatarUrl={user.avatarUrl} name={user.name} /> <CustomAvatar avatarUrl={user.avatarUrl} name={user.name} />
<div> <div>
<Text fz="sm" fw={500}> <Text fz="sm" fw={500}>
{user.name} {user.name}