diff --git a/src/features/user/profile/components/ContactOption.js b/src/features/user/profile/components/ContactOption.js new file mode 100644 index 0000000..4630546 --- /dev/null +++ b/src/features/user/profile/components/ContactOption.js @@ -0,0 +1,45 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { + ListItem, + ListItemText, + ListItemIcon, + Link, + Tooltip +} from "@material-ui/core"; + +const ContactOption = ({ tooltip, label, link, onClick, ...props }) => { + const linkLabel = label ?? link; + return ( + + + + + + {onClick ? ( + + {linkLabel} + + ) : ( + + {linkLabel} + + )} + + } + /> + + ); +}; + +ContactOption.propTypes = { + icon: PropTypes.object.isRequired, + tooltip: PropTypes.string.isRequired, + label: PropTypes.string, + link: PropTypes.string.isRequired, + onClick: PropTypes.func +}; + +export default ContactOption; diff --git a/src/features/user/profile/components/ContactOptions.js b/src/features/user/profile/components/ContactOptions.js new file mode 100644 index 0000000..4125638 --- /dev/null +++ b/src/features/user/profile/components/ContactOptions.js @@ -0,0 +1,148 @@ +import React, { useCallback, useMemo } from "react"; +import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; +import ContactOption from "./ContactOption"; +import BusinessCenterIcon from "@material-ui/icons/BusinessCenter"; +import EmailIcon from "@material-ui/icons/Email"; +import PhoneAndroidIcon from "@material-ui/icons/PhoneAndroid"; +import LanguageIcon from "@material-ui/icons/Language"; +import LinkedInIcon from "@material-ui/icons/LinkedIn"; +import GitHubIcon from "@material-ui/icons/GitHub"; +import RedditIcon from "@material-ui/icons/Reddit"; +import BookIcon from "@material-ui/icons/Book"; +import MenuBookIcon from "@material-ui/icons/MenuBook"; +import { useClipboard } from "../../../../hooks"; + +const icons = { + EMAIL: EmailIcon, + PHONE: PhoneAndroidIcon, + PORTFOLIO: BusinessCenterIcon, + LINKEDIN: LinkedInIcon, + GITHUB: GitHubIcon, + GITEA: GitHubIcon, + REDDIT: RedditIcon, + BLOG: BookIcon, + CURRICULUM_VITAE: MenuBookIcon, + DEFAULT: LanguageIcon +}; + +const tooltips = { + EMAIL: "Generic.SendEmail", + PHONE: "Generic.Copy", + PORTFOLIO: "User.Profile.OpenPortfolio", + DEFAULT: "Generic.OpenInNewTab" +}; + +const orderNumbers = { + PORTFOLIO: 1, + EMAIL: 2, + PHONE: 3, + CURRICULUM_VITAE: 4, + LINKEDIN: 5, + GITEA: 6, + GITHUB: 7, + BLOG: 8, + WEBSITE: 9, + REDDIT: 10, + DEFAULT: 100 +}; + +const getIcon = contactOption => { + const icon = icons[contactOption.contactTypeCode] || icons.DEFAULT; + return icon; +}; + +const getTooltip = contactOption => { + const tooltip = tooltips[contactOption.contactTypeCode] || tooltips.DEFAULT; + return tooltip; +}; + +const getOrderNumber = contactOption => { + const orderNo = + orderNumbers[contactOption.contactTypeCode] || orderNumbers.DEFAULT; + return orderNo; +}; + +const getLabel = (contactOption, userName) => { + switch (contactOption.contactTypeCode) { + case "EMAIL": + case "PHONE": + return contactOption.contactValue; + case "PORTFOLIO": + return userName; + default: + return contactOption.contactTypeName; + } +}; + +const handleEmailSending = email => event => { + window.location.href = `mailto:${email}`; + event.preventDefault(); +}; + +const ContactOptions = ({ contactOptions, userName }) => { + const { t } = useTranslation(); + const { copy } = useClipboard(); + + const getOnClickEvent = useCallback( + contactOption => { + switch (contactOption.contactTypeCode) { + case "EMAIL": + return handleEmailSending(contactOption.contactValue); + case "PHONE": + return copy(contactOption.contactValue); + default: + return undefined; + } + }, + [copy] + ); + + const enrichedContactOptions = useMemo( + () => + contactOptions.map(co => { + const icon = getIcon(co); + const tooltip = getTooltip(co); + const label = getLabel(co, userName); + const onClick = getOnClickEvent(co); + const orderNo = getOrderNumber(co); + const option = { + icon, + tooltip: t(tooltip), + label, + link: co.contactValue, + onClick, + orderNo + }; + return option; + }), + [contactOptions, getOnClickEvent, t, userName] + ); + + const sorted = useMemo( + () => enrichedContactOptions.sort((a, b) => a.orderNo - b.orderNo), + [enrichedContactOptions] + ); + + return ( + <> + {sorted.map((z, index) => ( + + ))} + + ); +}; + +ContactOptions.propTypes = { + contactOptions: PropTypes.array, + userName: PropTypes.object.isRequired +}; + +export default ContactOptions; diff --git a/src/features/user/profile/components/UserProfileCardContent.js b/src/features/user/profile/components/UserProfileCardContent.js index 7c32e60..c18c83a 100644 --- a/src/features/user/profile/components/UserProfileCardContent.js +++ b/src/features/user/profile/components/UserProfileCardContent.js @@ -11,10 +11,9 @@ import { Tooltip } from "@material-ui/core"; import UserProfilePicture from "./UserProfilePicture"; -import BusinessCenterIcon from "@material-ui/icons/BusinessCenter"; import { FileCopyOutlined } from "@material-ui/icons"; -import EmailIcon from "@material-ui/icons/Email"; -import { useToast } from "../../../../hooks"; +import ContactOptions from "./ContactOptions"; +import { useClipboard } from "../../../../hooks"; import { useTranslation } from "react-i18next"; import { makeStyles } from "@material-ui/core/styles"; import styles from "../styles"; @@ -22,65 +21,28 @@ import styles from "../styles"; const useStyles = makeStyles(styles); const UserProfileCardContent = ({ userData }) => { - const { email, profilePictureUrl } = userData; + const { profilePictureUrl } = userData; const { t } = useTranslation(); - const { info } = useToast(); const classes = useStyles(); - - const handleCopyToClipboard = url => () => { - navigator.clipboard.writeText(url); - info(t("Generic.CopiedToClipboard")); - }; - - const handleEmailSending = event => { - window.location.href = `mailto:${email}`; - event.preventDefault(); - }; + const { copy } = useClipboard(); const userName = `${userData.firstName} ${userData.lastName}`; return (
- + - - - - - - - {userName} - - - } - /> - - - - - - - - {email} - - - } - /> - + {profilePictureUrl && ( - + diff --git a/src/features/user/profile/components/UserProfileComponent.js b/src/features/user/profile/components/UserProfileComponent.js index 1caaf51..a16171c 100644 --- a/src/features/user/profile/components/UserProfileComponent.js +++ b/src/features/user/profile/components/UserProfileComponent.js @@ -11,9 +11,9 @@ const UserProfileComponent = ({ userData }) => { const userLoginDate = useMemo( () => t("DATE_FORMAT", { - date: { value: userData.createdAt, format: "DD-MM-YYYY HH:mm:ss" } + date: { value: userData.lastLoginDate, format: "DD-MM-YYYY HH:mm:ss" } }), - [t, userData.createdAt] + [t, userData.lastLoginDate] ); const userDescription = t("User.Profile.Description", { diff --git a/src/features/user/profile/components/UserProfileContainer.js b/src/features/user/profile/components/UserProfileContainer.js index 0fa469a..f9001d5 100644 --- a/src/features/user/profile/components/UserProfileContainer.js +++ b/src/features/user/profile/components/UserProfileContainer.js @@ -1,12 +1,10 @@ import React from "react"; -import { useTuitioDecodedToken } from "@flare/tuitio-client-react"; +import { useTuitioUserInfo } from "@flare/tuitio-client-react"; import UserProfileComponent from "./UserProfileComponent"; const UserProfileContainer = () => { - const { decodedToken } = useTuitioDecodedToken(); - return ( - <>{decodedToken && } - ); + const { userInfo } = useTuitioUserInfo(); + return <>{userInfo && }; }; export default UserProfileContainer; diff --git a/src/features/user/profile/components/UserProfilePicture.js b/src/features/user/profile/components/UserProfilePicture.js index 6ca0002..1c0f45c 100644 --- a/src/features/user/profile/components/UserProfilePicture.js +++ b/src/features/user/profile/components/UserProfilePicture.js @@ -7,15 +7,14 @@ import DefaultUserProfilePicture from "../../../../assets/images/DefaultUserProf const useStyles = makeStyles(style); -const UserProfilePicture = ({ userData }) => { +const UserProfilePicture = ({ pictureUrl }) => { const classes = useStyles(); - const { profilePictureUrl } = userData; - const url = profilePictureUrl ?? DefaultUserProfilePicture; + const url = pictureUrl ?? DefaultUserProfilePicture; return ; }; UserProfilePicture.propTypes = { - userData: PropTypes.object.isRequired + pictureUrl: PropTypes.string }; export default UserProfilePicture; diff --git a/src/hooks/index.js b/src/hooks/index.js index a6f8e8a..973e94d 100644 --- a/src/hooks/index.js +++ b/src/hooks/index.js @@ -1,4 +1,5 @@ import { useToast } from "./useToast"; import { useSensitiveInfo } from "../providers/SensitiveInfoProvider"; +import { useClipboard } from "./useClipboard"; -export { useToast, useSensitiveInfo }; +export { useToast, useSensitiveInfo, useClipboard }; diff --git a/src/hooks/useClipboard.js b/src/hooks/useClipboard.js new file mode 100644 index 0000000..b2fd329 --- /dev/null +++ b/src/hooks/useClipboard.js @@ -0,0 +1,18 @@ +import { useCallback } from "react"; +import { useTranslation } from "react-i18next"; +import { useToast } from "./useToast"; + +const useClipboard = () => { + const { t } = useTranslation(); + const { info } = useToast(); + const copy = useCallback( + url => () => { + navigator.clipboard.writeText(url); + info(t("Generic.CopiedToClipboard")); + }, + [info, t] + ); + return { copy }; +}; + +export { useClipboard };