diff --git a/code/Client/src/LayOut/DashboardLayout.jsx b/code/Client/src/LayOut/DashboardLayout.jsx index 89bca51c84e3a38263570de72272a0d7fc1aeb6b..e9a6dc28fe0803766646d9389ddc789c249c77bf 100644 --- a/code/Client/src/LayOut/DashboardLayout.jsx +++ b/code/Client/src/LayOut/DashboardLayout.jsx @@ -3,6 +3,7 @@ import Sidebar from './Sidebar'; import ReservesAdmin from '../pages/ReservesAdmin'; import AdminPanelServices from '../components/Services/AdminPanelServices'; import FormCRUDRooms from '../components/Rooms/FormCRUDRooms'; +import AccountForm from '../components/accounts/AccountForm'; function DashboardLayout() { // State to control which component to display @@ -17,6 +18,7 @@ function DashboardLayout() { {activeComponent === 'reserves' && <ReservesAdmin />} {activeComponent === 'services' && <AdminPanelServices />} {activeComponent === 'rooms' && <FormCRUDRooms />} + {activeComponent === 'accounts' && <AccountForm />} </div> </div> ); diff --git a/code/Client/src/LayOut/Sidebar.jsx b/code/Client/src/LayOut/Sidebar.jsx index 1f6ab08410467b4337ebe0758ebae0c398dcb0b9..0eefaaf6d643fb7eba30f4a790edae20364381e2 100644 --- a/code/Client/src/LayOut/Sidebar.jsx +++ b/code/Client/src/LayOut/Sidebar.jsx @@ -9,6 +9,7 @@ function Sidebar({ setActiveComponent }) { <li onClick={() => setActiveComponent('reserves')} className="block py-2 hover:bg-gray-100 hover:text-black cursor-pointer">Reserves</li> <li onClick={() => setActiveComponent('services')} className="block py-2 hover:bg-gray-100 hover:text-black cursor-pointer">Services</li> <li onClick={() => setActiveComponent('rooms')} className="block py-2 hover:bg-gray-100 hover:text-black cursor-pointer">Rooms</li> + <li onClick={() => setActiveComponent('accounts')} className="block py-2 hover:bg-gray-100 hover:text-black cursor-pointer">Accounts</li> </ul> </div> ); diff --git a/code/Client/src/components/PopUp.jsx b/code/Client/src/components/PopUp.jsx new file mode 100644 index 0000000000000000000000000000000000000000..519135839ea2b44a22b21147fd594491b507bb4f --- /dev/null +++ b/code/Client/src/components/PopUp.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/react/24/outline' +import FormButton from './registerComponents/FormButton'; + +const PopUp = ({information, firstButtonText, firstButtonOnClick, secondButtonText, secondButtonOnClick}) => { + return ( + <div className=" bg-black absolute bg-opacity-60 z-10 flex w-full h-full items-center justify-center"> + <div className="w-1/5 min-w-56 h-1/6 min-h-32 bg-gray-300 rounded-lg shadow-lg flex flex-col py-4 justify-between items-center"> + + <h3 className="primary-text text-center">{information}</h3> + + <div className='flex flex-row gap-7'> + <button onClick={firstButtonOnClick} type="button" className="bg-gray-600 hover:bg-gray-400 text-white font-bold h-1/5 min-h-10 px-4 rounded-xl focus:outline-none focus:shadow-outline flex items-center justify-center"> + <span className="">{firstButtonText}</span> + </button> + <button onClick={secondButtonOnClick} type="button" className="bg-red-700 hover:bg-red-500 text-white font-bold h-1/5 min-h-10 px-4 rounded-xl focus:outline-none focus:shadow-outline flex items-center justify-center"> + <span className="">{secondButtonText}</span> + </button> + </div> + </div> + + </div> + ); +}; + +export default PopUp; diff --git a/code/Client/src/components/accounts/AccountCountryRegionSelector.jsx b/code/Client/src/components/accounts/AccountCountryRegionSelector.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7bd94e3f29e4398644f227a47ad69123b1356028 --- /dev/null +++ b/code/Client/src/components/accounts/AccountCountryRegionSelector.jsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { CountryDropdown, RegionDropdown } from 'react-country-region-selector'; + +const AccountCountryRegionSelector = ({ country, selectCountry, region, selectRegion, countryError, regionError }) => { + return ( + <div className="flex flex-wrap"> + <div className="block mb-2 w-1/2 pr-2"> + <label className="block mb-2 text-sm font-medium text-gray-900 w-1/2 pr-2">Country</label> + <CountryDropdown + className={`block w-full p-3 border ${countryError ? 'border-red-500' : 'border-gray-300'} rounded`} + value={country} + onChange={selectCountry} + defaultOptionLabel = "Select a country" + /> + {countryError && <p className="text-red-500 text-xs italic">{countryError}</p>} + </div> + <div className="block mb-2 w-1/2 pl-2"> + <label className="block mb-2 text-sm font-medium text-gray-900 w-1/2 pr-2">Region</label> + <RegionDropdown + className={`block w-full p-3 border ${regionError ? 'border-red-500' : 'border-gray-300'} rounded`} + country={country} + value={region} + blankOptionLabel = "Select a region" + onChange={selectRegion} /> + {regionError && <p className="text-red-500 text-xs italic">{regionError}</p>} + </div> + </div> + ); +}; + +export default AccountCountryRegionSelector; \ No newline at end of file diff --git a/code/Client/src/components/accounts/AccountForm.jsx b/code/Client/src/components/accounts/AccountForm.jsx new file mode 100644 index 0000000000000000000000000000000000000000..a3dcf71bad632e2650668570eab53ae940f6532e --- /dev/null +++ b/code/Client/src/components/accounts/AccountForm.jsx @@ -0,0 +1,179 @@ +import React, { useState, useContext } from 'react'; +import Axios from '../../services/Axios'; +import { AuthContext } from '../loginComponents/AuthContext.jsx'; +import { toast } from 'react-toastify'; +import { useFormik } from 'formik'; +import * as Yup from 'yup'; +import AccountFormBox from './AccountFormBox.jsx'; +import AccountCountryRegionSelector from './AccountCountryRegionSelector.jsx'; +import RoleSelector from './AccountRolSelector.jsx'; + +function AccountForm() { + const [country, setCountry] = useState(''); + const [region, setRegion] = useState(''); + + const formik = useFormik({ + initialValues: { + email: '', + name: '', + lastName: '', + birthDate: '', + phone: '', + country: '', + region: '', + rol: '', + }, + validationSchema: Yup.object().shape({ + email: Yup.string().email('Invalid email').required('Required field'), + name: Yup.string().required('Required field'), + lastName: Yup.string().required('Required field'), + birthDate: Yup.date() + .required('Required field') + .test('is-of-age', 'The user must be at least 18 years old', function(value) { + const today = new Date(); + const birthDate = new Date(value); + const age = today.getFullYear() - birthDate.getFullYear(); + const monthDiff = today.getMonth() - birthDate.getMonth(); + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { + return age > 18; + } + return age >= 18; + }), + phone: Yup.string().required('Required field'), + country: Yup.string().required('Required field'), + region: Yup.string().required('Required field'), + rol: Yup.string().required('Required field'), + }), + onSubmit: async (values, { setErrors, resetForm }) => { + // Logic to submit the form + console.log(values); + try { + const response = await Axios.post('/accounts', values); + if (response.status === 201) { + console.log('Account created successfully'); + resetForm(); + toast.success('Account created successfully'); + } + } catch (error) { + if (error.response && error.response.status === 400) { + setErrors({ email: 'The email is already registered' }); + toast.error('The email is already registered'); + } else { + console.error(error); + toast.error('An error occurred. Please try again later'); + } + } + return 0; + }, + }); + + const handleButtonClick = () => { + formik.handleSubmit(); + }; + + const selectCountry = (val) => { + formik.handleChange('country')(val); + setCountry(val); + // Reset region when country changes + setRegion(''); + }; + + const selectRegion = (val) => { + formik.handleChange('region')(val); + setRegion(val); + }; + + return ( + <div className=' px-12'> + <div className=' px-4 py-5 bg-white shadow-lg rounded-lg border mx-auto'> + <h2 className="text-2xl font-semibold text-fourth text-center mb-6">Create an Account</h2> + <form className="flex flex-wrap -mx-2"> + <div className="px-2 w-full sm:w-1/2"> + <AccountFormBox + title="Name" + name="name" + type="text" + placeholder={"Enter the name"} + error={formik.touched.name && formik.errors.name} + value={formik.values.name} + change={formik.handleChange} + blur={formik.handleBlur} + /> + </div> + <div className="px-2 w-full sm:w-1/2"> + <AccountFormBox + title="Last Name" + name="lastName" + type="text" + placeholder={"Enter the last name"} + error={formik.touched.lastName && formik.errors.lastName} + value={formik.values.lastName} + change={formik.handleChange} + blur={formik.handleBlur} + /> + </div> + <div className="px-2 w-full sm:w-1/2"> + <AccountFormBox + title="Email" + name="email" + type="email" + placeholder={"Enter the email"} + error={formik.touched.email && formik.errors.email} + value={formik.values.email} + change={formik.handleChange} + blur={formik.handleBlur} + /> + </div> + <div className="px-2 w-full sm:w-1/2"> + <AccountFormBox + title="Birth Date" + name="birthDate" + type="date" + placeholder={"Enter the birth date"} + error={formik.touched.birthDate && formik.errors.birthDate} + value={formik.values.birthDate} + change={formik.handleChange} + blur={formik.handleBlur} + /> + </div> + <div className="px-2 w-full sm:w-1/2"> + <AccountFormBox + title="Phone" + name="phone" + type="text" + placeholder={"Enter the phone number"} + error={formik.touched.phone && formik.errors.phone} + value={formik.values.phone} + change={formik.handleChange} + blur={formik.handleBlur} + /> + </div> + <div className="px-2 w-full sm:w-1/2"> + <RoleSelector + value={formik.values.rol} + handleChange={formik.handleChange} + error={formik.touched.rol && formik.errors.rol} + /> + </div> + <div className="px-2 w-full"> + <AccountCountryRegionSelector + country={formik.values.country} + selectCountry={selectCountry} + region={formik.values.region} + selectRegion={selectRegion} + countryError={formik.touched.country && formik.errors.country} + regionError={formik.touched.region && formik.errors.region} + /> + </div> + <div className="px-2 w-full"> + <button onClick={handleButtonClick} type='button' className="mt-4 w-full bg-fourth hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg focus:outline-none focus:shadow-outline"> + Create Account + </button> + </div> + </form> + </div> + </div> + ); +} + +export default AccountForm; \ No newline at end of file diff --git a/code/Client/src/components/accounts/AccountFormBox.jsx b/code/Client/src/components/accounts/AccountFormBox.jsx new file mode 100644 index 0000000000000000000000000000000000000000..5d2bb38ef5dd0ef1bd4f723fe75db6da35f1b6d5 --- /dev/null +++ b/code/Client/src/components/accounts/AccountFormBox.jsx @@ -0,0 +1,22 @@ +import React from 'react'; + +const AccountFormBox = ({ title, name, type, error, value, change, blur, placeholder }) => { + return ( + <div> + <label className="block mb-2 text-sm font-medium text-gray-900">{title}</label> + <input + value={value} + onChange={change} + id={title} + name={name} + type={type} + onBlur={blur} + placeholder={placeholder} + className={`block w-full p-3 border ${error ? 'border-red-500' : 'border-gray-300'} rounded`} + /> + {error && <p className="text-red-500 text-xs italic">{error}</p>} + </div> + ); +}; + +export default AccountFormBox; \ No newline at end of file diff --git a/code/Client/src/components/accounts/AccountRolSelector.jsx b/code/Client/src/components/accounts/AccountRolSelector.jsx new file mode 100644 index 0000000000000000000000000000000000000000..9ad6e02b70c3769ea2b853b931f7cddc545bf89e --- /dev/null +++ b/code/Client/src/components/accounts/AccountRolSelector.jsx @@ -0,0 +1,21 @@ +import React from 'react'; + +const RoleSelector = ({ value, handleChange, error }) => { + return ( + <div> + <label className="block mb-2 text-sm font-medium text-gray-900">Role</label> + <select + name="rol" + value={value} + onChange={handleChange} + className={`block w-full p-3 border ${error ? 'border-red-500' : 'border-gray-300'} rounded`} + > + <option value="user">Client</option> + <option value="employee">Employee</option> + </select> + {error && <p className="text-red-500 text-xs italic">{error}</p>} + </div> + ); +}; + +export default RoleSelector; \ No newline at end of file diff --git a/code/Client/src/components/registerComponents/FormButton.jsx b/code/Client/src/components/registerComponents/FormButton.jsx index 915e1e8a45b4075e97a9a1f4d7f045f456fe627f..10b0e12ab3722b91b6b381b66f2afa963161e481 100644 --- a/code/Client/src/components/registerComponents/FormButton.jsx +++ b/code/Client/src/components/registerComponents/FormButton.jsx @@ -2,8 +2,8 @@ import React from 'react'; const FormButton = ({ onClick, children }) => { return ( - <button onClick={onClick} type="button" className="bg-secondary hover:bg-blue-700 text-white font-bold h-2/5 py-4 px-4 m-4 rounded-xl focus:outline-none focus:shadow-outline flex items-center justify-center"> - <span className="mt-2">{children}</span> + <button onClick={onClick} type="button" className="bg-secondary hover:bg-blue-700 text-white font-bold h-2/5 min-h-14 py-4 px-4 m-4 rounded-xl focus:outline-none focus:shadow-outline flex items-center justify-center"> + <span className="">{children}</span> </button> ); }; diff --git a/code/Client/src/pages/SignUpPage.jsx b/code/Client/src/pages/SignUpPage.jsx index 70b066e7fe517c12c3a11f5bdaabbba9555f2b63..a6113b55a108fdd4eb17f60b8ce42d368d682e3c 100644 --- a/code/Client/src/pages/SignUpPage.jsx +++ b/code/Client/src/pages/SignUpPage.jsx @@ -5,14 +5,11 @@ import * as Yup from 'yup'; import CountryRegionSelector from '../components/registerComponents/CountryRegionSelector'; import GrayBox from '../components/registerComponents/GrayBox'; import FormBox from '../components/registerComponents/FormBox'; -import { toast } from 'react-toastify'; -import { useNavigate } from 'react-router-dom'; function SignUpPage() { const [view, setview] = useState(0); // State to control the visibility of the first FormBox const [country, setCountry] = useState(''); const [region, setRegion] = useState(''); - const navigate = useNavigate(); const formik = useFormik({ initialValues: { @@ -34,7 +31,18 @@ function SignUpPage() { confirmPassword: Yup.string().oneOf([Yup.ref('password'), null], 'Passwords must match').required('Required field'), name: Yup.string().required('Required field'), lastName: Yup.string().required('Required field'), - birthDate: Yup.string().required('Required field'), + birthDate: Yup.date() + .required('Required field') + .test('is-of-age', 'You must be at least 18 years old', function(value) { + const today = new Date(); + const birthDate = new Date(value); + const age = today.getFullYear() - birthDate.getFullYear(); + const monthDiff = today.getMonth() - birthDate.getMonth(); + if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { + return age > 18; + } + return age >= 18; + }), phone: Yup.string().required('Required field'), country: Yup.string().required('Required field'), region: Yup.string().required('Required field'), @@ -44,9 +52,8 @@ function SignUpPage() { // Logic to submit the form try { const response = await Axios.post('/signup', values); - if (response.status === 200) { - toast.success('You have successfully registered'); - navigate('/login'); + if (response.status === 201) { + window.location.href = '/login'; } } catch (error) { if (error.response && error.response.status === 400) { diff --git a/code/Server/package.json b/code/Server/package.json index f5e304a6fe4fd2cf039a95a1134e8ec1e46324ed..0b008fba7a82a62a26703f886e916619ad9f8803 100644 --- a/code/Server/package.json +++ b/code/Server/package.json @@ -18,6 +18,7 @@ "jsonwebtoken": "^9.0.2", "mssql": "^10.0.2", "multer": "^1.4.5-lts.1", + "nodemailer": "^6.9.13", "uuid": "^9.0.1" }, "description": "" diff --git a/code/Server/src/accounts/controllers/accounts.js b/code/Server/src/accounts/controllers/accounts.js new file mode 100644 index 0000000000000000000000000000000000000000..429f10b3aec367aa96b0de5ddb605139dcc485d7 --- /dev/null +++ b/code/Server/src/accounts/controllers/accounts.js @@ -0,0 +1,45 @@ +import AccountsServices from "../services/accounts.js"; +import dotenv from 'dotenv'; + +dotenv.config(); + +class AccountsController { + static async createAccount(req, res) { + try { + const { email, name, lastName, phone, birthDate, rol } = req.body; + + const user = await AccountsServices.findUser(email); + if (user.length > 0) { + res.status(400).send({ + message: 'User already exists' + }); + } else { + const result = await AccountsServices.signup(email, name, lastName, phone, birthDate, rol); + + if (result === undefined) { + const password = await AccountsServices.generatePassword(); + const encryptedPassword = await AccountsServices.encrypt(password, process.env.SECRET_KEY); + await AccountsServices.signupPassword(email, encryptedPassword); + // Enviar correo de confirmación + try { + // Enviar correo de confirmación + await AccountsServices.sendSignupEmail(email, name, password); + + res.status(201).send({ + message: 'User registered successfully' + }); + } catch (emailError) { + console.error('Failed to send email:', emailError); + res.status(500).send({ + message: 'User registered but failed to send confirmation email' + }); + } + } + } + } catch (error) { + res.status(500).send(error.message); + } + } +} + +export default AccountsController; diff --git a/code/Server/src/accounts/routes/accounts.js b/code/Server/src/accounts/routes/accounts.js new file mode 100644 index 0000000000000000000000000000000000000000..5e22f7dd8b35a1f09259dd53092bd1c74caabede --- /dev/null +++ b/code/Server/src/accounts/routes/accounts.js @@ -0,0 +1,18 @@ +// signup.routes.js + +import { Router } from 'express'; +import AccountsController from '../controllers/accounts.js'; + +class AccountsRoutes { + constructor() { + this.router = Router(); + this.accountsRoute(); + } + + accountsRoute() { + this.router.post('/', AccountsController.createAccount); + } +} + +const accountsRoutes = new AccountsRoutes(); +export default accountsRoutes.router; \ No newline at end of file diff --git a/code/Server/src/accounts/services/accounts.js b/code/Server/src/accounts/services/accounts.js new file mode 100644 index 0000000000000000000000000000000000000000..f12824e67ee60a8e9d6f2fff422ecf94dbeda119 --- /dev/null +++ b/code/Server/src/accounts/services/accounts.js @@ -0,0 +1,79 @@ +import DbConnection from "../../config/dbconnection.js"; +import sql from "mssql"; // Asegúrate de importar el módulo sql +import CryptoJS from 'crypto-js'; +import nodemailer from 'nodemailer'; +import crypto from 'crypto'; + +class AccountsServices { + + static async signup(email, name, lastName, phone_number, birth_date, rol) { + const pool = await DbConnection.getInstance().getConnection(); + const result = await pool.request() + .input('email', sql.VarChar, email) + .input('name', sql.VarChar, name) + .input('last_name', sql.VarChar, lastName) + .input('phone_number', sql.VarChar, phone_number) + .input('birth_date', sql.Date, new Date(birth_date)) + .input('rol', sql.VarChar, rol) + .query('INSERT INTO t_user(email, name, last_name, phone_number, birth_date, rol) VALUES (@email, @name, @last_name, @phone_number, @birth_date, @rol)'); + await DbConnection.getInstance().closeConnection(); + return result.recordset; + } + + static async signupPassword(email, password) { + const pool = await DbConnection.getInstance().getConnection(); + const result = await pool.request() + .input('email', sql.VarChar, email) + .input('password', sql.VarChar, password) + .query('INSERT INTO password(email, password) VALUES (@email, @password)'); + await DbConnection.getInstance().closeConnection(); + return result.recordset; + } + + static async findUser(email) { + const pool = await DbConnection.getInstance().getConnection(); + const result = await pool.request() + .input('email', sql.VarChar, email) + .query('SELECT * FROM t_user WHERE email = @email'); + await DbConnection.getInstance().closeConnection(); + return result.recordset; + } + static async encrypt(password, key) { + const cipherText = CryptoJS.AES.encrypt(password, key).toString(); + return cipherText; + } + + static async sendSignupEmail(email, name, password) { + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS + } + }); + + const mailOptions = { + from: process.env.EMAIL_USER, + to: email, + subject: 'Account Created Successfully', + text: `Hello ${name}, your account has been created successfully! + + Here are your login details: + Email: ${email} + Password: ${password} + + Best regards, + Hazbin Hotel Team` + }; + + + + return transporter.sendMail(mailOptions); + } + + static async generatePassword(length = 12) { + return crypto.randomBytes(length).toString('base64').slice(0, length); + } +} + +export default AccountsServices; diff --git a/code/Server/src/app.js b/code/Server/src/app.js index ba4c90253f29cb917eea6dab4de058e11ef30e24..8c14ed8a7afd5fadf7baaa4b7752d407ffdbd600 100644 --- a/code/Server/src/app.js +++ b/code/Server/src/app.js @@ -5,6 +5,7 @@ import path from 'path'; import LoginRoutes from './user/routes/login.js'; import SignUpRoutes from './user/routes/signUp.js'; import reservationRoutes from './reserves/routes/reservation.js'; +import AccountsRoutes from './accounts/routes/accounts.js'; import { fileURLToPath } from 'url'; import RoomsRoutes from './rooms/routes/rooms.js'; @@ -38,7 +39,7 @@ app.use('/rooms', RoomsRoutes); app.use('/login', LoginRoutes); app.use('/signup', SignUpRoutes); app.use('/reservations', reservationRoutes); - +app.use('/accounts', AccountsRoutes); // Start server const PORT = process.env.PORT || 4000; diff --git a/code/Server/src/user/controllers/signUp.js b/code/Server/src/user/controllers/signUp.js index 71ee06b7e0232b83587ceb8fc446885a2fd0c7c2..ec1eb15a58e8fcc46fde071a0eebc0ed1729f983 100644 --- a/code/Server/src/user/controllers/signUp.js +++ b/code/Server/src/user/controllers/signUp.js @@ -6,7 +6,7 @@ dotenv.config(); class SignupController { static async signup(req, res) { try { - const { email, password, name, lastName, phone, birthDate, rol} = req.body; + const { email, password, name, lastName, phone, birthDate, rol } = req.body; const user = await SignupServices.findUser(email); @@ -14,17 +14,28 @@ class SignupController { res.status(400).send({ message: 'User already exists' }); - + } else { const result = await SignupServices.signup(email, name, lastName, phone, birthDate, rol); if (result === undefined) { const encryptedPassword = await SignupServices.encrypt(password, process.env.SECRET_KEY); await SignupServices.signupPassword(email, encryptedPassword); - - res.status(201).send({ - message: 'User registered successfully' - }); + + // Enviar correo de confirmación + try { + // Enviar correo de confirmación + await SignupServices.sendSignupEmail(email, name); + + res.status(201).send({ + message: 'User registered successfully' + }); + } catch (emailError) { + console.error('Failed to send email:', emailError); + res.status(500).send({ + message: 'User registered but failed to send confirmation email' + }); + } } } } catch (error) { @@ -33,4 +44,4 @@ class SignupController { } } -export default SignupController; \ No newline at end of file +export default SignupController; diff --git a/code/Server/src/user/services/signUp.js b/code/Server/src/user/services/signUp.js index 6c24263990966780d181e7aa2c2fc20ea04b26b6..7a6ceee5a18a0c07a31c2d57146837e38e760c52 100644 --- a/code/Server/src/user/services/signUp.js +++ b/code/Server/src/user/services/signUp.js @@ -1,6 +1,7 @@ import DbConnection from "../../config/dbconnection.js"; import sql from "mssql"; // Asegúrate de importar el módulo sql import CryptoJS from 'crypto-js'; +import nodemailer from 'nodemailer'; class SignupServices { @@ -41,6 +42,27 @@ class SignupServices { return cipherText; } + static async sendSignupEmail(email, name) { + const transporter = nodemailer.createTransport({ + service: 'gmail', + auth: { + user: process.env.EMAIL_USER, + pass: process.env.EMAIL_PASS + } + }); + + const mailOptions = { + from: process.env.EMAIL_USER, + to: email, + subject: 'Account Created Successfully', + text: `Hello ${name}, your account has been created successfully! + + Best regards, + Hazbin Hotel Team` + }; + + return transporter.sendMail(mailOptions); + } } export default SignupServices;