515 lines
14 KiB
C++
515 lines
14 KiB
C++
/*
|
|
File: AdminMenu.cpp
|
|
Description: Implementation file containing the method definitions of the
|
|
AdminMenu class, including menu handling, inventory operations,
|
|
user management, and combo package management functions.
|
|
Author: Trenser
|
|
Date:19-May-2026
|
|
*/
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include "AdminMenu.h"
|
|
#include "InputHelper.h"
|
|
#include "OutputHelper.h"
|
|
#include "User.h"
|
|
#include "Validator.h"
|
|
#include "Service.h"
|
|
#include "Utility.h"
|
|
#include "ComboPackage.h"
|
|
#include "Enums.h"
|
|
|
|
/*
|
|
Function: showMenu
|
|
Description: Displays the admin menu and handles user input until logout is selected.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::showMenu()
|
|
{
|
|
while (true)
|
|
{
|
|
try
|
|
{
|
|
int choice;
|
|
util::clear();
|
|
std::cout << "Admin Menu"
|
|
<< "\n1. View Stock Levels"
|
|
<< "\n2. Add Inventory Item"
|
|
<< "\n3. Remove Inventory Item"
|
|
<< "\n4. Check Stock Availability"
|
|
<< "\n5. Assign Job to Technician"
|
|
<< "\n6. Add Technician"
|
|
<< "\n7. Remove Customer/Technician"
|
|
<< "\n8. Create Service"
|
|
<< "\n9. Remove Service"
|
|
<< "\n10. Create Combo Package"
|
|
<< "\n11. Remove Combo Package"
|
|
<< "\n12. View Notifications"
|
|
<< "\n13. Change Password"
|
|
<< "\n14. Logout"
|
|
<< "\nEnter a choice: ";
|
|
util::read(choice);
|
|
if (!handleOperation(choice))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
catch (const std::exception& e)
|
|
{
|
|
std::cout << "Exception: " << e.what() << std::endl;
|
|
util::pressEnter();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: handleOperation
|
|
Description: Executes the corresponding admin operation based on the selected menu choice.
|
|
Parameter: int choice - selected menu option
|
|
Return type: bool - true if menu continues, false if logout
|
|
*/
|
|
bool AdminMenu::handleOperation(int choice)
|
|
{
|
|
switch (choice)
|
|
{
|
|
case 1:
|
|
viewStockLevels();
|
|
break;
|
|
case 2:
|
|
addInventoryItem();
|
|
break;
|
|
case 3:
|
|
removeInventoryItem();
|
|
break;
|
|
case 4:
|
|
checkStockAvailability();
|
|
break;
|
|
case 5:
|
|
assignJob();
|
|
break;
|
|
case 6:
|
|
addTechnician();
|
|
break;
|
|
case 7:
|
|
removeUser();
|
|
break;
|
|
case 8:
|
|
createService();
|
|
break;
|
|
case 9:
|
|
removeService();
|
|
break;
|
|
case 10:
|
|
createComboPackages();
|
|
break;
|
|
case 11:
|
|
removeComboPackage();
|
|
break;
|
|
case 12:
|
|
viewNotifications();
|
|
break;
|
|
case 13:
|
|
changePassword();
|
|
break;
|
|
case 14:
|
|
logout();
|
|
return false;
|
|
default:
|
|
std::cout << "Enter a valid choice!" << std::endl;
|
|
util::pressEnter();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
Function: logout
|
|
Description: Logs out the currently authenticated admin user.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::logout()
|
|
{
|
|
m_controller.logout();
|
|
}
|
|
/*
|
|
Function: changePassword
|
|
Description: Allows the admin to change their password after validation.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::changePassword()
|
|
{
|
|
std::string newPassword;
|
|
while (true)
|
|
{
|
|
util::clear();
|
|
std::cout << "Enter new password: ";
|
|
util::read(newPassword);
|
|
if (!util::isPasswordValid(newPassword))
|
|
{
|
|
std::cout << "Error: Password is not strong enough!\n";
|
|
util::pressEnter();
|
|
continue;
|
|
}
|
|
m_controller.changePassword(newPassword);
|
|
std::cout << "Password changed successfully\n";
|
|
util::pressEnter();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void AdminMenu::viewStockLevels()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::addInventoryItem()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::removeInventoryItem()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::checkStockAvailability()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::assignJob()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::createService()
|
|
{
|
|
}
|
|
|
|
void AdminMenu::removeService()
|
|
{
|
|
}
|
|
|
|
/*
|
|
Function: addTechnician
|
|
Description: Adds a new technician after validating username, password, email, and phone number.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::addTechnician()
|
|
{
|
|
util::clear();
|
|
std::string username, password, email, phoneNumber;
|
|
std::cout << std::left << std::setw(25) << "Enter Technician Username:";
|
|
util::read(username);
|
|
std::cout << std::setw(25) << "Enter Technician Password:";
|
|
util::read(password);
|
|
if(!util::isPasswordValid(password))
|
|
{
|
|
std::cout << "Error: Password is invalid!";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
std::cout << std::setw(25) << "Enter Technician Email:";
|
|
util::read(email);
|
|
if(!util::isEmailValid(email))
|
|
{
|
|
std::cout << "Error: Email is invalid!";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
std::cout << std::setw(25) << "Enter Technician Phone:";
|
|
util::read(phoneNumber);
|
|
if(!util::isPhoneNumberValid(phoneNumber))
|
|
{
|
|
std::cout << "Error: Phone Number is invalid!";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
m_controller.createTechnician(username, password, email, phoneNumber);
|
|
std::cout << "\nTechnician Added Successfully.\n";
|
|
util::pressEnter();
|
|
}
|
|
|
|
/*
|
|
Function: filterActiveUsers
|
|
Description: Filters out inactive users and returns a map of active users.
|
|
Parameter: const util::Map<std::string, const User*>& listOfUsers - all users
|
|
Return type: util::Map<std::string, const User*>
|
|
*/
|
|
static util::Map<std::string, const User*>
|
|
filterActiveUsers(const util::Map<std::string, const User*>& listOfUsers)
|
|
{
|
|
util::Map<std::string, const User*> activeUsers;
|
|
int inventorySize = listOfUsers.getSize();
|
|
for (int index = 0; index < inventorySize; index++)
|
|
{
|
|
const User* user = listOfUsers.getValueAt(index);
|
|
if (user != nullptr && user->getState() != util::State::INACTIVE)
|
|
{
|
|
activeUsers.insert(user->getId(), user);
|
|
}
|
|
}
|
|
return activeUsers;
|
|
}
|
|
|
|
/*
|
|
Function: displayAllActiveUsers
|
|
Description: Displays all active users in a tabular format with index, ID, username, and type.
|
|
Parameter: util::Map<std::string, const User*>& activeUsers - active users list
|
|
int activeUserCount - number of active users
|
|
Return type: void
|
|
*/
|
|
static void displayAllActiveUsers(util::Map<std::string, const User*>& activeUsers, int activeUserCount)
|
|
{
|
|
std::cout << std::left << std::setw(10) << "Index"
|
|
<< std::setw(15) << "User ID"
|
|
<< std::setw(25) << "Username"
|
|
<< std::setw(25) << "User Type"
|
|
<< std::endl;
|
|
for (int iterator = 0; iterator < activeUserCount; iterator++)
|
|
{
|
|
const User* user = activeUsers.getValueAt(iterator);
|
|
if (user != nullptr)
|
|
{
|
|
std::cout << std::left << std::setw(10) << (iterator + 1)
|
|
<< std::setw(15) << user->getId()
|
|
<< std::setw(25) << user->getUserName()
|
|
<< std::setw(25) << util::getUserTypeString(user->getUserType())
|
|
<< std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "No users found.\n";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: removeUser
|
|
Description: Removes a selected active user (customer or technician) from the system.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::removeUser()
|
|
{
|
|
util::clear();
|
|
int indexChoice;
|
|
auto listOfUsers = m_controller.getUsers();
|
|
auto listOfActiveUsers = filterActiveUsers(listOfUsers);
|
|
int activeUserCount = listOfActiveUsers.getSize();
|
|
if (activeUserCount < 1)
|
|
{
|
|
std::cout << "No Active users." << std::endl;
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
displayAllActiveUsers(listOfActiveUsers, activeUserCount);
|
|
std::cout << "Enter the index of the user to delete : ";
|
|
util::read(indexChoice);
|
|
if (indexChoice < 1 || indexChoice > activeUserCount)
|
|
{
|
|
std::cout << "Error Invaild index.\n" << std::endl;
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
const User* userToRemove = listOfActiveUsers.getValueAt(indexChoice - 1);
|
|
if (userToRemove != nullptr)
|
|
{
|
|
std::string userIdToRemove = userToRemove->getId();
|
|
m_controller.removeUser(userIdToRemove);
|
|
std::cout << userToRemove->getUserName() << " removed Successfully.\n";
|
|
}
|
|
util::pressEnter();
|
|
}
|
|
|
|
/*
|
|
Function: selectServiceFromServices
|
|
Description: Displays active services and allows the admin to select one by index.
|
|
Parameter: const util::Map<std::string, const Service*>& services - list of services
|
|
Return type: const Service* - selected service
|
|
*/
|
|
static const Service* selectServiceFromServices(const util::Map<std::string, const Service*>& services)
|
|
{
|
|
util::Map<int, const Service*> activeServicesMap;
|
|
int currentIndex = 1;
|
|
int userInputIndex;
|
|
std::cout << std::left
|
|
<< std::setw(10) << "Index"
|
|
<< std::setw(15) << "Service ID"
|
|
<< std::setw(25) << "Service Name"
|
|
<< std::setw(15) << "Estimated Cost"
|
|
<< std::endl;
|
|
for (int index = 0; index < services.getSize(); index++)
|
|
{
|
|
const Service* currentService = services.getValueAt(index);
|
|
if (currentService->getState() != util::State::ACTIVE)
|
|
{
|
|
continue;
|
|
}
|
|
activeServicesMap.insert(currentIndex, currentService);
|
|
double partsCost = calculatePartsCost(currentService);
|
|
std::cout << std::left
|
|
<< std::setw(10) << currentIndex
|
|
<< std::setw(15) << currentService->getId()
|
|
<< std::setw(25) << currentService->getName()
|
|
<< std::setw(15) << (currentService->getLaborCost() + partsCost)
|
|
<< std::endl;
|
|
currentIndex++;
|
|
}
|
|
if (activeServicesMap.getSize() == 0)
|
|
{
|
|
std::cout << "No active services available." << std::endl;
|
|
return nullptr;
|
|
}
|
|
std::cout << "Enter service index: ";
|
|
util::read(userInputIndex);
|
|
if (activeServicesMap.find(userInputIndex) == -1)
|
|
{
|
|
std::cout << "Invalid service index." << std::endl;
|
|
return nullptr;
|
|
}
|
|
return activeServicesMap[userInputIndex];
|
|
}
|
|
|
|
/*
|
|
Function: createComboPackages
|
|
Description: Creates a new combo package by selecting two active services and applying a discount.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::createComboPackages()
|
|
{
|
|
util::clear();
|
|
auto serviceList = m_controller.getServices();
|
|
const int numberOfServicesInPackage = 2;
|
|
util::Vector<std::string> selectedServiceID;
|
|
for (int iterator = 0; iterator < numberOfServicesInPackage; iterator++)
|
|
{
|
|
const Service* chosenService = selectServiceFromServices(serviceList);
|
|
if (chosenService == nullptr)
|
|
{
|
|
std::cout << "Failed to create combo package!";
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
selectedServiceID.push_back(chosenService->getId());
|
|
util::clear();
|
|
}
|
|
std::string packageName;
|
|
double discountPercentage;
|
|
std::cout << "Enter combo package name: ";
|
|
util::read(packageName);
|
|
std::cout << "Enter discount percentage: ";
|
|
util::read(discountPercentage);
|
|
if (discountPercentage < 0.0 || discountPercentage > 100.0)
|
|
{
|
|
std::cout << "Error: Discount percentage must be between 0 and 100." << std::endl;
|
|
util::pressEnter();
|
|
return;
|
|
}
|
|
m_controller.createComboPackage(packageName, selectedServiceID, discountPercentage);
|
|
std::cout << "Combo package '" << packageName << "' created successfully." << std::endl;
|
|
util::pressEnter();
|
|
}
|
|
|
|
/*
|
|
Function: displayComboPackagesWithIndex
|
|
Description: Displays combo packages with index, ID, name, and discount percentage.
|
|
Parameter: util::Map<int, const ComboPackage*>& currentComboPackageIndexMap - combo packages map
|
|
Return type: void
|
|
*/
|
|
static void displayComboPackagesWithIndex(util::Map<int, const ComboPackage*>& currentComboPackageIndexMap)
|
|
{
|
|
for (int iterator = 0; iterator < currentComboPackageIndexMap.getSize(); iterator++)
|
|
{
|
|
const ComboPackage* currentComboPackage = currentComboPackageIndexMap.getValueAt(iterator);
|
|
if (currentComboPackage == nullptr)
|
|
{
|
|
throw std::runtime_error("Error accessing the combopackage.\n");
|
|
}
|
|
if (iterator == 0)
|
|
{
|
|
std::cout << std::left
|
|
<< std::setw(8) << "Index"
|
|
<< std::setw(10) << "ID"
|
|
<< std::setw(20) << "Package Name"
|
|
<< std::setw(15) << "Discount (%)"
|
|
<< "\n";
|
|
}
|
|
std::cout << std::left
|
|
<< std::setw(8) << currentComboPackageIndexMap.getKeyAt(iterator)
|
|
<< std::setw(10) << currentComboPackage->getId()
|
|
<< std::setw(20) << currentComboPackage->getPackageName()
|
|
<< std::setw(15) << currentComboPackage->getDiscountPercentage()
|
|
<< "\n";
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: selectComboPackage
|
|
Description: Allows the admin to select an active combo package by index.
|
|
Parameter: util::Map<std::string, const ComboPackage*>& currentComboPackages - combo packages list
|
|
Return type: std::string - ID of the selected combo package
|
|
*/
|
|
static std::string selectComboPackage(util::Map<std::string, const ComboPackage*>& currentComboPackages)
|
|
{
|
|
util::Map<int, const ComboPackage*> currentComboPackageIndexMap;
|
|
if (currentComboPackages.getSize() == 0)
|
|
{
|
|
throw std::runtime_error("No combo packages are available.\n");
|
|
}
|
|
int currentIndex = 1, choice, selectedIndex;
|
|
for (int iterator = 0; iterator < currentComboPackages.getSize(); iterator++)
|
|
{
|
|
if (currentComboPackages.getValueAt(iterator)->getState() == util::State::INACTIVE)
|
|
{
|
|
continue;
|
|
}
|
|
currentComboPackageIndexMap.insert(currentIndex++, currentComboPackages.getValueAt(iterator));
|
|
}
|
|
if (currentComboPackageIndexMap.getSize() == 0)
|
|
{
|
|
throw std::runtime_error("No combo packages currently active.");
|
|
}
|
|
displayComboPackagesWithIndex(currentComboPackageIndexMap);
|
|
std::cout << "Enter your choice(Index): ";
|
|
util::read(choice);
|
|
selectedIndex = currentComboPackageIndexMap.find(choice);
|
|
if (selectedIndex != -1)
|
|
{
|
|
std::string selectedComboPackageID = currentComboPackageIndexMap.getValueAt(selectedIndex)->getId();
|
|
return selectedComboPackageID;
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Enter a valid choice.\n";
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/*
|
|
Function: removeComboPackage
|
|
Description: Removes a selected combo package from the system.
|
|
Parameter: None
|
|
Return type: void
|
|
*/
|
|
void AdminMenu::removeComboPackage()
|
|
{
|
|
util::clear();
|
|
util::Map<std::string, const ComboPackage*> currentComboPackages = m_controller.getComboPackages();
|
|
std::string selectedComboPackageID = selectComboPackage(currentComboPackages);
|
|
if (selectedComboPackageID != "")
|
|
{
|
|
m_controller.removeComboPackage(selectedComboPackageID);
|
|
std::cout << "Combo Package removed successfully.\n";
|
|
}
|
|
else
|
|
{
|
|
std::cout << "Combo package removal failed.\n";
|
|
}
|
|
util::pressEnter();
|
|
}
|
|
|
|
void AdminMenu::viewNotifications()
|
|
{
|
|
}
|