503 lines
13 KiB
C++
503 lines
13 KiB
C++
/*
|
|
Author: Joel Mathew Thomas
|
|
Date: 19-02-2026
|
|
*/
|
|
|
|
#include <stdexcept>
|
|
#include <iomanip>
|
|
#include "FoodDeliveryController.h"
|
|
#include "Menu.h"
|
|
#include "RestaurantOwnerMenu.h"
|
|
#include "CustomerMenu.h"
|
|
#include "DeliveryPartnerMenu.h"
|
|
#include "User.h"
|
|
#include "RestaurantOwner.h"
|
|
#include "Customer.h"
|
|
#include "DeliveryPartner.h"
|
|
#include "Restaurant.h"
|
|
#include "inputHelper.h"
|
|
#include "outputHelper.h"
|
|
|
|
static bool checkAccess(std::shared_ptr<User> user, const std::string& userWithAccess)
|
|
{
|
|
if (!user || user->getType() != userWithAccess)
|
|
{
|
|
std::cout << "You do not have permission to do this operation!\n";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static restaurants::iterator pickRestaurantFromRestaurants(RestaurantOwner& restaurantOwner)
|
|
{
|
|
util::clear();
|
|
int restaurantIndex = 1, restaurantChoiceIndex;
|
|
restaurants& ownerRestaurants = restaurantOwner.getRestaurants();
|
|
if (ownerRestaurants.empty())
|
|
{
|
|
std::cout << "You do not own any Restaurants!\n";
|
|
return ownerRestaurants.end();
|
|
}
|
|
std::cout << "Pick a Restaurant\n";
|
|
std::cout << std::left << std::setw(8) << "Index"
|
|
<< std::left << std::setw(5) << "ID"
|
|
<< std::left << std::setw(25) << "Name"
|
|
<< std::left << std::setw(10) << "Status"
|
|
<< "\n";
|
|
for (restaurants::iterator restaurantIterator = ownerRestaurants.begin(); restaurantIterator != ownerRestaurants.end(); restaurantIterator++, restaurantIndex++)
|
|
{
|
|
auto& restaurant = *(restaurantIterator->second);
|
|
std::cout
|
|
<< std::left << std::setw(8) << restaurantIndex
|
|
<< std::left << std::setw(5) << restaurant.getId()
|
|
<< std::left << std::setw(25) << restaurant.getName()
|
|
<< std::left << std::setw(10) << (restaurant.getStatus() ? "Open" : "Closed")
|
|
<< "\n";
|
|
}
|
|
std::cout << "\nSelect Index: ";
|
|
util::readValue<int>(restaurantChoiceIndex);
|
|
restaurantChoiceIndex--;
|
|
if (restaurantChoiceIndex < 0 || restaurantChoiceIndex >= ownerRestaurants.size())
|
|
{
|
|
return ownerRestaurants.end();
|
|
}
|
|
restaurants::iterator restaurantIterator = ownerRestaurants.begin();
|
|
std::advance(restaurantIterator, restaurantChoiceIndex);
|
|
return restaurantIterator;
|
|
}
|
|
|
|
static menuItems::iterator pickMenuFromMenuItems(menuItems& restaurantMenuItems)
|
|
{
|
|
util::clear();
|
|
int menuItemIndex = 1, menuItemChoiceIndex;
|
|
if (restaurantMenuItems.empty())
|
|
{
|
|
std::cout << "Restaurant doesn't have any Menu Items!\n";
|
|
return restaurantMenuItems.end();
|
|
}
|
|
std::cout << "Pick a Menu Item\n";
|
|
std::cout << std::left << std::setw(8) << "Index"
|
|
<< std::left << std::setw(5) << "ID"
|
|
<< std::left << std::setw(25) << "Name"
|
|
<< std::left << std::setw(50) << "Description"
|
|
<< std::left << std::setw(5) << "Price"
|
|
<< "\n";
|
|
for (menuItems::iterator menuItemIterator = restaurantMenuItems.begin(); menuItemIterator != restaurantMenuItems.end(); menuItemIterator++, menuItemIndex++)
|
|
{
|
|
auto& menuItem = *(menuItemIterator->second);
|
|
std::cout
|
|
<< std::left << std::setw(8) << menuItemIndex
|
|
<< std::left << std::setw(5) << menuItem.getId()
|
|
<< std::left << std::setw(25) << menuItem.getName()
|
|
<< std::left << std::setw(50) << menuItem.getDescription()
|
|
<< std::left << std::setw(5) << menuItem.getPrice()
|
|
<< "\n";
|
|
}
|
|
std::cout << "\nSelect Index: ";
|
|
util::readValue<int>(menuItemChoiceIndex);
|
|
menuItemChoiceIndex--;
|
|
if (menuItemChoiceIndex < 0 || menuItemChoiceIndex >= restaurantMenuItems.size())
|
|
{
|
|
return restaurantMenuItems.end();
|
|
}
|
|
menuItems::iterator menuItemIterator = restaurantMenuItems.begin();
|
|
std::advance(menuItemIterator, menuItemChoiceIndex);
|
|
return menuItemIterator;
|
|
}
|
|
|
|
void FoodDeliveryController::run()
|
|
{
|
|
bool isMenuActive = true;
|
|
while (isMenuActive)
|
|
{
|
|
int choice;
|
|
util::clear();
|
|
std::cout << "Food Delivery App\n"
|
|
"1. Login\n"
|
|
"2. Register\n"
|
|
"3. Exit\n"
|
|
"Choice?: ";
|
|
try
|
|
{
|
|
util::readValue<int>(choice);
|
|
if (choice == 1)
|
|
{
|
|
login();
|
|
}
|
|
else if (choice == 2)
|
|
{
|
|
registerUser();
|
|
}
|
|
else if (choice == 3)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Invalid Choice!\n";
|
|
}
|
|
util::pressEnter();
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
util::pressEnter();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::login()
|
|
{
|
|
util::clear();
|
|
std::string username, password;
|
|
std::cout << "Enter username: ";;
|
|
util::readString(username);
|
|
std::cout << "Enter password: ";;
|
|
util::readString(password);
|
|
users::iterator userIterator = m_users.find(username);
|
|
if (userIterator != m_users.end())
|
|
{
|
|
User& user = *(userIterator->second);
|
|
std::unique_ptr<Menu> menu;
|
|
if (user.login(password))
|
|
{
|
|
if (user.getType() == "RestaurantOwner")
|
|
{
|
|
menu = std::make_unique<RestaurantOwnerMenu>(*this, user.getName());
|
|
}
|
|
else if (user.getType() == "Customer")
|
|
{
|
|
menu = std::make_unique<CustomerMenu>(*this, user.getName());
|
|
}
|
|
else if (user.getType() == "DeliveryPartner")
|
|
{
|
|
menu = std::make_unique<DeliveryPartnerMenu>(*this, user.getName());
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("Invalid User");
|
|
}
|
|
m_authenticatedUser = userIterator->second;
|
|
menu->showMenu();
|
|
m_authenticatedUser.reset();
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Invalid Password! Try Again\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "User Not Found!\n";
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::registerUser()
|
|
{
|
|
try
|
|
{
|
|
std::string username, password, phone, name, email;
|
|
util::clear();
|
|
std::cout << "Enter Username: ";
|
|
util::readString(username);
|
|
if (m_users.find(username) != m_users.end())
|
|
{
|
|
std::cout << "User Already Exists!\n";
|
|
return;
|
|
}
|
|
std::cout << "Enter Password: ";
|
|
util::readString(password);
|
|
std::cout << "Enter Full Name: ";
|
|
util::readString(name);
|
|
std::cout << "Enter Phone: ";
|
|
util::readString(phone);
|
|
std::cout << "Enter Email: ";
|
|
util::readString(email);
|
|
while (true)
|
|
{
|
|
int choice;
|
|
std::cout << "Select User Type\n"
|
|
"1. Restaurant Owner\n"
|
|
"2. Customer\n"
|
|
"3. Delivery Partner\n"
|
|
"4. Cancel\n"
|
|
"Choice?: ";
|
|
util::readValue<int>(choice);
|
|
switch (choice)
|
|
{
|
|
case 1:
|
|
m_users[username] = std::make_shared<RestaurantOwner>(username, name, phone, password, email);
|
|
break;
|
|
case 2:
|
|
m_users[username] = std::make_shared<Customer>(username, name, phone, password, email);
|
|
break;
|
|
case 3:
|
|
m_users[username] = std::make_shared<DeliveryPartner>(username, name, phone, password, email);
|
|
break;
|
|
case 4:
|
|
return;
|
|
default:
|
|
util::clear();
|
|
std::cout << "Invalid Choice! Try Again\n";
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
std::cout << "User Registration Successful\n";
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::listRestaurants() const
|
|
{
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
restaurants& ownerRestaurants = restaurantOwner.getRestaurants();
|
|
if (ownerRestaurants.empty())
|
|
{
|
|
std::cout << "You do not own any Restaurants!\n";
|
|
return;
|
|
}
|
|
std::cout << "My Restaurants\n";
|
|
std::cout << std::left << std::setw(5) << "ID"
|
|
<< std::left << std::setw(25) << "Name"
|
|
<< std::left << std::setw(20) << "Status"
|
|
<< "\n";
|
|
for (auto& restaurantPair : ownerRestaurants)
|
|
{
|
|
auto& restaurant = *(restaurantPair.second);
|
|
std::cout << std::left << std::setw(5) << restaurant.getId()
|
|
<< std::left << std::setw(25) << restaurant.getName()
|
|
<< std::left << std::setw(20) << (restaurant.getStatus() ? "Open" : "Closed")
|
|
<< "\n";
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::addNewRestaurant()
|
|
{
|
|
std::string name;
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
std::cout << "Enter Restaurant Name: ";
|
|
util::readString(name);
|
|
std::shared_ptr<Restaurant> restaurant = std::make_shared<Restaurant>(name);
|
|
m_restaurants[restaurant->getId()] = restaurant;
|
|
restaurantOwner.addRestaurant(restaurant);
|
|
std::cout << "Restaurant " << restaurant->getName() << " with ID " << restaurant->getId() << " created successfully\n";
|
|
}
|
|
|
|
void FoodDeliveryController::updateRestaurantStatus() const
|
|
{
|
|
try
|
|
{
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner);
|
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
|
{
|
|
if (restaurantIterator->second->getStatus() == true)
|
|
{
|
|
restaurantIterator->second->setStatus(false);
|
|
}
|
|
else
|
|
{
|
|
restaurantIterator->second->setStatus(true);
|
|
}
|
|
listRestaurants();
|
|
std::cout << "Updated Restaurant " << restaurantIterator->second->getName() << " successfully\n";
|
|
}
|
|
else if (!restaurantOwner.getRestaurants().empty())
|
|
{
|
|
std::cout << "Invalid Index. Cannot update Restaurant status!\n";
|
|
return;
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::listRestaurantOrders()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::markOrderReady()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::listMenuItems() const
|
|
{
|
|
try
|
|
{
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner);
|
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
|
{
|
|
util::clear();
|
|
menuItems& restaurantMenuItems = restaurantIterator->second->getMenuItems();
|
|
if (restaurantMenuItems.empty())
|
|
{
|
|
std::cout << "Restaurant " << restaurantIterator->second->getName() << " has no Menu Items\n";
|
|
return;
|
|
}
|
|
std::cout << restaurantIterator->second->getName() << " Menu\n";
|
|
std::cout << std::left << std::setw(5) << "ID"
|
|
<< std::left << std::setw(25) << "Name"
|
|
<< std::left << std::setw(50) << "Description"
|
|
<< std::left << std::setw(5) << "Price"
|
|
<< "\n";
|
|
for (auto& menuItemPointer : restaurantMenuItems)
|
|
{
|
|
std::cout << std::left << std::setw(5) << menuItemPointer.second->getId()
|
|
<< std::left << std::setw(25) << menuItemPointer.second->getName()
|
|
<< std::left << std::setw(50) << menuItemPointer.second->getDescription()
|
|
<< std::left << std::setw(5) << menuItemPointer.second->getPrice()
|
|
<< "\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Invalid Index. Cannot display Menu Items!\n";
|
|
return;
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::addMenuItem() const
|
|
{
|
|
try
|
|
{
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner);
|
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
|
{
|
|
util::clear();
|
|
std::string name, description;
|
|
double price;
|
|
std::cout << "Enter Item Name: ";
|
|
util::readString(name);
|
|
std::cout << "Enter Item Description: ";
|
|
util::readString(description);
|
|
std::cout << "Enter Item Price: ";
|
|
util::readValue<double>(price);
|
|
MenuItem menuItem(name, description, price);
|
|
restaurantIterator->second->addMenuItem(menuItem);
|
|
std::cout << "Added new Menu Item " << menuItem.getName() << " with ID " << menuItem.getId() << " to Restaurant " << restaurantIterator->second->getName() << " successfully\n";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Invalid Index. Cannot add new Menu Item!\n";
|
|
return;
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::removeMenuItem() const
|
|
{
|
|
try
|
|
{
|
|
util::clear();
|
|
if (!checkAccess(m_authenticatedUser, "RestaurantOwner"))
|
|
{
|
|
return;
|
|
}
|
|
RestaurantOwner& restaurantOwner = *(std::dynamic_pointer_cast<RestaurantOwner>(m_authenticatedUser));
|
|
restaurants::iterator restaurantIterator = pickRestaurantFromRestaurants(restaurantOwner);
|
|
if (restaurantIterator != restaurantOwner.getRestaurants().end())
|
|
{
|
|
menuItems& restaurantMenuItems = restaurantIterator->second->getMenuItems();
|
|
menuItems::iterator menuItemIterator = pickMenuFromMenuItems(restaurantMenuItems);
|
|
if (menuItemIterator != restaurantMenuItems.end())
|
|
{
|
|
restaurantMenuItems.erase(menuItemIterator);
|
|
std::cout << "Removed Menu Item successfully\n";
|
|
}
|
|
else if (!restaurantMenuItems.empty())
|
|
{
|
|
std::cout << "Invalid Index. Cannot remove Menu Item!\n";
|
|
}
|
|
}
|
|
else if (!restaurantOwner.getRestaurants().empty())
|
|
{
|
|
std::cout << "Invalid Index. Cannot remove Menu Item!\n";
|
|
return;
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
}
|
|
}
|
|
|
|
void FoodDeliveryController::listCustomerOrders()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::placeOrder()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::cancelOrder()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::listDeliveryAssignments()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::acceptDeliveryAssignment()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::confirmDeliveryAssignment()
|
|
{
|
|
|
|
}
|
|
|
|
void FoodDeliveryController::viewProfile()
|
|
{
|
|
|
|
}
|