diff options
| author | Dayana31 <[email protected]> | 2022-04-21 17:27:08 -0500 |
|---|---|---|
| committer | Dayana31 <[email protected]> | 2022-04-21 17:27:08 -0500 |
| commit | 67c50667678dd0ce4709b29a854f6a47093a1ac5 (patch) | |
| tree | b6f9f39092ad54bf6b815984d32b37d7c7ca67ab /front/odiparpack/app/containers/Pages | |
| parent | 91140b24f0d49a9f89a080ee063e9eb023a4b73a (diff) | |
| parent | e13e630cd6e4fc0b1ff92098a28a770794c7bb9a (diff) | |
| download | DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.gz DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.tar.bz2 DP1_project-67c50667678dd0ce4709b29a854f6a47093a1ac5.zip | |
Merge branch 'gabshr' into dayana
Diffstat (limited to 'front/odiparpack/app/containers/Pages')
25 files changed, 2269 insertions, 0 deletions
diff --git a/front/odiparpack/app/containers/Pages/.DS_Store b/front/odiparpack/app/containers/Pages/.DS_Store Binary files differnew file mode 100644 index 0000000..f59225b --- /dev/null +++ b/front/odiparpack/app/containers/Pages/.DS_Store diff --git a/front/odiparpack/app/containers/Pages/BlankPage/index.js b/front/odiparpack/app/containers/Pages/BlankPage/index.js new file mode 100644 index 0000000..640da6e --- /dev/null +++ b/front/odiparpack/app/containers/Pages/BlankPage/index.js @@ -0,0 +1,28 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import { PapperBlock } from 'ba-components'; + +class BlankPage extends React.Component { + render() { + const title = brand.name + ' - Blank Page'; + const description = brand.desc; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <PapperBlock title="Blank Page" desc="Some text description"> + Content + </PapperBlock> + </div> + ); + } +} + +export default BlankPage; diff --git a/front/odiparpack/app/containers/Pages/Calendar/index.js b/front/odiparpack/app/containers/Pages/Calendar/index.js new file mode 100644 index 0000000..fd5f412 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Calendar/index.js @@ -0,0 +1,137 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import events from 'ba-api/eventData'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import 'ba-styles/vendors/react-big-calendar/react-big-calendar.css'; +import { EventCalendar, DetailEvent, AddEvent, Notification } from 'ba-components'; +import { + fetchAction, + addAction, + discardAction, + submitAction, + deleteAction, + closeNotifAction +} from 'ba-actions/CalendarEventActions'; + +const styles = { + root: { + display: 'block' + } +}; + +class Calendar extends React.Component { + state = { + anchorEl: false, + event: null, + anchorPos: { top: 0, left: 0 } + }; + + componentDidMount() { + this.props.fetchEventsData(events); + } + + handleClick = event => { + setTimeout(() => { + const target = document.getElementsByClassName('rbc-selected')[0]; + const targetBounding = target.getBoundingClientRect(); + this.setState({ + event, + anchorEl: true, + anchorPos: { top: targetBounding.top, left: targetBounding.left } + }); + }, 200); + }; + + handleClose = () => { + this.setState({ + anchorEl: false, + }); + }; + + render() { + const title = brand.name + ' - Calendar'; + const description = brand.desc; + const { anchorEl, anchorPos, event } = this.state; + const { + classes, + eventData, + openFrm, + addEvent, + discardEvent, + submit, + remove, + closeNotif, + messageNotif + } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Notification close={() => closeNotif()} message={messageNotif} /> + <div className={classes.root}> + <EventCalendar events={eventData.toJS()} handleEventClick={this.handleClick} /> + <DetailEvent + event={event} + anchorEl={anchorEl} + anchorPos={anchorPos} + close={this.handleClose} + remove={remove} + /> + <AddEvent + openForm={openFrm} + addEvent={addEvent} + closeForm={discardEvent} + submit={submit} + /> + </div> + </div> + ); + } +} + +Calendar.propTypes = { + classes: PropTypes.object.isRequired, + eventData: PropTypes.object.isRequired, + fetchEventsData: PropTypes.func.isRequired, + addEvent: PropTypes.func.isRequired, + submit: PropTypes.func.isRequired, + discardEvent: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + openFrm: PropTypes.bool.isRequired, + closeNotif: PropTypes.func.isRequired, + messageNotif: PropTypes.string.isRequired, +}; + +const reducer = 'calendar'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + eventData: state.getIn([reducer, 'events']), + openFrm: state.getIn([reducer, 'openFrm']), + messageNotif: state.getIn([reducer, 'notifMsg']), +}); + +const constDispatchToProps = dispatch => ({ + fetchEventsData: bindActionCreators(fetchAction, dispatch), + submit: bindActionCreators(submitAction, dispatch), + remove: bindActionCreators(deleteAction, dispatch), + addEvent: () => dispatch(addAction), + discardEvent: () => dispatch(discardAction), + closeNotif: () => dispatch(closeNotifAction), +}); + +const CalendarMapped = connect( + mapStateToProps, + constDispatchToProps +)(Calendar); + +export default withStyles(styles)(CalendarMapped); diff --git a/front/odiparpack/app/containers/Pages/Chat/index.js b/front/odiparpack/app/containers/Pages/Chat/index.js new file mode 100644 index 0000000..99cf875 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Chat/index.js @@ -0,0 +1,123 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import contactData from 'ba-api/contactData'; +import chatData from 'ba-api/chatData'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import { fetchAction, searchAction } from 'ba-actions/ContactActions'; +import { + fetchChatAction, + showChatAction, + sendAction, + hideDetailAction, + deleteAction +} from 'ba-actions/ChatActions'; +import { ContactList, ChatHeader, ChatRoom } from 'ba-components'; +import styles from 'ba-components/Contact/contact-jss'; + +class Chat extends React.Component { + componentDidMount() { + this.props.fetchChatData(chatData); + this.props.fetchContactData(contactData); + } + + render() { + const title = brand.name + ' - Chat App'; + const description = brand.desc; + const { + classes, + dataContact, + showDetail, + hideDetail, + keyword, + search, + dataChat, + chatSelected, + sendMessage, + remove, + showMobileDetail + } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.root}> + <ChatHeader + dataContact={dataContact} + chatSelected={chatSelected} + remove={remove} + showMobileDetail={showMobileDetail} + hideDetail={hideDetail} + /> + <ContactList + itemSelected={chatSelected} + dataContact={dataContact} + showDetail={showDetail} + search={search} + keyword={keyword} + /> + <ChatRoom + showMobileDetail={showMobileDetail} + dataChat={dataChat} + chatSelected={chatSelected} + dataContact={dataContact} + sendMessage={sendMessage} + /> + </div> + </div> + ); + } +} + +Chat.propTypes = { + classes: PropTypes.object.isRequired, + fetchContactData: PropTypes.func.isRequired, + fetchChatData: PropTypes.func.isRequired, + showDetail: PropTypes.func.isRequired, + hideDetail: PropTypes.func.isRequired, + sendMessage: PropTypes.func.isRequired, + search: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + keyword: PropTypes.string.isRequired, + dataContact: PropTypes.object.isRequired, + dataChat: PropTypes.object.isRequired, + chatSelected: PropTypes.number.isRequired, + showMobileDetail: PropTypes.bool.isRequired, +}; + +const reducerContact = 'contact'; +const reducerChat = 'chat'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + dataContact: state.getIn([reducerContact, 'contactList']), + dataChat: state.getIn([reducerChat, 'activeChat']), + chatSelected: state.getIn([reducerChat, 'chatSelected']), + showMobileDetail: state.getIn([reducerChat, 'showMobileDetail']), + keyword: state.getIn([reducerContact, 'keywordValue']), +}); + +const dispatchToProps = dispatch => ({ + fetchContactData: bindActionCreators(fetchAction, dispatch), + hideDetail: () => dispatch(hideDetailAction), + fetchChatData: bindActionCreators(fetchChatAction, dispatch), + showDetail: bindActionCreators(showChatAction, dispatch), + search: bindActionCreators(searchAction, dispatch), + sendMessage: bindActionCreators(sendAction, dispatch), + remove: () => dispatch(deleteAction), +}); + +const ChatMapped = connect( + mapStateToProps, + dispatchToProps +)(Chat); + +export default withStyles(styles)(ChatMapped); diff --git a/front/odiparpack/app/containers/Pages/Contact/index.js b/front/odiparpack/app/containers/Pages/Contact/index.js new file mode 100644 index 0000000..8ed34de --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Contact/index.js @@ -0,0 +1,166 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import data from 'ba-api/contactData'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import dummy from 'ba-api/dummyContents'; +import { + fetchAction, + showDetailAction, + hideDetailAction, + submitAction, + editAction, + addAction, + closeAction, + removeAction, + addToFavoriteAction, + searchAction, + closeNotifAction +} from 'ba-actions/ContactActions'; +import { + ContactHeader, + ContactList, + ContactDetail, + AddContact, + Notification +} from 'ba-components'; +import styles from 'ba-components/Contact/contact-jss'; + +class Contact extends React.Component { + componentDidMount() { + this.props.fetchData(data); + } + + submitContact = (item, avatar) => { + const { submit } = this.props; + const avatarBase64 = typeof avatar === 'object' ? URL.createObjectURL(avatar) : avatar; + const avatarPreview = avatar !== null ? avatarBase64 : dummy.user.avatar; + submit(item, avatarPreview); + } + + render() { + const title = brand.name + ' - Contact'; + const description = brand.desc; + const { + classes, + dataContact, + itemSelected, + showDetail, + hideDetail, + avatarInit, + open, + showMobileDetail, + add, + edit, + close, + remove, + favorite, + keyword, + search, + closeNotif, + messageNotif + } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Notification close={() => closeNotif()} message={messageNotif} /> + <div className={classes.root}> + <ContactHeader + hideDetail={hideDetail} + addContact={add} + total={dataContact.size} + showMobileDetail={showMobileDetail} + /> + <ContactList + clippedRight + itemSelected={itemSelected} + dataContact={dataContact} + showDetail={showDetail} + search={search} + keyword={keyword} + /> + <ContactDetail + showMobileDetail={showMobileDetail} + dataContact={dataContact} + itemSelected={itemSelected} + edit={edit} + remove={remove} + favorite={favorite} + /> + </div> + <AddContact + addContact={add} + openForm={open} + closeForm={close} + submit={this.submitContact} + avatarInit={avatarInit} + /> + </div> + ); + } +} + +Contact.propTypes = { + classes: PropTypes.object.isRequired, + avatarInit: PropTypes.string.isRequired, + fetchData: PropTypes.func.isRequired, + showDetail: PropTypes.func.isRequired, + hideDetail: PropTypes.func.isRequired, + keyword: PropTypes.string.isRequired, + open: PropTypes.bool.isRequired, + showMobileDetail: PropTypes.bool.isRequired, + add: PropTypes.func.isRequired, + close: PropTypes.func.isRequired, + submit: PropTypes.func.isRequired, + edit: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + favorite: PropTypes.func.isRequired, + search: PropTypes.func.isRequired, + dataContact: PropTypes.object.isRequired, + itemSelected: PropTypes.number.isRequired, + closeNotif: PropTypes.func.isRequired, + messageNotif: PropTypes.string.isRequired, +}; + +const reducer = 'contact'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + avatarInit: state.getIn([reducer, 'avatarInit']), + dataContact: state.getIn([reducer, 'contactList']), + itemSelected: state.getIn([reducer, 'selectedIndex']), + keyword: state.getIn([reducer, 'keywordValue']), + open: state.getIn([reducer, 'openFrm']), + showMobileDetail: state.getIn([reducer, 'showMobileDetail']), + messageNotif: state.getIn([reducer, 'notifMsg']), +}); + +const constDispatchToProps = dispatch => ({ + fetchData: bindActionCreators(fetchAction, dispatch), + showDetail: bindActionCreators(showDetailAction, dispatch), + hideDetail: () => dispatch(hideDetailAction), + submit: bindActionCreators(submitAction, dispatch), + edit: bindActionCreators(editAction, dispatch), + add: () => dispatch(addAction), + close: () => dispatch(closeAction), + remove: bindActionCreators(removeAction, dispatch), + favorite: bindActionCreators(addToFavoriteAction, dispatch), + search: bindActionCreators(searchAction, dispatch), + closeNotif: () => dispatch(closeNotifAction), +}); + +const ContactMapped = connect( + mapStateToProps, + constDispatchToProps +)(Contact); + +export default withStyles(styles)(ContactMapped); diff --git a/front/odiparpack/app/containers/Pages/Ecommerce/index.js b/front/odiparpack/app/containers/Pages/Ecommerce/index.js new file mode 100644 index 0000000..8eb15a4 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Ecommerce/index.js @@ -0,0 +1,117 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import data from 'ba-api/productData'; +import { SearchProduct, ProductGallery, Notification } from 'ba-components'; +import { + fetchAction, + addAction, + removeAction, + checkoutAction, + detailAction, + searchAction, + closeNotifAction +} from 'ba-actions/EcommerceActions'; + +class Ecommerce extends React.Component { + componentDidMount() { + this.props.fetchData(data); + } + + render() { + const title = brand.name + ' - Ecommerce'; + const description = brand.desc; + const { + dataProduct, + handleAddToCart, + dataCart, + removeItem, + checkout, + showDetail, + productIndex, + totalItems, + totalPrice, + search, + keyword, + closeNotif, + messageNotif + } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Notification close={() => closeNotif()} message={messageNotif} /> + <SearchProduct + dataCart={dataCart} + removeItem={removeItem} + checkout={checkout} + totalItems={totalItems} + totalPrice={totalPrice} + search={search} + /> + <ProductGallery + dataProduct={dataProduct} + showDetail={showDetail} + handleAddToCart={handleAddToCart} + productIndex={productIndex} + keyword={keyword} + /> + </div> + ); + } +} + +Ecommerce.propTypes = { + fetchData: PropTypes.func.isRequired, + handleAddToCart: PropTypes.func.isRequired, + removeItem: PropTypes.func.isRequired, + showDetail: PropTypes.func.isRequired, + checkout: PropTypes.func.isRequired, + search: PropTypes.func.isRequired, + keyword: PropTypes.string.isRequired, + dataProduct: PropTypes.object.isRequired, + dataCart: PropTypes.object.isRequired, + productIndex: PropTypes.number.isRequired, + totalItems: PropTypes.number.isRequired, + totalPrice: PropTypes.number.isRequired, + closeNotif: PropTypes.func.isRequired, + messageNotif: PropTypes.string.isRequired, +}; + +const reducer = 'ecommerce'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + keyword: state.getIn([reducer, 'keywordValue']), + dataProduct: state.getIn([reducer, 'productList']), + dataCart: state.getIn([reducer, 'cart']), + productIndex: state.getIn([reducer, 'productIndex']), + totalItems: state.getIn([reducer, 'totalItems']), + totalPrice: state.getIn([reducer, 'totalPrice']), + messageNotif: state.getIn([reducer, 'notifMsg']), +}); + +const constDispatchToProps = dispatch => ({ + fetchData: bindActionCreators(fetchAction, dispatch), + search: bindActionCreators(searchAction, dispatch), + handleAddToCart: bindActionCreators(addAction, dispatch), + removeItem: bindActionCreators(removeAction, dispatch), + showDetail: bindActionCreators(detailAction, dispatch), + checkout: () => dispatch(checkoutAction), + closeNotif: () => dispatch(closeNotifAction), +}); + +const EcommerceMapped = connect( + mapStateToProps, + constDispatchToProps +)(Ecommerce); + +export default EcommerceMapped; diff --git a/front/odiparpack/app/containers/Pages/Email/index.js b/front/odiparpack/app/containers/Pages/Email/index.js new file mode 100644 index 0000000..93285cb --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Email/index.js @@ -0,0 +1,210 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import data from 'ba-api/emailData'; +import { + EmailHeader, + EmailList, + EmailSidebar, + ComposeEmail, + Notification +} from 'ba-components'; +import { + fetchMailAction, + openMailAction, + filterAction, + composeAction, + discardAction, + searchAction, + sendAction, + moveAction, + deleteAction, + toggleStaredAction, + closeNotifAction +} from 'ba-actions/EmailActions'; + +const styles = theme => ({ + root: { + flexGrow: 1, + minHeight: 600, + zIndex: 1, + background: theme.palette.grey[50], + overflow: 'hidden', + display: 'flex', + boxShadow: theme.shadows[2] + } +}); + +// validation functions +const email = value => ( + value && !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value) + ? 'Invalid email' + : '' +); + +class Email extends React.Component { + state = { + to: '', + subject: '', + validMail: '', + mobileOpen: false, + }; + + componentDidMount() { + this.props.fetchData(data); + } + + handleChange = (event, name) => { + if (name === 'to') { + this.setState({ validMail: email(event.target.value) }); + } + this.setState({ + [name]: event.target.value, + }); + }; + + handleReply = (mail) => { + this.props.compose(); + this.setState({ + to: mail.get('name'), + subject: 'Reply: ' + mail.get('subject'), + }); + } + + handleCompose = () => { + this.props.compose(); + this.setState({ + to: ' ', + subject: ' ', + }); + } + + handleDrawerToggle = () => { + this.setState(state => ({ mobileOpen: !state.mobileOpen })); + }; + + render() { + const { + classes, + emailData, + openMail, + goto, + currentPage, + openFrm, + discard, + search, + keyword, + sendEmail, + moveTo, + remove, + toggleStar, + closeNotif, + messageNotif + } = this.props; + const { + to, + subject, + validMail, + mobileOpen + } = this.state; + const title = brand.name + ' - Email'; + const description = brand.desc; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Notification close={() => closeNotif()} message={messageNotif} /> + <EmailHeader search={search} handleDrawerToggle={this.handleDrawerToggle} /> + <EmailSidebar + compose={this.handleCompose} + goto={goto} + selected={currentPage} + handleDrawerToggle={this.handleDrawerToggle} + mobileOpen={mobileOpen} + /> + <EmailList + emailData={emailData} + openMail={openMail} + filterPage={currentPage} + keyword={keyword} + moveTo={moveTo} + remove={remove} + toggleStar={toggleStar} + reply={this.handleReply} + /> + <ComposeEmail + to={to} + subject={subject} + compose={this.handleCompose} + validMail={validMail} + sendEmail={sendEmail} + inputChange={this.handleChange} + open={openFrm} + closeForm={discard} + /> + </div> + ); + } +} + +Email.propTypes = { + classes: PropTypes.object.isRequired, + emailData: PropTypes.object.isRequired, + fetchData: PropTypes.func.isRequired, + openMail: PropTypes.func.isRequired, + goto: PropTypes.func.isRequired, + compose: PropTypes.func.isRequired, + discard: PropTypes.func.isRequired, + search: PropTypes.func.isRequired, + sendEmail: PropTypes.func.isRequired, + moveTo: PropTypes.func.isRequired, + remove: PropTypes.func.isRequired, + toggleStar: PropTypes.func.isRequired, + keyword: PropTypes.string.isRequired, + currentPage: PropTypes.string.isRequired, + openFrm: PropTypes.bool.isRequired, + closeNotif: PropTypes.func.isRequired, + messageNotif: PropTypes.string.isRequired, +}; + +const reducer = 'email'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + keyword: state.getIn([reducer, 'keywordValue']), + initValues: state.getIn([reducer, 'formValues']), + emailData: state.getIn([reducer, 'inbox']), + currentPage: state.getIn([reducer, 'currentPage']), + openFrm: state.getIn([reducer, 'openFrm']), + messageNotif: state.getIn([reducer, 'notifMsg']), +}); + +const constDispatchToProps = dispatch => ({ + fetchData: bindActionCreators(fetchMailAction, dispatch), + openMail: bindActionCreators(openMailAction, dispatch), + goto: bindActionCreators(filterAction, dispatch), + search: bindActionCreators(searchAction, dispatch), + moveTo: bindActionCreators(moveAction, dispatch), + remove: bindActionCreators(deleteAction, dispatch), + toggleStar: bindActionCreators(toggleStaredAction, dispatch), + compose: () => dispatch(composeAction), + discard: () => dispatch(discardAction), + sendEmail: bindActionCreators(sendAction, dispatch), + closeNotif: () => dispatch(closeNotifAction), +}); + +const EmailMapped = connect( + mapStateToProps, + constDispatchToProps +)(Email); + +export default withStyles(styles)(EmailMapped); diff --git a/front/odiparpack/app/containers/Pages/Error/index.js b/front/odiparpack/app/containers/Pages/Error/index.js new file mode 100644 index 0000000..b408b53 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Error/index.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import { Route } from 'react-router-dom'; +import { ErrorWrap } from 'ba-components'; + +const title = brand.name + ' - Aplication Error'; +const description = brand.desc; + +const Error = () => ( + <Route + render={({ staticContext }) => { + if (staticContext) { + staticContext.status = 404; // eslint-disable-line + } + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <ErrorWrap title="500" desc="Sorry, server goes wrong" /> + </div> + ); + }} + /> +); + +export default Error; diff --git a/front/odiparpack/app/containers/Pages/HelpSupport/ContactForm.js b/front/odiparpack/app/containers/Pages/HelpSupport/ContactForm.js new file mode 100644 index 0000000..2568943 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/HelpSupport/ContactForm.js @@ -0,0 +1,115 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { Field, reduxForm } from 'redux-form/immutable'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import { PapperBlock } from 'ba-components'; +import { initAction, clearAction } from 'ba-actions/ReduxFormActions'; +import { TextFieldRedux } from 'ba-components/Forms/ReduxFormMUI'; +import { Button } from '@material-ui/core'; +import styles from './helpSupport-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 ContactForm extends Component { + render() { + const trueBool = true; + const { + classes, + handleSubmit, + pristine, + reset, + submitting, + } = this.props; + return ( + <div className={classes.frmWrap}> + <PapperBlock title="Contact Us" desc="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse sed urna in justo euismod condimentum."> + <form onSubmit={handleSubmit}> + <div> + <Field + name="name" + component={TextFieldRedux} + placeholder="Name" + label="Name" + validate={required} + required + ref={this.saveRef} + className={classes.field} + /> + </div> + <div> + <Field + name="email" + component={TextFieldRedux} + placeholder="Email Field" + label="Email" + required + validate={[required, email]} + className={classes.field} + /> + </div> + <div className={classes.field}> + <Field + name="message" + className={classes.field} + component={TextFieldRedux} + validate={required} + placeholder="Message" + label="Message" + multiline={trueBool} + rows={4} + /> + </div> + <div> + <Button variant="contained" color="secondary" type="submit" disabled={submitting}> + Submit + </Button> + <Button + type="button" + disabled={pristine || submitting} + onClick={reset} + > + Reset + </Button> + </div> + </form> + </PapperBlock> + </div> + ); + } +} + +ContactForm.propTypes = { + classes: PropTypes.object.isRequired, + handleSubmit: PropTypes.func.isRequired, + reset: PropTypes.func.isRequired, + pristine: PropTypes.bool.isRequired, + submitting: PropTypes.bool.isRequired, +}; + +const mapDispatchToProps = dispatch => ({ + init: bindActionCreators(initAction, dispatch), + clear: () => dispatch(clearAction), +}); + +const ContactFormMapped = reduxForm({ + form: 'immutableExample', +})(ContactForm); + +const reducer = 'initval'; +const FormInit = connect( + state => ({ + force: state, + initialValues: state.getIn([reducer, 'formValues']) + }), + mapDispatchToProps, +)(ContactFormMapped); + +export default withStyles(styles)(FormInit); diff --git a/front/odiparpack/app/containers/Pages/HelpSupport/Qna.js b/front/odiparpack/app/containers/Pages/HelpSupport/Qna.js new file mode 100644 index 0000000..bb8a6ae --- /dev/null +++ b/front/odiparpack/app/containers/Pages/HelpSupport/Qna.js @@ -0,0 +1,141 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { ExpansionPanel, ExpansionPanelDetails, ExpansionPanelSummary, Typography } from '@material-ui/core'; +import styles from './helpSupport-jss'; + + +class Qna extends React.Component { + state = { + expanded: null, + }; + + handleChange = panel => (event, expanded) => { + this.setState({ + expanded: expanded ? panel : false, + }); + }; + + render() { + const { classes } = this.props; + const { expanded } = this.state; + + return ( + <div> + <ExpansionPanel expanded={expanded === 'panel1'} onChange={this.handleChange('panel1')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Pellentesque ac bibendum tortor?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Nulla facilisi. Phasellus sollicitudin nulla et quam mattis feugiat. Aliquam eget + maximus est, id dignissim quam. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel2'} onChange={this.handleChange('panel2')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Vivamus sit amet interdum elit?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Donec placerat, lectus sed mattis semper, neque lectus feugiat lectus, varius pulvinar + diam eros in elit. Pellentesque convallis laoreet laoreet. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel3'} onChange={this.handleChange('panel3')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Vestibulum nec mi suscipit?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas + eros, vitae egestas augue. Duis vel est augue. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel4'} onChange={this.handleChange('panel4')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Cras convallis lacus orci?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas + eros, vitae egestas augue. Duis vel est augue. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel5'} onChange={this.handleChange('panel5')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Quisque ut metus sit amet?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + enean sit amet magna vel magna fringilla fermentum. Donec sit amet nulla sed arcu pulvinar ultricies commodo id ligula. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel6'} onChange={this.handleChange('panel6')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Nulla vehicula leo ut augue tincidunt?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Curabitur egestas consequat lorem, vel fermentum augue porta id. Aliquam lobortis magna neque, gravida consequat velit venenatis at. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel7'} onChange={this.handleChange('panel7')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Vivamus sit amet interdum elit?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Donec dignissim, odio ac imperdiet luctus, ante nisl accumsan justo, et venenatis ante metus pellentesque sem. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel8'} onChange={this.handleChange('panel8')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Maecenas nisl libero, tincidunt id odio id?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Ut sed eros finibus, placerat orci id, dapibus mauris. Vestibulum consequat hendrerit lacus. In id nisi id neque venenatis molestie. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel9'} onChange={this.handleChange('panel9')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Vestibulum nec mi suscipit?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas + eros, vitae egestas augue. Duis vel est augue. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + <ExpansionPanel expanded={expanded === 'panel10'} onChange={this.handleChange('panel10')}> + <ExpansionPanelSummary expandIcon={<ExpandMoreIcon />}> + <Typography className={classes.heading}>Cras convallis lacus orci?</Typography> + </ExpansionPanelSummary> + <ExpansionPanelDetails> + <Typography> + Nunc vitae orci ultricies, auctor nunc in, volutpat nisl. Integer sit amet egestas + eros, vitae egestas augue. Duis vel est augue. + </Typography> + </ExpansionPanelDetails> + </ExpansionPanel> + </div> + ); + } +} + +Qna.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Qna); diff --git a/front/odiparpack/app/containers/Pages/HelpSupport/helpSupport-jss.js b/front/odiparpack/app/containers/Pages/HelpSupport/helpSupport-jss.js new file mode 100644 index 0000000..5c954cb --- /dev/null +++ b/front/odiparpack/app/containers/Pages/HelpSupport/helpSupport-jss.js @@ -0,0 +1,49 @@ +const styles = theme => ({ + title: { + display: 'block', + margin: `${theme.spacing(3)}px 0`, + color: theme.palette.common.white, + }, + iconTitle: { + position: 'relative', + top: theme.spacing(0.5), + marginRight: theme.spacing(0.5), + }, + heading: { + fontSize: theme.typography.pxToRem(15), + flexBasis: '100%', + fontWeight: 700, + flexShrink: 0, + }, + secondaryHeading: { + fontSize: theme.typography.pxToRem(15), + color: theme.palette.text.secondary, + }, + root: { + width: '100%', + flexGrow: 1, + padding: 30 + }, + field: { + width: '100%', + marginBottom: 20 + }, + fieldBasic: { + width: '100%', + marginBottom: 20, + marginTop: 10 + }, + inlineWrap: { + display: 'flex', + flexDirection: 'row' + }, + buttonInit: { + margin: theme.spacing(4), + textAlign: 'center' + }, + frmWrap: { + marginTop: theme.spacing(1) * -3 + } +}); + +export default styles; diff --git a/front/odiparpack/app/containers/Pages/HelpSupport/index.js b/front/odiparpack/app/containers/Pages/HelpSupport/index.js new file mode 100644 index 0000000..68df97b --- /dev/null +++ b/front/odiparpack/app/containers/Pages/HelpSupport/index.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import LiveHelp from '@material-ui/icons/LiveHelp'; +import { isWidthUp } from '@material-ui/core/withWidth'; +import { withStyles } from '@material-ui/core/styles'; +import { Typography, withWidth, Grid } from '@material-ui/core'; +import styles from './helpSupport-jss'; +import Qna from './Qna'; +import ContactForm from './ContactForm'; + + +class Settings extends React.Component { + showResult(values) { + setTimeout(() => { + this.setState({ valueForm: values }); + window.alert(`You submitted:\n\n${this.state.valueForm}`); + }, 500); // simulate server latency + } + + render() { + const title = brand.name; + const description = brand.desc; + const { classes, width } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Typography variant="h5" className={classes.title}> + <LiveHelp className={classes.iconTitle} /> + Help & Support + </Typography> + <Grid container spacing={2} direction={isWidthUp('md', width) ? 'row' : 'column-reverse'}> + <Grid item md={6} xs={12}> + <Qna /> + </Grid> + <Grid item md={6} xs={12}> + <ContactForm onSubmit={(values) => this.showResult(values)} /> + </Grid> + </Grid> + </div> + ); + } +} + +Settings.propTypes = { + classes: PropTypes.object.isRequired, + width: PropTypes.string.isRequired, +}; + +export default withStyles(styles)(withWidth()(Settings)); diff --git a/front/odiparpack/app/containers/Pages/Maintenance/index.js b/front/odiparpack/app/containers/Pages/Maintenance/index.js new file mode 100644 index 0000000..8771e51 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Maintenance/index.js @@ -0,0 +1,88 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Build from '@material-ui/icons/Build'; +import Settings from '@material-ui/icons/SettingsApplications'; +import Warning from '@material-ui/icons/Warning'; +import { Typography, Avatar, Hidden, Paper } from '@material-ui/core'; + +const styles = theme => ({ + root: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100%' + }, + paper: { + margin: 'auto', + padding: 40, + width: '90%', + [theme.breakpoints.up('sm')]: { + width: 600, + height: 300, + }, + textAlign: 'center' + }, + artwork: { + display: 'flex', + justifyContent: 'center', + marginBottom: 30 + }, + icon: { + margin: '10px 20px', + background: theme.palette.secondary.main, + color: theme.palette.common.white, + width: 100, + height: 100, + '& svg': { + fontSize: 64, + }, + }, +}); + +class Maintenance extends React.Component { + render() { + const title = brand.name + ' - Maintenance'; + const description = brand.desc; + const { classes } = this.props; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.container}> + <Paper className={classes.paper}> + <div className={classes.artwork}> + <Avatar className={classes.icon}><Build /></Avatar> + <Hidden xsDown> + <Avatar className={classes.icon}><Warning /></Avatar> + </Hidden> + <Hidden xsDown> + <Avatar className={classes.icon}><Settings /></Avatar> + </Hidden> + </div> + <Typography variant="h4" gutterBottom>Website under maintenance</Typography> + <Typography variant="subtitle1"> +Our website is under maintenance. We + {"'"} +ll be back shortly + </Typography> + </Paper> + </div> + </div> + ); + } +} + +Maintenance.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Maintenance); diff --git a/front/odiparpack/app/containers/Pages/Photos/index.js b/front/odiparpack/app/containers/Pages/Photos/index.js new file mode 100644 index 0000000..7068ed5 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Photos/index.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import imgData from 'ba-api/imgDataMasonry'; +import { PhotoGallery } from 'ba-components'; + +class Photos extends React.Component { + render() { + const title = brand.name + ' - Photo Gallery'; + const description = brand.desc; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <PhotoGallery imgData={imgData} /> + </div> + ); + } +} + +export default Photos; diff --git a/front/odiparpack/app/containers/Pages/Settings/DetailSettings.js b/front/odiparpack/app/containers/Pages/Settings/DetailSettings.js new file mode 100644 index 0000000..25bad64 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Settings/DetailSettings.js @@ -0,0 +1,203 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import classNames from 'classnames'; +import SettingsIcon from '@material-ui/icons/SettingsApplications'; +import CloseIcon from '@material-ui/icons/Close'; +import { withStyles } from '@material-ui/core/styles'; +import { + AppBar, + Grid, + Dialog, + Toolbar, + ListItemText, + ListItem, + List, + ListItemSecondaryAction, + Divider, + IconButton, + Typography, + Button, + Switch, + Slide, + InputLabel, + MenuItem, + FormControl, + Select, + Checkbox, + TextField, +} from '@material-ui/core'; +import styles from './settings-jss'; + + +const Transition = React.forwardRef(function Transition(props, ref) { // eslint-disable-line + return <Slide direction="up" ref={ref} {...props} />; +}); + +class DetailSettings extends React.Component { + state = { + checked: ['switch', 'check2'], + option: '', + }; + + handleToggle = value => () => { + const { checked } = this.state; + const currentIndex = checked.indexOf(value); + const newChecked = [...checked]; + + if (currentIndex === -1) { + newChecked.push(value); + } else { + newChecked.splice(currentIndex, 1); + } + + this.setState({ + checked: newChecked, + }); + }; + + handleChange = name => event => { + this.setState({ + [name]: event.target.value, + }); + }; + + handleChangeSelection = event => { + this.setState({ [event.target.name]: event.target.value }); + }; + + render() { + const { classes, open, handleClose } = this.props; + return ( + <Dialog + fullScreen + open={open} + onClose={handleClose} + TransitionComponent={Transition} + > + <AppBar className={classes.appBar}> + <Toolbar> + <IconButton color="inherit" onClick={handleClose} aria-label="Close"> + <CloseIcon /> + </IconButton> + <Typography variant="h6" color="inherit" className={classes.flex}> + Setting + </Typography> + <Button color="inherit" onClick={handleClose}> + done + </Button> + </Toolbar> + </AppBar> + <Grid container justify="center"> + <Grid item md={8} xs={12}> + <List> + <ListItem> + <ListItemText primary="Switch input" secondary="Odio ac imperdiet luctus" /> + <ListItemSecondaryAction> + <Switch + onChange={this.handleToggle('switch')} + checked={this.state.checked.indexOf('switch') !== -1} + /> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Another switch input" secondary="Lorem Ipsum" /> + <ListItemSecondaryAction> + <Switch + onChange={this.handleToggle('switch2')} + checked={this.state.checked.indexOf('switch2') !== -1} + /> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Checkbox input" secondary="Dolor sit amet" /> + <ListItemSecondaryAction> + <Checkbox + onChange={this.handleToggle('check')} + checked={this.state.checked.indexOf('check') !== -1} + /> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Another checkbox input" secondary="Donec dignissim" /> + <ListItemSecondaryAction> + <Checkbox + onChange={this.handleToggle('check2')} + checked={this.state.checked.indexOf('check2') !== -1} + /> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Selection field" secondary="Nam posuere accumsan porta" /> + <ListItemSecondaryAction> + <FormControl className={classes.formControl}> + <InputLabel htmlFor="age-simple">Option</InputLabel> + <Select + value={this.state.option} + onChange={this.handleChangeSelection} + inputProps={{ + name: 'option', + id: 'opt-simple', + }} + > + <MenuItem value=""> + <em>None</em> + </MenuItem> + <MenuItem value={10}>Option Ten</MenuItem> + <MenuItem value={20}>Option Twenty</MenuItem> + <MenuItem value={30}>Option Thirty</MenuItem> + </Select> + </FormControl> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Input text" secondary="Donec dignissim, odio ac imperdiet luctus" /> + <ListItemSecondaryAction> + <TextField + id="name" + label="Name" + className={classes.textField} + value={this.state.name} + onChange={this.handleChange('name')} + margin="normal" + /> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Input text" secondary="Donec dignissim, odio ac imperdiet luctus" /> + <ListItemSecondaryAction> + <Button variant="outlined" size="small" color="secondary" className={classes.button}> + Action Button + </Button> + </ListItemSecondaryAction> + </ListItem> + <Divider /> + <ListItem> + <ListItemText primary="Input text" secondary="Donec dignissim, odio ac imperdiet luctus" /> + <ListItemSecondaryAction> + <Button variant="outlined" size="small" color="secondary"> + <SettingsIcon className={classNames(classes.leftIcon, classes.iconSmall)} /> + Action Button Icon + </Button> + </ListItemSecondaryAction> + </ListItem> + </List> + </Grid> + </Grid> + </Dialog> + ); + } +} + +DetailSettings.propTypes = { + classes: PropTypes.object.isRequired, + open: PropTypes.bool.isRequired, + handleClose: PropTypes.func.isRequired, +}; + +export default withStyles(styles)(DetailSettings); diff --git a/front/odiparpack/app/containers/Pages/Settings/index.js b/front/odiparpack/app/containers/Pages/Settings/index.js new file mode 100644 index 0000000..2ab94d2 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Settings/index.js @@ -0,0 +1,117 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import SearchIcon from '@material-ui/icons/Search'; +import SettingsIcon from '@material-ui/icons/SettingsApplications'; +import { withStyles } from '@material-ui/core/styles'; +import settingList from 'ba-api/settingList'; +import { AppBar, Grid, Toolbar, Typography, Button, Icon } from '@material-ui/core'; +import DetailSettings from './DetailSettings'; +import styles from './settings-jss'; + + +class Settings extends React.Component { + state = { + open: false, + checked: ['switch', 'check2'], + keyword: '' + }; + + handleToggle = value => () => { + const { checked } = this.state; + const currentIndex = checked.indexOf(value); + const newChecked = [...checked]; + + if (currentIndex === -1) { + newChecked.push(value); + } else { + newChecked.splice(currentIndex, 1); + } + + this.setState({ + checked: newChecked, + }); + }; + + handleChange = name => event => { + this.setState({ + [name]: event.target.value, + }); + }; + + handleClickOpen = () => { + this.setState({ open: true }); + }; + + handleClose = () => { + this.setState({ open: false }); + }; + + handleSearch = event => { + this.setState({ keyword: event.target.value.toLowerCase() }); + } + + render() { + const title = brand.name; + const description = brand.desc; + const { classes } = this.props; + const { keyword } = this.state; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Typography variant="h5" className={classes.title}> + <SettingsIcon className={classes.iconTitle} /> + Appication Settings + </Typography> + <AppBar position="static" color="inherit" className={classes.searchSettings}> + <Toolbar> + <div className={classes.flex}> + <div className={classes.wrapper}> + <div className={classes.search}> + <SearchIcon /> + </div> + <input className={classes.input} placeholder="Find a setting" onChange={(event) => this.handleSearch(event)} /> + </div> + </div> + </Toolbar> + </AppBar> + <section className={classes.settingList}> + <Grid container spacing={2}> + {settingList.map(menu => { + const rawKey = menu.name + menu.caption; + if (rawKey.toLowerCase().indexOf(keyword) === -1) { + return false; + } + return ( + <Grid item md={3} sm={4} xs={12} key={menu.name}> + <Button variant="outlined" onClick={this.handleClickOpen} color="secondary" className={classes.button}> + <Icon className={classes.icon}>{menu.icon}</Icon> + {menu.name} + <Typography variant="caption" noWrap className={classes.info}> + {menu.caption} + </Typography> + </Button> + </Grid> + ); + })} + </Grid> + </section> + <DetailSettings open={this.state.open} handleClose={this.handleClose} /> + </div> + ); + } +} + +Settings.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Settings); diff --git a/front/odiparpack/app/containers/Pages/Settings/settings-jss.js b/front/odiparpack/app/containers/Pages/Settings/settings-jss.js new file mode 100644 index 0000000..5424d4e --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Settings/settings-jss.js @@ -0,0 +1,87 @@ +const styles = theme => ({ + appBar: { + position: 'relative', + }, + flex: { + flex: 1, + }, + title: { + display: 'block', + margin: `${theme.spacing(3)}px 0`, + color: theme.palette.common.white, + }, + searchSettings: { + marginBottom: theme.spacing(4), + }, + wrapper: { + fontFamily: theme.typography.fontFamily, + position: 'relative', + marginRight: theme.spacing(2), + marginLeft: theme.spacing(1), + borderRadius: 2, + display: 'block', + }, + search: { + width: 'auto', + height: '100%', + 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(4)}px`, + border: 0, + display: 'block', + verticalAlign: 'middle', + whiteSpace: 'normal', + background: 'none', + margin: 0, // Reset for Safari + color: 'inherit', + width: '100%', + '&:focus': { + outline: 0, + }, + }, + iconTitle: { + position: 'relative', + marginRight: theme.spacing(0.5), + }, + button: { + display: 'block', + width: '100%', + background: theme.palette.grey[50], + '&:hover': { + background: theme.palette.secondary.light + }, + '& $icon': { + margin: '0 auto', + display: 'block', + fontSize: 64 + }, + '& $info': { + display: 'block', + textTransform: 'none', + color: theme.palette.grey[500] + } + }, + info: {}, + icon: {}, + formControl: { + margin: theme.spacing(1), + minWidth: 120, + }, + selectEmpty: { + marginTop: theme.spacing(2), + }, + iconSmall: { + fontSize: 20, + }, + leftIcon: { + marginRight: theme.spacing(1), + }, +}); + +export default styles; diff --git a/front/odiparpack/app/containers/Pages/SocialMedia/index.js b/front/odiparpack/app/containers/Pages/SocialMedia/index.js new file mode 100644 index 0000000..3a5ae2c --- /dev/null +++ b/front/odiparpack/app/containers/Pages/SocialMedia/index.js @@ -0,0 +1,110 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import data from 'ba-api/timelineData'; +import { + fetchAction, + postAction, + toggleLikeAction, + fetchCommentAction, + postCommentAction, + closeNotifAction +} from 'ba-actions/SocmedActions'; +import { Timeline, WritePost, SideSection, Notification } from 'ba-components'; +import { Grid } from '@material-ui/core'; + +class SocialMedia extends React.Component { + componentDidMount() { + this.props.fetchData(data); + } + + render() { + const title = brand.name + ' - Social Media'; + const description = brand.desc; + const { + dataProps, + submitPost, + submitLike, + submitComment, + fetchComment, + commentIndex, + closeNotif, + messageNotif, + } = this.props; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Notification close={() => closeNotif()} message={messageNotif} /> + <Grid + container + alignItems="flex-start" + justify="flex-start" + direction="row" + spacing={3} + > + <Grid item md={8} xs={12}> + <div> + <WritePost submitPost={submitPost} /> + <Timeline + dataTimeline={dataProps} + onlike={submitLike} + submitComment={submitComment} + fetchComment={fetchComment} + commentIndex={commentIndex} + /> + </div> + </Grid> + <Grid item md={4} xs={12}> + <SideSection /> + </Grid> + </Grid> + </div> + ); + } +} + +SocialMedia.propTypes = { + fetchData: PropTypes.func.isRequired, + submitPost: PropTypes.func.isRequired, + submitLike: PropTypes.func.isRequired, + submitComment: PropTypes.func.isRequired, + dataProps: PropTypes.object.isRequired, + fetchComment: PropTypes.func.isRequired, + commentIndex: PropTypes.number.isRequired, + closeNotif: PropTypes.func.isRequired, + messageNotif: PropTypes.string.isRequired, +}; + +const reducer = 'socmed'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + dataProps: state.getIn([reducer, 'dataTimeline']), + commentIndex: state.getIn([reducer, 'commentIndex']), + messageNotif: state.getIn([reducer, 'notifMsg']), +}); + +const constDispatchToProps = dispatch => ({ + fetchData: bindActionCreators(fetchAction, dispatch), + submitPost: bindActionCreators(postAction, dispatch), + submitComment: bindActionCreators(postCommentAction, dispatch), + submitLike: bindActionCreators(toggleLikeAction, dispatch), + fetchComment: bindActionCreators(fetchCommentAction, dispatch), + closeNotif: () => dispatch(closeNotifAction), +}); + +const SocialMediaMapped = connect( + mapStateToProps, + constDispatchToProps +)(SocialMedia); + +export default SocialMediaMapped; diff --git a/front/odiparpack/app/containers/Pages/Standalone/LoginDedicated.js b/front/odiparpack/app/containers/Pages/Standalone/LoginDedicated.js new file mode 100644 index 0000000..9cba8fb --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Standalone/LoginDedicated.js @@ -0,0 +1,33 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import brand from 'ba-api/brand'; +import logo from 'ba-images/logo.svg'; +import styles from 'ba-containers/Templates/appStyles-jss'; +import { Hidden } from '@material-ui/core'; +import Login from '../Users/Login'; + +class LoginDedicated extends React.Component { + render() { + const { classes } = this.props; + return ( + <div className={classes.appFrameOuter}> + <main className={classes.outerContent} id="mainContent"> + <Hidden mdUp> + <div className={classes.brand}> + <img src={logo} alt={brand.name} /> + <h3>{brand.name}</h3> + </div> + </Hidden> + <Login /> + </main> + </div> + ); + } +} + +LoginDedicated.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default (withStyles(styles)(LoginDedicated)); diff --git a/front/odiparpack/app/containers/Pages/Standalone/NotFoundDedicated.js b/front/odiparpack/app/containers/Pages/Standalone/NotFoundDedicated.js new file mode 100644 index 0000000..3d78b32 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Standalone/NotFoundDedicated.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import styles from 'ba-containers/Templates/appStyles-jss'; +import Error from './../Error'; + +class NotFoundDedicated extends React.Component { + render() { + const { classes } = this.props; + return ( + <div className={classes.appFrameOuter}> + <main className={classes.outerContent} id="mainContent"> + <Error /> + </main> + </div> + ); + } +} + +NotFoundDedicated.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default (withStyles(styles)(NotFoundDedicated)); diff --git a/front/odiparpack/app/containers/Pages/UserProfile/index.js b/front/odiparpack/app/containers/Pages/UserProfile/index.js new file mode 100644 index 0000000..2065f68 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/UserProfile/index.js @@ -0,0 +1,131 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import dummy from 'ba-api/dummyContents'; +import AccountCircle from '@material-ui/icons/AccountCircle'; +import SupervisorAccount from '@material-ui/icons/SupervisorAccount'; +import Favorite from '@material-ui/icons/Favorite'; +import PhotoLibrary from '@material-ui/icons/PhotoLibrary'; +import { bindActionCreators } from 'redux'; +import { connect } from 'react-redux'; +import data from 'ba-api/timelineData'; +import { fetchAction } from 'ba-actions/SocmedActions'; +import { + Cover, + About, + Connection, + Favorites, + Albums +} from 'ba-components'; + +import { AppBar, Tabs, Tab, Hidden } from '@material-ui/core'; + +function TabContainer(props) { + return ( + <div style={{ paddingTop: 8 * 3 }}> + {props.children} + </div> + ); +} + +TabContainer.propTypes = { + children: PropTypes.node.isRequired, +}; + +class UserProfile extends React.Component { + state = { + value: 0, + }; + + componentDidMount() { + this.props.fetchData(data); + } + + handleChange = (event, value) => { + this.setState({ value }); + }; + + render() { + const title = brand.name + ' - Profile'; + const description = brand.desc; + const { dataProps } = this.props; + const { value } = this.state; + return ( + <div> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <Cover + coverImg="/images/material_bg.svg" + avatar={dummy.user.avatar} + name={dummy.user.name} + desc="Lorem ipsum dolor sit amet, consectetur adipiscing elit." + /> + <AppBar position="static" color="default"> + <Hidden mdUp> + <Tabs + value={this.state.value} + onChange={this.handleChange} + variant="fullWidth" + centered + indicatorColor="primary" + textColor="primary" + > + <Tab icon={<AccountCircle />} /> + <Tab icon={<SupervisorAccount />} /> + <Tab icon={<Favorite />} /> + <Tab icon={<PhotoLibrary />} /> + </Tabs> + </Hidden> + <Hidden smDown> + <Tabs + value={this.state.value} + onChange={this.handleChange} + variant="fullWidth" + centered + indicatorColor="primary" + textColor="primary" + > + <Tab icon={<AccountCircle />} label="ABOUT" /> + <Tab icon={<SupervisorAccount />} label="20 CONNECTIONS" /> + <Tab icon={<Favorite />} label="18 FAVORITES" /> + <Tab icon={<PhotoLibrary />} label="4 ALBUMS" /> + </Tabs> + </Hidden> + </AppBar> + {value === 0 && <TabContainer><About data={dataProps} /></TabContainer>} + {value === 1 && <TabContainer><Connection /></TabContainer>} + {value === 2 && <TabContainer><Favorites /></TabContainer>} + {value === 3 && <TabContainer><Albums /></TabContainer>} + </div> + ); + } +} + +UserProfile.propTypes = { + dataProps: PropTypes.object.isRequired, + fetchData: PropTypes.func.isRequired, +}; + +const reducer = 'socmed'; +const mapStateToProps = state => ({ + force: state, // force state from reducer + dataProps: state.getIn([reducer, 'dataTimeline']) +}); + +const constDispatchToProps = dispatch => ({ + fetchData: bindActionCreators(fetchAction, dispatch) +}); + +const UserProfileMapped = connect( + mapStateToProps, + constDispatchToProps +)(UserProfile); + +export default UserProfileMapped; diff --git a/front/odiparpack/app/containers/Pages/Users/LockScreen.js b/front/odiparpack/app/containers/Pages/Users/LockScreen.js new file mode 100644 index 0000000..2752ae6 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Users/LockScreen.js @@ -0,0 +1,55 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { LockForm } from 'ba-components'; +import styles from 'ba-components/Forms/user-jss'; +import { Grid } from '@material-ui/core'; + +class ResetPassword extends React.Component { + state = { + valueForm: [] + } + + submitForm(values) { + setTimeout(() => { + this.setState({ valueForm: values }); + console.log(`You submitted:\n\n${this.state.valueForm}`); + window.location.href = '/app'; + }, 500); // simulate server latency + } + + render() { + const title = brand.name + ' - Lock Screen'; + const description = brand.desc; + const { classes } = this.props; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.container}> + <Grid container spacing={3} alignItems="center" direction="row" justify="center"> + <Grid item md={4} xs={11}> + {/* ----------------------------------------------------------------------*/} + {/* Load Login Form */} + <LockForm onSubmit={(values) => this.submitForm(values)} /> + </Grid> + </Grid> + </div> + </div> + ); + } +} + +ResetPassword.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(ResetPassword); diff --git a/front/odiparpack/app/containers/Pages/Users/Login.js b/front/odiparpack/app/containers/Pages/Users/Login.js new file mode 100644 index 0000000..300f7b4 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Users/Login.js @@ -0,0 +1,85 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Type from 'ba-styles/Typography.scss'; +import ArrowForward from '@material-ui/icons/ArrowForward'; +import logo from 'ba-images/logo.svg'; +import { LoginForm } from 'ba-components'; +import styles from 'ba-components/Forms/user-jss'; + +import { Grid, Hidden, Typography } from '@material-ui/core'; + +class Login extends React.Component { + state = { + valueForm: [] + } + + submitForm(values) { + setTimeout(() => { + this.setState({ valueForm: values }); + console.log(`You submitted:\n\n${this.state.valueForm}`); + window.location.href = '/app'; + }, 500); // simulate server latency + } + + render() { + const title = brand.name + ' - Login'; + const description = brand.desc; + const { classes } = this.props; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.container}> + <Grid container spacing={3} alignItems="center" direction="row" justify="center"> + <Grid item container justify="center" spacing={0} className={classes.loginWrap}> + <Hidden smDown> + <Grid item md={6} className={classes.welcomeWrap}> + {/* Welcome Login */} + <div className={classes.welcome}> + <div className={classes.welcomeContent}> + <div className={classes.brand}> + <img src={logo} alt={brand.name} /> + <h3>{brand.name}</h3> + </div> + <Typography variant="h3"> + <span className={Type.light}>Hello there,</span> + </Typography> + <Typography variant="h6" className={classes.brandText}> + <span className={Type.regular}> + welcome to + {' '} + {brand.name} + </span> + </Typography> + </div> + <ArrowForward className={classes.decoBottom} /> + </div> + </Grid> + </Hidden> + <Grid item md={6} sm={8} xs={11}> + {/* ----------------------------------------------------------------------*/} + {/* Load Login Form */} + <LoginForm onSubmit={(values) => this.submitForm(values)} /> + </Grid> + </Grid> + </Grid> + </div> + </div> + ); + } +} + +Login.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Login); diff --git a/front/odiparpack/app/containers/Pages/Users/Register.js b/front/odiparpack/app/containers/Pages/Users/Register.js new file mode 100644 index 0000000..c139068 --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Users/Register.js @@ -0,0 +1,78 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import Type from 'ba-styles/Typography.scss'; +import ArrowForward from '@material-ui/icons/ArrowForward'; +import brand from 'ba-api/brand'; +import logo from 'ba-images/logo.svg'; +import { RegisterForm } from 'ba-components'; +import styles from 'ba-components/Forms/user-jss'; + +import { Grid, Hidden, Typography } from '@material-ui/core'; + +class Login extends React.Component { + state = { + valueForm: [] + } + + submitForm(values) { + setTimeout(() => { + this.setState({ valueForm: values }); + console.log(`You submitted:\n\n${this.state.valueForm}`); + window.location.href = '/app'; + }, 500); // simulate server latency + } + + render() { + const title = brand.name + ' - Register'; + const description = brand.desc; + const { classes } = this.props; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.container}> + <Grid container spacing={3} alignItems="center" direction="row" justify="center"> + <Grid item container justify="center" spacing={0} className={classes.loginWrap}> + <Hidden smDown> + <Grid item md={6} className={classes.welcomeWrap}> + {/* Welcome Login */} + <div className={classes.welcome}> + <div className={classes.welcomeContent}> + <div className={classes.brand}> + <img src={logo} alt={brand.name} /> + <h3>{brand.name}</h3> + </div> + <Typography variant="h4"> + <span className={Type.light}>Nice to meet You :)</span> + </Typography> + </div> + <ArrowForward className={classes.decoBottom} /> + </div> + </Grid> + </Hidden> + <Grid item md={6} sm={8} xs={11}> + {/* ----------------------------------------------------------------------*/} + {/* Load Register Form */} + <RegisterForm onSubmit={(values) => this.submitForm(values)} /> + </Grid> + </Grid> + </Grid> + </div> + </div> + ); + } +} + +Login.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(Login); diff --git a/front/odiparpack/app/containers/Pages/Users/ResetPassword.js b/front/odiparpack/app/containers/Pages/Users/ResetPassword.js new file mode 100644 index 0000000..e80253d --- /dev/null +++ b/front/odiparpack/app/containers/Pages/Users/ResetPassword.js @@ -0,0 +1,54 @@ +import React from 'react'; +import { Helmet } from 'react-helmet'; +import brand from 'ba-api/brand'; +import PropTypes from 'prop-types'; +import { withStyles } from '@material-ui/core/styles'; +import { ResetForm } from 'ba-components'; +import styles from 'ba-components/Forms/user-jss'; +import { Grid } from '@material-ui/core'; + +class ResetPassword extends React.Component { + state = { + valueForm: [] + } + + submitForm(values) { + setTimeout(() => { + this.setState({ valueForm: values }); + console.log(`You submitted:\n\n${this.state.valueForm}`); + }, 500); // simulate server latency + } + + render() { + const title = brand.name + ' - Reset Password'; + const description = brand.desc; + const { classes } = this.props; + return ( + <div className={classes.root}> + <Helmet> + <title>{title}</title> + <meta name="description" content={description} /> + <meta property="og:title" content={title} /> + <meta property="og:description" content={description} /> + <meta property="twitter:title" content={title} /> + <meta property="twitter:description" content={description} /> + </Helmet> + <div className={classes.container}> + <Grid container spacing={3} alignItems="center" direction="row" justify="center"> + <Grid item md={6} xs={11}> + {/* ----------------------------------------------------------------------*/} + {/* Load Login Form */} + <ResetForm onSubmit={(values) => this.submitForm(values)} /> + </Grid> + </Grid> + </div> + </div> + ); + } +} + +ResetPassword.propTypes = { + classes: PropTypes.object.isRequired, +}; + +export default withStyles(styles)(ResetPassword); |
