Added Google and Facebook login, added styling for login form

This commit is contained in:
2019-10-22 03:52:27 +05:30
parent 1c5a26d18a
commit 461f51ac3b
36 changed files with 2052 additions and 153 deletions

1184
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,10 +6,12 @@
"@svgr/webpack": "4.3.2",
"@typescript-eslint/eslint-plugin": "^2.2.0",
"@typescript-eslint/parser": "^2.2.0",
"autoprefixer": "^9.6.5",
"babel-eslint": "10.0.3",
"babel-jest": "^24.9.0",
"babel-plugin-named-asset-import": "^0.3.4",
"babel-preset-react-app": "^9.0.2",
"bootstrap": "^4.3.1",
"camelcase": "^5.2.0",
"case-sensitive-paths-webpack-plugin": "2.2.0",
"css-loader": "2.1.1",
@@ -25,6 +27,7 @@
"eslint-plugin-react-hooks": "^1.6.1",
"file-loader": "3.0.1",
"fs-extra": "7.0.1",
"gapi-script": "0.0.5",
"html-webpack-plugin": "4.0.0-beta.5",
"identity-obj-proxy": "3.0.0",
"is-wsl": "^1.1.0",
@@ -32,15 +35,18 @@
"jest-environment-jsdom-fourteen": "0.1.0",
"jest-resolve": "24.9.0",
"jest-watch-typeahead": "0.4.0",
"jquery": "^3.4.1",
"mini-css-extract-plugin": "0.8.0",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "5.0.3",
"pnp-webpack-plugin": "1.5.0",
"popper.js": "^1.16.0",
"postcss-flexbugs-fixes": "4.1.0",
"postcss-loader": "3.0.0",
"postcss-normalize": "7.0.1",
"postcss-preset-env": "6.7.0",
"postcss-safe-parser": "4.0.1",
"precss": "^4.0.0",
"react": "^16.10.2",
"react-app-polyfill": "^1.0.4",
"react-dev-utils": "^9.1.0",
@@ -70,7 +76,9 @@
"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"generate": "plop"
"generate": "plop",
"server": "node-env-run server --exec nodemon | pino-colada",
"dev": "run-p server start"
},
"eslintConfig": {
"extends": "react-app"
@@ -148,8 +156,16 @@
"@babel/preset-env": "^7.6.3",
"@babel/preset-react": "^7.6.3",
"babel-loader": "^8.0.6",
"body-parser": "^1.19.0",
"express": "^4.17.1",
"express-pino-logger": "^4.0.0",
"node-env-run": "^3.0.2",
"nodemon": "^1.19.4",
"npm-run-all": "^4.1.5",
"pino-colada": "^1.4.5",
"plop": "^2.5.2",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9"
}
},
"proxy": "http://localhost:3001"
}

View File

@@ -9,11 +9,15 @@
name="description"
content="Web site created using create-react-app"
/>
<meta name="google-signin-client_id" content="59720049592-8vg2ne03m148cdru5ko9t7upjn5retoe.apps.googleusercontent.com">
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_GB/sdk.js#xfbml=1&autoLogAppEvents=1&version=v4.0&appId=445645186070378"></script>
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<link rel="stylesheet" type="text/css" href="./index.css" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.

17
server/index.js Normal file
View File

@@ -0,0 +1,17 @@
const express = require('express');
const bodyParser = require('body-parser');
const pino = require('express-pino-logger')();
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(pino);
app.get('/api/greeting', (req, res) => {
const name = req.query.name || 'World';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ greeting: `Hello ${name}!` }));
});
app.listen(3001, () =>
console.log('Express server is running on localhost:3001')
);

View File

