contact info refactoring

master
Tudor Stanciu 2023-04-01 20:17:23 +03:00
parent 3d3f8fe811
commit c5e7319324
3 changed files with 68 additions and 53 deletions

View File

@ -5,15 +5,32 @@ import {
ListItemText, ListItemText,
ListItemIcon, ListItemIcon,
Link, Link,
Tooltip Tooltip,
IconButton
} from "@material-ui/core"; } from "@material-ui/core";
const ContactIcon = ({ onIconClick, iconTooltip, ...props }) => {
if (!onIconClick) return <props.icon />;
return (
<Tooltip title={iconTooltip}>
<IconButton size="small" onClick={onIconClick}>
<props.icon />
</IconButton>
</Tooltip>
);
};
ContactIcon.propTypes = {
onIconClick: PropTypes.func,
iconTooltip: PropTypes.string
};
const ContactOption = ({ tooltip, label, link, onClick, ...props }) => { const ContactOption = ({ tooltip, label, link, onClick, ...props }) => {
const linkLabel = label ?? link; const linkLabel = label ?? link;
return ( return (
<ListItem dense> <ListItem dense>
<ListItemIcon> <ListItemIcon>
<props.icon /> <ContactIcon {...props} />
</ListItemIcon> </ListItemIcon>
<ListItemText <ListItemText
primary={ primary={
@ -35,11 +52,11 @@ const ContactOption = ({ tooltip, label, link, onClick, ...props }) => {
}; };
ContactOption.propTypes = { ContactOption.propTypes = {
icon: PropTypes.object.isRequired,
tooltip: PropTypes.string.isRequired, tooltip: PropTypes.string.isRequired,
label: PropTypes.string, label: PropTypes.string,
link: PropTypes.string.isRequired, link: PropTypes.string.isRequired,
onClick: PropTypes.func onClick: PropTypes.func,
onIconClick: PropTypes.func
}; };
export default ContactOption; export default ContactOption;

View File

@ -12,6 +12,7 @@ import GitHubIcon from "@material-ui/icons/GitHub";
import RedditIcon from "@material-ui/icons/Reddit"; import RedditIcon from "@material-ui/icons/Reddit";
import BookIcon from "@material-ui/icons/Book"; import BookIcon from "@material-ui/icons/Book";
import MenuBookIcon from "@material-ui/icons/MenuBook"; import MenuBookIcon from "@material-ui/icons/MenuBook";
import FileCopyOutlinedIcon from "@material-ui/icons/FileCopyOutlined";
import { useClipboard } from "../../../../hooks"; import { useClipboard } from "../../../../hooks";
const icons = { const icons = {
@ -24,6 +25,7 @@ const icons = {
REDDIT: RedditIcon, REDDIT: RedditIcon,
BLOG: BookIcon, BLOG: BookIcon,
CURRICULUM_VITAE: MenuBookIcon, CURRICULUM_VITAE: MenuBookIcon,
PROFILE_PICTURE: FileCopyOutlinedIcon,
DEFAULT: LanguageIcon DEFAULT: LanguageIcon
}; };
@ -68,6 +70,7 @@ const getLabel = (contactOption, userName) => {
switch (contactOption.contactTypeCode) { switch (contactOption.contactTypeCode) {
case "EMAIL": case "EMAIL":
case "PHONE": case "PHONE":
case "PROFILE_PICTURE":
return contactOption.contactValue; return contactOption.contactValue;
case "PORTFOLIO": case "PORTFOLIO":
return userName; return userName;
@ -81,7 +84,7 @@ const handleEmailSending = email => event => {
event.preventDefault(); event.preventDefault();
}; };
const ContactOptions = ({ contactOptions, userName, profilePictureItem }) => { const ContactOptions = ({ contactOptions, userName }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { copy } = useClipboard(); const { copy } = useClipboard();
@ -99,6 +102,21 @@ const ContactOptions = ({ contactOptions, userName, profilePictureItem }) => {
[copy] [copy]
); );
const getIconClickEvent = useCallback(
contactOption => {
switch (contactOption.contactTypeCode) {
case "PROFILE_PICTURE":
return {
onIconClick: copy(contactOption.contactValue),
iconTooltip: t("Generic.Copy")
};
default:
return { onIconClick: undefined, iconTooltip: undefined };
}
},
[copy, t]
);
const enrichedContactOptions = useMemo( const enrichedContactOptions = useMemo(
() => () =>
contactOptions.map(co => { contactOptions.map(co => {
@ -106,6 +124,7 @@ const ContactOptions = ({ contactOptions, userName, profilePictureItem }) => {
const tooltip = getTooltip(co); const tooltip = getTooltip(co);
const label = getLabel(co, userName); const label = getLabel(co, userName);
const onClick = getOnClickEvent(co); const onClick = getOnClickEvent(co);
const { onIconClick, iconTooltip } = getIconClickEvent(co);
const orderNo = getOrderNumber(co); const orderNo = getOrderNumber(co);
const option = { const option = {
icon, icon,
@ -113,11 +132,13 @@ const ContactOptions = ({ contactOptions, userName, profilePictureItem }) => {
label, label,
link: co.contactValue, link: co.contactValue,
onClick, onClick,
onIconClick,
iconTooltip,
orderNo orderNo
}; };
return option; return option;
}), }),
[contactOptions, getOnClickEvent, t, userName] [contactOptions, getOnClickEvent, getIconClickEvent, t, userName]
); );
const sorted = useMemo( const sorted = useMemo(
@ -135,17 +156,17 @@ const ContactOptions = ({ contactOptions, userName, profilePictureItem }) => {
label={z.label} label={z.label}
link={z.link} link={z.link}
onClick={z.onClick} onClick={z.onClick}
onIconClick={z.onIconClick}
iconTooltip={z.iconTooltip}
/> />
))} ))}
{profilePictureItem && <>{profilePictureItem}</>}
</List> </List>
); );
}; };
ContactOptions.propTypes = { ContactOptions.propTypes = {
contactOptions: PropTypes.array, contactOptions: PropTypes.array,
userName: PropTypes.string.isRequired, userName: PropTypes.string.isRequired
profilePictureItem: PropTypes.node
}; };
export default ContactOptions; export default ContactOptions;

View File

@ -1,19 +1,8 @@
import React from "react"; import React, { useMemo } from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import { import { Grid } from "@material-ui/core";
Grid,
ListItem,
ListItemText,
ListItemIcon,
Link,
IconButton,
Tooltip
} from "@material-ui/core";
import UserProfilePicture from "./UserProfilePicture"; import UserProfilePicture from "./UserProfilePicture";
import { FileCopyOutlined } from "@material-ui/icons";
import ContactOptions from "./ContactOptions"; import ContactOptions from "./ContactOptions";
import { useClipboard } from "../../../../hooks";
import { useTranslation } from "react-i18next";
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles";
import styles from "../styles"; import styles from "../styles";
@ -21,11 +10,26 @@ const useStyles = makeStyles(styles);
const UserProfileCardContent = ({ userData }) => { const UserProfileCardContent = ({ userData }) => {
const { profilePictureUrl } = userData; const { profilePictureUrl } = userData;
const { t } = useTranslation();
const classes = useStyles(); const classes = useStyles();
const { copy } = useClipboard();
const userName = `${userData.firstName} ${userData.lastName}`; const userName = useMemo(
() => `${userData.firstName} ${userData.lastName}`,
[userData.firstName, userData.lastName]
);
const _contactOptions = useMemo(
() =>
profilePictureUrl
? [
...userData.contactOptions,
{
id: userData.contactOptions.length + 1,
contactTypeCode: "PROFILE_PICTURE",
contactValue: profilePictureUrl
}
]
: userData.contactOptions,
[profilePictureUrl, userData.contactOptions]
);
return ( return (
<div className={classes.panel}> <div className={classes.panel}>
@ -33,35 +37,8 @@ const UserProfileCardContent = ({ userData }) => {
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} sm={6}> <Grid item xs={12} sm={6}>
<ContactOptions <ContactOptions
contactOptions={userData.contactOptions} contactOptions={_contactOptions}
userName={userName} userName={userName}
profilePictureItem={
<>
{profilePictureUrl && (
<ListItem dense>
<ListItemIcon>
<Tooltip title={t("Generic.Copy")}>
<IconButton
size="small"
onClick={copy(profilePictureUrl)}
>
<FileCopyOutlined />
</IconButton>
</Tooltip>
</ListItemIcon>
<ListItemText
primary={
<Tooltip title={t("Generic.OpenInNewTab")}>
<Link href={profilePictureUrl} target="_blank">
{profilePictureUrl}
</Link>
</Tooltip>
}
/>
</ListItem>
)}
</>
}
/> />
</Grid> </Grid>
</Grid> </Grid>