From 20066ec1ba0735aa40305772d3a01ed647d7e316 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Tue, 1 Feb 2022 21:49:05 +0300 Subject: [PATCH] refactor: user profile component decomposition --- src/components/UserProfile/Avatar/Avatar.tsx | 20 +++++ .../UserProfile/Avatar/ChatButton.tsx | 19 ++++ src/components/UserProfile/Avatar/index.ts | 13 +++ src/components/UserProfile/Info/About.tsx | 16 ++++ src/components/UserProfile/Info/Details.tsx | 30 +++++++ src/components/UserProfile/Info/Heading.tsx | 19 ++++ src/components/UserProfile/Info/Info.tsx | 12 +++ src/components/UserProfile/Info/index.ts | 21 +++++ src/components/UserProfile/index.tsx | 29 +++++++ src/pages/user/user.tsx | 87 +++++-------------- 10 files changed, 203 insertions(+), 63 deletions(-) create mode 100644 src/components/UserProfile/Avatar/Avatar.tsx create mode 100644 src/components/UserProfile/Avatar/ChatButton.tsx create mode 100644 src/components/UserProfile/Avatar/index.ts create mode 100644 src/components/UserProfile/Info/About.tsx create mode 100644 src/components/UserProfile/Info/Details.tsx create mode 100644 src/components/UserProfile/Info/Heading.tsx create mode 100644 src/components/UserProfile/Info/Info.tsx create mode 100644 src/components/UserProfile/Info/index.ts create mode 100644 src/components/UserProfile/index.tsx diff --git a/src/components/UserProfile/Avatar/Avatar.tsx b/src/components/UserProfile/Avatar/Avatar.tsx new file mode 100644 index 0000000..e1b507f --- /dev/null +++ b/src/components/UserProfile/Avatar/Avatar.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Flex, Avatar as ChakraAvatar, AvatarBadge as ChakraAvatarBadge, useColorModeValue } from '@chakra-ui/react'; +import type { IAvatarProps } from '.'; + +const Avatar: React.FC = props => { + const { name, isOnline } = props; + const onlineColor = isOnline ? 'green.500' : 'red.500'; + const borderColor = useColorModeValue('#E2E8F0', '#2D3748'); + + return ( + + + + + {props.children} + + ); +}; + +export { Avatar }; diff --git a/src/components/UserProfile/Avatar/ChatButton.tsx b/src/components/UserProfile/Avatar/ChatButton.tsx new file mode 100644 index 0000000..92f0158 --- /dev/null +++ b/src/components/UserProfile/Avatar/ChatButton.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Button, ButtonProps } from '@chakra-ui/react'; +import { MdOutlineMessage } from 'react-icons/md'; +import { useHistory } from 'react-router-dom'; +import type { IChatButtonProps } from '.'; + +const ChatButton: React.FC = props => { + const { userid } = props; + const history = useHistory(); + const handleChat = () => history.push(`/chat/${userid}`); + + return ( + + ); +}; + +export { ChatButton }; diff --git a/src/components/UserProfile/Avatar/index.ts b/src/components/UserProfile/Avatar/index.ts new file mode 100644 index 0000000..e2e6c6b --- /dev/null +++ b/src/components/UserProfile/Avatar/index.ts @@ -0,0 +1,13 @@ +import { Avatar } from './Avatar'; +import { ChatButton } from './ChatButton'; + +export interface IAvatarProps { + name: string; + isOnline: boolean; +} + +export interface IChatButtonProps { + userid: string; +} + +export { Avatar, ChatButton }; diff --git a/src/components/UserProfile/Info/About.tsx b/src/components/UserProfile/Info/About.tsx new file mode 100644 index 0000000..51457c4 --- /dev/null +++ b/src/components/UserProfile/Info/About.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Box, Text } from '@chakra-ui/react'; +import type { IAboutProps } from '.'; + +const About: React.FC = () => { + return ( + + + Lorem ipsum dolor sit amet consectetur adipisicing elit. A quibusdam sapiente quisquam vero harum ipsam officiis + rerum. Cum, excepturi nulla. + + + ); +}; + +export { About }; diff --git a/src/components/UserProfile/Info/Details.tsx b/src/components/UserProfile/Info/Details.tsx new file mode 100644 index 0000000..2881764 --- /dev/null +++ b/src/components/UserProfile/Info/Details.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { Flex, Text, Icon, Divider } from '@chakra-ui/react'; +import { CalendarIcon, RepeatClockIcon } from '@chakra-ui/icons'; +import type { IDetailsProps } from '.'; + +const Details: React.FC = ({ registered, lastLogin }) => { + return ( + <> + + + + + + Joined: {new Date(registered).toLocaleDateString()} + + + + + + Last login: {lastLogin} + + + + + + + ); +}; + +export { Details }; diff --git a/src/components/UserProfile/Info/Heading.tsx b/src/components/UserProfile/Info/Heading.tsx new file mode 100644 index 0000000..85778f9 --- /dev/null +++ b/src/components/UserProfile/Info/Heading.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import UserBadge from '@educt/components/UserBadge'; +import { Flex, Box, Heading as ChakraHeading } from '@chakra-ui/react'; +import type { IHeadingProps } from '.'; + +const Heading: React.FC = ({ fullname, roles }) => { + return ( + + + {fullname} •  + + + + + + ); +}; + +export { Heading }; diff --git a/src/components/UserProfile/Info/Info.tsx b/src/components/UserProfile/Info/Info.tsx new file mode 100644 index 0000000..6faeb84 --- /dev/null +++ b/src/components/UserProfile/Info/Info.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Box } from '@chakra-ui/react'; + +const Info: React.FC = props => { + return ( + + {props.children} + + ); +}; + +export { Info }; diff --git a/src/components/UserProfile/Info/index.ts b/src/components/UserProfile/Info/index.ts new file mode 100644 index 0000000..50ad6c1 --- /dev/null +++ b/src/components/UserProfile/Info/index.ts @@ -0,0 +1,21 @@ +import { IUser } from '@educt/interfaces'; +import { Info } from './Info'; +import { Heading } from './Heading'; +import { Details } from './Details'; +import { About } from './About'; + +export interface IHeadingProps { + fullname: string; + roles: IUser['roles']; +} + +export interface IDetailsProps { + registered: string; + lastLogin: string; +} + +export interface IAboutProps { + about: string; +} + +export { Info, Heading, Details, About }; diff --git a/src/components/UserProfile/index.tsx b/src/components/UserProfile/index.tsx new file mode 100644 index 0000000..399c265 --- /dev/null +++ b/src/components/UserProfile/index.tsx @@ -0,0 +1,29 @@ +import React, { createContext } from 'react'; +import { BoxProps, Flex } from '@chakra-ui/react'; +import { IUser } from '@educt/interfaces'; +import { Avatar, ChatButton, IAvatarProps, IChatButtonProps } from './Avatar'; +import { About, Details, Heading, IAboutProps, IDetailsProps, IHeadingProps, Info } from './Info'; + +interface IUserProfileComposition { + Avatar: React.FC; + ChatButton: React.FC; + Info: React.FC; + Heading: React.FC; + Details: React.FC; + About: React.FC; +} + +export const UserProfileContext = createContext(undefined); + +const UserProfile: React.FC & IUserProfileComposition = props => { + return {props.children}; +}; + +UserProfile.Avatar = Avatar; +UserProfile.ChatButton = ChatButton; +UserProfile.Info = Info; +UserProfile.Heading = Heading; +UserProfile.Details = Details; +UserProfile.About = About; + +export { UserProfile }; diff --git a/src/pages/user/user.tsx b/src/pages/user/user.tsx index 0ca51f9..8660c78 100644 --- a/src/pages/user/user.tsx +++ b/src/pages/user/user.tsx @@ -1,29 +1,19 @@ import React from 'react'; -import { PageContent, PageWrapper } from '@educt/components/PageElements'; -import { IPageProps } from '@educt/interfaces'; -import { useFetchUser } from '@educt/hooks/queries/user/useFetchUser'; -import { Redirect, useParams } from 'react-router-dom'; +import { Redirect } from 'react-router-dom'; import LoadingPage from '@educt/components/LoadingPage'; -import { - Box, - Button, - Flex, - Avatar, - Text, - Heading, - useColorModeValue, - Icon, - AvatarBadge, - Divider, -} from '@chakra-ui/react'; -import { MdOutlineMessage } from 'react-icons/md'; -import UserBadge from '@educt/components/UserBadge'; -import { CalendarIcon, RepeatClockIcon } from '@chakra-ui/icons'; +import { PageContent, PageWrapper } from '@educt/components/PageElements'; +import { UserProfile } from '@educt/components/UserProfile'; +import type { IPageProps } from '@educt/interfaces'; + +/** + * Hooks + */ +import { useParams } from 'react-router-dom'; +import { useFetchUser } from '@educt/hooks/queries/user/useFetchUser'; const UserPage: React.FC = () => { const { id } = useParams<{ id: string }>(); const { data: user, error, isLoading } = useFetchUser(id); - const color = useColorModeValue('#E2E8F0', '#2D3748'); if (error?.response?.status === 404) return ; @@ -32,49 +22,20 @@ const UserPage: React.FC = () => { return ( - - - - - - - - - - - {user.fullname} •  - - - - - - - - - - - Registered: {new Date(user.created_at).toLocaleDateString()} - - - - - - Last login: 3 min ago - - - - - - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. A quibusdam sapiente quisquam vero harum ipsam - officiis rerum. Cum, excepturi nulla. - - - - + + + + + + + + + + );