summaryrefslogtreecommitdiffstats
path: root/front/odiparpack/app/containers/Pages
diff options
context:
space:
mode:
Diffstat (limited to 'front/odiparpack/app/containers/Pages')
-rw-r--r--front/odiparpack/app/containers/Pages/.DS_Storebin0 -> 6148 bytes
-rw-r--r--front/odiparpack/app/containers/Pages/BlankPage/index.js28
-rw-r--r--front/odiparpack/app/containers/Pages/Calendar/index.js137
-rw-r--r--front/odiparpack/app/containers/Pages/Chat/index.js123
-rw-r--r--front/odiparpack/app/containers/Pages/Contact/index.js166
-rw-r--r--front/odiparpack/app/containers/Pages/Ecommerce/index.js117
-rw-r--r--front/odiparpack/app/containers/Pages/Email/index.js210
-rw-r--r--front/odiparpack/app/containers/Pages/Error/index.js33
-rw-r--r--front/odiparpack/app/containers/Pages/HelpSupport/ContactForm.js115
-rw-r--r--front/odiparpack/app/containers/Pages/HelpSupport/Qna.js141
-rw-r--r--front/odiparpack/app/containers/Pages/HelpSupport/helpSupport-jss.js49
-rw-r--r--front/odiparpack/app/containers/Pages/HelpSupport/index.js58
-rw-r--r--front/odiparpack/app/containers/Pages/Maintenance/index.js88
-rw-r--r--front/odiparpack/app/containers/Pages/Photos/index.js27
-rw-r--r--front/odiparpack/app/containers/Pages/Settings/DetailSettings.js203
-rw-r--r--front/odiparpack/app/containers/Pages/Settings/index.js117
-rw-r--r--front/odiparpack/app/containers/Pages/Settings/settings-jss.js87
-rw-r--r--front/odiparpack/app/containers/Pages/SocialMedia/index.js110
-rw-r--r--front/odiparpack/app/containers/Pages/Standalone/LoginDedicated.js33
-rw-r--r--front/odiparpack/app/containers/Pages/Standalone/NotFoundDedicated.js24
-rw-r--r--front/odiparpack/app/containers/Pages/UserProfile/index.js131
-rw-r--r--front/odiparpack/app/containers/Pages/Users/LockScreen.js55
-rw-r--r--front/odiparpack/app/containers/Pages/Users/Login.js85
-rw-r--r--front/odiparpack/app/containers/Pages/Users/Register.js78
-rw-r--r--front/odiparpack/app/containers/Pages/Users/ResetPassword.js54
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
new file mode 100644
index 0000000..f59225b
--- /dev/null
+++ b/front/odiparpack/app/containers/Pages/.DS_Store
Binary files differ
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 &amp; 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);