diff --git a/src/App.tsx b/src/App.tsx index 443851c..4adffc2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, useEffect } from 'react'; import { Router, Switch } from 'react-router-dom'; import { routes } from './routes.config'; diff --git a/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx b/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx index cd2164e..4fddfb1 100644 --- a/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx +++ b/src/components/Modals/AddStudentsModal/AddSudentsModal.tsx @@ -53,7 +53,7 @@ const AddStudentsModal: React.FC = ({ icon={MdGroup} heading='Add new students' description='Attach new students to current course.' - confirmText='Add students' + confirmText='Add' isOpen={isOpen} onClose={onClose} onProceed={handleAttachStudents} diff --git a/src/components/PageElements/index.tsx b/src/components/PageElements/index.tsx index 1d06fc4..b11f8c6 100644 --- a/src/components/PageElements/index.tsx +++ b/src/components/PageElements/index.tsx @@ -1,17 +1,23 @@ import React from 'react'; import { BoxProps, Box, Flex, Heading, Text, Divider } from '@chakra-ui/react'; -interface IPageHeadingProps extends BoxProps { +interface IPageComposition { + Heading: React.FC; + Content: React.FC; + Footer: React.FC; +} + +const Page: React.FC & IPageComposition = props => { + return {props.children}; +}; + +interface IPageHeadingProps { headingPrefix?: JSX.Element; heading: string; description?: string; } -export const PageWrapper: React.FC = props => { - return {props.children}; -}; - -export const PageHeading: React.FC = props => { +Page.Heading = props => { const { headingPrefix, heading, description, ...boxProps } = props; return ( @@ -26,15 +32,17 @@ export const PageHeading: React.FC = props => { ); }; -export const PageContent: React.FC = props => ( +Page.Content = props => ( {props.children} ); -export const PageFooter: React.FC = props => ( +Page.Footer = props => ( {props.children} ); + +export { Page }; diff --git a/src/components/UserProfile/Avatar/Avatar.tsx b/src/components/UserProfile/Avatar/Avatar.tsx new file mode 100644 index 0000000..cc6ba4d --- /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 ( + + + {isOnline && } + + {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..191590b --- /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 | undefined; +} + +export interface IChatButtonProps { + userid: string; +} + +export { Avatar, ChatButton }; diff --git a/src/components/UserProfile/Base/Base.tsx b/src/components/UserProfile/Base/Base.tsx new file mode 100644 index 0000000..09e6f7c --- /dev/null +++ b/src/components/UserProfile/Base/Base.tsx @@ -0,0 +1,12 @@ +import { Flex, FlexProps } from '@chakra-ui/react'; +import React from 'react'; + +const Base: React.FC = props => { + return ( + + {props.children} + + ); +}; + +export { Base }; diff --git a/src/components/UserProfile/Base/index.ts b/src/components/UserProfile/Base/index.ts new file mode 100644 index 0000000..32893c8 --- /dev/null +++ b/src/components/UserProfile/Base/index.ts @@ -0,0 +1 @@ +export { Base } from './Base'; diff --git a/src/components/UserProfile/Info/About.tsx b/src/components/UserProfile/Info/About.tsx new file mode 100644 index 0000000..7f4fe5e --- /dev/null +++ b/src/components/UserProfile/Info/About.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Box, Text } from '@chakra-ui/react'; +import type { IAboutProps } from '.'; + +const About: React.FC = ({ about }) => { + return ( + + + {about ? ( + about + ) : ( + + No description provided + + )} + + + ); +}; + +export { About }; diff --git a/src/components/UserProfile/Info/Details.tsx b/src/components/UserProfile/Info/Details.tsx new file mode 100644 index 0000000..b856a8a --- /dev/null +++ b/src/components/UserProfile/Info/Details.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import moment from 'moment'; +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 ? `${moment(lastLogin).fromNow()}` : 'Never'} + + + + + + + ); +}; + +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..7ce80d6 --- /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: IUser['last_login']; +} + +export interface IAboutProps { + about: IUser['about']; +} + +export { Info, Heading, Details, About }; diff --git a/src/components/UserProfile/Settings/Entry.tsx b/src/components/UserProfile/Settings/Entry.tsx new file mode 100644 index 0000000..dda09f5 --- /dev/null +++ b/src/components/UserProfile/Settings/Entry.tsx @@ -0,0 +1,8 @@ +import React from 'react'; +import { Flex } from '@chakra-ui/react'; + +const Entry: React.FC = props => { + return {props.children}; +}; + +export { Entry }; diff --git a/src/components/UserProfile/Settings/EntryContent.tsx b/src/components/UserProfile/Settings/EntryContent.tsx new file mode 100644 index 0000000..568ca77 --- /dev/null +++ b/src/components/UserProfile/Settings/EntryContent.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Flex } from '@chakra-ui/react'; + +const EntryContent: React.FC = props => { + return ( + + {props.children} + + ); +}; + +export { EntryContent }; diff --git a/src/components/UserProfile/Settings/Fields/index.tsx b/src/components/UserProfile/Settings/Fields/index.tsx new file mode 100644 index 0000000..d810b4a --- /dev/null +++ b/src/components/UserProfile/Settings/Fields/index.tsx @@ -0,0 +1,196 @@ +import React from 'react'; +import { + Box, + FormControl, + FormHelperText, + FormLabel, + Input, + InputGroup, + InputRightElement, + InputProps, + Button, + Textarea, + Text, + TextareaProps, + Select, + SelectProps, + Switch, + SwitchProps, + ButtonProps, +} from '@chakra-ui/react'; +import { SaveButton } from '@educt/components/Buttons'; + +/** + * Hooks + */ +import { useColorMode } from '@chakra-ui/react'; +import { useSettingsContext } from '../context'; +import { useHistory } from 'react-router-dom'; + +const InputWithButton: React.FC< + InputProps & { buttonText?: string | undefined; buttonHandler?: () => void } +> = props => { + const { buttonText, buttonHandler, ...inputProps } = props; + + return ( + + + + + + + ); +}; + +export const FullnameInput: React.FC = props => ( + + Fullname + + +); + +export const EmailInput: React.FC = props => { + const history = useHistory(); + + const onChangeEmail = () => history.push(`/profile/change-email`); + + return ( + + Email + + + ); +}; + +export const AboutInput: React.FC = props => { + const { + form: { + register, + formState: { errors }, + }, + } = useSettingsContext(); + + return ( + + About +