- π Motivation
- 𧱠Build Status
- π¨ Code Style
- βοΈ Tech and Frameworks used
- π₯ Features & Screenshots
- π» Code Examples
- βοΈ Installation
- π API Reference
- π§ͺ Tests
- π§π»βπ« How to Use
- π€ Contribute
- Β©οΈ Credits
- π License
Welcome to WanderQuest, your ultimate travel companion designed to transform vacation planning into an effortless and unforgettable experience! Whether you're longing for serene beaches, historic landmarks, or thrilling family adventures, our platform caters to every travel dream.
- This project is under development and should not be used in a production settings
- Check Issues for a list of all the reported issues
- More automated tests should be added in the future
- More documentation should be added
We use Prettier to enforce a consistent code style.
Useful Commands
- Check formatting using Prettier
npm run format
- And then fix formatting using Prettier
npm run format:fix
- NodeJs
- Express
- ReactJs
- MongoDB
- Mongoose
- Prettier
- MUI
- React Router
- React Hook Form
- React Query
- Formik
- Toastify
- Socket.io
- Firebase Storage
- NodeMailer
- JsonWebToken
- Bcrypt
- Postman
User Registration π
- Register as a tourist/advertiser/tour guide/seller with essential details.
- Submit a request to register as an advertiser/tour guide/seller with professional details.
- Upload required documents for advertiser/tour guide/seller registration.

Administrator Functions π©βπΌ
- Add/remove another administrator.
- Add/remove a tourism governor.
- Manage all users.
- Add/edit/remove/view products/activities/itineraries/categories/tags.
- Archive/unarchive products.
- Accept or reject advertiser/tour guide/seller registration requests.
- View information uploaded by advertiser/tour guide/seller.
- View complaints.
- Mark a complaint as pending or resolved or reply to it.
- Create/delete/view promocodes.
- Search/Filter/Sort for a product based on product name/price/ratings.
- Advanced analytics or dashboards showing trends







Account Management π
- Change password.
- Reset forgotten password via email.
- Request to delete account.
Seller FunctionsποΈ
- Accept Terms and Conditions.
- Create/Read/Update their profile with their information including name and description. If accepted on the system.
- View a list of all available products.
- Search/Filter/Sort for a product based on product name/price/ratings.
- Add/Edit/View a product with its details, price and available quantity.
- Upload a picture.
- View/Filter sales report
- Archive/unarchive products.
- Search/Filter/Sort for a product based on product name/price/ratings.
- Detailed performance analytics

Advertiser Functionsπ’
- Accept Terms and Conditions.
- Create/Read/Update their profile with their information. If accepted on the system.
- View a list of all advertisers.
- Create/update/delete activities.
- View created activities.
- Create/view transportation posts.
- Get/mark as read notifications.
- Analytics to track the performance of activities or posts

Tourist Functionsπ
- Read/Update their profile with their information.
- Book trips.
- Pay for bookings using wallet or credit card.
- Add to/remove from/view wishlist.
- View saved events.
- View all orders.
- Issue/cancel an order.
- View available products/ upcoming activities/itineraries/places.
- Search/Filter/Sort for a product based on product name/price/ratings.
- Rate/review a product.
- Redeem points/promocode.
- File a complaint.
- View my complaints/level/available points.
- Change preferred currency.
- Manage notifications.
- Be notified/request to be notified for when a saved event is open for bookings.
- Be reminded of your Booked Events getting Within 4 days of check.
- Recieve a promocode on your birthday in notifications.
- View/add/remove/edit/checkout to/from cart.
- Cancelation policies or refund requests tied to bookings.
- Wallet management, such as transaction history or adding funds to the wallet.
- Save/bookmark specific promocodes or offers.




Tour Guide FunctionsπΊοΈ
- Accept Terms and Conditions.
- Create/Read/Update their profile with their information. If accepted on the system.
- View a list of all advertisers.
- Create/update/delete/view/activate/deactivate itineraries.
- Rate/comment on tour guide.
- Manage notifications.


