Traveling and exploring new places can be both exciting and overwhelming. The plethora of options available for destinations, activities, accommodations, and services can make planning a trip daunting. Wanderlust aims to solve this by providing a comprehensive platform that centralizes all travel-related information. Our goal is to empower travelers to make informed decisions by offering:
- A user-friendly interface to discover and explore various locations.
- Detailed information on activities, attractions, and services available at each destination.
- A robust itinerary planning tool to help users organize their trips efficiently.
- Personalized recommendations based on user preferences and past activities.
- Features for both travelers and service providers, such as user authentication, location and activity management, and advertiser and seller management.
- An integrated preference tagging system to enhance the user experience by offering tailored suggestions.
By integrating these features, Wanderlust aspires to be the go-to platform for all travel enthusiasts, making travel planning seamless, enjoyable, and personalized.
- Current Phase: Development
- Upcoming Tasks:
- Implement testing using Jest
- Complete authorization middleware across all routes
- Organize backend structure for better maintainability
Our project adheres to a set of coding standards to ensure consistency, readability, and maintainability across the codebase. Please follow these guidelines when contributing:
- Indentation: Use 2 spaces for indentation.
- File Naming: Use
camelCase
for JavaScript files. - Comments: Use comments to explain the purpose of the code, not the implementation.
- Variables: Use
const
for variables that do not change andlet
for variables that might change. - Functions: Use arrow functions (
() => {}
) for anonymous functions and method definitions inside classes. - Semicolons: Always use semicolons at the end of statements.
- Quotes: Use single quotes for strings, except to avoid escaping.
- Modules: Use ES6 module syntax (
import
andexport
) instead of CommonJS (require
andmodule.exports
). - Error Handling: Always handle errors gracefully using
try...catch
blocks or error-handling middleware in Express.js.
- Structure: Use semantic HTML5 elements (
<header>
,<nav>
,<section>
,<footer>
, etc.). - Attributes: Use double quotes for attribute values.
- Selectors: Use class selectors over ID selectors for styling. Avoid using element selectors.
- Naming Convention: Follow the BEM (Block Element Modifier) methodology for naming classes.
- Properties Ordering: Group related properties together (e.g., positioning, box model, typography).
By adhering to these coding standards, we ensure that our codebase remains clean, efficient, and easy to understand for all contributors.
Our project leverages a modern tech stack to deliver a seamless and efficient experience for users. The following technologies and frameworks are used:
- Node.js: A JavaScript runtime built on Chrome's V8 JavaScript engine, used for building fast and scalable server-side applications.
- Express.js: A minimal and flexible Node.js web application framework that provides a robust set of features to develop web and mobile applications.
- MongoDB: A NoSQL database that uses a flexible, JSON-like document structure, making it easy to store and query data.
- React: A JavaScript library for building user interfaces, maintained by Facebook and a community of developers. It allows for the creation of reusable UI components.
- Vite: A build tool that provides a faster and leaner development experience for modern web projects. It is used for setting up and developing the React frontend.
- HTML: The standard markup language for documents designed to be displayed in a web browser.
- CSS: A style sheet language used for describing the presentation of a document written in HTML.
- User Authentication and Authorization: Implemented using JWT tokens.
- Location and Activity Management: CRUD operations for locations and activities.
- Advertiser and Seller Management: Management of advertisers and sellers within the platform.
- Preference Tagging System: Users can filter itineraries based on their preferences.
- Itinerary Planning: Users can create, update, delete, and share itineraries. Itinerary ratings and reviews are also supported.
- Promo Codes and Discounts: Handling of promo codes and birthday promotions for tourists.
- Booking Management: Booking and cancellation of itineraries, with payment processing.
- Notification System: Sends notifications and emails for events like birthdays and bookings.
- Guided Tours: A step-by-step guide for users using
intro.js
. - Filter and Search: Users can filter itineraries by date, budget, language, and preferences.
- Interactive Maps: Integration with Google Maps API for location-based services.
- Responsive Design: Frontend built with React and Vite, ensuring responsive design for various devices.
Example of initializing the Express server and connecting to MongoDB:
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const bodyParser = require("body-parser");
require("dotenv").config();
const app = express();
app.use(express.json());
app.use(bodyParser.json());
app.use(cors());
const port = process.env.PORT || "8000";
const MongoURI = process.env.MONGO_URI;
mongoose
.connect(MongoURI)
.then(() => {
console.log("MongoDB is now connected!");
app.listen(port, () => {
console.log(`Listening to requests on http://localhost:${port}`);
});
})
.catch((err) => console.log(err));
Example of Creating an Itinerary
const createItinerary = async (req, res) => {
const {
title,
activities,
locations,
timeline,
languageOfTour,
price,
rating,
availableDates,
accessibility,
pickupLocation,
dropoffLocation,
isActive,
} = req.body;
try {
const token = req.headers.authorization.split(" ")[1];
const decodedToken = jwt.verify(token, process.env.JWT_SECRET);
const creatorId = decodedToken.id;
const itinerary = await Itinerary.create({
title,
activities,
locations,
timeline,
languageOfTour,
price,
rating,
availableDates,
accessibility,
pickupLocation,
dropoffLocation,
isActive,
creator: creatorId,
});
const populatedItenary = await Itinerary.findById(itinerary._id).populate(
"activities"
);
res.status(200).json(populatedItenary);
} catch (error) {
res.status(400).json({ error: error.message });
}
};
Fetching Promo Codes in React
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const CreatePromocode = () => {
const [code, setCode] = useState('');
const [discount, setDiscount] = useState('');
const [promoCodes, setPromoCodes] = useState([]);
useEffect(() => {
fetchPromoCodes();
}, []);
const fetchPromoCodes = async () => {
try {
const response = await axios.get('http://localhost:8000/api/admin/promoCodes');
setPromoCodes(response.data);
} catch (error) {
console.error('Error fetching promo codes:', error);
}
};
const handleCreatePromoCode = async (e) => {
e.preventDefault();
try {
const response = await axios.post('http://localhost:8000/api/admin/createPromoCode', { code, discount });
if (response.status === 201) {
fetchPromoCodes(); // Refresh the list of promo codes
setCode('');
setDiscount('');
}
} catch (error) {
console.error('Error creating promo code:', error);
}
};
return (
<div className="container mt-4">
<h1>Create Promo Code</h1>
<form onSubmit={handleCreatePromoCode}>
<div className="mb-3">
<label htmlFor="code" className="form-label">Promo Code</label>
<input
type="text"
className="form-control"
id="code"
value={code}
onChange={(e) => setCode(e.target.value)}
required
/>
</div>
<div className="mb-3">
<label htmlFor="discount" className="form-label">Discount (%)</label>
<input
type="number"
className="form-control"
id="discount"
value={discount}
onChange={(e) => setDiscount(e.target.value)}
required
/>
</div>
<button type="submit" className="btn btn-primary">Create Promo Code</button>
</form>
<h2 className="mt-4">Existing Promo Codes</h2>
<table className="table">
<thead>
<tr>
<th scope="col">Code</th>
<th scope="col">Discount</th>
<th scope="col">Expiry Date</th>
</tr>
</thead>
<tbody>
{promoCodes.map((promoCode) => (
<tr key={promoCode._id}>
<td>{promoCode.code}</td>
<td>{promoCode.discount}%</td>
<td>{new Date(promoCode.expiryDate).toLocaleDateString()}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default CreatePromocode;
- Clone the repository:
git clone https://github.com/Advanced-computer-lab-2024/Wanderlust.git
- Install dependencies for both backend and frontend:
cd Wanderlust/Backend/server npm install cd ../frontend/react-wl/src npm install
- Create a
.env
file in the backend directory and add your MongoDB URI:MONGO_URI=your_mongodb_uri FLIGHT_API_KEY=ed8a7354aa4175d87801e50dfd692947
POST /signup
: User signupPOST /login
: User login
POST /createLocation
: Create a new locationGET /getLocations
: Get all locationsPUT /updateLocation/:id
: Update a location by IDDELETE /deleteLocation/:id
: Delete a location by IDGET /getLocation/:id
: Get a location by ID
GET /getTourist
: Get tourist detailsPOST /createTourist/
:userId: Create a touristPUT /updateTourist/
:username: Update tourist detailsGET /viewAll
: View all touristsPUT /redeemPoints/
:username: Redeem pointsPUT /addProductToWishlist/
:productId: Add product to wishlistGET /getWishlist
: Get wishlistDELETE /removeProductFromWishlist/
:productId: Remove product from wishlistPUT /addProductToCart/
:productId: Add product to cartDELETE /removeFromCart/
:productId: Remove product from cartPUT /cart/changeQuantity/
:productId: Change cart item quantityPOST /cart/checkout
: Checkout orderPOST /cart/paymentSuccess
: Card payment successGET /viewAllOrders
: View all ordersGET /viewOrder/:orderId
: View order detailsDELETE /cancelOrder/:touristId/
:orderId: Cancel orderPOST /addDeliveryAddress
: Add delivery addressDELETE /removeDeliveryAddress/:addressId
: Remove delivery addressPUT /updateDeliveryAddress/:addressId
: Update delivery addressGET /deliveryAddresses
: Get delivery addressesPOST /usePromoCode/:touristId
: Use promo codePOST /receiveBirthdayPromo/:touristId
: Receive birthday promoPOST /createSystemNotification
: Create system notification
POST /addProduct
: Add a new productPUT /updateProductByName
: Update product by nameGET /searchProductByName
: Search product by nameGET /filterProductsByPrice
: Filter products by priceGET /sortedByRating
: Get products sorted by ratingGET /viewAllProducts
: View all productsGET /viewAvailableProducts
: View available productsDELETE /deleteproduct
: Delete product by namePUT /archiveProduct
: Archive productPUT /unarchiveProduct
: Unarchive productPOST /product/rate:
Rate a productGET /product/:productId/details
: View product detailsPOST /product/sale
: Add sale to product
POST /createActivity
: Create a new activityGET /getActivity
: Get all activitiesGET /getActivityGuest
: Get activities for guestsGET /getActivityById
: Get activity by IDPUT /updateActivity
: Update an activityDELETE /deleteActivity
: Delete an activityGET /filterActivities
: Filter activitiesGET /sortActivities
: Sort activitiesGET /searchActivity
: Search activitiesGET /activities
: Get activities by category nameGET /share/:activityId
: Generate shareable linkPOST /shareMail/
:activityId/email: Send activity link via emailPOST /rate/:activityId
: Rate an activityPOST /bookActivity
: Book an activityPOST /paymentSuccess
: Card payment successDELETE /cancelActivityBooking/
:bookingId: Cancel activity bookingPOST /saveActivity
: Save an activityPOST /unsaveActivity
: Unsave an activityGET /savedActivities/:touristId
: Get saved activitiesPOST /requestNotification
: Request notificationPUT /activity/:id/flag
: Flag an activityPUT /activity/:id/unflag
: Unflag an activity
POST /addTourismGovernor
: Add tourism governorDELETE /delete
: Delete accountGET /usernames
: Get all user detailsPOST /create
: Create adminGET /pendingUsers
: Get pending usersPUT /approvePendingUser/
:userId: Approve pending userGET /profile
: Get admin detailsGET /userStatistics
: Get user statisticsPOST /createPromoCode
: Create promo codeGET /getNotifications
: Get notificationsGET /promoCodes
: Get promo codesPOST /login
: Admin loginPOST /updatepassword
: Update admin passwordGET /getLoggedInUser
: Get logged-in userGET /getLoggedInInfo
: Get logged-in infoPOST /acceptTerms
: Accept termsGET /requestDeleteAccount
: Request to delete account
Currently, testing is performed manually using Postman for API endpoints. Automated testing is planned to be implemented using Jest.
-
Example 1: Admin Login
- Endpoint:
http://localhost:8000/api/admin/login
- Method: POST
- Body:
{ "username": "nada", "password": "nada123", "role": "admin" }
- Endpoint:
-
Example 2: Rate Itinerary
- Endpoint:
http://localhost:3000/api/itinerary/rate
- Method: POST
- Body:
{ "itineraryId": "60d5f9b8f8d2c9b8f8d2c9b8", "rating": 5, "review": "Amazing tour! Highly recommend." }
- Endpoint:
-
Example 3: update Loctaion
- Endpoint:
http://localhost:3000/api/location/create
- Method: POST
- Endpoint:
-
Example 4: Get Loctaion
- Endpoint:
http://localhost:3000/api/location/getall
- Method: GET
- Endpoint:
-
Example 5: Create Loctaion
- Endpoint:
http://localhost:3000/api/location/update/60d5f9b8f8d2c9b8f8d2c9b8
- Method: POST
- Endpoint:
-
Example 6: Delete Location
- Endpoint:
http://localhost:8000/api/location/delete/60d5f9b8f8d2c9b8f8d2c9b8
- Method: DELETE
- Endpoint:
-
Example 7: Create Tourist
- Endpoint:
http://localhost:8000/api/tourist/create
- Method: POST
- Endpoint:
-
Example 8: Get Tourist
- Endpoint:
http://localhost:8000/api/tourist/get
- Method: GET
- Endpoint:
-
Example 9: Delete Tourist
- Endpoint:
http://localhost:8000/api/tourist/update
- Method: PUT
- Endpoint:
-
Example 10: Delete Tourist
- Endpoint:
http://localhost:8000/api/tourist/delete
- Method: DELETE
- Endpoint:
-
Example 11: Add products to wishlist
- Endpoint:
http://localhost:8000/api/wishlist/add
- Method: PUT
- Endpoint:
-
Example 12: Get wishlist
- Endpoint:
http://localhost:8000/api/wishlist/get
- Method: GET
- Endpoint:
-
Example 13: Remove Products from wishlist
- Endpoint:
http://localhost:8000/api/wishlist/remove/60d5f9b8f8d2c9b8f8d2c9b8
- Method: PUT
- Endpoint:
-
Example 14: Create Activity
- Endpoint:
http://localhost:8000/api/activity/create
- Method: POST
- Endpoint:
-
Example 15: Get activity by id=
- Endpoint:
http://localhost:8000/api/activity/getactivity/60d5f9b8f8d2c9b8f8d2c9b8
- Method: PUT
- Endpoint:
-
Example 16: Update activity
- Endpoint:
http://localhost:8000/api/activity/update/60d5f9b8f8d2c9b8f8d2c9b8
- Method: PUT
- Endpoint:
- Implement unit and integration tests using Jest and Supertest.
-
Start the backend server:
cd Backend cd server nodemon app
-
Start the frontend server:
cd ../frontend/react-wl/src npm run dev
-
Open your browser and navigate to
http://localhost:8000
for the backend andhttp://localhost:3000
for the frontend.
- Amgad Tahoun
- Nada Tamer
- Yousef Abdelhamid
- Khaled Essam
- Khaled Mostafa
- Amr Hesham
- Amr Khaled
- Ali Mousa
- Shahd Hesham
- Shahd Elfeky
We welcome contributions to Wanderlust! Follow the steps below to contribute:
-
Fork the repository.
-
Clone your forked repository to your local machine:
git clone https://github.com/your-username/Wanderlust.git cd Wanderlust
-
Create a new branch for your feature or bug fix.
git checkout -b feature/your-feature-name
-
Make your changes and commit them with clear and descriptive messages.
git commit -m "Add feature: your feature name"
-
Push your changes to your forked repository.
git push origin feature/your-feature-name
-
Open a pull request in the original repository, describing the changes and linking to any relevant issues.
Wanderlust leverages various third-party services and libraries to enhance functionality:
-
Lucid React - Icon library for React.
-
Material UI - React UI framework for building responsive interfaces.
-
UiVerse - Design resources and UI components.
-
NodeMailer - Module for sending emails from Node.js.
-
MongoDB Atlas - Cloud database service.
-
Stripe Web Elements - Payment processing integration.
This project is licensed under the Apache 2.0 License.