├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json └── src ├── App.js ├── assets ├── icons │ ├── all.png │ ├── appointments.png │ ├── body.png │ ├── close.png │ ├── line.png │ ├── logo.png │ ├── makeup.png │ ├── massage.png │ ├── menu.png │ ├── messages.png │ ├── nails.png │ ├── refresh.png │ ├── scroll.png │ ├── star.png │ ├── tick.png │ ├── tickbox.png │ ├── waxing.png │ └── zoom.png └── images │ ├── banner_01.jpeg │ ├── banner_02.jpeg │ ├── banner_03.jpeg │ ├── image2.jpeg │ ├── image3.jpeg │ ├── image4.jpeg │ ├── image5.jpeg │ ├── image6.jpeg │ └── salon.jpeg ├── components ├── About │ ├── About.js │ └── About.module.scss ├── Admin │ ├── Appointments │ │ ├── Appointment │ │ │ ├── Appointment.js │ │ │ └── Appointment.module.scss │ │ ├── Appointments.js │ │ ├── Appointments.module.scss │ │ └── Preview │ │ │ ├── Preview.js │ │ │ └── Preview.module.scss │ ├── Auth │ │ ├── Auth.js │ │ └── Auth.module.scss │ ├── Inbox │ │ ├── Inbox.js │ │ ├── Inbox.module.scss │ │ ├── Message │ │ │ ├── Message.js │ │ │ └── Message.module.scss │ │ └── Preview │ │ │ ├── Preview.js │ │ │ └── Preview.module.scss │ └── Menu │ │ ├── Menu.js │ │ └── Menu.module.scss ├── Booking │ ├── Checkout │ │ ├── Checkout.js │ │ ├── Checkout.module.scss │ │ └── Stripe │ │ │ ├── CardSectionStyles.css │ │ │ └── Stripe.js │ ├── Details │ │ ├── Details.js │ │ └── Details.module.scss │ ├── Schedule │ │ ├── Schedule.js │ │ └── Schedule.module.scss │ └── Success │ │ ├── Success.js │ │ └── Success.module.scss ├── Contacts │ ├── Contacts.js │ ├── Contacts.module.scss │ ├── Form │ │ ├── Form.js │ │ └── Form.module.scss │ └── Map │ │ └── Map.js ├── Footer │ ├── Footer.js │ └── Footer.module.scss ├── Gallery │ ├── Gallery.js │ └── Gallery.module.scss ├── Navigation │ ├── Navigation.js │ └── Navigation.module.scss ├── Services │ ├── Services.js │ ├── Services.module.scss │ └── availableServices.js ├── Summary │ ├── Summary.js │ └── Summary.module.scss ├── Testimonials │ ├── Testimonials.js │ └── Testimonials.module.scss └── UI │ └── Spinner │ ├── Spinner.js │ └── Spinner.module.scss ├── config └── constants.js ├── containers ├── Admin │ ├── Admin.js │ └── Admin.module.scss ├── Banner │ ├── Banner.js │ └── Banner.module.scss ├── Booking │ ├── Booking.js │ └── Booking.module.scss └── Section │ ├── Section.js │ └── Section.module.scss ├── hoc └── Layout │ ├── Layout.js │ ├── Layout.module.scss │ └── reset.css └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .eslintcache 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :cherry_blossom: About 2 | 3 | Beauty at Luxx is a single page application build for a beauty salon with integrated booking system. 4 | 5 | Website preview: 6 | https://mivladie.github.io/beautyatluxx/ 7 | 8 | # :memo: Table of Contents 9 | 10 | * [:memo: Table of Contents](#memo-table-of-contents) 11 | * [:rocket: Quick Start](#rocket-quick-start) 12 | * [Step 1: Installing the dependencies](#step-1-installing-the-dependencies) 13 | * [Step 2: Setting up configurations](#step-2-setting-up-configurations) 14 | * [Step 3: Launching the server](#step-3-launching-the-server) 15 | * [:desktop_computer: Installation](#desktop_computer-installation) 16 | * [NodeJS](#nodejs) 17 | * [:keyboard: Available Scripts](#keyboard-available-scripts) 18 | * [:green_book: Learn More](#green_book-learn-more) 19 | * [ReactJS](#reactjs) 20 | * [React Google Maps](#react-google-maps) 21 | * [Stripe](#stripe) 22 | * [Sass](#sass) 23 | 24 | # :rocket: Quick Start 25 | 26 | > You must have installed all of the software applications in the [installation](#desktop_computer-installation) section. 27 | 28 | Quick start guide to set the server up and running. 29 | 30 | ## Step 1: Installing the dependencies 31 | 32 | ### Run `npm install` 33 | 34 | Installs all of the necessary dependencies. 35 | 36 | ## Step 2: Setting up configurations 37 | 38 | ### Google Maps (optional) 39 | 40 | * Open `/src/config/constants.js` file; 41 | * Assign the API key to the `GOOGLE_MAPS_API_KEY` constant; 42 | * Save the file. 43 | 44 | ### Stripe 45 | 46 | * Open `/src/config/constants.js` file; 47 | * Assign the Stripe publishable key to the `STRIPE_PUBLISHABLE_KEY` constant; 48 | * Save the file. 49 | 50 | ## Step 3: Launching the server 51 | 52 | ### Run `npm start` 53 | 54 | Starts the server in the development mode. 55 | 56 | # :desktop_computer: Installation 57 | 58 | In order to run the server, you must have installed all of the necessary software listed below. 59 | 60 | ## NodeJS 61 | 62 | Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. 63 | 64 | * [Download](https://nodejs.org/en/) 65 | 66 | # :keyboard: Available Scripts 67 | 68 | In the project directory, you can run: 69 | 70 | ### `npm install` 71 | 72 | Installs all of the necessary dependencies. 73 | 74 | ### `npm start` 75 | 76 | Runs the app in the development mode on port `:3000`. 77 | 78 | ### `npm run build` 79 | 80 | Builds the app for production to the `/build` folder. 81 | 82 | # :green_book: Learn More 83 | 84 | References to the packages used in the project. 85 | 86 | ## ReactJS 87 | 88 | React is a JavaScript library for building user interfaces. 89 | 90 | * [Getting Started](https://reactjs.org/docs/getting-started.html) 91 | 92 | ## React Google Maps 93 | 94 | `react-google-maps` provides a set of React components wrapping the underlying Google Maps JavaScript API v3 instances. 95 | 96 | * [Documentation](https://tomchentw.github.io/react-google-maps/#documentation) 97 | 98 | ## Stripe 99 | 100 | Stripe is a technology company that builds economic infrastructure for the internet. 101 | 102 | * [Documentation](https://stripe.com/docs) 103 | 104 | ## Sass 105 | 106 | Sass is a preprocessor scripting language that is interpreted or compiled into CSS. 107 | 108 | * [Documentation](https://sass-lang.com/documentation) 109 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "beautyatluxx", 3 | "version": "1.0.0", 4 | "homepage": "https://mivladie.github.io/beautyatluxx/", 5 | "private": true, 6 | "scripts": { 7 | "start": "react-scripts start", 8 | "build": "react-scripts build", 9 | "predeploy": "npm run build", 10 | "deploy": "gh-pages -d build", 11 | "test": "react-scripts test", 12 | "eject": "react-scripts eject" 13 | }, 14 | "eslintConfig": { 15 | "extends": "react-app" 16 | }, 17 | "browserslist": { 18 | "production": [ 19 | ">0.2%", 20 | "not dead", 21 | "not op_mini all" 22 | ], 23 | "development": [ 24 | "last 1 chrome version", 25 | "last 1 firefox version", 26 | "last 1 safari version" 27 | ] 28 | }, 29 | "dependencies": { 30 | "@stripe/react-stripe-js": "^1.16.1", 31 | "@stripe/stripe-js": "^1.46.0", 32 | "axios": "^1.2.1", 33 | "react": "^16.14.0", 34 | "react-dom": "^16.14.0", 35 | "react-google-maps": "^9.4.5", 36 | "react-scripts": "^5.0.1" 37 | }, 38 | "devDependencies": { 39 | "gh-pages": "^4.0.0", 40 | "sass": "^1.56.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MiVladie/beautyatluxx/4eca17ac5d2b40661db0e997cb427aa40656af80/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 |Praesent felis felis, pretium sit amet vehicula at, posuere at mauris.
19 |Praesent felis felis, pretium sit amet vehicula at, posuere at mauris.
25 |Praesent felis felis, pretium sit amet vehicula at, posuere at mauris.
31 |Praesent felis felis, pretium sit amet vehicula at, posuere at mauris.
37 |Name: { name }
22 |Email: { email }
25 |Booked At: { bookedAt.getDate() + '/' + (bookedAt.getMonth() + 1) + '/' + bookedAt.getFullYear() + ' ' + bookedAt.getHours() + ':' + (bookedAt.getMinutes() < 10 ? '0' : '') + bookedAt.getMinutes() }
31 |Phone: { phone }
34 |Appointment Date: { date.getDate() + '/' + (date.getMonth() + 1) + '/' + date.getFullYear() + ' ' + date.getHours() + ':' + (date.getMinutes() < 10 ? '0' : '') + date.getMinutes() }
40 |Payment: { payment }
43 |Services: { listedServices }
49 |{ payment === 'venue' ? 'Due pay:' : 'Amount paid:' }{ price }
52 |{ appointment.name }
{ appointment.payment }
{ appointment.service }
{ appointment.date.getDate() + '/' + (appointment.date.getMonth() + 1) + '/' + appointment.date.getFullYear() + ' ' + appointment.date.getHours() + ':' + (appointment.date.getMinutes() < 10 ? '0' : '') + appointment.date.getMinutes() }
Total appointments: { allAppointments.length }
45 | 46 |Name: { name }
17 |Email: { email }
20 |Date: { date }
26 |Phone: { phone }
29 |Message: { text }
34 |{ name }
{ contact }
{ text }
{ date }
Total messages: { Object.keys(messages).length }
38 | 39 |Messages
16 |Appointments
21 |Close
26 |{ ('0' + new Date(data.service.time).getHours()).slice(-2) + ":" + ('0' + new Date(data.service.time).getMinutes()).slice(-2) }
41 | 42 |{ new Date(data.service.time).getDate() + ' ' + monthNames[new Date(data.service.time).getMonth()] }
{ weekNames[new Date(data.service.time).getDay()] }
{ service.name }
51 |{ service.duration >= 60 && (~~(service.duration / 60) + ' hrs') } { service.duration % 60 !== 0 ? service.duration % 60 + ' mins' : '' }
52 |Payment method:
62 |{ data.details.payment === 'venue' ? 'Pay at venue' : 'Pay with card' }
63 |{ meta }
} 67 |Order total:
73 |£{ countTotalPrice() }
74 |By clicking 'Pay now' button, you agree to our Booking Terms
} 81 | 82 |Please, enter your information
28 | 29 |Please, choose the payment method
44 | 45 |Please, provide a valid email address
} 54 | 55 |{ weekNames[day.getDay()] }
60 | { day.getDate() } 61 |Sorry, there are no available slots.
Please, select another day.
{ ('0' + new Date(time).getHours()).slice(-2) + ":" + ('0' + new Date(time).getMinutes()).slice(-2) }
70 |Select
71 | 72 |An email with the appointment details was sent to: { email }
17 |Have any questions? Feel free to use contact form below to get in touch with us. We will answer you as soon as possible!
25 | 26 | 27 |
27 | Copyright Beauty at Luxx © {new Date().getFullYear()}
28 | All Rights Reserved
29 |
31 | Website created by{' '} 32 | 33 | 34 | letscomit 35 | 36 | 37 |
38 |{ services[service - 1].name }
55 |now £{ ('' + services[service - 1].price).includes('.') ? services[service - 1].price.toFixed(2) : services[service - 1].price }
56 |{ services[service - 1].duration >= 60 && (~~(services[service - 1].duration / 60) + ' hrs') } { services[service - 1].duration % 60 !== 0 ? services[service - 1].duration % 60 + ' mins' : '' }
60 |save up to 20%
61 |{ category.name }
78 |{ types[type - 1].name }
87 | { types[type - 1].services.some(e => activeServices.includes(e)) ? : '' } 88 |Vestibulum ut mauris euismod, tristique augue sed, consequat metus. Duis fermentum massa ac metus suscipit tincidunt. Praesent felis felis, pretium sit amet vehicula at, posuere at mauris.
12 |
18 | Monday:
19 | 10:00 AM - 6:30 PM
20 |
21 | Tuesday:
22 | 10:00 AM - 6:30 PM
23 |
24 | Wednesday:
25 | 10:00 AM - 8:00 PM
26 |
27 | Thursday:
28 | 10:00 AM - 8:00 PM
29 |
30 | Friday:
31 | 10:00 AM - 6:30 PM
32 |
33 | Saturday:
34 | 10:00 AM - 6:00 PM
35 |
36 | Sunday:
37 | 11:00 AM - 5:00 PM
38 |
39 |
46 | Address:
47 | 43 High Street, Ealing,
London, W5 5DB
48 |
49 | Phone:
50 | +44 7342 216193
51 |
52 | Email:
53 | letscomit@gmail.com
54 |
55 |
{ review.text }
26 |Our qualified expert provides a full range of services to meet all customer needs.
29 | Book now 30 |{ error }
149 | : process === 'Schedule' && !loading 150 | ?{ props.description }
13 |