@eureca/eureca-ui
Version:
UI component library of Eureca's user and admin apps
232 lines (211 loc) • 6.28 kB
JavaScript
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { format } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import { Box, Grid, Typography, useTheme } from '@material-ui/core/';
import { FiChevronLeft } from 'react-icons/fi';
import { useWindowSize } from '../../hooks/useWindowSizeSSR';
import { colors } from '../../theme/colors';
import { Flex } from '../Flex';
import { Avatar } from '../Avatar';
function MessageCard({ message = {}, isActive, onClick = () => {}, isMobile }) {
const { title, date, sender } = message;
return (
<Flex
directionRow
alignCenter
justifySpaceBetween
cursorPointer
p={2}
mb={[1, 0]}
bgcolor={isActive ? colors.white : colors.gray5}
style={{
border: isMobile ? `2px solid ${colors.gray5}` : `1px solid ${colors.white}`,
borderRadius: isMobile ? 4 : 0,
}}
onClick={onClick}
>
<Box>
<Box mb={1}>
<Typography
variant={isMobile ? 'h6' : 'body1'}
style={{ color: isActive ? colors.gray2 : colors.gray3 }}
>
{title.length > 33 ? `${title.slice(0, 33)}...` : title}
</Typography>
</Box>
<Typography
variant="body2"
style={{
fontSize: isMobile ? '.875rem' : '.625rem',
color: colors.gray3,
}}
>
{format(date, 'dd, MMMM, yyyy', { locale: ptBR })}
</Typography>
</Box>
<Avatar name={sender.name} size={isMobile ? 48 : 36} src={sender.avatar} />
</Flex>
);
}
MessageCard.propTypes = {
message: PropTypes.shape({
title: PropTypes.string,
date: PropTypes.instanceOf(Date),
sender: PropTypes.shape({
name: PropTypes.string,
avatar: PropTypes.string,
}),
}),
isActive: PropTypes.bool,
onClick: PropTypes.func,
isMobile: PropTypes.bool,
};
function MessageHeader({ sender, date }) {
return (
<Flex directionRow alignCenter>
<Box mr={1}>
<Avatar name={sender.name} src={sender.avatar} />
</Box>
<Flex
width={1}
flexDirection={['column', 'row']}
justifyContent={['initial', 'space-between']}
>
<Flex directionRow alignCenter>
<Typography style={{ marginRight: 4 }}>{sender.name}</Typography>
<Typography style={{ color: colors.gray3 }}>{`<${sender.email}>`}</Typography>
</Flex>
<Typography
variant="body2"
style={{ fontSize: '.875rem', lineHeight: 2, color: colors.gray3 }}
>
{format(date, 'dd, MMMM, yyyy', { locale: ptBR })}
</Typography>
</Flex>
</Flex>
);
}
MessageHeader.propTypes = {
sender: PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
name: PropTypes.string,
email: PropTypes.string,
avatar: PropTypes.string,
}),
date: PropTypes.object,
};
function MessagePanel({ message }) {
const { title = '', sender = {}, date = new Date(), body = '' } = message;
const theme = useTheme();
return (
<Flex py={4} px={6} border={`1px solid ${colors.gray5}`} bgcolor={colors.white}>
<Typography variant="body1">{title}</Typography>
<MessageHeader sender={sender} date={date} />
<Typography
style={{ fontSize: '.625rem', fontWeight: theme.typography.fontWeightLight, lineHeight: 2 }}
>
{body}
</Typography>
</Flex>
);
}
MessagePanel.propTypes = {
message: PropTypes.object,
title: PropTypes.string,
sender: PropTypes.object,
date: PropTypes.object,
body: PropTypes.any,
};
function MessagePanelMobile({ message, onClose }) {
const { title = '', sender = {}, date = new Date(), body = '' } = message;
const theme = useTheme();
return (
<Flex
position="fixed"
top={0}
left={0}
width={1}
height={1}
zIndex={999}
px={2}
pb={5}
bgcolor={colors.white}
border={`1px solid ${colors.gray5}`}
>
<Flex my={4} width={32} height={32} justifyCenter alignCenter cursorPointer onClick={onClose}>
<FiChevronLeft size="32" />
</Flex>
<Box px={2}>
<Typography variant="body1" style={{ fontSize: '2rem', lineHeight: 1.5 }}>
{title}
</Typography>
<Box mt={3} mb={3}>
<MessageHeader sender={sender} date={date} />
</Box>
</Box>
<Typography
variant="body1"
style={{ fontWeight: theme.typography.fontWeightLight, overflowY: 'auto' }}
>
{body}
</Typography>
</Flex>
);
}
MessagePanelMobile.propTypes = {
message: PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
title: PropTypes.string,
sender: PropTypes.object,
date: PropTypes.object,
body: PropTypes.any,
}),
onClose: PropTypes.func,
};
function Messages({ data = [], ...props }) {
const theme = useTheme();
const size = useWindowSize();
const isMobile = size?.width < theme.breakpoints.values.sm;
const [activeMessage, setActiveMessage] = useState(isMobile ? null : 0);
const toggleMessage = index => setActiveMessage(index);
useEffect(() => {
setActiveMessage(isMobile ? null : 0);
}, [isMobile]);
return (
<Grid container style={{ overflow: 'hidden', borderRadius: 4 }} {...props}>
<Grid item xs={12} sm={4}>
{data.map((item, index) => {
return (
<MessageCard
key={item.id}
message={item}
isActive={index === activeMessage || isMobile}
isMobile={isMobile}
onClick={e => {
e.stopPropagation();
toggleMessage(index);
}}
/>
);
})}
</Grid>
{activeMessage !== null && (
<Grid item xs={12} sm={8}>
{isMobile ? (
<MessagePanelMobile
message={data[activeMessage]}
onClose={() => setActiveMessage(null)}
/>
) : (
<MessagePanel message={data[activeMessage]} />
)}
</Grid>
)}
</Grid>
);
}
Messages.propTypes = {
data: PropTypes.array,
};
export { Messages };