From e13e630cd6e4fc0b1ff92098a28a770794c7bb9a Mon Sep 17 00:00:00 2001 From: gabrhr <73925454+gabrhr@users.noreply.github.com> Date: Wed, 20 Apr 2022 10:19:29 -0500 Subject: =?UTF-8?q?A=C3=B1adir=20plantilla?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base para front --- .../app/components/Contact/AddContact.js | 82 ++++++ .../app/components/Contact/AddContactForm.js | 273 ++++++++++++++++++++ .../app/components/Contact/ContactDetail.js | 195 ++++++++++++++ .../app/components/Contact/ContactHeader.js | 62 +++++ .../app/components/Contact/ContactList.js | 112 ++++++++ .../app/components/Contact/contact-jss.js | 282 +++++++++++++++++++++ 6 files changed, 1006 insertions(+) create mode 100644 front/odiparpack/app/components/Contact/AddContact.js create mode 100644 front/odiparpack/app/components/Contact/AddContactForm.js create mode 100644 front/odiparpack/app/components/Contact/ContactDetail.js create mode 100644 front/odiparpack/app/components/Contact/ContactHeader.js create mode 100644 front/odiparpack/app/components/Contact/ContactList.js create mode 100644 front/odiparpack/app/components/Contact/contact-jss.js (limited to 'front/odiparpack/app/components/Contact') diff --git a/front/odiparpack/app/components/Contact/AddContact.js b/front/odiparpack/app/components/Contact/AddContact.js new file mode 100644 index 0000000..2690f1d --- /dev/null +++ b/front/odiparpack/app/components/Contact/AddContact.js @@ -0,0 +1,82 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Add from '@material-ui/icons/Add'; +import { Tooltip, Fab } from '@material-ui/core'; +import AddContactForm from './AddContactForm'; +import FloatingPanel from '../Panel/FloatingPanel'; +import styles from './contact-jss'; + + +class AddContact extends React.Component { + constructor(props) { + super(props); + this.state = { + img: '', + files: [] + }; + this.onDrop = this.onDrop.bind(this); + } + + onDrop(filesVal) { + const { files } = this.state; + const filesLimit = 1; + let oldFiles = files; + oldFiles = oldFiles.concat(filesVal); + if (oldFiles.length > filesLimit) { + console.log('Cannot upload more than ' + filesLimit + ' items.'); + } else { + this.setState({ img: filesVal[0] }); + } + } + + sendValues = (values) => { + const { submit } = this.props; + const { img } = this.state; + const { avatarInit } = this.props; + const avatar = img === null ? avatarInit : img; + setTimeout(() => { + submit(values, avatar); + this.setState({ img: null }); + }, 500); + } + + render() { + const { + classes, + openForm, + closeForm, + avatarInit, + addContact + } = this.props; + const { img } = this.state; + const branch = ''; + return ( +
+ + addContact()} className={classes.addBtn}> + + + + + + +
+ ); + } +} + +AddContact.propTypes = { + classes: PropTypes.object.isRequired, + submit: PropTypes.func.isRequired, + addContact: PropTypes.func.isRequired, + openForm: PropTypes.bool.isRequired, + avatarInit: PropTypes.string.isRequired, + closeForm: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(AddContact); diff --git a/front/odiparpack/app/components/Contact/AddContactForm.js b/front/odiparpack/app/components/Contact/AddContactForm.js new file mode 100644 index 0000000..0b51684 --- /dev/null +++ b/front/odiparpack/app/components/Contact/AddContactForm.js @@ -0,0 +1,273 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Dropzone from 'react-dropzone'; +import { withStyles } from '@material-ui/core/styles'; +import Type from 'ba-styles/Typography.scss'; +import PhotoCamera from '@material-ui/icons/PhotoCamera'; +import { connect } from 'react-redux'; +import { reduxForm, Field } from 'redux-form/immutable'; +import PermContactCalendar from '@material-ui/icons/PermContactCalendar'; +import Bookmark from '@material-ui/icons/Bookmark'; +import LocalPhone from '@material-ui/icons/LocalPhone'; +import Email from '@material-ui/icons/Email'; +import Smartphone from '@material-ui/icons/Smartphone'; +import LocationOn from '@material-ui/icons/LocationOn'; +import Work from '@material-ui/icons/Work'; +import Language from '@material-ui/icons/Language'; +import css from 'ba-styles/Form.scss'; +import { Button, Avatar, IconButton, Typography, Tooltip, InputAdornment } from '@material-ui/core'; +import { TextFieldRedux } from '../Forms/ReduxFormMUI'; +import styles from './contact-jss'; + + +// validation functions +const required = value => (value == null ? 'Required' : undefined); +const email = value => ( + value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) + ? 'Invalid email' + : undefined +); + +class AddContactForm extends React.Component { + saveRef = ref => { + this.ref = ref; + return this.ref; + }; + + render() { + const { + classes, + reset, + pristine, + submitting, + handleSubmit, + onDrop, + imgAvatar + } = this.props; + let dropzoneRef; + const acceptedFiles = ['image/jpeg', 'image/png', 'image/bmp']; + const fileSizeLimit = 300000; + const imgPreview = img => { + if (typeof img !== 'string' && img !== '') { + return URL.createObjectURL(imgAvatar); + } + return img; + }; + return ( +
+
+
+
+ Upload Avatar + { dropzoneRef = node; }} + > + {({ getRootProps, getInputProps }) => ( +
+ +
+ )} +
+
+ + + { + dropzoneRef.open(); + }} + > + + + +
+
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+ + + + ) + }} + /> +
+
+
+ + +
+
+
+ ); + } +} + +AddContactForm.propTypes = { + classes: PropTypes.object.isRequired, + handleSubmit: PropTypes.func.isRequired, + reset: PropTypes.func.isRequired, + onDrop: PropTypes.func.isRequired, + pristine: PropTypes.bool.isRequired, + submitting: PropTypes.bool.isRequired, + imgAvatar: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired, +}; + +const AddContactFormRedux = reduxForm({ + form: 'immutableAddContact', + enableReinitialize: true, +})(AddContactForm); + +const AddContactInit = connect( + state => ({ + initialValues: state.getIn(['contact', 'formValues']) + }) +)(AddContactFormRedux); + +export default withStyles(styles)(AddContactInit); diff --git a/front/odiparpack/app/components/Contact/ContactDetail.js b/front/odiparpack/app/components/Contact/ContactDetail.js new file mode 100644 index 0000000..f6d2dfc --- /dev/null +++ b/front/odiparpack/app/components/Contact/ContactDetail.js @@ -0,0 +1,195 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import classNames from 'classnames'; +import Edit from '@material-ui/icons/Edit'; +import Star from '@material-ui/icons/Star'; +import StarBorder from '@material-ui/icons/StarBorder'; +import MoreVertIcon from '@material-ui/icons/MoreVert'; +import LocalPhone from '@material-ui/icons/LocalPhone'; +import Email from '@material-ui/icons/Email'; +import Smartphone from '@material-ui/icons/Smartphone'; +import LocationOn from '@material-ui/icons/LocationOn'; +import Work from '@material-ui/icons/Work'; +import Language from '@material-ui/icons/Language'; +import { + List, + ListItem, + ListItemText, + ListItemAvatar, + Avatar, + Menu, + MenuItem, + IconButton, + Typography, + Divider, +} from '@material-ui/core'; +import styles from './contact-jss'; + + +const optionsOpt = [ + 'Block Contact', + 'Delete Contact', + 'Option 1', + 'Option 2', + 'Option 3', +]; + +const ITEM_HEIGHT = 48; + +class ContactDetail extends React.Component { + state = { + anchorElOpt: null, + }; + + handleClickOpt = event => { + this.setState({ anchorElOpt: event.currentTarget }); + }; + + handleCloseOpt = () => { + this.setState({ anchorElOpt: null }); + }; + + deleteContact = (item) => { + this.props.remove(item); + this.setState({ anchorElOpt: null }); + } + + render() { + const { + classes, + dataContact, + itemSelected, + edit, + favorite, + showMobileDetail + } = this.props; + const { anchorElOpt } = this.state; + return ( +
+
+
+ favorite(dataContact.get(itemSelected))}> + {dataContact.getIn([itemSelected, 'favorited']) ? () : } + + edit(dataContact.get(itemSelected))}> + + + + + + + {optionsOpt.map(option => { + if (option === 'Delete Contact') { + return ( + this.deleteContact(dataContact.get(itemSelected))}> + {option} + + ); + } + return ( + + {option} + + ); + })} + +
+ + + {dataContact.getIn([itemSelected, 'name'])} + + {dataContact.getIn([itemSelected, 'title'])} + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ ); + } +} + +ContactDetail.propTypes = { + classes: PropTypes.object.isRequired, + showMobileDetail: PropTypes.bool.isRequired, + dataContact: PropTypes.object.isRequired, + itemSelected: PropTypes.number.isRequired, + edit: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + favorite: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(ContactDetail); diff --git a/front/odiparpack/app/components/Contact/ContactHeader.js b/front/odiparpack/app/components/Contact/ContactHeader.js new file mode 100644 index 0000000..f17a1a4 --- /dev/null +++ b/front/odiparpack/app/components/Contact/ContactHeader.js @@ -0,0 +1,62 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import ArrowBack from '@material-ui/icons/ArrowBack'; +import PermContactCalendar from '@material-ui/icons/PermContactCalendar'; +import Add from '@material-ui/icons/Add'; +import { AppBar, Toolbar, Typography, Button, IconButton } from '@material-ui/core'; +import styles from './contact-jss'; + + +class ContactHeader extends React.Component { + render() { + const { + classes, + addContact, + total, + hideDetail, + showMobileDetail + } = this.props; + return ( + + + {showMobileDetail && ( + hideDetail()} + className={classes.navIconHide} + > + + + )} + + + {' '} +Contacts ( + {total} +) + + + + + ); + } +} + +ContactHeader.propTypes = { + classes: PropTypes.object.isRequired, + showMobileDetail: PropTypes.bool.isRequired, + addContact: PropTypes.func.isRequired, + hideDetail: PropTypes.func.isRequired, + total: PropTypes.number.isRequired, +}; + +export default withStyles(styles)(ContactHeader); diff --git a/front/odiparpack/app/components/Contact/ContactList.js b/front/odiparpack/app/components/Contact/ContactList.js new file mode 100644 index 0000000..545687d --- /dev/null +++ b/front/odiparpack/app/components/Contact/ContactList.js @@ -0,0 +1,112 @@ +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import classNames from 'classnames'; +import SearchIcon from '@material-ui/icons/Search'; +import PermContactCalendar from '@material-ui/icons/PermContactCalendar'; +import Star from '@material-ui/icons/Star'; +import { + Drawer, + Divider, + List, + ListItem, + ListItemText, + ListItemAvatar, + Avatar, + BottomNavigation, + BottomNavigationAction, +} from '@material-ui/core'; +import styles from './contact-jss'; + + +class ContactList extends React.Component { + state = { + filter: 'all', + }; + + handleChange = (event, value) => { + this.setState({ filter: value }); + }; + + render() { + const { + classes, + dataContact, + itemSelected, + showDetail, + search, + keyword, + clippedRight + } = this.props; + const { filter } = this.state; + const favoriteData = dataContact.filter(item => item.get('favorited') === true); + const getItem = dataArray => dataArray.map(data => { + const index = dataContact.indexOf(data); + if (data.get('name').toLowerCase().indexOf(keyword) === -1) { + return false; + } + return ( + showDetail(data)} + > + + + + + + ); + }); + return ( + + +
+
+
+
+
+ +
+ search(event)} placeholder="Search Contact" /> +
+
+
+ + + {filter === 'all' ? getItem(dataContact) : getItem(favoriteData)} + +
+
+ + } /> + } /> + +
+ ); + } +} + +ContactList.propTypes = { + classes: PropTypes.object.isRequired, + dataContact: PropTypes.object.isRequired, + keyword: PropTypes.string.isRequired, + itemSelected: PropTypes.number.isRequired, + showDetail: PropTypes.func.isRequired, + search: PropTypes.func.isRequired, + clippedRight: PropTypes.bool, +}; + +ContactList.defaultProps = { + clippedRight: false +}; + +export default withStyles(styles)(ContactList); diff --git a/front/odiparpack/app/components/Contact/contact-jss.js b/front/odiparpack/app/components/Contact/contact-jss.js new file mode 100644 index 0000000..6745527 --- /dev/null +++ b/front/odiparpack/app/components/Contact/contact-jss.js @@ -0,0 +1,282 @@ +import { amber, blue, deepPurple as purple, teal, brown, red } from '@material-ui/core/colors'; + +const drawerWidth = 240; +const drawerHeight = 630; + +const styles = theme => ({ + root: { + flexGrow: 1, + height: drawerHeight, + zIndex: 1, + overflow: 'hidden', + position: 'relative', + [theme.breakpoints.up('sm')]: { + display: 'flex', + }, + borderRadius: 2, + boxShadow: theme.shadows[2] + }, + addBtn: { + position: 'fixed', + bottom: 30, + right: 30, + zIndex: 100 + }, + appBar: { + zIndex: theme.zIndex.drawer + 1, + background: theme.palette.secondary.main, + height: 64, + display: 'flex', + justifyContent: 'center', + '& $avatar': { + marginRight: 10 + }, + '& h2': { + flex: 1 + }, + '& $button': { + color: theme.palette.common.white + } + }, + button: { + [theme.breakpoints.down('sm')]: { + display: 'none' + }, + }, + online: { + background: '#CDDC39' + }, + bussy: { + background: '#EF5350' + }, + idle: { + background: '#FFC107' + }, + offline: { + background: '#9E9E9E' + }, + status: { + padding: '2px 6px', + '& span': { + borderRadius: '50%', + display: 'inline-block', + marginRight: 2, + width: 10, + height: 10, + border: `1px solid ${theme.palette.common.white}` + } + }, + appBarShift: { + marginLeft: 0, + width: '100%', + transition: theme.transitions.create(['width', 'margin'], { + easing: theme.transitions.easing.sharp, + duration: theme.transitions.duration.enteringScreen, + }), + [theme.breakpoints.up('md')]: { + marginLeft: drawerWidth, + width: `calc(100% - ${drawerWidth}px)`, + }, + }, + drawerPaper: { + [theme.breakpoints.up('sm')]: { + width: drawerWidth, + }, + position: 'relative', + paddingBottom: 65, + height: drawerHeight, + }, + clippedRight: {}, + toolbar: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: 8, + position: 'relative', + '&$clippedRight': { + marginTop: 66 + } + }, + content: { + flexGrow: 1, + paddingTop: 64, + backgroundColor: theme.palette.background.paper, + }, + detailPopup: { + [theme.breakpoints.down('xs')]: { + position: 'absolute', + top: 0, + left: 0, + zIndex: 1200, + width: '100%', + overflow: 'auto', + height: 'calc(100% - 50px)' + } + }, + title: { + display: 'flex', + flex: 1, + '& svg': { + marginRight: 5 + } + }, + flex: { + flex: 1, + }, + searchWrapper: { + fontFamily: theme.typography.fontFamily, + position: 'relative', + borderRadius: 2, + display: 'block', + background: theme.palette.grey[100] + }, + search: { + width: 'auto', + height: '100%', + top: 0, + left: 20, + position: 'absolute', + pointerEvents: 'none', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + input: { + font: 'inherit', + padding: `${theme.spacing(1)}px ${theme.spacing(1)}px ${theme.spacing(1)}px ${theme.spacing(6)}px`, + border: 0, + display: 'block', + verticalAlign: 'middle', + whiteSpace: 'normal', + background: 'none', + margin: 0, // Reset for Safari + color: 'inherit', + width: '100%', + '&:focus': { + outline: 0, + }, + }, + bottomFilter: { + position: 'absolute', + width: '100%', + [theme.breakpoints.up('sm')]: { + width: 240, + }, + zIndex: 2000, + bottom: 0, + left: 0, + background: theme.palette.grey[100], + borderTop: `1px solid ${theme.palette.grey[300]}`, + borderRight: `1px solid ${theme.palette.grey[300]}`, + }, + avatar: {}, + userName: { + textAlign: 'left' + }, + cover: { + padding: 20, + height: 130, + position: 'relative', + background: theme.palette.primary.light, + width: '100%', + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', + '& $avatar': { + boxShadow: theme.shadows[4], + width: 100, + height: 100, + marginRight: 20 + }, + }, + opt: { + position: 'absolute', + top: 10, + right: 10, + }, + favorite: { + color: amber[500] + }, + redIcon: { + background: red[50], + '& svg': { + color: red[500] + } + }, + brownIcon: { + background: brown[50], + '& svg': { + color: brown[500] + } + }, + tealIcon: { + background: teal[50], + '& svg': { + color: teal[500] + } + }, + blueIcon: { + background: blue[50], + '& svg': { + color: blue[500] + } + }, + amberIcon: { + background: amber[50], + '& svg': { + color: amber[500] + } + }, + purpleIcon: { + background: purple[50], + '& svg': { + color: purple[500] + } + }, + field: { + width: '100%', + marginBottom: 20, + '& svg': { + color: theme.palette.grey[400], + fontSize: 18, + } + }, + uploadAvatar: { + width: '100%', + height: '100%', + background: theme.palette.grey[200], + boxShadow: theme.shadows[4], + }, + selected: { + background: theme.palette.secondary.light, + borderLeft: `2px solid ${theme.palette.secondary.main}`, + paddingLeft: 22, + '& h3': { + color: theme.palette.secondary.dark + } + }, + hiddenDropzone: { + display: 'none' + }, + avatarWrap: { + width: 100, + height: 100, + margin: '10px auto 30px', + position: 'relative' + }, + buttonUpload: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)' + }, + navIconHide: { + marginRight: theme.spacing(1), + [theme.breakpoints.up('sm')]: { + display: 'none' + } + } +}); + +export default styles; -- cgit v1.2.3