├── .gitignore
├── .DS_Store
├── notes
├── src
├── .DS_Store
├── assets
│ ├── .DS_Store
│ ├── blur.jpg
│ ├── Blur-600.jpg
│ ├── coffee-shop.jpg
│ ├── geometry_@2X.png
│ ├── giftly
│ │ ├── .DS_Store
│ │ ├── giftly.png
│ │ └── readme.txt
│ ├── geometry
│ │ ├── .DS_Store
│ │ ├── geometry.png
│ │ └── readme.txt
│ ├── noun_350980_cc.png
│ └── geometry2
│ │ ├── geometry2.png
│ │ └── readme.txt
├── stylus
│ ├── .DS_Store
│ └── main.styl
├── about.js
├── salon.js
├── menu.js
├── createUser.js
├── login.js
├── app.js
├── header.js
├── setupServices.js
├── home.js
├── setup.js
├── setupTime.js
├── times.js
└── dashboard.js
├── public
├── .DS_Store
└── main.css
├── README.md
├── package.json
├── database-json
├── index.html
└── gulpfile.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | public/app.js
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/.DS_Store
--------------------------------------------------------------------------------
/notes:
--------------------------------------------------------------------------------
1 | notes
2 |
3 | setupTime:
4 | -allow user to add time for each stylist name
5 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/.DS_Store
--------------------------------------------------------------------------------
/public/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/public/.DS_Store
--------------------------------------------------------------------------------
/src/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/.DS_Store
--------------------------------------------------------------------------------
/src/assets/blur.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/blur.jpg
--------------------------------------------------------------------------------
/src/stylus/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/stylus/.DS_Store
--------------------------------------------------------------------------------
/src/assets/Blur-600.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/Blur-600.jpg
--------------------------------------------------------------------------------
/src/assets/coffee-shop.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/coffee-shop.jpg
--------------------------------------------------------------------------------
/src/assets/geometry_@2X.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/geometry_@2X.png
--------------------------------------------------------------------------------
/src/assets/giftly/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/giftly/.DS_Store
--------------------------------------------------------------------------------
/src/assets/geometry/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/geometry/.DS_Store
--------------------------------------------------------------------------------
/src/assets/giftly/giftly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/giftly/giftly.png
--------------------------------------------------------------------------------
/src/assets/noun_350980_cc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/noun_350980_cc.png
--------------------------------------------------------------------------------
/src/assets/geometry/geometry.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/geometry/geometry.png
--------------------------------------------------------------------------------
/src/assets/geometry2/geometry2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sylvianguy/walk-in-app/HEAD/src/assets/geometry2/geometry2.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # walk-in-app
2 | Appointment booking app for beauty salons. Built with React and Firebase 🔥
3 |
4 | Live url : https://walk-in-87122.firebaseapp.com/
5 |
--------------------------------------------------------------------------------
/src/about.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 |
4 | export default class About extends React.Component {
5 | render() {
6 | return (
7 |
This is an ABOOT page!
8 | )
9 | }
10 | }
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/salon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export default class Salon extends React.Component {
4 |
5 | render() {
6 | return (
7 | This is the {this.props.params.client} Salon page!
8 | )
9 | }
10 | }
--------------------------------------------------------------------------------
/src/assets/geometry/readme.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | ========================================================
4 | This pattern is downloaded from www.subtlepatterns.com
5 | If you need more, that's where to get'em.
6 | ========================================================
7 |
8 |
--------------------------------------------------------------------------------
/src/assets/giftly/readme.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | ========================================================
4 | This pattern is downloaded from www.subtlepatterns.com
5 | If you need more, that's where to get'em.
6 | ========================================================
7 |
8 |
--------------------------------------------------------------------------------
/src/assets/geometry2/readme.txt:
--------------------------------------------------------------------------------
1 |
2 |
3 | ========================================================
4 | This pattern is downloaded from www.subtlepatterns.com
5 | If you need more, that's where to get'em.
6 | ========================================================
7 |
8 |
--------------------------------------------------------------------------------
/src/menu.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class Menu extends React.Component {
5 | render() {
6 | return (
7 |
8 |
this.props.addAppointment()}>
9 |
16 |
17 | )
18 | }
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "noted",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "babel-preset-es2015": "^6.13.2",
13 | "babel-preset-react": "^6.11.1",
14 | "babelify": "^7.3.0",
15 | "browser-sync": "^2.14.0",
16 | "browserify": "^13.1.0",
17 | "connect-history-api-fallback": "^1.3.0",
18 | "gulp": "^3.9.1",
19 | "gulp-notify": "^2.2.0",
20 | "gulp-plumber": "^1.1.0",
21 | "gulp-stylus": "^2.6.0",
22 | "react": "^15.3.0",
23 | "react-bootstrap-sweetalert": "^3.0.0",
24 | "react-dom": "^15.3.0",
25 | "react-router": "^2.6.1",
26 | "vinyl-buffer": "^1.0.0",
27 | "vinyl-source-stream": "^1.1.0"
28 | },
29 | "dependencies": {
30 | "moment": "^2.15.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/database-json:
--------------------------------------------------------------------------------
1 | {
2 | //firebase.database.ref(salonName)
3 | //.ref(`${salonName}/employees/${name}`).push({})
4 | //.ref(`${salonName}/employees/maria`).push({})
5 | "aCs4qMCI5ahJJOdRyPAdinjZ19Z2": {
6 | }
7 | "stylistics": {
8 | "employees": {
9 | "-2fasdfasfef": {
10 | "name": "Maria",
11 | "availbleTime": {
12 | "0ffsfasff": "10:00am",
13 | "0ffsfasff": "10:00am"
14 | }
15 | }
16 | },
17 | "services": {
18 | "klfa;lsfj": "Hair"
19 | },
20 | "bookings": {
21 | "kfdlas": {
22 | "customersName": "Ryan",
23 | "stylist": "Maria",
24 | "time": "10:00am",
25 | "service": "Hair",
26 | "notes": "Needs good hair"
27 | },
28 | "kfdlas": {
29 | "customersName": "Arianne",
30 | "stylist": "Maria",
31 | "time": "10:30am",
32 | "service": "Hair",
33 | "notes": "Needs good hair"
34 | }
35 | }
36 | },
37 | "nailedit" : {
38 | "employees": {
39 |
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Walkin App
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const gulp = require('gulp');
3 | const stylus = require('gulp-stylus');
4 | const babel = require('babelify');
5 | const browserify = require('browserify');
6 | const source = require('vinyl-source-stream');
7 | const buffer = require('vinyl-buffer');
8 | const browserSync = require('browser-sync');
9 | const reload = browserSync.reload;
10 | const historyApiFallback = require('connect-history-api-fallback');
11 | const notify = require('gulp-notify');
12 | const plumber = require('gulp-plumber');
13 | // const moment = require('moment');
14 |
15 |
16 | gulp.task('js', () => {
17 | return browserify('src/app.js')
18 | .transform('babelify', {
19 | presets: ['es2015','react']
20 | })
21 | .bundle()
22 | .on('error',notify.onError({
23 | message: "Error: <%= error.message %>",
24 | title: 'Error in JS 💀'
25 | }))
26 | .pipe(source('app.js'))
27 | .pipe(buffer())
28 | .pipe(gulp.dest('public/'))
29 | .pipe(reload({stream:true}));
30 | });
31 |
32 | gulp.task('styl', function() {
33 | gulp.src('./src/stylus/main.styl')
34 | .pipe(stylus())
35 | .pipe(gulp.dest('./public/'))
36 | .pipe(reload({stream: true}));
37 | });
38 |
39 | gulp.task('bs', () => {
40 | browserSync.init({
41 | server: {
42 | baseDir: './'
43 | },
44 | middleware: [historyApiFallback()]
45 | });
46 | });
47 |
48 | gulp.task('default', ['js','bs', 'styl'], () => {
49 | gulp.watch('src/**/*.js',['js']);
50 | gulp.watch('./src/stylus/*.styl', ['styl']);
51 | // gulp.watch('src/stylus/main.css', reload);
52 | });
53 |
54 |
--------------------------------------------------------------------------------
/src/createUser.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class createUser extends React.Component {
5 | createUser(e) {
6 | e.preventDefault();
7 | const user = {
8 | name: this.createName.value,
9 | email: this.createEmail.value,
10 | password: this.createPassword.value,
11 | confirm: this.confirmPassword.value
12 | }
13 |
14 | if(user.password === user.confirm) {
15 | firebase.auth().createUserWithEmailAndPassword(user.email, user.password)
16 | .then((data) => {
17 | console.log(data);
18 | var userId = data.uid;
19 | firebase.database().ref(userId).set({
20 | name:user.name,
21 | password: user.password,
22 | email: user.email
23 | })
24 | //push to a new router
25 | this.context.router.push('/times');
26 |
27 | })
28 | .catch(function(error) {
29 | var errorCode = error.code;
30 | var errorMessage = error.message;
31 | });
32 | }
33 | }
34 | render() {
35 | return (
36 |
37 |
45 |
46 | )
47 | }
48 | }
49 |
50 | createUser.contextTypes = {
51 | router: React.PropTypes.object
52 | }
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/login.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class Login extends React.Component {
5 | constructor() {
6 | super();
7 | this.state = {
8 | user: {
9 | email: "",
10 | password: ""
11 | },
12 | errorMessage: false
13 | }
14 | this.handleChange = this.handleChange.bind(this)
15 | this.loginUser = this.loginUser.bind(this)
16 | }
17 | handleChange(e) {
18 | const ogUser = Object.assign({}, this.state.user);
19 | ogUser[e.target.name] = e.target.value
20 | this.setState({
21 | user: ogUser
22 | })
23 | }
24 | loginUser(e) {
25 | e.preventDefault();
26 | const user = this.state.user;
27 | firebase.auth().signInWithEmailAndPassword(user.email, user.password)
28 | .then((res) => {
29 | const userId = res.uid;
30 | firebase.database().ref(userId)
31 | .on('value', (data) => {
32 | // console.log("lalala", data.val()) -
33 | })
34 | this.context.router.push('/dashboard');
35 | })
36 | .catch((err) => {
37 | this.setState({
38 | errorMessage: true
39 | })
40 | })
41 | }
42 | render() {
43 | const errorMessage = (
44 | The password is invalid or the user does not have a password
45 | )
46 | return (
47 |
54 |
55 | )
56 | }
57 | }
58 |
59 | Login.contextTypes = {
60 | router: React.PropTypes.object
61 | }
--------------------------------------------------------------------------------
/src/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDom from 'react-dom';
3 | import { Route, Router, Link, browserHistory, IndexRoute } from 'react-router';
4 | import About from './about';
5 | import Salon from './salon';
6 | import Home from './home';
7 | import Login from './login';
8 | import CreateUser from './createUser';
9 | import Setup from './setup';
10 | import SetupTime from './setupTime';
11 | import SetupServices from './setupServices';
12 | import Dashboard from './dashboard';
13 | import Header from './header';
14 | import Times from './times';
15 |
16 | class App extends React.Component {
17 | constructor() {
18 | super();
19 | this.state = {
20 | userAuth: []
21 | };
22 | var config = {
23 | apiKey: "AIzaSyACnQ3DNs0ye0yrgLGC6ispWgbOeUHFdM8",
24 | authDomain: "walk-in-87122.firebaseapp.com",
25 | databaseURL: "https://walk-in-87122.firebaseio.com",
26 | storageBucket: "walk-in-87122.appspot.com",
27 | messagingSenderId: "789650229559"
28 | };
29 | firebase.initializeApp(config);
30 | }
31 |
32 | componentDidMount() {
33 | //check to see if user is logged in
34 |
35 | }
36 |
37 | render() {
38 | const header =
39 | return (
40 |
41 | {header}
42 |
43 | {this.props.children}
44 |
45 |
46 |
47 | )
48 | }
49 |
50 | }
51 |
52 | ReactDom.render(
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | , document.getElementById('app'));
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/src/header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 | import Menu from './menu';
4 |
5 | export default class Header extends React.Component{
6 | constructor() {
7 | super();
8 | this.state = {
9 | signedIn: false,
10 | userName: ''
11 | }
12 | this.signOut = this.signOut.bind(this)
13 | }
14 | componentDidMount() {
15 | firebase.auth().onAuthStateChanged((user) => {
16 | var userId = user.uid
17 | console.log(user)
18 | firebase.database().ref(userId)
19 | .on('value', (res) => {
20 | // console.log("what", res.val())
21 | this.setState({
22 | userName: res.val().name
23 | })
24 | })
25 |
26 | const currentUser = firebase.auth().currentUser;
27 | // console.log("curee", currentUser
28 | if(currentUser === null) {
29 | console.log("not logged in")
30 | this.setState({
31 | signedIn: false
32 | })
33 | }else {
34 | console.log("logged In")
35 | this.setState({
36 | signedIn: true
37 | })
38 | }
39 | })
40 | }
41 | signOut() {
42 | console.log("sign out")
43 | firebase.auth().signOut()
44 | .then(() => {
45 | console.log("success");
46 | this.setState({
47 | signedIn: false
48 | })
49 | this.context.router.push('/');
50 | })
51 | .catch((err) => {
52 | console.log("error");
53 | })
54 | }
55 | render() {
56 | const loggedIn = this.signOut()}>Sign Out;
57 | const loggedOut = Sign In;
58 | const createAccount = Create Account;
59 | const greeting = Hello, {this.state.userName}!
;
60 | const showLoginInfo = (
61 |
62 | {this.state.signedIn ? greeting : null}
63 | {this.state.signedIn ? null : createAccount}
64 | {this.state.signedIn ? loggedIn : loggedOut}
65 |
66 | )
67 | return (
68 |
74 | )
75 | }
76 | }
77 |
78 | Header.contextTypes = {
79 | router: React.PropTypes.object
80 | }
--------------------------------------------------------------------------------
/src/setupServices.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class setupServices extends React.Component {
5 | constructor() {
6 | super();
7 | this.state = {
8 | services: [],
9 | currentServices: ''
10 | }
11 | }
12 |
13 | componentDidMount() {
14 | firebase.auth().onAuthStateChanged((user) => {
15 | firebase.database().ref(`${user.uid}/services`)
16 | .on('value', (res) => {
17 | const allData = res.val();
18 | console.log("what", res.val())
19 | const allDataArray = [];
20 | for(let key in allData) {
21 | allDataArray.push({
22 | key: key,
23 | service: allData[key]
24 | })
25 | }
26 |
27 | this.setState({
28 | services: allDataArray
29 | })
30 |
31 | })
32 | })
33 | }
34 |
35 | removeServices(serviceToRemove) {
36 | // const currentKey = servicesToRemove.key
37 | const currentUser = firebase.auth().currentUser;
38 |
39 | firebase.database().ref(`${currentUser.uid}/services/${serviceToRemove.key}`).remove();
40 | }
41 |
42 | addServices(e) {
43 | e.preventDefault();
44 | const inputValue = this.createService.value;
45 |
46 | const currentState = this.state.services
47 | currentState.push(inputValue);
48 |
49 |
50 | this.setState({
51 | services: currentState
52 | })
53 |
54 |
55 | const currentUser = firebase.auth().currentUser;
56 | if(currentUser) {
57 | firebase.database().ref(`${currentUser.uid}/services`)
58 | .push(inputValue)
59 | }
60 |
61 | }
62 | render() {
63 | return (
64 |
65 |
66 | Add your services here
67 |
72 |
73 |
74 | {this.state.services.map((service, i) =>{
75 | return (
76 |
82 | )
83 | })}
84 |
85 |
NEXT
86 |
87 | )
88 | }
89 | }
--------------------------------------------------------------------------------
/src/home.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class Home extends React.Component {
5 | constructor() {
6 | super();
7 | this.state = {
8 | user: {
9 | email: "",
10 | password: ""
11 | }
12 | }
13 | this.handleChange = this.handleChange.bind(this)
14 | this.signInGoogle = this.signInGoogle.bind(this)
15 | this.handleSubmit = this.handleSubmit.bind(this)
16 | this.signInFacebook = this.signInFacebook.bind(this)
17 | this.signInWithEmail = this.signInWithEmail.bind(this)
18 | }
19 | handleChange(e) {
20 | const ogUser = Object.assign({}, this.state.user);
21 | ogUser[e.target.name] = e.target.value
22 | this.setState({
23 | user: ogUser
24 | })
25 | }
26 | signInGoogle(e) {
27 | e.preventDefault()
28 | const provider = new firebase.auth.GoogleAuthProvider();
29 | firebase.auth().signInWithPopup(provider).then(function(result) {
30 | // This gives you a Google Access Token. You can use it to access the Google API.
31 | const token = result.credential.accessToken;
32 | // The signed-in user info.
33 | const user = result.user;
34 | this.context.router.push('/setup');
35 | // ...
36 | }).catch(function(error) {
37 | // Handle Errors here.
38 | const errorCode = error.code;
39 | const errorMessage = error.message;
40 | // The email of the user's account used.
41 | const email = error.email;
42 | // The firebase.auth.AuthCredential type that was used.
43 | const credential = error.credential;
44 | // ...
45 | });
46 | }
47 | signInFacebook(e) {
48 | e.preventDefault();
49 | var provider = new firebase.auth.FacebookAuthProvider();
50 | firebase.auth().signInWithPopup(provider).then(function(result) {
51 | // This gives you a Facebook Access Token. You can use it to access the Facebook API.
52 | var token = result.credential.accessToken;
53 | // The signed-in user info.
54 | var user = result.user;
55 | // ...
56 | }).catch(function(error) {
57 | // Handle Errors here.
58 | var errorCode = error.code;
59 | var errorMessage = error.message;
60 | // The email of the user's account used.
61 | var email = error.email;
62 | // The firebase.auth.AuthCredential type that was used.
63 | var credential = error.credential;
64 | // ...
65 | });
66 | }
67 | signInWithEmail() {
68 | // e.preventDefault();
69 | const user = this.state.user;
70 | firebase.auth().signInWithEmailAndPassword(user.email, user.password)
71 | .then((res) => {
72 | const userId = res.uid;
73 | firebase.database().ref(userId)
74 | .on('value', (data) => {
75 | console.log("lalala", data.val())
76 | })
77 | this.context.router.push('/dashboard');
78 | })
79 | .catch((err) => {
80 | this.setState({
81 | errorMessage: true
82 | })
83 | })
84 | }
85 | handleSubmit(e) {
86 | console.log("does it work?");
87 | e.preventDefault();
88 | }
89 | render() {
90 | return (
91 |
92 |
93 |
110 |
111 |
W
112 | Welcome to the Walk-in app
113 |
114 |
115 |
116 | )
117 | }
118 | }
119 |
120 | Home.contextTypes = {
121 | router: React.PropTypes.object
122 | }
--------------------------------------------------------------------------------
/src/setup.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 | export default class Setup extends React.Component {
5 |
6 | constructor() {
7 | super();
8 | this.state = {
9 | employees: [],
10 | allTimeSlots: [],
11 | handleModal: false,
12 | employeeKey: '',
13 | }
14 | this.handleModal = this.handleModal.bind(this);
15 | this.displayModal = this.displayModal.bind(this);
16 | this.closeModal = this.closeModal.bind(this);
17 | this.addTime = this.addTime.bind(this)
18 | }
19 | componentDidMount() {
20 | //whenever a value is a changed, tell us about it!
21 | firebase.auth().onAuthStateChanged((user) => {
22 | const theCurrentUser = firebase.auth().currentUser;
23 | firebase.database().ref(`${theCurrentUser.uid}/employees`)
24 | .on('value', (res) => {
25 | const userData = res.val();
26 | const dataArray = [];
27 |
28 | for(let key in userData) {
29 | userData[key].key = key;
30 | dataArray.push(userData[key]);
31 | }
32 | this.setState({
33 | employees: dataArray
34 | })
35 | });
36 |
37 | firebase.database().ref(`${theCurrentUser.uid}/times`)
38 | .on('value', (res) => {
39 | console.log("value", res.val())
40 | this.setState({
41 | allTimeSlots: res.val()
42 | })
43 | })
44 | });
45 | }
46 |
47 | handleModal(employee) {
48 | this.setState({
49 | handleModal: true,
50 | employeeKey: employee.key
51 | })
52 | }
53 |
54 | closeModal() {
55 | this.setState({
56 | handleModal: false
57 | })
58 | }
59 |
60 | addTime(value) {
61 | console.log(value)
62 | const employeeKey = this.state.employeeKey
63 | const currentUser = firebase.auth().currentUser;
64 | const currentUserId = currentUser.uid;
65 | if(currentUser) {
66 | firebase.database().ref(`${currentUserId}/employees/${employeeKey}/times`)
67 | .push({
68 | time: value,
69 | booked: false
70 | });
71 | }
72 | }
73 |
74 | displayModal() {
75 | const timeSlots = this.state.allTimeSlots;
76 |
77 | return (
78 |
79 |
80 |
81 |
82 | {timeSlots.map((item, i) => {
83 | return - this.addTime(item)} className="timesGrid__single timesGrid__single--inactive">{item}
84 | })}
85 |
86 |
87 |
88 |
89 | )
90 |
91 | }
92 |
93 | addEmployees(e) {
94 | e.preventDefault();
95 |
96 | const employee = {
97 | //create this after you have created the ref in input
98 | name: this.createEmployee.value
99 | }
100 | //clear my input on submit
101 | this.createEmployee.value = "";
102 | let newEmployees = [];
103 | const employeeName = employee.name;
104 | const currentState = this.state.employees;
105 |
106 | newEmployees = currentState;
107 | const pushed = newEmployees.push(employeeName);
108 |
109 | this.setState({
110 | employees: newEmployees
111 | })
112 |
113 | const theCurrentUser = firebase.auth().currentUser
114 | const currentUserId = theCurrentUser.uid
115 |
116 | if(theCurrentUser) {
117 | firebase.database().ref(`${currentUserId}/employees`)
118 | //pushing single employee rather than the whole list
119 | .push(employee);
120 | }
121 | }
122 | removeEmployee(employeeToRemove) {
123 | const currentUser = firebase.auth().currentUser;
124 | firebase.database().ref(`${currentUser.uid}/employees/${employeeToRemove.key}`).remove();
125 | }
126 | render() {
127 | return (
128 |
129 |
Setup all of your stuff here
130 |
131 |
135 | Employees:
136 | {this.state.employees.map((employee, i) => {
137 | return (
138 |
139 |
140 |
this.removeEmployee.call(this, employee) }>
141 |
{employee.name}
142 |
143 |
149 |
150 | )
151 | })}
152 | {this.displayModal()}
153 |
154 |
NEXT
155 |
156 | )
157 | }
158 | }
--------------------------------------------------------------------------------
/src/setupTime.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 |
4 |
5 | export default class setupTime extends React.Component {
6 |
7 | constructor() {
8 | super();
9 | this.state = {
10 | times: [],
11 | employees: [],
12 | currentEmployee: '',
13 | currentEmployeeName: '',
14 | currentTimeId: [],
15 | color: 'button'
16 | }
17 | }
18 | componentDidMount() {
19 | firebase.auth().onAuthStateChanged((user) => {
20 | const currentUser = firebase.auth().currentUser;
21 | firebase.database().ref(`${currentUser.uid}/employees`)
22 | .on('value', (res) => {
23 |
24 | const employeeData = res.val();
25 | const dataArray = [];
26 |
27 | //loop over the employeeData
28 | for(let key in employeeData) {
29 |
30 | employeeData[key].key = key;
31 | dataArray.push(employeeData[key])
32 | }
33 | this.setState({
34 | employees: dataArray
35 | })
36 | })
37 | })
38 | }
39 |
40 | handleClick(target) {
41 | // const dataArray = target.classList;
42 | target.classList.toggle('button--active');
43 | }
44 | addTime(e) {
45 | e.preventDefault();
46 |
47 | //store the value on the input
48 | const time = this.createTime.value
49 |
50 | // console.log("TIME", time);
51 | const timeArray = [];
52 | const totalTimes = timeArray.push(time);
53 | //call FUNCTION and pass in the time value here
54 |
55 | const currentUser = firebase.auth().currentUser;
56 | const currentUserId = currentUser.uid;
57 | if(currentUser) {
58 | firebase.database().ref(`${currentUserId}/employees/${this.state.currentEmployee}/times`)
59 | //pushing single employee rather than the whole list
60 | .push({
61 | time: time,
62 | booked: false
63 | });
64 | this.createTime.value = '';
65 | }
66 |
67 |
68 | // const moment = require('moment');
69 | // const blah = moment().format('MMMM Do YYYY, h:mm:ss a');
70 | }
71 | getEmployeeObj(employeeId) {
72 | //get that specific object from the employee from firebase
73 | //get that data from the employee that was clicked on
74 | let employeeInfo = [];
75 | const currentState = this.state.times;
76 | employeeInfo = currentState;
77 | employeeInfo.push(employeeId)
78 |
79 | this.setState({
80 | times: employeeInfo
81 | })
82 |
83 | }
84 |
85 | //GETS THE PERSON ID
86 | chooseEmployee(personId,e) {
87 | //Now that we have the employee
88 | //We want to somehow track that that is the one we selected
89 |
90 | //THIS FUNCTIONALITY WILL NOT BE IN HERE!
91 | //We need to save the employee key somehow
92 | const selectedEmployee = personId.key;
93 | const selectedEmployeeName = personId.name
94 | console.log('employee', selectedEmployee);
95 |
96 | console.log("person id", personId)
97 |
98 | this.setState({
99 | currentEmployee: selectedEmployee
100 | });
101 |
102 | this.setState({
103 | currentEmployeeName: selectedEmployeeName
104 | })
105 |
106 | // this.handleClick.call(this,e.target);
107 |
108 |
109 | //And reference that key(state) in another function.
110 |
111 |
112 | }
113 | removeTime(timeToRemove) {
114 | console.log("time to remove", timeToRemove);
115 | const testing = this.state.currentTimeId;
116 | console.log("what is this?", testing)
117 |
118 | // timeToRemove.remove();
119 | const currentUser = firebase.auth().currentUser;
120 | //get the key that was clicked on
121 | //use the time to remove after we have found the key
122 |
123 | firebase.database().ref(`${currentUser.uid}/employees/${this.state.currentEmployee}/times/${timeToRemove.key}`).remove();
124 | console.log(`${currentUser.uid}/employees/${this.state.currentEmployee}/times/${timeToRemove.key}`);
125 |
126 | }
127 |
128 | renderTime(times) {
129 | const timesArray = [];
130 | const keyArray = [];
131 | const combo = [];
132 |
133 | for(let key in times) {
134 | timesArray.push({
135 | times: times[key],
136 | key: key
137 | })
138 | keyArray.push(key)
139 | }
140 | console.log(timesArray);
141 | return (
142 | timesArray.map((item) => {
143 | return (
144 |
145 | this.removeTime.call(this, item) }>
146 |
{item.times.time}
147 |
148 | )
149 | })
150 |
151 | )
152 |
153 | }
154 | render() {
155 | return (
156 |
157 |
Step 2: Set up available time for employees.
158 |
165 |
166 | {this.state.employees.map((item, i) => {
167 |
168 | return (
169 |
179 | )
180 | })}
181 | NEXT
182 |
183 |
184 | )
185 |
186 | }
187 | }
--------------------------------------------------------------------------------
/src/times.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 | import Menu from './menu';
4 |
5 | export default class Times extends React.Component {
6 | constructor() {
7 | super();
8 | this.state = {
9 | getStartTime: '',
10 | getEndTime: '',
11 | timeSlots: [],
12 | currentTimeSlots: [],
13 | toggleMenu: false
14 | }
15 | this.increment = this.increment.bind(this);
16 | this.getStartTime = this.getStartTime.bind(this);
17 | this.getEndTime = this.getEndTime.bind(this);
18 | this.renderTimes = this.renderTimes.bind(this);
19 | this.addTimes = this.addTimes.bind(this);
20 | this.showMenu = this.showMenu.bind(this)
21 | this.hideMenu = this.hideMenu.bind(this)
22 | }
23 | componentDidMount() {
24 | firebase.auth().onAuthStateChanged((user) => {
25 | const theCurrentUser = firebase.auth().currentUser;
26 | const currentUserId = theCurrentUser.uid;
27 | console.log(currentUserId)
28 | firebase.database().ref(`${theCurrentUser.uid}/times`)
29 | .on('value', (res) => {
30 | const results = res.val();
31 | console.log("ressssss", results);
32 | this.setState({
33 | currentTimeSlots: results
34 | })
35 | })
36 |
37 |
38 | });
39 | function call(pagenum) {
40 | return $.ajax
41 | }
42 |
43 | const arrayOfCalls = []
44 |
45 | for(i = 0; i < 4; i++) {
46 | arrayOfCalls.push(call(25))
47 | }
48 |
49 | Promise.All(arrayOfCalls)
50 | .then(res => {
51 | console.log(res);
52 | })
53 |
54 |
55 | // firebase.auth().onAuthStateChanged((user) => {
56 | // firebase.database().ref(`${theCurrentUser.uid}/employees`)
57 | // .on('value', (res) => {
58 | // console.log("ssss", res.val())
59 | // // const times = res.val();
60 | // // const timesArray = Object.keys(times);
61 | // // console.log("key",times[timesArray])
62 | // // this.setState({
63 | // // currentTimeSlots: times[timesArray]
64 | // // })
65 | // // times.timesArray
66 |
67 |
68 | // })
69 | // })
70 | }
71 |
72 | showMenu() {
73 | this.setState({
74 | toggleMenu: true
75 | })
76 | }
77 |
78 | hideMenu() {
79 | this.setState({
80 | toggleMenu: false
81 | })
82 | }
83 |
84 |
85 | addTimes(e) {
86 | e.preventDefault();
87 | // console.log("lala", this.state.timeSlots)
88 | const currentUser = firebase.auth().currentUser;
89 |
90 | //when you add times
91 | console.log("CURRE", this.state.currentTimeSlots)
92 | //remove times in database
93 | //add times in database
94 |
95 |
96 | if(currentUser) {
97 | firebase.database().ref(`${currentUser.uid}/times`)
98 |
99 | .set(this.state.timeSlots)
100 | }
101 | }
102 | getStartTime(e) {
103 | console.log("this working?")
104 | const startTime = parseInt(e.target.value)
105 | this.setState({
106 | getStartTime: startTime
107 | })
108 | }
109 | getEndTime(e) {
110 | const endTime = parseInt(e.target.value);
111 | this.setState({
112 | getEndTime: endTime
113 | })
114 | }
115 |
116 | increment(e) {
117 | let incrementBy = parseInt(e.target.value);
118 | console.log("lalalla", incrementBy)
119 | let startTime = this.state.getStartTime;
120 | const endTime = this.state.getEndTime;
121 | const times = [];
122 | var ap = ['AM', 'PM']
123 |
124 | //get the start and end number i.e 10:00am - 9:00pm
125 | let done = true;
126 | let i = 0;
127 | let startMin = 0;
128 | let hour = startTime;
129 | while(done) {
130 | startMin = startMin + incrementBy;
131 | if(startMin >= 60) {
132 | startMin = 0;
133 | hour++;
134 | }
135 |
136 | times[i] = ('0' + hour) + ':' + (startMin === 0 ? "00" : startMin);
137 | if(hour >= endTime) {
138 | done = false;
139 | }
140 | i++;
141 | }
142 | this.setState({
143 | timeSlots: times
144 | })
145 |
146 | this.renderTimes();
147 |
148 | }
149 |
150 | renderTimes() {
151 |
152 | if(this.state.timeSlots !== '') {
153 | return this.state.currentTimeSlots.map((item, i) => {
154 | console.log("the time")
155 | return {item}
156 | })
157 | }
158 | }
159 |
160 | render(){
161 | let saveBtn = ()
162 | return (
163 |
216 | )
217 | }
218 | }
--------------------------------------------------------------------------------
/src/dashboard.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Link} from 'react-router';
3 | import SweetAlert from 'react-bootstrap-sweetalert';
4 | import Menu from './menu';
5 | // import {}
6 |
7 | export default class Dashboard extends React.Component {
8 | constructor() {
9 | super();
10 | this.state = {
11 | currentUser: '',
12 | currentUserId: '',
13 | customerName: [],
14 | selectedObj: [],
15 | stylists: [],
16 | selectedStylist: [],
17 | stylistTimes: {},
18 | services: [],
19 | chosenTime: "",
20 | service: "",
21 | bookingInfo: [],
22 | removeModal: false,
23 | personId: "",
24 | alert: null,
25 | addAppModal: false,
26 | toggleMenu: false
27 | }
28 | this.customerName = this.customerName.bind(this)
29 | this.bookAppointment = this.bookAppointment.bind(this)
30 | this.addAppointment = this.addAppointment.bind(this)
31 | this.closeAppModal = this.closeAppModal.bind(this)
32 | this.showMenu = this.showMenu.bind(this)
33 | this.hideMenu = this.hideMenu.bind(this)
34 | }
35 |
36 | componentDidMount() {
37 | firebase.auth().onAuthStateChanged((user) => {
38 | const theCurrentUser = firebase.auth().currentUser;
39 | const currentUserId = theCurrentUser.uid;
40 | this.setState({
41 | currentUser: theCurrentUser,
42 | currentUserId
43 | })
44 |
45 | firebase.database().ref(`${theCurrentUser.uid}/employees`)
46 | .on('value', (res) => {
47 | const userData = res.val();
48 | // console.log("current", userData);
49 | const dataArray = [];
50 | const bookingTime = [];
51 |
52 | for(let key in userData) {
53 | const timesObj = userData[key].times;
54 | dataArray.push({
55 | key: key,
56 | name: userData[key].name,
57 | times: userData[key].times
58 | })
59 | }
60 |
61 | this.setState({
62 | stylists: dataArray,
63 | justTimes: bookingTime
64 | })
65 |
66 | }),
67 | firebase.database().ref(`${theCurrentUser.uid}/services`)
68 | .on('value', (res) => {
69 | const servicesArray = []
70 | const servicesData = res.val();
71 |
72 | for(let key in servicesData) {
73 | servicesArray.push({
74 | key: key,
75 | serviceName: servicesData[key]
76 | })
77 |
78 | }
79 |
80 | this.setState({
81 | services: servicesArray
82 | })
83 |
84 | })
85 |
86 | })
87 | }
88 | showMenu() {
89 | console.log("mousing over");
90 | this.setState({
91 | toggleMenu: true
92 | })
93 | }
94 | hideMenu() {
95 | this.setState({
96 | toggleMenu: false
97 | })
98 | }
99 | customerName(e) {
100 | console.log(e.target.value);
101 | this.setState({
102 | customerName: e.target.value
103 | })
104 | }
105 |
106 | closeAppModal() {
107 | this.setState({
108 | addAppModal: false,
109 | toggleMenu: false
110 | })
111 | }
112 |
113 | addAppointment() {
114 | this.setState({
115 | addAppModal: true,
116 | toggleMenu: true
117 | })
118 | }
119 | removeAppointment(removedInfo) {
120 | const stylists = this.state.stylists;
121 | const currentUser = this.state.currentUser;
122 | const currentUserId = this.state.currentUserId;
123 |
124 | if(currentUser) {
125 | firebase.database().ref(`${currentUserId}/employees/${this.state.personId}/times/${removedInfo.key}/bookingInfo`).remove();
126 | }
127 |
128 | if(currentUser) {
129 | firebase.database().ref(`${currentUserId}/employees/${this.state.personId}/times/${removedInfo.key}`).update({
130 | booked: false
131 | });
132 | }
133 |
134 | this.setState({
135 | removeModal: true
136 | })
137 | }
138 |
139 | bookAppointment(e) {
140 | e.preventDefault();
141 | const selectedObj = this.state.selectedObj
142 | const currentUser = this.state.currentUser;
143 | const currentUserId = this.state.currentUserId;
144 | const chosenTime = this.state.chosenTime;
145 | const customerName = this.state.customerName;
146 | const notes = this.createNote.value;
147 | const service = this.state.service;
148 |
149 | if(currentUser) {
150 | firebase.database().ref(`${currentUserId}/employees/${selectedObj.key}/times/${chosenTime}/bookingInfo`).set({
151 | customerName,
152 | service,
153 | notes
154 | });
155 | }
156 |
157 | if(currentUser) {
158 | firebase.database().ref(`${currentUserId}/employees/${selectedObj.key}/times/${chosenTime}`).update({
159 | booked:true
160 | });
161 | }
162 |
163 | }
164 |
165 | getAvailability() {
166 | const stylistName = {
167 | name: this.selectedStylist.value
168 | }
169 | //filtering stylists ???
170 | let filteredStylist = this.state.stylists.filter((style) => {
171 | return style.name === stylistName.name;
172 | });
173 |
174 | filteredStylist = filteredStylist[0];
175 | this.setState({
176 | selectedStylist: stylistName,
177 | stylistTimes: filteredStylist.times,
178 | selectedObj: filteredStylist
179 | });
180 |
181 | }
182 |
183 | renderTimes() {
184 | const times = this.state.stylistTimes
185 | const timesArray = []
186 | for(let key in times) {
187 | timesArray.push({
188 | key: key,
189 | time: times[key]
190 | })
191 | }
192 | return (
193 | timesArray.map((time, i) => {
194 | if(time.time.booked !== true) {
195 | return
196 |
197 | }
198 | })
199 | )
200 | }
201 |
202 | chooseTime() {
203 | const time = this.selectedTimes.value;
204 | const stylistList = this.state.stylistTimes;
205 | const timesArray = [];
206 |
207 | for(let key in stylistList) {
208 | timesArray.push({
209 | key: key,
210 | time: stylistList[key]
211 | })
212 | }
213 | let filteredTime = timesArray.filter((item) => {
214 | return item.time.time === time;
215 | })
216 | this.setState({
217 | chosenTime: filteredTime[0].key
218 | })
219 | }
220 |
221 | getServices() {
222 | //get list of services from firebase
223 | const services = this.state.services;
224 |
225 | this.setState({
226 | service: this.selectedService.value
227 | })
228 | }
229 | getTimes() {
230 | const allTimes = this.state.stylists
231 | return (
232 | allTimes.map((time) => {
233 | // console.log("what", time)
234 | const timesArray = [];
235 | for(let key in time.times) {
236 | //ONLY display time if it is booked
237 | if( time.times[key].booked !== false) {
238 | timesArray.push(time.times[key].time);
239 | }
240 | }
241 | return (
242 |
243 |
{time.name}
244 |
245 | {timesArray.map((single, i) => {
246 | return (
247 | //passing THIS in this function bounds this to
248 | //the dashboard
249 | - this.bookingModal.call(this,e,time, single)}>{single}
250 | )
251 | })}
252 |
253 |
254 | )
255 | })
256 | )
257 |
258 | }
259 |
260 | displayModal() {
261 | const bookingInfo = this.state.bookingInfo
262 | const allTimes = this.state.stylists
263 | const info = bookingInfo[0];
264 | const bookingArray = [];
265 | if(info) {
266 | // console.log('displaymodal', info.service)
267 | return (
268 |
269 |
270 | this.closeModal.call(this)} className="fa fa-times" aria-hidden="true">
271 |
Stylist: {info.stylistName}
272 | Time: {info.time}
273 | Client Name: {info.clientName}
274 | Service: {info.service}
275 | Notes: {info.notes}
276 |
277 |
278 |
279 | )
280 | }
281 |
282 |
283 | }
284 |
285 | closeModal() {
286 | this.setState({
287 | removeModal: true
288 | })
289 | }
290 |
291 | bookingModal(e,person,bookedTime) {
292 | this.setState({
293 | removeModal: false,
294 | personId: person.key
295 | })
296 | const time = bookedTime;
297 | const stylistName = person.name;
298 | const bookedTimes = person.times
299 | const dataArray = [];
300 |
301 | for(let key in bookedTimes){
302 | // timesArray.push(bookedTimes[key].time)
303 | if (bookedTimes[key].time === time) {
304 | const bookingInfo = bookedTimes[key].bookingInfo;
305 | const customerName = bookingInfo.customerName;
306 | dataArray.push({
307 | stylistName: stylistName,
308 | clientName: bookingInfo.customerName,
309 | service: bookingInfo.service,
310 | notes: bookingInfo.notes,
311 | time,
312 | key
313 |
314 | })
315 |
316 |
317 | }
318 | }
319 | this.setState({
320 | bookingInfo: dataArray
321 | })
322 | }
323 |
324 | sweetAlert() {
325 | this.setState({
326 | alert: ( this.hideAlert()}>
327 | Appointment booked!
328 | )
329 | });
330 |
331 | }
332 | hideAlert() {
333 | this.setState({
334 | alert: null,
335 | addAppModal: false
336 | });
337 | }
338 | render() {
339 | return (
340 |
341 |
342 |
387 |
388 |
Appointment Schedule
389 |
390 | {this.getTimes()}
391 |
392 | {this.displayModal()}
393 | {this.state.alert}
394 |
395 |
397 | )
398 |
399 | }
400 | }
--------------------------------------------------------------------------------
/src/stylus/main.styl:
--------------------------------------------------------------------------------
1 | article,aside,details,figcaption,figure,footer,header,hgroup,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden]{display:none;}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:700;}dfn{font-style:italic;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;}pre{white-space:pre-wrap;word-wrap:break-word;}q{quotes:\201C \201D \2018 \2019;}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-.5em;}sub{bottom:-.25em;}img{border:0;}svg:not(:root){overflow:hidden;}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,html input[type=button],/* 1 */
2 | input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;}button[disabled],input[disabled]{cursor:default;}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}body,figure{margin:0;}legend,button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}
3 |
4 | .clearfix:after {visibility: hidden; display: block; font-size: 0; content: " "; clear: both; height: 0; }
5 |
6 | * { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
7 |
8 |
9 | /*
10 | Main Header
11 | */
12 |
13 |
14 | //*************************************//
15 | //variables//
16 | //************************************//
17 |
18 | $blue-white = #f7f7f7
19 | $blue-pale = #e1e7ea
20 | $blue-dark-l = #c8d6dd
21 | $button-yellow = #fbd20a
22 | $accent-color = #71d2d4
23 | $red = #f04e59
24 | $black = #454648
25 |
26 | $font-lato = 'Lato', sans-serif;
27 | $font-playfair = 'Playfair Display', serif;
28 | $font-size-sm = 1.7rem
29 | $font-weight-thin = 300
30 | $playfair-thin = 400
31 |
32 |
33 |
34 | //*************************************//
35 | //Base Element Styles//
36 | //************************************//
37 |
38 | html
39 | font-size 64.5%
40 |
41 | body
42 | background $blue-white
43 | color #182020
44 | font-family $font-lato
45 | font-size $font-size-sm
46 | font-weight $font-weight-thin
47 | letter-spacing 1.3px
48 | position relative
49 |
50 |
51 | li
52 | list-style none
53 | text-align center
54 | color black
55 |
56 | a
57 | color black
58 | text-decoration none
59 |
60 | ul,
61 | h1,
62 | h2,
63 | h3
64 | margin 0
65 | padding 0
66 | font-family $font-lato
67 |
68 | header
69 | background-color: rgba(255,255,255,0.99);
70 | border-bottom: 1px solid rgba(0,0,0,0.07);
71 | box-shadow: 0px 3px 8px -4px rgba(0,0,0,0.15);
72 | padding 8px 25px
73 |
74 | .mainHeader__block.wrapper
75 | display flex
76 | justify-content space-between
77 | align-items center
78 | .mainHeader__cta
79 | display flex
80 | align-items center
81 | a
82 | margin-left 15px
83 |
84 | button
85 | border none
86 | background $button-yellow
87 | color white
88 | padding 10px 31px
89 |
90 | input
91 | border-radius 4px
92 |
93 | h1
94 | padding 15px
95 | text-align center
96 | color white
97 | letter-spacing 2px
98 | font-family: 'Raleway', sans-serif;
99 | color $accent-color
100 | font-weight 300
101 | font-size 1.5rem
102 | position relative
103 | z-index 0
104 | &:before
105 | content ""
106 | border 2px solid $accent-color
107 | width 35px
108 | height 35px
109 | position absolute
110 | left 50%
111 | top 50%
112 | transform translate(-50%, -50%)
113 | z-index -1
114 | border-radius 50%
115 |
116 | h2
117 | font-family $font-playfair
118 | font-size 3rem
119 | font-style italic
120 | font-weight $playfair-thin
121 |
122 | h4
123 | margin 0
124 | color grey
125 |
126 | h3.subheading
127 | margin-bottom 20px
128 | width 100%
129 | font-weight 600
130 |
131 | .config__wrapper
132 | h2
133 | padding 26px 0 20px 0
134 | border-bottom 2px solid $accent-color
135 | margin-bottom 43px
136 | color $accent-color
137 |
138 | .wrapper
139 | max-width 880px
140 | margin 0 auto
141 | // margin-top 30px
142 |
143 | //*************************************//
144 | //Button Styles//
145 | //************************************//
146 |
147 | .button
148 | background white
149 | width 210px
150 | padding 10px 15px
151 | text-align center
152 | border none
153 | font-weight $font-weight-thin
154 | transition all 0.3s
155 | &--next
156 | background $button-yellow
157 | float right
158 | margin-bottom 40px
159 | font-weight 600
160 | color white
161 | &--active
162 | background $button-yellow
163 | width 200px
164 | padding 10px 15px
165 | text-align center
166 | &--submit
167 | height 46px
168 | width 100%
169 | color white
170 | background $accent-color
171 | // background $button-yellow
172 | font-weight 700
173 | margin-top 20px
174 | &--remove
175 | background #f04e59
176 | width auto
177 | color white
178 | margin-top 20px
179 | &--add
180 | background pink
181 | &--round
182 | background $accent-color
183 | border 1px solid $accent-color
184 | padding: 9px 13px;
185 | border-radius: 17px;
186 | font-size 1.3rem
187 | transition all 0.3s
188 | color white
189 | &:hover
190 | background darken($accent-color, 15)
191 | border 1px solid $accent-color
192 | cursor pointer
193 | &--round-createAcc
194 | background none
195 | color $accent-color
196 | &:hover
197 | background $accent-color
198 | border 1px solid $accent-color
199 | color white
200 | cursor pointer
201 | .remove
202 | background $red
203 | .fa-minus
204 | color $red
205 | .fa-plus
206 | color $accent-color
207 |
208 | input:focus
209 | outline none
210 | border 2px solid $accent-color
211 |
212 | //*************************************//
213 | //Dashboard Styles//
214 | //************************************//
215 |
216 | .form__container
217 | position absolute
218 | left 0
219 | top 0
220 | bottom 0
221 | right 0
222 | height 330px
223 | background $accent-color
224 | &.hide
225 | display none
226 | &.show
227 | display block
228 |
229 | .dashboard
230 | margin-top 60px
231 | background $blue-pale
232 | position relative
233 | padding: 83px 40px 111px;
234 |
235 | .fa-times
236 | position absolute
237 | right 20px
238 | top 20px
239 | font-size 2.5rem
240 | color $accent-color
241 | padding 12px
242 |
243 | .appointment
244 | background $blue-pale
245 | margin 50px 0 40px 0
246 | border-radius: 7px;
247 | h2
248 | color black
249 | padding 20px
250 | &__schedule
251 | display flex
252 | justify-content center
253 | align-items center
254 | border-top 2px solid white
255 | ul
256 | display flex
257 | width 77%
258 | padding 14px 10px
259 | border-left 2px solid white
260 | min-height 74px
261 | li
262 | margin 0 4px
263 | padding 14px 10px
264 | background $accent-color
265 | width 80px
266 | &:hover
267 | cursor pointer
268 | a
269 | color white
270 | h3
271 | width 20%
272 | margin 0 auto
273 | text-align center
274 |
275 | //*************************************//
276 | //Modal for the Dashboard
277 | //************************************//
278 |
279 | .modal
280 | background rgba(0,0,0,0.5)
281 | position fixed
282 | width 100%
283 | height 100%
284 | left 0
285 | top 0
286 | &--close
287 | display none
288 | &__box
289 | background white
290 | width 559px
291 | // width 500px
292 | position absolute
293 | left 50%
294 | top 50%
295 | transform translate(-50%, -50%)
296 | padding 20px
297 | font-size 20px
298 | .fa-times
299 | float right
300 | font-size 25px
301 | color grey
302 | h3
303 | padding 5px 0
304 | color $accent-color
305 | span
306 | color grey
307 | font-weight $font-weight-thin
308 | margin-left 8px
309 |
310 |
311 | //*************************************//
312 | //Selection Styles//
313 | //************************************//
314 |
315 | .selection
316 | margin-bottom 21px
317 | display flex
318 | flex-wrap wrap
319 | justify-content space-between
320 | padding 30px
321 | background $blue-pale
322 | &__block
323 | width 32%
324 | display: flex;
325 | flex-direction: column;
326 | margin-bottom 16px
327 | -webkit-box-shadow: 0 3px 8px rgba(187, 187, 187, 0.3);
328 | justify-content space-between
329 | height 95px
330 | &__duo
331 | display flex
332 | position relative
333 | &:nth-type(even)
334 | margin-bottom 0
335 | a
336 | width 100%
337 | .button
338 | width: auto
339 | padding 10px;
340 | position relative
341 | .button.addTime
342 | text-align center
343 | .fa
344 | margin-right 4px
345 | padding 14px 16px
346 | background white
347 |
348 | //*************************************//
349 | //General Form Styles//
350 | //************************************//
351 |
352 | form
353 | .form--option
354 | flex-basis 200px
355 | flex-grow 1
356 | margin 0 12px
357 | .three--col
358 | display flex
359 | width 100%
360 | justify-content space-between
361 | margin 0
362 | label
363 | width 40%
364 | &.sml--col
365 | width 28%
366 | p
367 | margin 12px 0 6px 0
368 | color white
369 |
370 | label
371 | background $blue-white
372 | padding 0 0 0 64px
373 | position relative
374 | width 100%
375 | display inline-block
376 | margin-bottom 20px
377 | height 50px
378 | input
379 | height 100%
380 | width 100%
381 | outline none
382 | border 0
383 | background $blue-white
384 | &:after
385 | content ""
386 | width 3px
387 | height 100%
388 | background $blue-pale
389 | position absolute
390 | left 50px
391 | top 0
392 | select,
393 | textarea
394 | display block
395 | &:hover
396 | cursor pointer
397 | select
398 | border 0
399 | outline 0
400 | width 100%
401 | height 100%
402 | -webkit-appearance none
403 | -webkit-border-radius 0px
404 | textarea
405 | height 150px
406 | width 100%
407 | border 0
408 | border 3px solid white
409 | background none
410 | svg
411 | width 26px
412 | position absolute
413 | left 13px
414 | top 13px
415 | .fa-cogs,
416 | .fa-clock-o
417 | font-size 26px
418 | position absolute
419 | left 12px
420 | top 12px
421 |
422 | form.selection__duo
423 | width 100%
424 | margin-bottom 16px
425 |
426 | .textInput
427 | padding 12px
428 | border none
429 | width 100%
430 |
431 | //*************************************//
432 | //Sign In / Sign Out Styles//
433 | //************************************//
434 |
435 | .signIn__box
436 | max-width: 490px;
437 | margin: 0 auto;
438 | padding: 16px 44px 26px 44px
439 | position relative
440 | .signIn__box--buttons
441 | display flex
442 | justify-content space-between
443 | .signIn__box--social
444 | position relative
445 | p
446 | color: #71d2d4;
447 | background: white;
448 | position: relative;
449 | z-index: 1;
450 | display: inline-block;
451 | left: 50%;
452 | top: 8px;
453 | width: 45px;
454 | text-align: center;
455 | transform: translateX(-50%);
456 | &:after
457 | content ""
458 | background #ebebeb
459 | position absolute
460 | top 30px
461 | left 0
462 | width 100%
463 | height 2px
464 |
465 | h2
466 | text-align center
467 | // color $black
468 | color grey
469 | padding-bottom 5px
470 | position relative
471 | margin-bottom 25px
472 | input
473 | padding: 10px;
474 | width: 100%;
475 | border: none;
476 | margin: 10px 0;
477 | font-weight: 300;
478 | border 2px solid rgb(235, 235, 235)
479 | .button--login
480 | background $accent-color
481 | bottom 0
482 | left 0
483 | width 48%
484 | margin-top 10px
485 | border none
486 | color white
487 | &:hover
488 | background darken($accent-color, 15)
489 |
490 | .button--submit-bare
491 | width 48%
492 | background none
493 | border 2px solid $accent-color
494 | color $accent-color
495 | &:hover
496 | background $accent-color
497 | color white
498 | .button--google
499 | background #d23f31
500 | border none
501 | color white
502 | margin-top: 29px
503 | .button--facebook
504 | background #3b5998
505 | color white
506 |
507 | .timesGrid
508 | width 100%
509 | min-height 100px
510 | display flex
511 | justify-content flex-start
512 | align-items flex-start
513 | flex-wrap wrap
514 | &__single
515 | // padding 10px
516 | padding 13px 18px
517 | background $accent-color
518 | margin 0 10px 10px 0
519 | margin-right 10px
520 | color white
521 | &--inactive
522 | background #E6E7E8
523 | color grey
524 |
525 | //*************************************//
526 | //Menu button styles//
527 | //************************************//
528 |
529 | .addAppointment
530 | width 60px
531 | height 60px
532 | background $button-yellow
533 | position fixed
534 | right 50px
535 | bottom 50px
536 | border-radius 50%
537 | display flex
538 | justify-content center
539 | align-items center
540 | box-shadow: 0 0 4px rgba(0,0,0,.14), 0 4px 8px rgba(0,0,0,.28);
541 | .fa-plus
542 | color white
543 | font-size 2.5rem
544 | transition all 0.3s
545 | &:hover
546 | .fa-plus
547 | transform rotate(45deg)
548 |
549 | .menu__container
550 | position fixed
551 | right 78px
552 | bottom 120px
553 | .menu
554 | display flex
555 | flex-direction column
556 | justify-content flex-end
557 | width 21px
558 | transition all 0.5s
559 | li
560 | margin-right 30px
561 | margin-top 11px
562 | transition all 0.3s
563 | &:hover
564 | .fa
565 | background #68b1b2
566 | cursor pointer
567 |
568 | .fa
569 | background: $accent-color
570 | width: 37px
571 | height: 37px
572 | border-radius: 50%
573 | padding-top: 11px
574 | padding-left: 2px
575 | color white
576 | transition all 0.3s
577 | .hide
578 | opacity 0
579 | visibility hidden
580 | .show
581 | opacity 1
582 | visibility visible
583 |
584 | //*************************************//
585 | //Welcome Section//
586 | //************************************//
587 | .welcome
588 | background: $blue-pale;
589 | box-shadow: 5px 5px 8px -4px rgba(0,0,0,0.15);
590 | margin-top 40px
591 | .welcome--wrapper
592 | display flex
593 | .welcome--right
594 | width 50%
595 | padding 40px
596 | background-image url("/src/assets/coffee-shop.jpg");
597 | background-repeat no-repeat
598 | background-position: center right
599 | background-size: cover;
600 | position relative
601 | display flex
602 | justify-content center
603 | align-items center
604 | text-align center
605 | flex-direction column
606 | h2
607 | color white
608 | h1
609 | font-size 3rem
610 | &:before
611 | width 65px
612 | height 65px
613 | &:before
614 | content ""
615 | background rgba(58,86,144,0.8)
616 | position absolute
617 | top 0
618 | left 0
619 | bottom 0
620 | right 0
621 |
622 | .welcome--left
623 | width 50%
624 | padding 7px
625 | background white
626 | p
627 | color grey
628 | text-align center
629 | padding-bottom 10px
630 | h2
631 | font-size 4rem
632 | position relative
633 | z-index 1
634 | line-height 1.3
635 | margin-top 20px
636 | margin-bottom 0
637 |
638 |
639 |
640 |
641 |
642 |
--------------------------------------------------------------------------------
/public/main.css:
--------------------------------------------------------------------------------
1 | article,
2 | aside,
3 | details,
4 | figcaption,
5 | figure,
6 | footer,
7 | header,
8 | hgroup,
9 | nav,
10 | section,
11 | summary {
12 | display: block;
13 | }
14 | audio,
15 | canvas,
16 | video {
17 | display: inline-block;
18 | }
19 | audio:not([controls]) {
20 | display: none;
21 | height: 0;
22 | }
23 | [hidden] {
24 | display: none;
25 | }
26 | html {
27 | font-family: sans-serif;
28 | -webkit-text-size-adjust: 100%;
29 | -ms-text-size-adjust: 100%;
30 | }
31 | a:focus {
32 | outline: thin dotted;
33 | }
34 | a:active,
35 | a:hover {
36 | outline: 0;
37 | }
38 | h1 {
39 | font-size: 2em;
40 | }
41 | abbr[title] {
42 | border-bottom: 1px dotted;
43 | }
44 | b,
45 | strong {
46 | font-weight: 700;
47 | }
48 | dfn {
49 | font-style: italic;
50 | }
51 | mark {
52 | background: #ff0;
53 | color: #000;
54 | }
55 | code,
56 | kbd,
57 | pre,
58 | samp {
59 | font-family: monospace, serif;
60 | font-size: 1em;
61 | }
62 | pre {
63 | white-space: pre-wrap;
64 | word-wrap: break-word;
65 | }
66 | q {
67 | quotes: 2 1C 2 1D 2 18 2 19;
68 | }
69 | small {
70 | font-size: 80%;
71 | }
72 | sub,
73 | sup {
74 | font-size: 75%;
75 | line-height: 0;
76 | position: relative;
77 | vertical-align: baseline;
78 | }
79 | sup {
80 | top: -0.5em;
81 | }
82 | sub {
83 | bottom: -0.25em;
84 | }
85 | img {
86 | border: 0;
87 | }
88 | svg:not(:root) {
89 | overflow: hidden;
90 | }
91 | fieldset {
92 | border: 1px solid #c0c0c0;
93 | margin: 0 2px;
94 | padding: 0.35em 0.625em 0.75em;
95 | }
96 | button,
97 | input,
98 | select,
99 | textarea {
100 | font-family: inherit;
101 | font-size: 100%;
102 | margin: 0;
103 | }
104 | button,
105 | input {
106 | line-height: normal;
107 | }
108 | button,
109 | html input[type=button],
110 | input[type=reset],
111 | input[type=submit] {
112 | -webkit-appearance: button;
113 | cursor: pointer;
114 | }
115 | button[disabled],
116 | input[disabled] {
117 | cursor: default;
118 | }
119 | input[type=checkbox],
120 | input[type=radio] {
121 | box-sizing: border-box;
122 | padding: 0;
123 | }
124 | input[type=search] {
125 | -webkit-appearance: textfield;
126 | -moz-box-sizing: content-box;
127 | -webkit-box-sizing: content-box;
128 | box-sizing: content-box;
129 | }
130 | input[type=search]::-webkit-search-cancel-button,
131 | input[type=search]::-webkit-search-decoration {
132 | -webkit-appearance: none;
133 | }
134 | textarea {
135 | overflow: auto;
136 | vertical-align: top;
137 | }
138 | table {
139 | border-collapse: collapse;
140 | border-spacing: 0;
141 | }
142 | body,
143 | figure {
144 | margin: 0;
145 | }
146 | legend,
147 | button::-moz-focus-inner,
148 | input::-moz-focus-inner {
149 | border: 0;
150 | padding: 0;
151 | }
152 | .clearfix:after {
153 | visibility: hidden;
154 | display: block;
155 | font-size: 0;
156 | content: " ";
157 | clear: both;
158 | height: 0;
159 | }
160 | * {
161 | -moz-box-sizing: border-box;
162 | -webkit-box-sizing: border-box;
163 | box-sizing: border-box;
164 | }
165 | /*
166 | Main Header
167 | */
168 | html {
169 | font-size: 64.5%;
170 | }
171 | body {
172 | background: #f7f7f7;
173 | color: #182020;
174 | font-family: 'Lato', sans-serif;
175 | font-size: 1.7rem;
176 | font-weight: 300;
177 | letter-spacing: 1.3px;
178 | position: relative;
179 | }
180 | li {
181 | list-style: none;
182 | text-align: center;
183 | color: #000;
184 | }
185 | a {
186 | color: #000;
187 | text-decoration: none;
188 | }
189 | ul,
190 | h1,
191 | h2,
192 | h3 {
193 | margin: 0;
194 | padding: 0;
195 | font-family: 'Lato', sans-serif;
196 | }
197 | header {
198 | background-color: rgba(255,255,255,0.99);
199 | border-bottom: 1px solid rgba(0,0,0,0.07);
200 | box-shadow: 0px 3px 8px -4px rgba(0,0,0,0.15);
201 | padding: 8px 25px;
202 | }
203 | .mainHeader__block.wrapper {
204 | display: flex;
205 | justify-content: space-between;
206 | align-items: center;
207 | }
208 | .mainHeader__cta {
209 | display: flex;
210 | align-items: center;
211 | }
212 | .mainHeader__cta a {
213 | margin-left: 15px;
214 | }
215 | button {
216 | border: none;
217 | background: #fbd20a;
218 | color: #fff;
219 | padding: 10px 31px;
220 | }
221 | input {
222 | border-radius: 4px;
223 | }
224 | h1 {
225 | padding: 15px;
226 | text-align: center;
227 | color: #fff;
228 | letter-spacing: 2px;
229 | font-family: 'Raleway', sans-serif;
230 | color: #71d2d4;
231 | font-weight: 300;
232 | font-size: 1.5rem;
233 | position: relative;
234 | z-index: 0;
235 | }
236 | h1:before {
237 | content: "";
238 | border: 2px solid #71d2d4;
239 | width: 35px;
240 | height: 35px;
241 | position: absolute;
242 | left: 50%;
243 | top: 50%;
244 | transform: translate(-50%, -50%);
245 | z-index: -1;
246 | border-radius: 50%;
247 | }
248 | h2 {
249 | font-family: 'Playfair Display', serif;
250 | font-size: 3rem;
251 | font-style: italic;
252 | font-weight: 400;
253 | }
254 | h4 {
255 | margin: 0;
256 | color: #808080;
257 | }
258 | h3.subheading {
259 | margin-bottom: 20px;
260 | width: 100%;
261 | font-weight: 600;
262 | }
263 | .config__wrapper h2 {
264 | padding: 26px 0 20px 0;
265 | border-bottom: 2px solid #71d2d4;
266 | margin-bottom: 43px;
267 | color: #71d2d4;
268 | }
269 | .wrapper {
270 | max-width: 880px;
271 | margin: 0 auto;
272 | }
273 | .button {
274 | background: #fff;
275 | width: 210px;
276 | padding: 10px 15px;
277 | text-align: center;
278 | border: none;
279 | font-weight: 300;
280 | transition: all 0.3s;
281 | }
282 | .button--next {
283 | background: #fbd20a;
284 | float: right;
285 | margin-bottom: 40px;
286 | font-weight: 600;
287 | color: #fff;
288 | }
289 | .button--active {
290 | background: #fbd20a;
291 | width: 200px;
292 | padding: 10px 15px;
293 | text-align: center;
294 | }
295 | .button--submit {
296 | height: 46px;
297 | width: 100%;
298 | color: #fff;
299 | background: #71d2d4;
300 | font-weight: 700;
301 | margin-top: 20px;
302 | }
303 | .button--remove {
304 | background: #f04e59;
305 | width: auto;
306 | color: #fff;
307 | margin-top: 20px;
308 | }
309 | .button--add {
310 | background: #ffc0cb;
311 | }
312 | .button--round {
313 | background: #71d2d4;
314 | border: 1px solid #71d2d4;
315 | padding: 9px 13px;
316 | border-radius: 17px;
317 | font-size: 1.3rem;
318 | transition: all 0.3s;
319 | color: #fff;
320 | }
321 | .button--round:hover {
322 | background: #3abcbf;
323 | border: 1px solid #71d2d4;
324 | cursor: pointer;
325 | }
326 | .button--round-createAcc {
327 | background: none;
328 | color: #71d2d4;
329 | }
330 | .button--round-createAcc:hover {
331 | background: #71d2d4;
332 | border: 1px solid #71d2d4;
333 | color: #fff;
334 | cursor: pointer;
335 | }
336 | .remove {
337 | background: #f04e59;
338 | }
339 | .fa-minus {
340 | color: #f04e59;
341 | }
342 | .fa-plus {
343 | color: #71d2d4;
344 | }
345 | input:focus {
346 | outline: none;
347 | border: 2px solid #71d2d4;
348 | }
349 | .form__container {
350 | position: absolute;
351 | left: 0;
352 | top: 0;
353 | bottom: 0;
354 | right: 0;
355 | height: 330px;
356 | background: #71d2d4;
357 | }
358 | .form__container.hide {
359 | display: none;
360 | }
361 | .form__container.show {
362 | display: block;
363 | }
364 | .dashboard {
365 | margin-top: 60px;
366 | background: #e1e7ea;
367 | position: relative;
368 | padding: 83px 40px 111px;
369 | }
370 | .dashboard .fa-times {
371 | position: absolute;
372 | right: 20px;
373 | top: 20px;
374 | font-size: 2.5rem;
375 | color: #71d2d4;
376 | padding: 12px;
377 | }
378 | .appointment {
379 | background: #e1e7ea;
380 | margin: 50px 0 40px 0;
381 | border-radius: 7px;
382 | }
383 | .appointment h2 {
384 | color: #000;
385 | padding: 20px;
386 | }
387 | .appointment__schedule {
388 | display: flex;
389 | justify-content: center;
390 | align-items: center;
391 | border-top: 2px solid #fff;
392 | }
393 | .appointment__schedule ul {
394 | display: flex;
395 | width: 77%;
396 | padding: 14px 10px;
397 | border-left: 2px solid #fff;
398 | min-height: 74px;
399 | }
400 | .appointment__schedule ul li {
401 | margin: 0 4px;
402 | padding: 14px 10px;
403 | background: #71d2d4;
404 | width: 80px;
405 | }
406 | .appointment__schedule ul li:hover {
407 | cursor: pointer;
408 | }
409 | .appointment__schedule ul li a {
410 | color: #fff;
411 | }
412 | .appointment__schedule h3 {
413 | width: 20%;
414 | margin: 0 auto;
415 | text-align: center;
416 | }
417 | .modal {
418 | background: rgba(0,0,0,0.5);
419 | position: fixed;
420 | width: 100%;
421 | height: 100%;
422 | left: 0;
423 | top: 0;
424 | }
425 | .modal--close {
426 | display: none;
427 | }
428 | .modal__box {
429 | background: #fff;
430 | width: 559px;
431 | position: absolute;
432 | left: 50%;
433 | top: 50%;
434 | transform: translate(-50%, -50%);
435 | padding: 20px;
436 | font-size: 20px;
437 | }
438 | .modal__box .fa-times {
439 | float: right;
440 | font-size: 25px;
441 | color: #808080;
442 | }
443 | .modal__box h3 {
444 | padding: 5px 0;
445 | color: #71d2d4;
446 | }
447 | .modal__box h3 span {
448 | color: #808080;
449 | font-weight: 300;
450 | margin-left: 8px;
451 | }
452 | .selection {
453 | margin-bottom: 21px;
454 | display: flex;
455 | flex-wrap: wrap;
456 | justify-content: space-between;
457 | padding: 30px;
458 | background: #e1e7ea;
459 | }
460 | .selection__block {
461 | width: 32%;
462 | display: flex;
463 | flex-direction: column;
464 | margin-bottom: 16px;
465 | -webkit-box-shadow: 0 3px 8px rgba(187,187,187,0.3);
466 | justify-content: space-between;
467 | height: 95px;
468 | }
469 | .selection__duo {
470 | display: flex;
471 | position: relative;
472 | }
473 | .selection__duo:nth-type(even) {
474 | margin-bottom: 0;
475 | }
476 | .selection__duo a {
477 | width: 100%;
478 | }
479 | .selection__duo .button {
480 | width: auto;
481 | padding: 10px;
482 | position: relative;
483 | }
484 | .selection__duo .button.addTime {
485 | text-align: center;
486 | }
487 | .selection__duo .fa {
488 | margin-right: 4px;
489 | padding: 14px 16px;
490 | background: #fff;
491 | }
492 | form .form--option {
493 | flex-basis: 200px;
494 | flex-grow: 1;
495 | margin: 0 12px;
496 | }
497 | form .three--col {
498 | display: flex;
499 | width: 100%;
500 | justify-content: space-between;
501 | margin: 0;
502 | }
503 | form .three--col label {
504 | width: 40%;
505 | }
506 | form .three--col label.sml--col {
507 | width: 28%;
508 | }
509 | form p {
510 | margin: 12px 0 6px 0;
511 | color: #fff;
512 | }
513 | form label {
514 | background: #f7f7f7;
515 | padding: 0 0 0 64px;
516 | position: relative;
517 | width: 100%;
518 | display: inline-block;
519 | margin-bottom: 20px;
520 | height: 50px;
521 | }
522 | form label input {
523 | height: 100%;
524 | width: 100%;
525 | outline: none;
526 | border: 0;
527 | background: #f7f7f7;
528 | }
529 | form label:after {
530 | content: "";
531 | width: 3px;
532 | height: 100%;
533 | background: #e1e7ea;
534 | position: absolute;
535 | left: 50px;
536 | top: 0;
537 | }
538 | form select,
539 | form textarea {
540 | display: block;
541 | }
542 | form select:hover,
543 | form textarea:hover {
544 | cursor: pointer;
545 | }
546 | form select {
547 | border: 0;
548 | outline: 0;
549 | width: 100%;
550 | height: 100%;
551 | -webkit-appearance: none;
552 | -webkit-border-radius: 0px;
553 | }
554 | form textarea {
555 | height: 150px;
556 | width: 100%;
557 | border: 0;
558 | border: 3px solid #fff;
559 | background: none;
560 | }
561 | form svg {
562 | width: 26px;
563 | position: absolute;
564 | left: 13px;
565 | top: 13px;
566 | }
567 | form .fa-cogs,
568 | form .fa-clock-o {
569 | font-size: 26px;
570 | position: absolute;
571 | left: 12px;
572 | top: 12px;
573 | }
574 | form.selection__duo {
575 | width: 100%;
576 | margin-bottom: 16px;
577 | }
578 | .textInput {
579 | padding: 12px;
580 | border: none;
581 | width: 100%;
582 | }
583 | .signIn__box {
584 | max-width: 490px;
585 | margin: 0 auto;
586 | padding: 16px 44px 26px 44px;
587 | position: relative;
588 | }
589 | .signIn__box .signIn__box--buttons {
590 | display: flex;
591 | justify-content: space-between;
592 | }
593 | .signIn__box .signIn__box--social {
594 | position: relative;
595 | }
596 | .signIn__box .signIn__box--social p {
597 | color: #71d2d4;
598 | background: #fff;
599 | position: relative;
600 | z-index: 1;
601 | display: inline-block;
602 | left: 50%;
603 | top: 8px;
604 | width: 45px;
605 | text-align: center;
606 | transform: translateX(-50%);
607 | }
608 | .signIn__box .signIn__box--social:after {
609 | content: "";
610 | background: #ebebeb;
611 | position: absolute;
612 | top: 30px;
613 | left: 0;
614 | width: 100%;
615 | height: 2px;
616 | }
617 | .signIn__box h2 {
618 | text-align: center;
619 | color: #808080;
620 | padding-bottom: 5px;
621 | position: relative;
622 | margin-bottom: 25px;
623 | }
624 | .signIn__box input {
625 | padding: 10px;
626 | width: 100%;
627 | border: none;
628 | margin: 10px 0;
629 | font-weight: 300;
630 | border: 2px solid #ebebeb;
631 | }
632 | .signIn__box .button--login {
633 | background: #71d2d4;
634 | bottom: 0;
635 | left: 0;
636 | width: 48%;
637 | margin-top: 10px;
638 | border: none;
639 | color: #fff;
640 | }
641 | .signIn__box .button--login:hover {
642 | background: #3abcbf;
643 | }
644 | .signIn__box .button--submit-bare {
645 | width: 48%;
646 | background: none;
647 | border: 2px solid #71d2d4;
648 | color: #71d2d4;
649 | }
650 | .signIn__box .button--submit-bare:hover {
651 | background: #71d2d4;
652 | color: #fff;
653 | }
654 | .signIn__box .button--google {
655 | background: #d23f31;
656 | border: none;
657 | color: #fff;
658 | margin-top: 29px;
659 | }
660 | .signIn__box .button--facebook {
661 | background: #3b5998;
662 | color: #fff;
663 | }
664 | .timesGrid {
665 | width: 100%;
666 | min-height: 100px;
667 | display: flex;
668 | justify-content: flex-start;
669 | align-items: flex-start;
670 | flex-wrap: wrap;
671 | }
672 | .timesGrid__single {
673 | padding: 13px 18px;
674 | background: #71d2d4;
675 | margin: 0 10px 10px 0;
676 | margin-right: 10px;
677 | color: #fff;
678 | }
679 | .timesGrid__single--inactive {
680 | background: #e6e7e8;
681 | color: #808080;
682 | }
683 | .addAppointment {
684 | width: 60px;
685 | height: 60px;
686 | background: #fbd20a;
687 | position: fixed;
688 | right: 50px;
689 | bottom: 50px;
690 | border-radius: 50%;
691 | display: flex;
692 | justify-content: center;
693 | align-items: center;
694 | box-shadow: 0 0 4px rgba(0,0,0,0.14), 0 4px 8px rgba(0,0,0,0.28);
695 | }
696 | .addAppointment .fa-plus {
697 | color: #fff;
698 | font-size: 2.5rem;
699 | transition: all 0.3s;
700 | }
701 | .addAppointment:hover .fa-plus {
702 | transform: rotate(45deg);
703 | }
704 | .menu__container {
705 | position: fixed;
706 | right: 78px;
707 | bottom: 120px;
708 | }
709 | .menu__container .menu {
710 | display: flex;
711 | flex-direction: column;
712 | justify-content: flex-end;
713 | width: 21px;
714 | transition: all 0.5s;
715 | }
716 | .menu__container .menu li {
717 | margin-right: 30px;
718 | margin-top: 11px;
719 | transition: all 0.3s;
720 | }
721 | .menu__container .menu li:hover .fa {
722 | background: #68b1b2;
723 | cursor: pointer;
724 | }
725 | .menu__container .menu li .fa {
726 | background: #71d2d4;
727 | width: 37px;
728 | height: 37px;
729 | border-radius: 50%;
730 | padding-top: 11px;
731 | padding-left: 2px;
732 | color: #fff;
733 | transition: all 0.3s;
734 | }
735 | .hide {
736 | opacity: 0;
737 | visibility: hidden;
738 | }
739 | .show {
740 | opacity: 1;
741 | visibility: visible;
742 | }
743 | .welcome {
744 | background: #e1e7ea;
745 | box-shadow: 5px 5px 8px -4px rgba(0,0,0,0.15);
746 | margin-top: 40px;
747 | }
748 | .welcome .welcome--wrapper {
749 | display: flex;
750 | }
751 | .welcome .welcome--right {
752 | width: 50%;
753 | padding: 40px;
754 | background-image: url("/src/assets/coffee-shop.jpg");
755 | background-repeat: no-repeat;
756 | background-position: center right;
757 | background-size: cover;
758 | position: relative;
759 | display: flex;
760 | justify-content: center;
761 | align-items: center;
762 | text-align: center;
763 | flex-direction: column;
764 | }
765 | .welcome .welcome--right h2 {
766 | color: #fff;
767 | }
768 | .welcome .welcome--right h1 {
769 | font-size: 3rem;
770 | }
771 | .welcome .welcome--right h1:before {
772 | width: 65px;
773 | height: 65px;
774 | }
775 | .welcome .welcome--right:before {
776 | content: "";
777 | background: rgba(58,86,144,0.8);
778 | position: absolute;
779 | top: 0;
780 | left: 0;
781 | bottom: 0;
782 | right: 0;
783 | }
784 | .welcome .welcome--left {
785 | width: 50%;
786 | padding: 7px;
787 | background: #fff;
788 | }
789 | .welcome .welcome--left p {
790 | color: #808080;
791 | text-align: center;
792 | padding-bottom: 10px;
793 | }
794 | .welcome h2 {
795 | font-size: 4rem;
796 | position: relative;
797 | z-index: 1;
798 | line-height: 1.3;
799 | margin-top: 20px;
800 | margin-bottom: 0;
801 | }
802 |
--------------------------------------------------------------------------------