@@ -6,12 +6,12 @@ const InputField = ({meta}) => {
return (
<div className={styles['c-InputField']}>
<div
className={`form-wrapper__form-row c-form-field ${
className={`form-group row ${
meta.container_class ? meta.container_class : ''
}`}
aria-required={meta.aria_required}
>
<label htmlFor={meta.id}>
<label htmlFor={meta.id} className="col-12 col-sm-3 col-lg-12 col-form-label">
{meta.validation.required.isRequired && !meta.isStandAloneField && (
<span className="required-indicator">* </span>
)}
@@ -20,12 +20,12 @@ const InputField = ({meta}) => {
{meta.secondaryLabel ? (
<span className="field--label-description">{meta.secondaryLabel}</span>
) : null}
<div className="form-wrapper__field-wrapper">
<div className="col-12 col-sm-9 col-12">
{meta.error && (
<span className="form-wrapper__field-error">{meta.errorMessage}</span>
)}
<input
className={meta.error ? 'error' : ''}
className={`form-control ${meta.error ? 'error' : ''}`}
type={meta.type}
id={meta.id}
name={meta.name}
@@ -38,6 +38,7 @@ const InputField = ({meta}) => {
required={meta.validation.required.isRequired ? 'required' : ''}
minLength={meta.validation.rules.minlength}
maxLength={meta.validation.rules.maxlength}
placeholder={meta.placeholder}
aria-required={meta.aria_required}
aria-invalid={meta.aria_invalid}
// onFocus={onBlurProp ? onBlurProp : this.onFocusHandler}
@@ -50,6 +51,7 @@ const InputField = ({meta}) => {
}
onFocus={meta.handlers.onFocusHandler}
onChange={meta.handlers.onChangeHandler}
style={{width: '100%'}}
/>
</div>
</div>

View File

@@ -1,12 +1,13 @@
.c-InputField {
margin-bottom: 20px;
label {
float: left;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
}
margin-bottom: 10px;
margin-top: 10px;
// label {
// float: left;
// display: flex;
// align-items: center;
// justify-content: center;
// margin-right: 10px;
// }
input[type="text"],input[type="password"] {
padding: 5px;
width: 70%;

View File

@@ -1,4 +1,6 @@
/* PLOP_INJECT_IMPORT */
import SideBar from './SideBar';
import Jumbotron from './Jumbotron';
import FormFieldContainer from './FormFieldContainer';
import Form from './Form';
import SocialLogin from './SocialLogin';
@@ -10,6 +12,8 @@ import PageLoader from './PageLoader';
export {
/* PLOP_INJECT_EXPORT */
SideBar,
Jumbotron,
FormFieldContainer,
Form,
SocialLogin,

View File

@@ -1,4 +0,0 @@
.c-login {
// Root Class. Contains all core styles, typically for the component's
// wrapper element.
}

View File

@@ -1,40 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
class Login extends React.Component {
render() {
const {
className,
text
} = this.props
const classes = classNames('c-login', {
// 'c--modifier': bool ? true : false
}, className)
return (
<div className={classes}>
I am an example! {text}
</div>
)
}
}
Login.propTypes = {
/**
* PropTypes comments are REQUIRED for components to be included
* in the styleguide
*/
text: PropTypes.string.isRequired,
/**
* Adds values to the attribute of the root element
*/
className: PropTypes.string,
}
export default Login

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './LoginForm.module.css';
import styles from './LoginForm.module.scss';
import loginFormFields from './../../../config/forms-meta/login-form.json'
import Form from './../common/Form'

View File

@@ -1,3 +0,0 @@
.c-LoginForm {
}

View File

@@ -0,0 +1,3 @@
.c-LoginForm {
padding: 1rem;
}

View File

@@ -1,9 +1,18 @@
import React from 'react';
import styles from './PageLoader.module.scss';
const PageLoader = props => {
return (
<div className="c-page-loader">
<p>Loading...</p>
<div className={styles['c-PageLoader']}>
<div className={styles['is-animate']}>
<div className={styles.l}>l</div>
<div className={styles.l}>o</div>
<div className={styles.l}>a</div>
<div className={styles.l}>d</div>
<div className={styles.l}>i</div>
<div className={styles.l}>n</div>
<div className={styles.l}>g</div>
</div>
</div>
)
};

View File

@@ -1,3 +0,0 @@
.c-PageLoader {
}

View File

@@ -0,0 +1,82 @@
@import url('https://fonts.googleapis.com/css?family=Indie+Flower');
.c-PageLoader {
margin-top: 50%;
display: flex;
align-items: center;
justify-content: center;
.is-animate {
background: #ffb200;
box-sizing: border-box;
font-size: 66px;
display: -webkit-inline-box;
padding: 14px;
border-radius: 7px;
}
.is-animate > div {
animation-name: style;
display: -webkit-inline-box;
color: #fff;
padding: 9px;
background: #ffb200;
font-family: 'Indie Flower', cursive;
box-shadow: 2px 2px 9px 2px;
}
.l{
animation: letterspacing 1s infinite alternate cubic-bezier(.2, 0, 0, 1);
}
.is-animate > div {
animation-duration: 1s;
animation-fill-mode: both;
animation-iteration-count: infinite;
}
.is-animate > div:nth-child(1) { animation-delay: 0.0s }
.is-animate > div:nth-child(2) { animation-delay: 0.1s }
.is-animate > div:nth-child(3) { animation-delay: 0.2s }
.is-animate > div:nth-child(4) { animation-delay: 0.3s }
.is-animate > div:nth-child(5) { animation-delay: 0.4s }
.is-animate > div:nth-child(6) { animation-delay: 0.5s }
.is-animate > div:nth-child(7) { animation-delay: 0.6s }
@keyframes style {
from {
transform: scale3d(1, 1, 1);
}
30% {
box-shadow: 0px 0px 0px 0px;
transform: scale3d(1.25, 0.75, 1);
}
40% {
transform: scale3d(0.75, 1.25, 1);
}
50% {
transform: scale3d(1.15, 0.85, 1);
}
65% {
transform: scale3d(.95, 1.05, 1);
}
75% {
transform: scale3d(1.05, .95, 1);
}
to {
transform: scale3d(1, 1, 1);
}
}
@keyframes letterspacing {
0% {
filter: blur(0.1rem);
}
100% {
filter: blur(0.5rem);
}
to {
letter-spacing: none;
filter: blur(0rem);
}
}
}

View File

@@ -0,0 +1,52 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './SideBar.module.scss';
const SideBar = props => {
// return (
// <nav id="sidebar" class="active">
// <div class="sidebar-header">
// <button type="button" id="sidebarCollapse" class="btn btn-info">
// <i class="fas fa-align-justify"></i>
// </button>
// <h3 class="logotext">Microbot</h3>
// <!-- <strong>MB</strong> -->
// </div>
// <ul class="list-unstyled components">
// <li *ngFor="let tab of tabsData"
// [ngClass]="{active: tab.activeClass}">
// <a [routerLink]="tab.href">
// <i [ngClass]="['fas', tab.tabImage]"></i>
// <span class="hideable hide">{{tab.tabText}}</span>
// </a>
// <ul
// class="collapse list-unstyled"
// id="pageSubmenu"
// *ngIf="tab.subList">
// <li>
// <a href="#">Repo</a>
// </li>
// <li>
// <a href="#">Issues</a>
// </li>
// <li>
// <a href="#">Admin</a>
// </li>
// </ul>
// </li>
// </ul>
// </nav>
// );
return null
};
SideBar.defaultProps = {
};
SideBar.propTypes = {
};
export default SideBar;

View File

@@ -0,0 +1,459 @@
$themeColor-Light: #EEE2DC;
// $themeColor-Dark:#252525;
$themeColor-Dark:#E3E2DF;
$theme-font: verdana, sans-serif;
// $theme-supplementer: #f39c12;
$theme-supplementer: #5D001E;
$theme-supplementer-transparent: rgba(93,0,30,0.3);
.c-SideBar {
background: $theme-supplementer-transparent;
z-index: 20;
p {
font-family: 'Poppins', sans-serif;
font-size: 1.1em;
font-weight: 300;
line-height: 1.7em;
// color: #999;
}
a,
a:hover,
a:focus {
color: inherit;
text-decoration: none;
transition: all 0.3s;
}
.navbar {
padding: 15px 10px;
background: #fff;
border: none;
border-radius: 0 5px 5px 0;
margin-bottom: 40px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
}
.navbar-btn {
box-shadow: none;
outline: none !important;
border: none;
}
.line {
width: 100%;
height: 1px;
border-bottom: 1px dashed #ddd;
margin: 20px 0;
}
i,
span {
display: inline-block;
}
/* ---------------------------------------------------
SIDEBAR STYLE
----------------------------------------------------- */
.wrapper {
display: flex;
align-items: stretch;
font-family: 'Poppins', sans-serif;
background-color: $themeColor-Dark;
}
#sidebar {
min-width: 250px;
max-width: 250px;
// background: $theme-supplementer-transparent;
color: $themeColor-Dark;
transition: all 0.3s;
}
#sidebar.active {
min-width: 80px;
max-width: 80px;
text-align: center;
}
#sidebar.active .sidebar-header h3,
#sidebar.active .CTAs {
display: none;
}
.sidebar-header h3 {
display: inline;
padding-left: 0.6em;
vertical-align: middle;
}
#sidebar.active .sidebar-header strong {
display: block;
}
#sidebar ul li a {
text-align: left;
}
#sidebar.active ul li a {
padding: 20px 10px;
text-align: center;
font-size: 0.85em;
}
#sidebar.active ul li a i {
margin-right: 0;
display: block;
font-size: 1.8em;
margin-bottom: 5px;
}
#sidebar.active ul ul a {
padding: 10px !important;
}
#sidebar.active .dropdown-toggle::after {
top: auto;
bottom: 10px;
right: 50%;
-webkit-transform: translateX(50%);
-ms-transform: translateX(50%);
transform: translateX(50%);
}
#sidebar .sidebar-header {
padding: 20px;
background:$themeColor-Dark;
}
#sidebar .sidebar-header strong {
display: none;
font-size: 1.8em;
}
#sidebar ul.components {
padding: 20px 0;
border-bottom: 3px solid $themeColor-Dark;
}
#sidebar ul li a {
padding: 10px;
font-size: 1.1em;
display: block;
}
#sidebar ul li a:hover {
color: $theme-supplementer;
background: $themeColor-Light;
}
#sidebar ul li a i {
margin-right: 10px;
}
#sidebar ul li.active>a,
a[aria-expanded="true"] {
color: $theme-supplementer;
background:$themeColor-Dark;
}
a[data-toggle="collapse"] {
position: relative;
}
.dropdown-toggle::after {
display: block;
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
ul ul a {
font-size: 0.9em !important;
padding-left: 30px !important;
background: white;
font-weight: bolder;
}
ul.CTAs {
padding: 20px;
}
ul.CTAs a {
text-align: center;
font-size: 0.9em !important;
display: block;
border-radius: 5px;
margin-bottom: 5px;
}
a.download {
background: #fff;
color: #7386D5;
}
a.article,
a.article:hover {
background: #6d7fcc !important;
color: #fff !important;
}
/* ---------------------------------------------------
CONTENT STYLE
----------------------------------------------------- */
#content {
width: 100%;
padding: 20px;
min-height: 100vh;
transition: all 0.3s;
}
/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */
@media (max-width: 768px) {
#sidebar {
min-width: 80px;
max-width: 80px;
text-align: center;
margin-left: -80px !important;
}
.dropdown-toggle::after {
top: auto;
bottom: 10px;
right: 50%;
-webkit-transform: translateX(50%);
-ms-transform: translateX(50%);
transform: translateX(50%);
}
#sidebar.active {
margin-left: 0 !important;
}
#sidebar .sidebar-header h3,
#sidebar .CTAs {
display: none;
}
#sidebar .sidebar-header strong {
display: block;
}
#sidebar ul li a {
padding: 20px 10px;
}
#sidebar ul li a span {
font-size: 0.85em;
}
#sidebar ul li a i {
margin-right: 0;
display: block;
}
#sidebar ul ul a {
padding: 10px !important;
}
#sidebar ul li a i {
font-size: 1.3em;
}
#sidebar {
margin-left: 0;
}
#sidebarCollapse span {
display: none;
}
.text-muted {
color: #bcb !important;
}
}
@media(min-width: 576px) {
.card-group>.card:first-child {
border-top-right-radius: .25rem;
border-bottom-right-radius: .25rem;
}
.card-group>.card:not(:first-child):not(:last-child):not(:only-child) {
border-radius: .25rem;
}
.card-group>.card:last-child {
border-top-left-radius: .25rem;
border-bottom-left-radius: .25rem;
}
}
/* -------------------------------------------------
ADDITIONS
--------------------------------------------------*/
.hide {
display: none;
}
.prompt {
display: flex;
width: 2em;
border-right: 1px solid #c99034;
// background-color: #f5d38b;
background-color: $theme-supplementer;
width: 4%;
margin-bottom: 40px;
border-radius: 4px 0 0 4px;
}
.promptext {
animation:blinkingText 0.8s infinite;
// color: #975f04;
// color: $themeColor-Light;
text-align: center;
line-height: 2em;
font: 1.5em bolder;
margin: auto;
}
.good {
animation: anim .3s ease-in-out;
}
.repoLink {
color: #000;
font-weight: bolder;
text-decoration: underline;
}
.headerprompt {
display: flex;
width: 100%;
}
.logotext {
color: $theme-supplementer;
}
#content nav div.collapse li a.nav-link i.far {
color: $theme-supplementer;
font-size: 1.8em;
padding: 0.2em;
}
#loading-img {
background: url(http://preloaders.net/preloaders/360/Velocity.gif) center center no-repeat;
height: 100%;
z-index: 20;
}
.overlay {
background: #e9e9e9;
display: none;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.5;
}
.loader {
border: 0px solid #f3f3f3;
border-radius: 50%;
border-top: 2px solid #3498db;
border-right: 2px solid #3498db;
width: 20px;
height: 20px;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
}
.card:not(.widget) {
background: linear-gradient(to right, white, lightblue)
}
.light-red {
// background:linear-gradient(white, lightblue);
background: linear-gradient(to right, white, #dfc99a)
}
// f3d98c
.featureRequest {
background-color : #007bff;
color: white;
font-size: 1.5em;
padding: 10px 20px;
border-radius: 30px;
}
#featureRequest {
position: fixed;
bottom: 2em;
right: 2.5em;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
@keyframes anim {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes blinkingText {
0%{ color: $themeColor-Light; }
49%{ color: transparent; }
50%{ color: transparent; }
99%{ color:transparent; }
100%{ color: $themeColor-Light; }
}
/* --------------------------------------------------
OVERRIDES
--------------------------------------------------*/
.btn:not(.featureRequest) {
background-color: $theme-supplementer;
color: $themeColor-Dark
}
#content #header .navbar {
width: 96%;
}
.navbar-form {
width: 88%;
}
.form-control {
padding: .6rem 1em;
}
.container-fluid {
padding-left: 0.3em;
}
.card-group {
flex-direction:column;
}
#command.form-control {
width: 92%;
}
.ml-auto {
margin-left: 0!important;
}
.btn-info {
border-color: orange;
}
.btn-info:hover {
border-color: orange;
opacity: 1
}
}

View File

@@ -0,0 +1,8 @@
import React from 'react';
import SideBar from './SideBar';
describe('SideBar', () => {
it('renders without error', () => {
});
});

View File

@@ -0,0 +1,3 @@
import SideBar from './SideBar';
export default SideBar;

View File

@@ -1,13 +1,62 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './SocialLogin.module.css';
import {withRouter} from 'react-router-dom'
import {gapi} from 'gapi-script'
import styles from './SocialLogin.module.scss';
const SocialLogin = props => {
return (
<div className={styles.root}>
</div>
);
};
class SocialLogin extends React.Component{
constructor(props) {
super(props)
this.width = 254
this.height = 50
this.onSuccess = this.onSuccess.bind(this)
this.onFailure = this.onFailure.bind(this)
}
componentDidMount() {
gapi.signin2.render('g-signin2', {
'scope': 'profile email',
'width': this.width,
'height': this.height,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.onSuccess,
'onfailure': this.onFailure
});
}
onSuccess(googleUser) {
console.log('Logged in as: ' + googleUser.getBasicProfile().getName());
this.props.history.push('/home')
}
onFailure(error) {
console.log(error);
}
render() {
return (
<div className={styles['c-SocialLogin']}>
<div className="row">
<div className="col-12">
<div className="g-signin2" id="g-signin2"></div>
</div>
<div className="col-12">
<div
className="fb-login-button"
data-width={this.width}
data-height={this.height}
data-size="large"
data-button-type="continue_with"
data-auto-logout-link="false"
data-use-continue-as="true"
/>
</div>
</div>
</div>
);
}
}
SocialLogin.defaultProps = {
@@ -17,4 +66,4 @@ SocialLogin.propTypes = {
};
export default SocialLogin;
export default withRouter(SocialLogin)

View File

@@ -1,3 +0,0 @@
.c-SocialLogin {
}

View File

@@ -0,0 +1,10 @@
.c-SocialLogin {
padding: 1rem;
margin-bottom: 2rem;
display: flex;
justify-content: center;
.abcRioButtonBlue {
background: white;
color: #585f6b;
}
}

View File

@@ -1,12 +1,29 @@
import React from 'react'
import PropTypes from 'prop-types'
import * as styles from './Form.module.css'
import * as styles from './Form.module.scss'
import FormFieldContainer from '../FormFieldContainer';
class Form extends React.Component {
constructor(props) {
super(props)
this.state = {
name: '',
greeting: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.onFocusHandler = this.onFocusHandler.bind(this)
}
handleChange(event) {
this.setState({ name: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
fetch(`/api/greeting?name=${encodeURIComponent(this.state.name)}`)
.then(response => response.json())
.then(state => this.setState(state));
}
onFocusHandler() {
@@ -39,7 +56,7 @@ class Form extends React.Component {
onFocus={this.onFocusHandler}
customBlurHandler={
formFieldObject.impactsShippingOptions ||
formFieldObject.id === 'number'
formFieldObject.id === 'number'
? customBlurHandler
: null
}
@@ -60,7 +77,12 @@ class Form extends React.Component {
return formFieldObject !== null
})
return <fieldset className={styles['c-Form']}>{inputListSection}</fieldset>
return (
<form className={styles['c-Form']} onSubmit={this.handleSubmit}>
<fieldset>{inputListSection}</fieldset>
<button type="submit" className="btn btn-primary btn-block" style={{marginTop: '15px', background: 'black'}}>Submit</button>
</form>
)
}
}

View File

@@ -1,9 +0,0 @@
.c-Form {
padding: 15px;
/* width: 400px; */
text-align: center;
margin-left: auto;
margin-right: auto;
margin-top: 40px;
border: 1px solid lightgrey;
}

View File

@@ -0,0 +1,7 @@
.c-Form {
padding: 15px;
background: #ddd;
border: 1px solid #bbb;
border-radius: 3px;
margin-top: 10px;
}

View File

@@ -0,0 +1,28 @@
import React from 'react';
import PropTypes from 'prop-types'
import styles from './Jumbotron.module.scss';
import {Link} from 'react-router-dom'
const Jumbotron = props => {
return (
<div className={`${styles['c-Jumbotron']} jumbotron`}>
<h1 className="display-4">{props.jumboText}</h1>
<p className="lead">{props.subText}</p>
<hr className={`${styles['my-4']} my-4`}/>
<p>{props.jumboDescription}</p>
<p className="lead">
<Link className="btn btn-primary btn-lg" to="#" role="button">Let's get started</Link>
<Link className="btn btn-primary btn-lg float-right" to="#" role="button" style={{marginLeft: '15px'}}>{props.furtherLink}</Link>
</p>
</div>
);
};
Jumbotron.propTypes = {
furtherLink: PropTypes.string,
jumboDescription: PropTypes.string,
jumboText: PropTypes.string,
subText: PropTypes.string
};
export default Jumbotron;

View File

@@ -0,0 +1,8 @@
.c-Jumbotron {
background: #222;
color: #bbbbbb;
margin-bottom: 0;
.my-4 {
border-color: #bbb;
}
}

View File

@@ -0,0 +1,8 @@
import React from 'react';
import Jumbotron from './Jumbotron';
describe('Jumbotron', () => {
it('renders without error', () => {
});
});

View File

@@ -0,0 +1,3 @@
import Jumbotron from './Jumbotron';
export default Jumbotron;

View File

@@ -2,7 +2,7 @@
"login": {
"email": {
"label": "Email ID",
"placeholder": "Please enter your email ID...",
"placeholder": "Email ID",
"type": "text",
"id": "email",
"elementType": "input",
@@ -18,7 +18,7 @@
},
"password": {
"label": "Password",
"placeholder": "Select a strong password...",
"placeholder": "Password",
"type": "password",
"id": "password",
"elementType": "input",

View File

@@ -7,6 +7,8 @@ import {createPropsSelector} from 'reselect-immutable-helpers'
import * as actions from './actions'
import {getHome} from './selectors'
import Sidebar from './../../components/molecules/side-bar'
class Home extends React.Component {
constructor(props) {
super(props)
@@ -21,8 +23,7 @@ class Home extends React.Component {
render() {
return (
<div className={styles.Home}>
<h1 className="u-padding-top-md u-margin-bottom-sm">Home page</h1>
<p className="u-margin-bottom-md">Tips for getting started on this page:</p>
<Sidebar />
</div>
)
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import styles from './Login.module.scss';
import React from 'react'
import PropTypes from 'prop-types'
import styles from './Login.module.scss'
import {connect} from 'react-redux'
import {createPropsSelector} from 'reselect-immutable-helpers'
@@ -8,6 +8,7 @@ import * as actions from './actions'
import {getLogin, getFormErrors, getFormValues} from './selectors'
import LoginForm from '../../components/molecules/LoginForm'
import SocialLogin from '../../components/molecules/SocialLogin'
import Jumbotron from '../../components/molecules/common/Jumbotron/Jumbotron'
class Login extends React.Component {
constructor(props) {
@@ -21,20 +22,32 @@ class Login extends React.Component {
}
render() {
console.log("in login")
const {updateFormErrors, updateFormValues, formErrors, formValues} = this.props
return (
<div className={styles.Login}>
<h1 className="u-padding-top-md u-margin-bottom-sm">Welcome to Ecstatica</h1>
<p className="u-margin-bottom-md">Please login to continue</p>
<LoginForm
updateFormValues={updateFormValues}
updateFormErrors={updateFormErrors}
formErrors={formErrors}
formValues={formValues}
/>
<p className={styles.loginSplitter}>OR</p>
<SocialLogin />
<div className={`${styles.Login} container`}>
<div className="row">
<div className="col-12 col-lg-8">
<Jumbotron
jumboText="Welcome To Ecstatica"
subText="Show us what you've got!"
jumboDescription="An app for professional photographers, to provide a window to the world, to demonstrate the art within."
furtherLink="Learn more"
/>
</div>
<div className="col-12 col-lg-4">
<div className={styles.loginContainer}>
<p className={styles['c-login-intimation']}>Let's get to know each other, shall we!</p>
<LoginForm
updateFormValues={updateFormValues}
updateFormErrors={updateFormErrors}
formErrors={formErrors}
formValues={formValues}
/>
<p className={styles.loginSplitter}>OR</p>
<SocialLogin />
</div>
</div>
</div>
</div>
)
}

View File

@@ -1,11 +1,32 @@
.Login {
.loginSplitter {
text-align: center;
margin-top: 20px;
margin-bottom: 20px;
text-transform: capitalize;
font-size: 25px;
font-weight: bolder;
line-height: 30px;
background: #222;
max-width: unset;
@media only screen and (max-width: 1140px) {
padding-left: unset;
padding-right: unset;
margin-right: unset;
margin-left: unset;
}
.loginContainer {
border: 2px solid grey;
border-radius: 0.3rem;
margin: 1rem;
background: #eee;
padding-bottom: 20px;
.c-login-intimation {
padding: 15px 5px 15px 15px;
background: black;
color: white;
margin-bottom: 0;
}
.loginSplitter {
text-align: center;
margin-top: 10px;
margin-bottom: 10px;
text-transform: capitalize;
font-size: 25px;
font-weight: bolder;
line-height: 30px;
}
}
}

View File

@@ -1,5 +1,6 @@
body {
margin: 0;
background-color: #222!important;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
@@ -11,3 +12,17 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
.abcRioButtonBlue {
background-color: white!important;
color: #585f6b!important;
border-radius: 3px;
}
.g-signin2, .fb-login-button {
display: flex!important;
justify-content: center;
margin-bottom: 10px;
border-radius: 5px;
}

View File

@@ -5,6 +5,8 @@ import {createStore, applyMiddleware} from 'redux'
import * as serviceWorker from './serviceWorker';
import Router from './app/router';
import reducer from './app/reducer'
import './index.css'
import 'bootstrap/dist/css/bootstrap.min.css'
const store = createStore(reducer, applyMiddleware(thunk))