How to Build a Booking System with Strapi and Nuxt
In this tutorial, we will learn how to build a simple hotel booking system with Strapi and NuxtJs. The hotel booking system will allow us to enter new guests into our database, send emails to our guests to notify them of their booking, and check out guests from the hotel.
Prerequisites
What'll you need for this tutorial:
Table of Contents:
- Getting started with Strapi
- Setting up our Strapi backend
- Setting users permission
- Building the front-end
- Using the Nuxt-Strapi module for authentication
- Setting up emails using Nodemailer
What you’ll Build
I hope you're excited about this project. Let's get started.
The Github repositories for this project can be found here:
Front-end
Backend
Getting Started with Strapi
What is Strapi?
The Strapi documentation says that "Strapi is a flexible, open-source Headless CMS that gives developers the freedom to choose their favorite tools and frameworks while also allowing editors to manage and distribute their content easily."
Strapi enables the world's largest companies to accelerate content delivery while building beautiful digital experiences by making the admin panel and API extensible through a plugin system.
Installing Strapi
The documentation works you through installing Strapi from the CLI, the minimum requirements for running Strapi, and how to create a quickstart project.
The Quickstart project uses SQLite as the default database, but feel free to use whatever database you like.
yarn create strapi-app my-project --quickstart //using yarn
npx create-strapi-app my-project --quickstart //using npx
Replace my-project
with the name you wish to call your application directory. Your package manager will create a directory with the name and will install Strapi.
If you have followed the instructions correctly, you should have Strapi installed on your machine.
yarn develop //using yarn
npm run develop //using npm
To start our development server, Strapi starts our app on http://localhost:1337/admin
.
Setting up our Strapi backend
Now let's start building the backend of our Application.
Creating the hotel Admin user for our application
The user we are creating here is the admin for our hotel booking system. Say an account has access to our Application and can add guests to the system.
- Open up your Strapi admin panel in your browser by visiting
localhost:1337/admin
. - On the sidebar under
collection, types
clickUsers
. - Click
Add new user
- Then add a
username
,password
,email
, and check the click theconfirm
button.
- Then add a
Building our Guests collection type
- On the sidebar under
plugins
, click onContent-Types builder
. - Click on
create new collection type
. - Fill in the display name as
guests
clickcontinue
.- Select the
text
field and label itfullname
, leave the selection asshort text
, then clickadd another field
- Repeat the procedure to create the
checkIn
,leaveDate
,status
fields as they are alltext
fields. Click onadd another field
. - Next, we add the
paid
field, which is aboolean
value. - Finally, select
Number
, name the fieldroomNo
, selectinteger
type.
- Select the
The final Guests
collection type should look like this:
Building our Rooms collection type
Next, we'll build our rooms
collection type.
- On the sidebar under
plugins
, click onContent-Types builder
- Click on
create new collection type
- Fill in the display name as
rooms
clickcontinue
- Select the
text
field and label ittype
, leave the selection asshort text
, then clickadd another field
- Next, we add the
occupied
field, which is aboolean
value, clickadd another field
- Select
Number
, name the fieldroomNo
, selectinteger
type, - Repeat the previous instruction to create a
beds
field which is also aninteger
- Finally, choose
Relation
, name the fieldguests
, then select a one-to-one relationship as follows
- Select the
The final version of your rooms
collection type should look like the image below.
Seeding the database
We'll have to add some data to our rooms
collection type. Follow the instructions below to do this
- In your Strapi admin panel, under
collection types
, click onRooms
- Click
add new rooms
and fill in the data appropriately.
Your rooms collection type should have the following data but feel free to add as many rooms as possible.
Next, we have to set up our user permission for authenticated users.
Setting user permission
- Click on Settings under
GENERAL
in the side menu - Click on
Roles
under Users and Permissions Plugin. - It will display a list of roles. Click on
authenticated
- Scroll down, under
Permissions
, click onApplication
, - Under
guests
clickselect all
, - Under
rooms
, clickselect all
- Click
save
, then go back.
Your Permissions should look exactly like this:
Installing Nuxt.js
Next, we will install and configure NuxtJs to work with our Strapi backend.
To install Nuxt.js, visit the Nuxt.js docs or run one of these commands to get started.
yarn create nuxt-app <project-name> //using yarn
npx create-nuxt-app <project-name> //using npx
npm init nuxt-app <project-name> //using npm
The command will ask you some questions (name, Nuxt options, U.I. framework, TypeScript, linter, testing framework, etc.).
We want to use Nuxt in SSR mode, Server Hosting, and Tailwind CSS as our preferred CSS framework, so select those, then choose whatever options for the rest.
Preferably leave out C.I., commit-linting, style-linting, and the rest but do whatever you like. All we'll be needing in this tutorial is what I've mentioned above.
Once all questions are answered, it will install all the dependencies. The next step is to navigate to the project folder and launch it.
cd <project-name
yarn dev //using yarn
npm run dev //using npm
We should have the Nuxt.js Application running on http://localhost:3000.
Building our Index page
Run the following command in your terminal to open up your index page
cd pages
code index.vue
Fill up the file with the following code
<template>
<div>
<Loading v-if="loading" />
<Login v-if="!loading"/>
</div>
</template>
<script>
import Loading from '~/components/Loading.vue'
export default {
components: { Loading },
middleware({ $auth, redirect }) {
if($auth.$storage.getCookie("authenticated") === true) {
redirect('/dashboard/guests')
}
},
data() {
return {
loading: true,
timeout: Math.floor(Math.random() * 1000),
}
},
mounted() {
setTimeout(() => {
this.loading = false;
}, this.timeout)
}
}
</script>
Building the loading component
Run the following command in your terminal to create a loading
component
cd components
touch Loading.vue
Fill up the file with the following code
<template>
<div>
<div class="grid items-center justify-center h-screen">
<div class="w-40 bg-blue-500 h-40 rounded-full"></div>
</div>
</div>
</template>
<script>
export default {
name: 'Loading'
}
</script>
<style scoped>
</style>
Building out our vuex store
Nuxt comes with a store directory pre-built for us. To activate our vuex
store, we have to create an index.js
file in the store directory as follows.
cd store
touch index.js
Fill it up with the following codes
export const state = () => ({
addGuest: false,
allGuests: [],
allRooms: []
})
export const getters = {
addGuest: state => state.addGuest,
// retrieve all guests from state
allGuests: state => state.allGuests,
// retrieve all rooms from state
allRooms: state => state.allRooms,
}
export const actions = {
toggleAddGuest({ commit }) {
commit('toggleAddGuest')
}
}
export const mutations = {
toggleAddGuest(state) {
state.addGuest = !state.addGuest
},
fetchGuests(state, guests) {
state.allGuests = guests
},
fetchRooms(state, rooms) {
state.allRooms = rooms
},
updateGuests(state, guest) {
state.allGuests.unshift(guest)
},
updateRoom(state, data) {
const { guest, active, room } = data
const curRoom = state.allRooms.find(el =>
el.id === room.id
)
state.allRooms[curRoom].guest = guest
state.allRooms[curRoom].active = active
}
}
We'll build out the login
component, but first, we need to install the @nuxtjs/strapi
package to assist us with that.
Using the @Nuxtjs/Strapi module for authentication
Installing @nuxtjs/strapi module
Run the following commands in order to install the module
yarn add @nuxtjs/strapi //using yarn
npm install @nuxtjs/strapi //using npm
Open up your nuxt.config.js
file and add the following
export default {
modules: [
//.....
'@nuxtjs/strapi'],
strapi: {
entities: ['guests', 'rooms']
}
}
Now we can use the module in our code as follows
await this.$strapi.login({ identifier: '', password: '' }) //for login
We'll also install the @nuxtjs/auth package for added protection on the front-end of our Application
Run the following commands in order to install the module
yarn add @nuxtjs/auth-next //using yarn
npm install @nuxtjs/auth-next //using npm
Open up your nuxt.config.js
file and add the following
modules: [
//...
'@nuxtjs/auth-next'
],
Building the login component
In order to create a Login
component, run the following commands
cd components
touch Login.vue
Fill it up with the following code
<template>
<div class="grid w-4/5 md:w-3/5 mx-auto items-center justify-center h-screen">
<div class="w-full">
<h1 class="font-black text-6xl mb-10">Welcome Admin</h1>
<form @submit="login">
<div class="">
<label for="username" class="w-full my-3">Username</label>
<input id="username" v-model="username" placeholder="Enter Username" type="text" class="w-full my-3 p-3 border-2">
</div>
<div class="">
<label for="password" class="my-3">Password</label>
<span class="">
<font-awesome-icon v-if="!passwordVisible" :icon="['fas', 'eye']" class="cursor-pointer w-5" @click='switchVisibility' />
<font-awesome-icon v-if="passwordVisible" :icon="['fas', 'eye-slash']" class="cursor-pointer text-gray-400 w-5" @click='switchVisibility' />
</span>
<div class="">
<input
id="password"
v-model="password" placeholder="Enter password"
:type="passwordFieldType"
class="my-3 p-3 border-2 w-full"
>
</div>
</div>
<button type="submit" class="flex items-center justify-center p-4 bg-blue-500 text-white my-3 rounded-lg">
Login <font-awesome-icon class="mx-3" :icon="['fas', 'arrow-right']" />
</button>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'Login',
middleware({ $auth }) {
if($auth.$storage.getCookie("authenticated") === true) {
redirect('/dashboard/guest')
}
},
data() {
return {
username: '',
password: '',
passwordFieldType: 'password',
passwordVisible: false
}
},
methods: {
async login(e) {
e.preventDefault()
try {
await this.$strapi.login({ identifier: this.username, password: this.password })
if(this.$strapi.user) {
this.$auth.$storage.setCookie("authenticated", true)
this.$router.push('/dashboard/guests')
}
} catch (e) {
alert('Wrong credentials', e)
}
},
switchVisibility() {
this.passwordFieldType = this.passwordFieldType === 'password' ? 'text' : 'password'
this.passwordVisible = !this.passwordVisible
}
}
}
</script>
<style scoped>
</style>
What we're doing here is just enabling the Admin user to Login to our Application. On success, we redirect the user to the dashboard/guest
page to perform admin functionalities. Then in the middleware function, we check if the user is logged in or not before granting access to the dashboard/guests
page.
Building our SideNav
component
To create a SideNav
component, run the following commands
cd components
touch SideNav.vue
Fill it up with the following code
<template>
<div>
<!-- side nav -->
<div class=" ">
<div class="">
<NuxtLogo class="w-20 mx-auto" />
</div>
<div class="text-white text-center w-full mb-5">
<NuxtLink to="/dashboard">
<div ref="index" class="p-5 w-1/3 text-xl mx-auto rounded-full">
<font-awesome-icon :icon="['fas', 'home']" />
</div>
<p class="text-sm text-white">Home</p>
</NuxtLink>
</div>
<div class="text-white text-center w-full mb-5">
<NuxtLink to="/dashboard/guests">
<div ref="guests" class="p-5 w-1/3 text-xl mx-auto rounded-full">
<font-awesome-icon :icon="['fas', 'users']" />
</div>
<p class="text-sm text-white">Guests</p>
</NuxtLink>
</div>
<div class="text-white text-center w-full my-5">
<NuxtLink to="/dashboard/rooms">
<div ref="rooms" class="w-1/3 text-xl mx-auto rounded-full p-5">
<font-awesome-icon :icon="['fas', 'bed']" />
</div>
<p class="text-sm text-white">Rooms</p>
</NuxtLink>
</div>
<div class="text-white text-center cursor-pointer w-full my-7">
<p @click="logout">Logout</p>
</div>
</div>
<!-- end of first div -->
</div>
</template>
<script>
export default {
name: 'SideNav',
props: ['page'],
methods: {
async logout() {
await this.$strapi.logout()
.then(() => {
this.$auth.$storage.setCookie("authenticated", false)
this.$nuxt.$router.push('/')
})
}
},
mounted() {
// get current link item
const item = this.$refs[this.page]
// change it's class
const addClass = ['bg-purple-800', 'shadow-xl']
addClass.forEach(e => {
item.classList.add(e)
});
}
}
</script>
<style scoped>
</style>
The SideNav
component hold our logout
method which calls the
this.$strapi.logout()
method.
Building the dashboard/index
page
Run the following commands to create a pages/dashboard/index
page
cd pages
mkdir dashboard
cd dashboard
touch index.vue
Fill it up with the following code
<template>
<div>
<div class="flex w-screen flex-row">
<!-- first div here -->
<!-- side menu -->
<SideNav class="hidden sm:block sm:w-1/6 h-screen bg-purple-600" :page="routeName" />
<!-- main display -->
<!-- second div here -->
<div class="w-full overflow-x-hidden md:w-5/6 h-screen">
<div class="w-screen h-10 m-8">
<h1 class="font-black">Welcome, user</h1>
</div>
<div class="w-4/5 mx-auto min-h-screen">
<div class="block sm:grid sm:grid-cols-2 sm:gap-4 mb-10 items-center justify-center">
<div class="mb-10 sm:mb-0 w-full rounded-xl p-28 bg-pink-300">
</div>
<div class="mb-10 sm:mb-0 w-full rounded-xl p-32 h-full bg-green-300">
</div>
</div>
<div class='w-full rounded-xl mb-20 p-32 h-full bg-blue-300'>
</div>
</div>
</div>
<!-- end of second div -->
</div>
</div>
</template>
<script>
export default {
data() {
return {
routeName: 'index'
}
},
}
</script>
<style scoped>
</style>
Building the dashboard/rooms
page
Run the following commands to create a pages/dashboard/rooms
page
cd pages
cd dashboard
touch rooms.vue
Fill it up with the following code
<template>
<div>
<div class="flex w-screen flex-row">
<!-- first div here -->
<!-- side menu -->
<SideNav class="hidden sm:block sm:w-1/6 h-screen bg-purple-600" :page="routeName" />
<!-- main display -->
<!-- second div here -->
<div class="w-full overflow-x-hidden md:w-5/6 h-screen">
<div class="w-screen h-10 m-8">
<h1 class="font-black">All Rooms</h1>
</div>
<div class="w-4/5 mx-auto min-h-screen">
<div class="block sm:grid sm:grid-cols-2 sm:gap-4 mb-10 items-center justify-center">
<div class="mb-10 sm:mb-0 w-full rounded-xl p-28 bg-pink-300">
</div>
<div class="mb-10 sm:mb-0 w-full rounded-xl p-32 h-full bg-green-300">
</div>
</div>
<div class='w-full rounded-xl mb-20 p-32 h-full bg-blue-300'>
</div>
</div>
</div>
<!-- end of second div -->
</div>
</div>
</template>
<script>
export default {
data() {
return {
routeName: 'rooms'
}
},
}
</script>
<style scoped>
</style>
Building the dashboard/guests
page
Run the following commands to create a pages/dashboard/guests
page
cd pages
cd dashboard
touch guests.vue
Fill it up with the following code
<template>
<div>
<div ref="guest" class="flex w-screen flex-row">
<!-- first div here -->
<!-- side menu -->
<SideNav class="hidden sm:block sm:w-1/6 h-screen bg-purple-600" :page="routeName" />
<!-- main display -->
<!-- second div here -->
<div class="w-full relative overflow-x-hidden md:w-5/6 h-screen">
<div v-if="addGuest" class="w-screen h-full top-0 bottom-0 z-10 fixed bg-opacity-30 bg-gray-300">
<AddGuest class="z-10 top-5 left-0 overflow-y-scroll right-0 shadow-2xl bottom-5 bg-white mx-auto fixed" />
</div>
<div class="w-screen h-10 m-8">
<h1 class="text-2xl text-gray-500 font-black">Manage Guests</h1>
</div>
<div class="w-4/5 mx-auto min-h-screen">
<div class="block sm:grid sm:grid-cols-2 sm:gap-4 mb-10 items-center justify-center">
<!-- active users -->
<div class="mb-10 sm:mb-0 shadow-2xl grid grid-cols-2 items-center justify-center gap-6 text-white w-full rounded-xl p-8 lg:p-16 bg-pink-500">
<font-awesome-icon class="text-6xl lg:text-8xl" :icon="['fas', 'users']" />
<div class="text-2xl font-bold">
<p>Over {{ allGuests.length }} Guests Lodged </p>
</div>
</div>
<!-- messages -->
<div class="">
<div class="my-3 font-black">
<font-awesome-icon :icon="['fas', 'bell']" /> Notifications
</div>
<div class="mb-10 sm:mb-0 w-full divide-y divide-white text-sm relative rounded-xl text-white p-5 h-32 overflow-y-scroll bg-green-500">
<p class="p-2">
<font-awesome-icon :icon="['fas', 'circle']" />
Alexander Godwin checked just checked into room 43
</p>
<p class="p-2">
<font-awesome-icon :icon="['fas', 'circle']" />
Alexander Godwin checked just checked into room 43
</p>
</div>
</div>
</div>
<!-- table part -->
<div class="w-full grid grid-cols-2 space-between items-center">
<h1 class="my-5 text-2xl font-black">All Guests</h1>
<div class="text-right">
<button class="p-3 text-white rounded-md bg-gray-500" @click="toggleAddGuest">
Add Guest <font-awesome-icon class="ml-2" :icon="['fas', 'plus']" />
</button>
</div>
</div>
<div class='w-full rounded-xl overflow-x-scroll mb-20 min-h-full bg-white'>
<div class="table w-full">
<div class="w-full table-row-group">
<!-- heading row -->
<div class="table-row bg-black rounded-xl text-white">
<div class="table-cell">
<div class="m-3">Name</div>
</div>
<div class="table-cell">
<div class="m-3">Room NO.</div>
</div>
<div class="table-cell">
<div class="m-3">Status</div>
</div>
<div class="table-cell">
<div class="m-3">Paid</div>
</div>
<div class="table-cell">
<div class="m-3">Checked In</div>
</div>
<div class="table-cell">
<div class="m-3">Leave Date</div>
</div>
<div class="table-cell">
<div class="m-3">Action</div>
</div>
</div>
<!-- end of heading row -->
<div v-for="(guest, i) in allGuests" :key="i" class="table-row bg-gray-500 text-white">
<div class="table-cell">
<div class="m-3">{{ guest.fullname }}</div>
</div>
<div class="table-cell">
<div class="m-3">{{ guest.roomNo }}</div>
</div>
<div class="table-cell">
<div class="m-3">{{ guest.status }}</div>
</div>
<div class="table-cell">
<div class="m-3">{{ guest.paid }}</div>
</div>
<div class="table-cell">
<div class="m-3">{{ guest.checkIn }} </div>
</div>
<div class="table-cell">
<div class="m-3">{{ guest.leaveDate }}</div>
</div>
<div>
<button v-if="guest.status === 'active'" @click="checkOut(guest)" class="p-2 m-3 bg-green-500">
check-out
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- end of second div -->
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
middleware({ $strapi, $auth, redirect }) {
if($auth.$storage.getCookie("authenticated") === false) {
redirect('/')
}
},
async asyncData({ $strapi, store }) {
const guests = await $strapi.$guests.find({
_sort: 'published_at:DESC'
})
store.commit('fetchGuests', guests)
const rooms = await $strapi.$rooms.find()
store.commit('fetchRooms', rooms)
},
data() {
return {
routeName: 'guests',
}
},
methods: {
...mapActions(['toggleAddGuest']),
async checkOut(guest) {
await this.$strapi.$rooms.update(guest.roomNo, {
guests: null,
occupied: false
})
const rooms = await this.$strapi.$rooms.find()
this.$store.commit('fetchRooms', rooms)
await this.$strapi.$guests.update(guest.id, {
status: 'inactive'
})
const guests = await this.$strapi.$guests.find({
_sort: 'published_at:DESC'
})
this.$store.commit('fetchGuests', guests)
},
},
computed: {
...mapGetters(['addGuest', 'allGuests', 'allRooms'])
},
}
</script>
<style scoped>
</style>
This guests
page has most of our functionality, as it allows us to:
- Fetch
guests
from our Strapi API and push them to our vuex store - Display all our guests at a table.
- Fetch
rooms
from our Strapi API and push them to the vuex store - Check out a
guest
from the hotel.
When a guest is checked-out from the hotel their status becomes inactive and the check out button is not displayed for them.
Building the add guest
component
We'll build the component to add the guest to a free hotel room in our database. Run the following commands to create a AddGuests
component
cd components
touch AddGuests.vue
Fill it up with the following code
<template>
<div class="p-10 shadow-xl shadow-yellow-300 w-3/4 sm:w-1/2 rounded-xl max-h-screen">
<div class="m-2">
<h1 class="font-black text-yellow-800">New Guest</h1>
</div>
<div>
<form @submit.prevent="newGuest">
<div class="p-2 text-sm">
<label class="font-bold text-yellow-800 text-sm" for="checkin">FullName</label>
<input v-model="fullname" type="text" class="py-3 pr-3 w-full border-b-2 border-gray-200 focus:outline-none hover:border-yellow-300">
</div>
<div class="p-2 text-sm">
<label class="font-bold text-yellow-800 text-sm" for="checkin">Email</label>
<input v-model="email" type="email" class="py-3 pr-3 w-full border-b-2 border-gray-200 focus:outline-none hover:border-yellow-300">
</div>
<!-- check in and check out -->
<div class="p-2">
<div class="mb-3 text-sm">
<label class="font-bold text-yellow-800" for="checkin">Check In</label>
<input v-model="checkIn" id="checkin" class="py-3 pr-3 w-full border-b-2 border-gray-200 focus:outline-none hover:border-yellow-300" type="date">
</div>
<div class="text-sm">
<label class="font-bold text-yellow-800 text-sm" for="leavedate">Leave Date</label>
<input v-model="leaveDate" id="leavedate" class="py-3 pr-3 w-full border-b-2 border-gray-200 focus:outline-none hover:border-yellow-300" type="date">
</div>
</div>
<div class="text-sm p-2">
<label for="rooms" class="text-sm text-yellow-800 font-bold">Select Room</label>
<select v-model="RoomNo" id="rooms" name="" class="py-3 pr-3 w-full border-b-2 border-gray-200 focus:outline-none hover:border-yellow-300">
<option v-for="(room, i) in allRooms.filter(el => el.occupied === false).map(el => el.roomNo)" :key="i" :value="room">{{ room }}</option>
</select>
</div>
<div class="my-3">
<button class="p-3 bg-green-500 text-white" type="submit">
Submit
</button>
<button class="p-3 bg-red-500 text-white" @click.prevent="toggleAddGuest">
Cancel
</button>
</div>
</form>
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
name: 'AddGuest',
data() {
return {
fullname: '',
RoomNo: '',
checkIn: '',
leaveDate: '',
email: ''
}
},
computed: {
...mapGetters(['allRooms'])
},
methods: {
async newGuest() {
const newGuest = {
fullname: this.fullname,
checkIn: this.checkIn,
leaveDate: this.leaveDate,
roomNo: parseInt(this.RoomNo),
status: 'active',
paid: true,
email: this.email
}
const { guest } = await this.$strapi.$guests.create(newGuest)
console.log("guest", guest)
await this.$strapi.$rooms.update(this.RoomNo, {
occupied: true,
guest
})
this.$store.commit('updateGuests', guest)
const rooms = await this.$strapi.$rooms.find()
this.$store.commit('fetchRooms', rooms)
this.toggleAddGuest()
},
...mapActions(['toggleAddGuest',])
}
}
</script>
<style scoped>
</style>
The result of the code above. I have just one empty room left in my database since the other two rooms are occupied, so I can only select room 2.
Next, we'll build a feature into our backend that allows us to send emails to our guests once they are added to our database.
Setting up emails using Nodemailer
To set up emails with Nodemailer, open up the folder with your Strapi code in your favorite code editor. Then follow the instructions below:
Installing Nodemailer
To install nodemailer, run the following command from your terminal.
yarn add nodemailer //using yarn
npm install nodemailer //using npm
Once that's done, run the following commands to create an api/emails/services/Email.js
file in your Strapi code base
cd api
mkdir emails
cd emails
mkdir services
cd services
touch Email.js
Open up the Email.js
file and fill it up with the following code
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
service: 'gmail',
port: '465',
secure: true,
host: 'smtp.gmail.com',
auth: {
user: process.env.USERNAME,
pass: process.env.PASSWORD,
},
});
module.exports = {
send: (from, to, subject, text) => {
// Setup e-mail data.
const options = {
from,
to,
subject,
text,
};
// Return a promise of the function that sends the email.
return transporter.sendMail(options);
},
};
Next up locate the .env/example
file and rename it to .env
the add the following lines.
USERNAME=<YOUR_EMAIL>
PASSWORD=<YOUR_PASSWORD>
Remember to replace both <YOUR_EMAIL>
and <YOUR_PASSWORD>
with your actual email address and password.
In order to use the email function in our code, open up the api/guests/controllers/guest.js
file and fill it up with the following code
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/developer-docs/latest/development/backend-customization.html#core-controllers)
* to customize this controller
*/
module.exports = {
async create(ctx) {
let { fullname: name, email, roomNo, checkIn, leaveDate } = ctx.request.body
strapi.services.email.send(
'alecgee73@gmail.com',
email,
'Room booked successfully',
`Hello ${name}, Welcome to Mars hotel,you booked ${roomNo} from ${checkIn} to ${leaveDate} enjoy yourself`
)
.then((res) => console.log(res))
.catch(err => console.log(err))
ctx.send({
guest : await strapi.query('guests').create(ctx.request.body)
})
}
};
What we're doing here is modifying the Strapi to create
a function to do the following;
- Call the email service we created using the
strapi.services.email.send()
function, to send an email to our new guest, - Create the new guest in our database using the
strapi.query().create()
function, - Finally returning the created guest using
ctx.send()
function.
Now whenever a new guest is created, they will receive an email from the hotel booking system.
Conclusion
What we've seen so far is how to create a simple hotel booking system using Strapi. You could do more, add more features and tailor the Application according to your needs. No matter what front-end framework you are using, the Strapi logic remains the same, and that's nice, Be sure to do more and explore.