diff --git a/.vscode/settings.json b/.vscode/settings.json index 7a3fdfb..f178db4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,9 @@ "utility": "cpp", "limits": "cpp", "*.tcc": "cpp", - "ostream": "cpp" + "ostream": "cpp", + "chrono": "cpp", + "random": "cpp", + "valarray": "cpp" } } \ No newline at end of file diff --git a/data/products.json b/data/products.json index 6db2ab0..4813264 100644 --- a/data/products.json +++ b/data/products.json @@ -21,6 +21,61 @@ "price": 13.0, "quantity": 313, "sku": "321" + }, + { + "barcode": "123", + "category": "NA", + "description": "NA", + "expiration_date": "NA", + "id": "123", + "name": "hotdog", + "price": 13.0, + "quantity": 123, + "sku": "NA" + }, + { + "barcode": "123123", + "category": "NA", + "description": "NA", + "expiration_date": "NA", + "id": "123123", + "name": "dog", + "price": 123.0, + "quantity": 2, + "sku": "NA" + }, + { + "barcode": "12323123", + "category": "NA", + "description": "NA", + "expiration_date": "NA", + "id": "12323123", + "name": "alpha", + "price": 123.0, + "quantity": 2, + "sku": "NA" + }, + { + "barcode": "200", + "category": "NA", + "description": "NA", + "expiration_date": "NA", + "id": "200", + "name": "400", + "price": 3333.0, + "quantity": 333333, + "sku": "NA" + }, + { + "barcode": "12321313", + "category": "NA", + "description": "NA", + "expiration_date": "NA", + "id": "12321313", + "name": "pony", + "price": 300000.0, + "quantity": 2, + "sku": "NA" } ] } \ No newline at end of file diff --git a/main.cpp b/main.cpp index 5723bbc..9a07307 100644 --- a/main.cpp +++ b/main.cpp @@ -136,25 +136,32 @@ void displayFilterMenu() { std::cout << "\n=========== Advanced Filter ===========\n"; std::cout << "1. Filter by Price Range\n"; std::cout << "2. Filter by Category\n"; - std::cout << "3. Back to Product Management\n"; - std::cout << "Please enter your choice (1-3): "; + std::cout << "3. Filter by Name Alphabetically\n"; + std::cout << "4. Filter by Quantity Range\n"; + std::cout << "5. Filter by Prefix\n"; + std::cout << "6. Back to Product Management\n"; std::cin >> choice; switch (choice) { case 1: - std::cout << "Enter Price Range (e.g., 10-20): "; - std::cin >> filterQuery; - std::cout << - "Filtering by Price Range. (This functionality is not yet implemented, please be patience.)\n"; + filterPriceRange(); displayFilterMenu(); break; case 2: - std::cout << "Enter Category: "; - std::cin >> filterQuery; - std::cout << - "Filtering by Category. (This functionality is not yet implemented, please be patience.)\n"; + filterCategory(); displayFilterMenu(); break; case 3: + filterName(); + displayFilterMenu(); + break; + case 4: + filterQuantityRange(); + displayFilterMenu(); + break; + case 5: + filterPrefix(); + displayFilterMenu(); + case 6: displayProductManagementMenu(); break; default: diff --git a/main.exe b/main.exe index 4d0191f..eff6f9c 100644 Binary files a/main.exe and b/main.exe differ diff --git a/src/filter.h b/src/filter.h new file mode 100644 index 0000000..4913d9c --- /dev/null +++ b/src/filter.h @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include "../libraries/json.hpp" + +using namespace std; +using json = nlohmann::json; + +class Filter{ +public: + Filter(const string& productsPath){ + _path = productsPath; + loadFromFile(); + } + + virtual vector apply() const = 0; + +protected: + string _path; + json _data; + + void loadFromFile() { + ifstream pPath(_path); + if (!pPath.is_open()) { + cerr << "Error opening file: " << _path << endl; + return; + } + pPath >> _data; + pPath.close(); + } +}; + + + +class PriceRangeFilter : public Filter{ +public: + PriceRangeFilter(const string& productsPath, const double& minPrice, const double& maxPrice) : Filter(productsPath){ + _minPrice = minPrice; + _maxPrice = maxPrice; + } + + vector apply() const override{ + vector filteredData; + + // Apply price range filtering logic using _data, _minPrice, and _maxPrice + for (const auto& product : _data["products"]) { + double price = product["price"]; + if (price >= _minPrice && price <= _maxPrice) { + filteredData.push_back(product); + } + } + + return filteredData; + } +private: + double _minPrice; + double _maxPrice; +}; + +class ExpirationDateFilter : public Filter { +public: + ExpirationDateFilter(const string& productsPath, const string& expirationDate) + : Filter(productsPath), _expirationDate(expirationDate) { + } + + vector apply() const override { + vector filteredData; + + // Convert the expiration date string to a time_point + auto targetTime = convertToDatePoint(_expirationDate); + + // Apply expiration date filtering logic using _data and targetTime + for (const auto& product : _data["product"]) { + string itemExpiration = product["expiration"]; + auto itemTime = convertToDatePoint(itemExpiration); + + if (itemTime <= targetTime) { + filteredData.push_back(product); + } + } + + return filteredData; + } + +private: + string _expirationDate; + + // Convert a date string to a time_point + static chrono::system_clock::time_point convertToDatePoint(const string& dateStr) { + // Assuming the dateStr is in the format "YYYY-MM-DD" + struct std::tm tm = {}; + sscanf(dateStr.c_str(), "%d-%d-%d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday); + tm.tm_year -= 1900; + tm.tm_mon -= 1; + + time_t time = mktime(&tm); + return chrono::system_clock::from_time_t(time); + } +}; + +class CategoryFilter : public Filter{ +public: + CategoryFilter(const string& productsPath, const string& name) : Filter(productsPath){ + _name = name; + } + + vector apply() const override{ + vector filteredData; + + for (const auto& product : _data["products"]) { + string name = product["category"]; + if (_name == name) { + filteredData.push_back(product); + } + } + + return filteredData; + } +private: + string _name; +}; + +class NameFilter : public Filter { +public: + NameFilter(const string& productsPath) : Filter(productsPath){ + + } + + vector apply() const override { + vector filteredData; + + for (const auto& product : _data["products"]) { + filteredData.push_back(product); + } + + sort(filteredData.begin(), filteredData.end(), [](const json& a, const json& b) { + string nameA = a["name"]; + string nameB = b["name"]; + return nameA < nameB; + }); + + + return filteredData; + } +}; + +class QuantityFilter : public Filter { +public: + QuantityFilter(const string& productsPath, const int& minQuantity, const int& maxQuantity) : Filter(productsPath){ + _minQuantity = minQuantity; + _maxQuantity = maxQuantity; + } + + vector apply() const override { + vector filteredData; + + // Apply price range filtering logic using _data, _minQuantity, and _maxQuantity + for (const auto& product : _data["products"]) { + double price = product["quantity"]; + if (price >= _minQuantity && price <= _maxQuantity) { + filteredData.push_back(product); + } + } + + return filteredData; + } +private: + int _minQuantity; + int _maxQuantity; +}; + +class PrefixFilter : public Filter { +public: + PrefixFilter(const string& productsPath, const string& prefix) : Filter(productsPath){ + _prefix = prefix; + } + + vector apply() const override { + vector filteredData; + + for (const auto& product : _data["products"]) { + const string productName = product["name"]; + + if (productName.compare(0, _prefix.length(), _prefix) == 0) { + filteredData.push_back(product); + } + } + + return filteredData; + } + +private: + string _prefix; +}; \ No newline at end of file diff --git a/src/mainmenuhelpers.h b/src/mainmenuhelpers.h index 885dc2d..66bc507 100644 --- a/src/mainmenuhelpers.h +++ b/src/mainmenuhelpers.h @@ -4,12 +4,18 @@ #include "productDatabase.h" +#include "filter.h" + using namespace std; void addMenu(); void deleteProduct(); bool updateProduct(string productId = "", int requestedQuantity = -1); double acceptNumber(const string & prompt); +void filterPriceRange(); +void filterCategory(); +void filterQuantityRange(); +void filterPrefix(); void addMenu() { productDatabase manage("data/products.json"); @@ -266,4 +272,151 @@ double acceptNumber(const string & prompt) { } return number; -} \ No newline at end of file +} + +void filterPriceRange(){ + int min = INT_MIN; + int max = INT_MAX; + + cout << "Enter the minimum price: "; + cin >> min; + cout << "Enter the maximum price: "; + cin >> max; + + if(min > max){ + cout << "Invalid option\n\n"; + return; + } + + string productsPath = "data/products.json"; + PriceRangeFilter priceFilter(productsPath, min, max); + + vector res = priceFilter.apply(); + + if(res.size() == 0){ + cout << endl; + cout << "No results found" << endl; + } + + productDatabase manage(productsPath); + int count = 1; + cout << endl; + for(auto i : res){ + cout << count << "." << endl; + count++; + manage.viewProduct(i["id"]); + cout << endl; + } + +} + +void filterCategory(){ + string name; + cout << "Enter a category name: "; + cin >> name; + + string productsPath = "data/products.json"; + CategoryFilter categoryFilter(productsPath, name); + + vector res = categoryFilter.apply(); + + if(res.size() == 0){ + cout << endl; + cout << "No results found" << endl; + } + + productDatabase manage(productsPath); + int count = 1; + cout << endl; + for(auto i : res){ + cout << count << "." << endl; + count++; + manage.viewProduct(i["id"]); + cout << endl; + } +} + +void filterName(){ + cout << "Sorting all products alphabetically\n"; + + string productsPath = "data/products.json"; + NameFilter nameFilter(productsPath); + + vector res = nameFilter.apply(); + + if(res.size() == 0){ + cout << endl; + cout << "No results found" << endl; + } + + productDatabase manage(productsPath); + int count = 1; + cout << endl; + for(auto i : res){ + cout << count << "." << endl; + count++; + manage.viewProduct(i["id"]); + cout << endl; + } +} + +void filterQuantityRange(){ + int min = INT_MIN; + int max = INT_MAX; + + cout << "Enter the minimum quantity: "; + cin >> min; + cout << "Enter the maximum quantity: "; + cin >> max; + + if(min > max){ + cout << "Invalid option\n\n"; + return; + } + + string productsPath = "data/products.json"; + QuantityFilter quantityFilter(productsPath, min, max); + + vector res = quantityFilter.apply(); + + if(res.size() == 0){ + cout << endl; + cout << "No results found" << endl; + } + + productDatabase manage(productsPath); + int count = 1; + cout << endl; + for(auto i : res){ + cout << count << "." << endl; + count++; + manage.viewProduct(i["id"]); + cout << endl; + } +} + +void filterPrefix(){ + string prefix; + cout << "Enter the prefix: "; + cin >> prefix; + + string productsPath = "data/products.json"; + PrefixFilter prefixFilter(productsPath, prefix); + + vector res = prefixFilter.apply(); + + if(res.size() == 0){ + cout << endl; + cout << "No results found" << endl; + } + + productDatabase manage(productsPath); + int count = 1; + cout << endl; + for(auto i : res){ + cout << count << "." << endl; + count++; + manage.viewProduct(i["id"]); + cout << endl; + } +}