Tourism Governor FunctionsποΈ
- Create/update/delete/view places.
- Add/view tags.
FE Admin Dashboard Routes Example
<ul>
<li>
<Link href="/admin/Requests">Users Management</Link>
</li>
<li>
<Link href="/admin/deleteAccount">Delete Account</Link>
</li>
<li>
<Link href="/admin/addGovernor">Add Tourism Governor</Link>
</li>
<li>
<Link href="/admin/addAdmin">Add Admin</Link>
</li>
<li>
<Link href="/admin/editprod">Add Product</Link>
</li>
<li>
<Link href="/admin/complaints">Complaints</Link>
</li>
<li>
<Link href="/admin/promoCodes">Create Promocode</Link>
</li>
<li>
<Link href="/admin/prefTags">Preference Tags</Link>
</li>
</ul>
BE Authentication Routes
router.post('/register', registerUser);
router.post('/login', login);
router.get('/user', requireAuth(), getUser);
router.post('/changePassword', requireAuth(), changePassword);
router.post('/uploadDocuments', requireAuth(), uploadDocuments);
router.get('/getDocuments/:id', requireAuth(), getUserDocuments);
router.get('/getUsersRequestingAcceptance', requireAuth({ role: 'Admin' }), getUsersRequestingAcceptance);
router.get('/getDocumentByFileID/:id', requireAuth(), getDocumentByFileID);
router.patch('/acceptUser/:id', requireAuth({ role: 'Admin' }), acceptUser);
router.patch('/acceptTerms', requireAuth(), acceptTerms);
router.patch('/requestAccountDeletion', requireAuth(), requestAccountDeletion);
router.post('/requestForgetPasswordEmail', requestForgetPasswordEmail);
router.post('/resetPassword', resetPassword);
router.post('/logout', logout);
BE Promocode Creation Controller
const createPromo = async (req, res) => {
const { code, type, discount, birthday, touristId } = req.body;
const admin = req.user._id;
const expiry = Date.now() + (7 * 24 * 60 * 60 * 1000);
// Validate input
if (!code || !type || !discount) {
return res.status(400).json({ error: ' fields are required' });
}
try {
// Checking if the username already exists
const existingPromo = await PromoCode.findOne({ code });
if (existingPromo) {
return res.status(400).json({ error: 'Promocode already exists' });
}
const promocode = await PromoCode.create({
code,
type,
discount,
expiryDate: expiry,
createdBy: admin
});
const tourists = await Tourist.find();
// Create notifications for each tourist
const notifications = tourists.map(tourist => ({
userID: tourist._id,
message: `New promo code available: ${code}`,
reason: 'New Promo Code',
ReasonID: promocode._id // Optional reference to the promo code
}));
// Insert all notifications at once
await NotificationModel.insertMany(notifications);
res.status(200).json(promocode)
} catch (error) {
res.status(400).json({ error: error.message })
}
};
BE Promocode Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const promoCodeSchema = new Schema({
code: { type: String, required: true, unique: true },
type: { type: String, enum: ['PERCENTAGE', 'FIXED'], required: true },
discount: { type: Number, required: true },
expiryDate: { type: Date, required: true },
createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'Admin', required: false },
birthday: { type: Boolean, required: false },
touristId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Tourist",
required: false,
default:null,
validate: {
validator: function (value) {
return !this.birthday || (this.birthday && value);
},
message: 'touristId is required to create a birthday promocode'
}
}
}, { timestamps: true });
const PromoCode = mongoose.model('PromoCode', promoCodeSchema);
module.exports = {PromoCode};
BE Promocode Applier in Payment
async function applyPromoCodes(userId, amount) {
try {
const user = await User.findById(userId);
if (!user || !user.activePromoCodes || user.activePromoCodes.length === 0) {
console.log('No active promo codes found for this user.');
return amount; // Return original amount if no promo codes
}
let finalAmount = amount;
for (const promo of user.activePromoCodes) {
switch (promo.type) {
case 'FIXED':
const fixedDiscount = await convertCurrency(promo.discount, 'USD', user.preferredCurrency);
finalAmount = Math.max(0, finalAmount - fixedDiscount);
break;
case 'PERCENTAGE':
finalAmount = Math.max(0, finalAmount - (finalAmount * promo.discount) / 100);
break;
default:
console.log('Unknown promo type:', promo.type);
}
}
user.activePromoCodes = [];
await user.save();
return finalAmount;
} catch (error) {
console.error('Error applying promo codes:', error);
throw error;
}
}
BE Deduction from Wallet Helper
TouristSchema.methods.deduceFromWallet = async function (amount) {
try {
if (amount > this.wallet) {
throw new Error('Insufficient wallet balance');
}
this.wallet -= amount;
let pointsEarned;
switch (this.level) {
case 1:
pointsEarned = amount * 0.5;
break;
case 2:
pointsEarned = amount * 1;
break;
case 3:
pointsEarned = amount * 1.5;
break;
default:
pointsEarned = 0;
break;
}
this.totalPoints += pointsEarned;
this.availablePoints += pointsEarned;
// await sendEmail(this.email,'Payment regarding WanderQuest',`${amount} has been deducted from your wallet`);
await this.save();
} catch (error) {
console.error('Error deducting from wallet:', error);
throw error; // Re-throw the error to be handled by the caller
}
}
mkdir WanderQuest
cd WanderQuest
- Clone this repo
git clone https://github.com/Advanced-computer-lab-2024/WanderQuest.git
- Install dependencies
cd WanderQuest
npm install
- How to run: Add a
.env
in thebackend
of this repoWanderQuest
PORT=4000
MONGO_URI=mongodb+srv://wndrqstaclproj:[email protected]/?retryWrites=true&w=majority&appName=WanderQuest
SECRET=thisisatestsecretcode1234!
EXCHANGE_RATE_API_KEY=878b382f87f70b368b1a1b77
SMTP_HOST=smtp-relay.brevo.com
SMTP_PORT=587
[email protected]
SMTP_PASS=xsmtpsib-f4616267d504380fe69fed5abead6b1cca0de777b8b51ca4e11529084c48d7d0-Egz8brFnH0tZ1a9q
[email protected]
STRIPE_SECRET_KEY=rk_test_51QRfekFYbqa6jLuacYBGvdPJNTTSb5JIjiHUaNFnFzC2OpONxNoMy8QlE3tEVFP4fwnKo2hUfaburyCbjjWoDWWN00M07wztsy
- Start Front-End
cd Front-End
cd wanderquest
npm run dev
- Start Back-End in a different terminal
cd Back-End
npm run dev
API 1: Tourist Registration
POST: http://localhost:4000/auth/register
Request Body
{
"username": "johndoe",
"email": "[email protected]",
"password": "Password123!",
"role": "tourist",
"nationality": "Egyptian",
"mobileNumber": "+201234567890",
"dob": "1990-01-01",
"job": "Engineer"
}
Success Response (201)
{
"userId": "675661f5f97bdd3f05225196",
"username": "johndoe",
"role": "tourist",
"accepted": true
}
API 2: Tour Guide Registration
POST: http://localhost:4000/auth/register
Request Body
{
"username": "guidejohn",
"email": "[email protected]",
"password": "Guide123!",
"role": "tourGuide",
"yearsOfExperience": 5,
"mobileNumber": "+201234567891",
"previousWork": ["Pyramids Tours", "Nile Cruises"]
}
Success Response (201)
{
"userId": "675661f5f97bdd3f05225197",
"username": "guidejohn",
"role": "tourGuide",
"accepted": false
}
API 3: Create Activity
POST: http://localhost:4000/advertiser/activity
Request Body
{
"title": "Desert Safari",
"description": "Experience the thrill of desert adventure",
"price": 150,
"category": "675661f5f97bdd3f05225198",
"location": "Dubai Desert",
"date": "2024-12-25",
"time": "14:00",
"capacity": 20,
"tags": ["675661f5f97bdd3f05225199", "675661f5f97bdd3f05225200"]
}
Success Response (201)
{
"activityId": "675661f5f97bdd3f05225201",
"title": "Desert Safari",
"price": 150,
"capacity": 20,
"createdBy": "675661f5f97bdd3f05225202"
}
API 4: Create Product
POST: http://localhost:4000/seller/addProduct
Request Body
{
"name": "Traditional Scarf",
"price": 299.99,
"description": "Handmade Egyptian cotton scarf",
"availableAmount": 50,
"picture": {
"filename": "scarf.jpg",
"contentType": "image/jpeg",
"fileID": "675661f5f97bdd3f05225203"
}
}
Success Response (201)
{
"productId": "675661f5f97bdd3f05225204",
"name": "Traditional Scarf",
"price": 299.99,
"seller": "675661f5f97bdd3f05225205"
}
API 5: Create Booking
POST: http://localhost:4000/booking/activity
Request Body
{
"bookingType": "activity",
"activityId": "675661f5f97bdd3f05225201",
"paid": false,
"startDate": "2024-12-25",
"details": {
"numberOfParticipants": 2,
"specialRequests": "Vegetarian meals"
}
}
Success Response (201)
{
"bookingId": "675661f5f97bdd3f05225206",
"status": "booked",
"totalAmount": 300
}
API 6: Create Order
POST: http://localhost:4000/tourist/cart/checkout
Request Body
{
"products": [
{
"productId": "675661f5f97bdd3f05225204",
"quantity": 2
}
],
"deliveryAddress": "675661f5f97bdd3f05225207"
}
Success Response (201)
{
"orderId": "675661f5f97bdd3f05225208",
"totalPrice": 599.98,
"status": "pending",
"paymentStatus": "pending"
}
API 7: Process Payment
POST: http://localhost:4000/payment/handleBookingPayment
Request Body
{
"bookingId": "675661f5f97bdd3f05225206",
"amount": 300,
"currency": "EGP",
"method": "wallet"
}
Success Response (200)
{
"paymentId": "675661f5f97bdd3f05225209",
"status": "completed",
"paidAmount": 300
}
API 8: Add Delivery Address
POST: http://localhost:4000/tourist/addDeliveryAddresses
Request Body
{
"street": "123 Main St",
"city": "Cairo",
"state": "Cairo Governorate",
"postalCode": "11511",
"country": "Egypt",
"googleMapsUrl": "https://maps.google.com/?q=30.0444,31.2357"
}
Success Response (201)
{
"addressId": "675661f5f97bdd3f05225207",
"message": "Delivery address added successfully"
}
API 9: File Complaint
POST: http://localhost:4000/tourist/fileComplaint
Request Body
{
"title": "Late Tour Guide",
"body": "The tour guide was 30 minutes late for the scheduled tour",
"date": "2024-01-15T10:30:00.000Z"
}
Success Response (201)
{
"complaintId": "675661f5f97bdd3f05225210",
"status": "Pending",
"createdAt": "2024-01-15T10:30:00.000Z"
}
API 10: Rate Activity
POST: http://localhost:4000/tourist/activity/rate/:id
Request Body
{
"rating": 4,
"comment": "Great experience, very well organized",
"touristId": "675661f5f97bdd3f05225196"
}
Success Response (200)
{
"activityId": "675661f5f97bdd3f05225201",
"newAverageRating": 4.5,
"totalRatings": 15
}
API 11: Create Itinerary
POST: http://localhost:4000/tourGuide/create
Request Body
{
"title": "Cairo Historical Tour",
"description": "Explore ancient Egyptian history",
"activities": ["675661f5f97bdd3f05225201", "675661f5f97bdd3f05225202"],
"price": 2500,
"duration": 5,
"maxParticipants": 15,
"startDates": ["2024-02-01", "2024-02-15"]
}
Success Response (201)
{
"itineraryId": "675661f5f97bdd3f05225211",
"title": "Cairo Historical Tour",
"tourGuideId": "675661f5f97bdd3f05225197",
"status": "active"
}
API 12: Create Promo Code
POST: http://localhost:4000/admin/promo
Request Body
{
"code": "SUMMER2024",
"type": "PERCENTAGE",
"discount": 15,
"expiryDate": "2024-08-31T23:59:59.999Z",
"birthday": false
}
Success Response (201)
{
"promoId": "675661f5f97bdd3f05225212",
"code": "SUMMER2024",
"status": "active",
"createdAt": "2024-01-15T10:30:00.000Z"
}
API 13: Book Transportation
POST: http://localhost:4000/booking/transportation
Request Body
{
"bookingType": "transportation",
"details": {
"transportationId": "675661f5f97bdd3f05225200",
"passengers": 2,
"luggageCount": 3
},
"paid": false,
"startDate": "2024-02-01T09:00:00.000Z"
}
Success Response (201)
{
"bookingId": "675661f5f97bdd3f05225213",
"status": "booked",
"totalAmount": 100
}
API 14: Update User Profile
PUT: http://localhost:4000/tourist/profile
Request Body
{
"mobileNumber": "+201234567892",
"nationality": "American",
"job": "Software Engineer",
"email": "[email protected]"
}
Success Response (200)
{
"userId": "675661f5f97bdd3f05225196",
"message": "Profile updated successfully",
"updatedFields": ["mobileNumber", "nationality", "job", "email"]
}
API 15: View Sales Report
GET: http://localhost:4000/seller/salesReport
Response Body
{
"totalRevenue": 15000,
"totalSales": 50,
"productDetails": [
{
"productId": "675661f5f97bdd3f05225204",
"name": "Traditional Scarf",
"sales": 20,
"revenue": 5999.80
}
],
"periodStart": "2024-01-01T00:00:00.000Z",
"periodEnd": "2024-01-31T23:59:59.999Z"
}
API 16: Get User Notifications
GET: http://localhost:4000/tourist/notifs
Response Body
{
"notifications": [
{
"_id": "675661f5f97bdd3f05225214",
"message": "Your booking has been confirmed",
"reason": "booking_confirmation",
"ReasonID": "675661f5f97bdd3f05225206",
"seen": false,
"createdAt": "2024-01-15T10:30:00.000Z"
}
],
"unreadCount": 1
}
API 17: Rate Tour Guide
POST: http://localhost:4000/tourGuide/rate/:tourGuideId
Request Body
{
"rating": 5,
"comment": "Excellent knowledge and communication skills",
"touristId": "675661f5f97bdd3f05225196"
}
Success Response (200)
{
"tourGuideId": "675661f5f97bdd3f05225197",
"newAverageRating": 4.8,
"totalRatings": 25
}
API 18: Create Place
POST: http://localhost:4000/tourGoverner/addPlace
Request Body
{
"title": "Great Pyramids of Giza",
"description": "One of the Seven Wonders of the Ancient World",
"location": "Al Haram, Giza Governorate",
"openingHours": "8:00 AM - 5:00 PM",
"ticketPrices": [400, 200, 100],
"tags": [
{ "type": "Historical" },
{ "type": "UNESCO" }
],
"pictures": ["base64EncodedImage1", "base64EncodedImage2"]
}
Success Response (201)
{
"placeId": "675661f5f97bdd3f05225215",
"title": "Great Pyramids of Giza",
"message": "Place added successfully"
}
Test 1: User Registration Flow
POST: http://localhost:4000/auth/register
Test Cases:
{
"validCase": {
"input": {
"username": "testuser",
"email": "[email protected]",
"password": "Password123",
"role": "tourist"
},
"expectedResponse": {
"status": 201,
"body": {
"message": "Registration successful"
}
}
},
"invalidCase": {
"input": {
"username": "test",
"email": "invalid-email",
"password": "123"
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid input data"
}
}
}
}
Test 2: Authentication Flow
POST: http://localhost:4000/auth/login
Test Cases:
{
"validLogin": {
"input": {
"username": "testuser",
"password": "Password123"
},
"expectedResponse": {
"status": 200,
"body": {
"token": "jwt_token"
}
}
},
"invalidLogin": {
"input": {
"username": "testuser",
"password": "wrongpass"
},
"expectedResponse": {
"status": 401,
"body": {
"error": "Invalid credentials"
}
}
}
}
Test 3: Activity Booking Flow
POST: http://localhost:4000/booking/activity
Test Cases:
{
"validBooking": {
"input": {
"activityId": "675661f5f97bdd3f05225197",
"date": "2024-12-25",
"participants": 2
},
"expectedResponse": {
"status": 201,
"body": {
"bookingId": "675661f5f97bdd3f05225198"
}
}
},
"invalidBooking": {
"input": {
"activityId": "675661f5f97bdd3f05225197",
"participants": 100
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Insufficient capacity"
}
}
}
}
Test 4: Payment Processing Flow
POST: http://localhost:4000/payment/handleBookingPayment
Test Cases:
{
"validPayment": {
"input": {
"bookingId": "675661f5f97bdd3f05225198",
"amount": 200,
"method": "wallet"
},
"expectedResponse": {
"status": 200,
"body": {
"transactionId": "675661f5f97bdd3f05225199"
}
}
},
"insufficientFunds": {
"input": {
"bookingId": "675661f5f97bdd3f05225198",
"amount": 10000,
"method": "wallet"
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Insufficient funds"
}
}
}
}
Test 5: Cart Management Flow
POST: http://localhost:4000/tourist/cart/add
Test Cases:
{
"addToCart": {
"input": {
"productId": "675661f5f97bdd3f05225196",
"quantity": 2
},
"expectedResponse": {
"status": 200,
"body": {
"message": "Added to cart"
}
}
},
"invalidQuantity": {
"input": {
"productId": "675661f5f97bdd3f05225196",
"quantity": -1
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid quantity"
}
}
}
}
Test 6: Itinerary Creation Flow
POST: http://localhost:4000/tourGuide/create
Test Cases:
{
"validItinerary": {
"input": {
"title": "Egypt Explorer",
"activities": ["675661f5f97bdd3f05225197"],
"duration": 7,
"price": 1500
},
"expectedResponse": {
"status": 201,
"body": {
"itineraryId": "675661f5f97bdd3f05225200"
}
}
},
"invalidItinerary": {
"input": {
"title": "",
"duration": -1
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid itinerary data"
}
}
}
}
Test 7: Rating System Flow
POST: http://localhost:4000/tourist/activity/rate/:id
Test Cases:
{
"validRating": {
"input": {
"rating": 5,
"comment": "Great experience!"
},
"expectedResponse": {
"status": 200,
"body": {
"newAverageRating": 4.5
}
}
},
"invalidRating": {
"input": {
"rating": 6,
"comment": ""
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid rating value"
}
}
}
}
Test 8: Profile Update Flow
PUT: http://localhost:4000/tourist/profile
Test Cases:
{
"validUpdate": {
"input": {
"name": "John Doe",
"phone": "+1234567890"
},
"expectedResponse": {
"status": 200,
"body": {
"message": "Profile updated"
}
}
},
"invalidUpdate": {
"input": {
"phone": "invalid-phone"
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid phone format"
}
}
}
}
Test 9: Complaint System Flow
POST: http://localhost:4000/tourist/fileComplaint
Test Cases:
{
"validComplaint": {
"input": {
"subject": "Booking Issue",
"description": "Activity cancelled"
},
"expectedResponse": {
"status": 201,
"body": {
"complaintId": "675661f5f97bdd3f05225201"
}
}
},
"invalidComplaint": {
"input": {
"subject": ""
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Subject required"
}
}
}
}
Test 10: Notification System Flow
GET: http://localhost:4000/tourist/notifs
Test Cases:
{
"validRequest": {
"expectedResponse": {
"status": 200,
"body": {
"notifications": [
{
"message": "Booking confirmed",
"seen": false
}
]
}
}
}
}
Test 11: Promo Code Flow
POST: http://localhost:4000/tourist/redeemCode
Test Cases:
{
"validPromo": {
"input": {
"code": "SUMMER2024",
"orderId": "675661f5f97bdd3f05225203"
},
"expectedResponse": {
"status": 200,
"body": {
"discountAmount": 50
}
}
},
"invalidPromo": {
"input": {
"code": "INVALID"
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid promo code"
}
}
}
}
Test 12: Transportation Booking Flow
POST: http://localhost:4000/booking/transportation
Test Cases:
{
"validBooking": {
"input": {
"transportationId": "675661f5f97bdd3f05225204",
"seats": 2,
"date": "2024-12-25"
},
"expectedResponse": {
"status": 201,
"body": {
"bookingId": "675661f5f97bdd3f05225205"
}
}
},
"invalidBooking": {
"input": {
"seats": -1
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid seats number"
}
}
}
}
Test 13: User Statistics Flow
GET: http://localhost:4000/admin/userStats
Test Cases:
{
"validRequest": {
"expectedResponse": {
"status": 200,
"body": {
"totalUsers": 1000,
"newUsersPerMonth": [
{
"month": "January",
"count": 50
}
]
}
}
}
}
Test 14: Activity Creation Flow
POST: http://localhost:4000/advertiser/activity
Test Cases:
{
"validActivity": {
"input": {
"title": "Desert Safari",
"price": 100,
"capacity": 20
},
"expectedResponse": {
"status": 201,
"body": {
"activityId": "675661f5f97bdd3f05225206"
}
}
},
"invalidActivity": {
"input": {
"price": -100
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid price"
}
}
}
}
Test 15: Password Reset Flow
POST: http://localhost:4000/auth/resetPassword
Test Cases:
{
"validReset": {
"input": {
"email": "[email protected]",
"otp": "123456",
"newPassword": "NewPassword123"
},
"expectedResponse": {
"status": 200,
"body": {
"message": "Password reset successful"
}
}
},
"invalidReset": {
"input": {
"email": "[email protected]",
"otp": "wrong-otp"
},
"expectedResponse": {
"status": 400,
"body": {
"error": "Invalid OTP"
}
}
}
}
We use Postman
to manually test all our api references by making sure the response is as expected.
Make sure to follow the Installation steps first
Tourist π
Sign Up & Profile Management:
- Register with email, username, password, mobile number, nationality, DOB, and occupation.
- Update your profile, including wallet information and vacation preferences (historic areas, beaches, shopping, etc.).
Planning Your Vacation:
- Search for specific museums, activities, or itineraries by name, category, or tag.
- Filter activities and itineraries by budget, date, category, preferences, or language.
- Sort upcoming events or itineraries by price or ratings.
Booking & Payments:
- Book flights, hotels, transportation, and tickets to events directly through the app.
- Pay online via credit/debit card (Stripe) or wallet balance.
- Receive payment receipts via email.
Personalized Experience:
- Bookmark events to view later or request notifications when bookings open.
- Redeem loyalty points for wallet cash and earn badges based on your level.
Ratings & Feedback:
- Rate and comment on events, activities, or itineraries you participated in.
- Rate and review your tour guide.
Notifications & Updates:
- Get reminders for upcoming bookings via app and email.
- View all your upcoming and past paid activities.
Cancellations & Refunds:
- Cancel bookings 48 hours before the event to receive a wallet refund.
Complaints & Support:
- File complaints with title, description, and date for admin review.
Tour Guide πΊοΈ
Sign Up & Profile Management:
- Register with email, username, and password.
- Upload required documents for admin approval.
- Create or update your profile with personal details, experience, and work history.
Itinerary Management:
- Create, read, update, or delete itineraries with details like activities, locations, timeline, price, accessibility, and language.
- Activate/deactivate itineraries with bookings.
Analytics & Sales:
- View a sales report with revenue from your itineraries.
- Filter sales reports by itinerary, date, or month.
- View a report of tourists using your itineraries and filter by month.
Notifications:
- Receive alerts if an itinerary is flagged as inappropriate.
- Get notified of bookings or cancellations for your itineraries.
Advertiser π’
Sign Up & Profile Management:
- Register with email, username, and password.
- Upload required documents for admin approval.
- Create or update your profile with company details like website, hotline, and company profile.
Activity Management:
- Create, read, update, or delete activities with details like date, time, location, price, category, tags, and discounts.
- View a list of all your created activities.
Analytics & Sales:
- View a sales report with revenue from your activities.
- Filter sales reports by activity, date, or month.
- View a report of tourists attending your activities and filter by month.
Notifications:
- Receive alerts if an activity is flagged as inappropriate.
- Get notified of bookings or cancellations for your activities.
Seller ποΈ
Sign Up & Profile Management:
- Register with email, username, and password.
- Upload required documents for admin approval.
- Create or update your profile with name and description of your store.
Gift Shop Management:
- Add and manage products in the in-app gift shop.
- View sales reports for your store.
- Filter sales reports by product, date, or month.
Tourism Governor ποΈ
Sign Up & Management:
- Create museums and historical places with details like description, pictures, location, hours, and ticket prices.
- Create tags for categorizing historical places (e.g., type, historical period).
- Update or delete museums and tags as needed.
Overview:
- View a list of all museums and historical places youβve created.
Administrator π©βπΌ
User Management:
- Accept or reject registration requests for tour guides, advertisers, and sellers based on uploaded documents.
- Add or remove other admins and tourism governors.
- View the total number of users and monthly new user stats.
Content Management:
- Create, read, update, or delete activity categories and preference tags.
- Flag events or itineraries deemed inappropriate.
Complaint Management:
- View and manage complaints from users.
- Mark complaints as pending, resolved, or reply directly.
Analytics & Reports:
- View and filter sales reports by product, date, or month.
- Access a comprehensive revenue report for events, itineraries, and gift shop sales.
Make sure to check out the π₯ Features & Screenshots !
We welcome contributions to WanderQuest. If you want to contribute, it's as easy as:
- Fork the repo
- Create a new branch (
git checkout -b my-new-feature
) - Make changes
- Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
- Wait for your PR to be reviewed and merged
NOTE
We welcome all contributions, but please make sure to follow our code style and linting rules. You can check the Code Style section for more details.
- Mongoose docs
- Express docs
- ReactJs docs
- NodeJs docs
- Prettier docs
- MUI docs
- React Router docs
- React Hook Form docs
- React Query docs
- Formik docs
- Toastify docs
- Mongoose Crash Course
- Express Crash Course
- ReactJs Crash Course
- MUI Crash Course
- React Router Crash Course
- React Hook Form Crash Course
- React Query Crash Course
The software is open source under the Apache 2.0 License
.