diff --git a/.gitignore b/.gitignore index 59e1fc7..603d4ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ # Ignore src/includes/error-logs.txt src/sales-prediction-algorithm/sales_prediction.json - -.phpunit.result.cache +src/includes/charts/weekly_sales_data.json +.phpunit.result.cache \ No newline at end of file diff --git a/src/accounts.php b/src/accounts.php index 4f8bf14..411a67f 100644 --- a/src/accounts.php +++ b/src/accounts.php @@ -36,6 +36,16 @@ + + + + + + + + + + - - - - - - - - ' . $row['flavor'] . '
'; } echo ''; - echo '
'; + echo '
'; echo 'Product Image'; echo '
'; echo '
'; echo '
'; echo '
'; - echo ' ' . $row['item_name'] . '
'; + echo ' ' . $row['item_name'] . '
'; echo '' . $row['price'] . ''; echo '
'; @@ -106,14 +106,14 @@ echo '' . $row['size'] . 'oz' . '
'; } echo '
'; - echo '
'; + echo '
'; echo 'Product Image'; echo '
'; echo '
'; echo '
'; echo '
'; - echo ' ' . $row['item_name'] . '
'; + echo ' ' . $row['item_name'] . '
'; echo '' . $row['price'] . ''; echo '
'; @@ -149,12 +149,12 @@ - @@ -226,14 +201,7 @@ Monthly Sales
- +
@@ -246,7 +214,7 @@
- WEEKLY SALE + FROM PREVIOUS WEEK
@@ -317,7 +285,15 @@ "; } - $jsonTopPickData = json_encode($topPickData); + // Fetch the all the items from the database + $sql = "SELECT antecedent, consequent FROM frequent_items"; + $result = $db->query($sql); + + $topPickDatas = []; + if ($result->num_rows > 0) { + while ($row = $result->fetch_assoc()) { + $topPickDatas[] = [addslashes($row["antecedent"]), '+', addslashes($row["consequent"])];}} + $jsonTopPickData = json_encode($topPickDatas); ?> @@ -344,34 +320,18 @@
- - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/javascript/accounts.js b/src/javascript/accounts.js index 6d58963..a866192 100644 --- a/src/javascript/accounts.js +++ b/src/javascript/accounts.js @@ -82,13 +82,52 @@ $(document).ready(function () { $(input).val(value); }; - $("#lastName, #firstName, #middleName").on("input", function (event) { - preventLeadingSpace(event); - }); + function truncateExceedingCharacters() { + let lastName = $("#lastName").val(); + let firstName = $("#firstName").val(); + let middleName = $("#middleName").val(); + let username = $("#username").val(); + let email = $("#email").val(); + let password = $("#password").val(); + + if (lastName.length > 100) { + lastName = lastName.slice(0, 100); + $("#lastName").val(lastName); + } - $("#username, #email, #password").on("input", function (event) { - preventSpace(event); - }); + if (firstName.length > 100) { + firstName = firstName.slice(0, 100); + $("#firstName").val(firstName); + } + + if (middleName.length > 100) { + middleName = middleName.slice(0, 100); + $("#middleName").val(middleName); + } + + if (username.length > 50) { + username = username.slice(0, 50); + $("#username").val(username); + } + + if (email.length > 100) { + email = email.slice(0, 100); + $("#email").val(email); + } + + if (password.length > 20) { + password = password.slice(0, 20); + $("#password").val(password); + } + } + + $("#lastName, #firstName, #middleName, #username, #email, #password").on( + "input", + function (event) { + preventLeadingSpace(event); + truncateExceedingCharacters(); + } + ); // Function to check if all input fields are valid function areAllInputsValid() { @@ -117,8 +156,8 @@ $(document).ready(function () { regex, errorMessage, errorContainer, - validMessage, - validContainer, + // validMessage, + // validContainer, isTaken = false, takenMessage = "", takenErrorContainer = null @@ -139,19 +178,19 @@ $(document).ready(function () { input.classList.remove("was-validated"); input.classList.remove("is-valid"); errorContainer.textContent = errorMessage; - validContainer.textContent = ""; + // validContainer.textContent = ""; } else if (isTaken) { input.classList.add("is-invalid"); input.classList.remove("was-validated"); input.classList.remove("is-valid"); takenErrorContainer.textContent = takenMessage; - validContainer.textContent = ""; + // validContainer.textContent = ""; } else { input.classList.remove("is-invalid"); input.classList.add("is-valid"); input.classList.remove("was-validated"); errorContainer.textContent = ""; - validContainer.textContent = validMessage; + // validContainer.textContent = validMessage; } // Check if all inputs are valid and enable/disable button accordingly @@ -169,9 +208,9 @@ $(document).ready(function () { this, /^(?!\s)[^\d]+$/, "Please use a valid last name.", - document.getElementById("errorLastName"), - "Last name looks good!", - document.getElementById("validLastName") + document.getElementById("errorLastName") + // "Last name looks good!", + // document.getElementById("validLastName") ); }); @@ -180,9 +219,9 @@ $(document).ready(function () { this, /^(?!\s)[^\d]+$/, "Please use a valid first name.", - document.getElementById("errorFirstName"), - "First name looks good!", - document.getElementById("validFirstName") + document.getElementById("errorFirstName") + // "First name looks good!", + // document.getElementById("validFirstName") ); }); @@ -203,9 +242,9 @@ $(document).ready(function () { this, /^(?!\s)[^\d]+$/, "Please use a valid middle name.", - document.getElementById("errorMiddleName"), - "Middle name looks good!", - document.getElementById("validMiddleName") + document.getElementById("errorMiddleName") + // "Middle name looks good!", + // document.getElementById("validMiddleName") ); } }); @@ -216,10 +255,10 @@ $(document).ready(function () { validateInput( this, /^[^\s]{1,50}$/, - "Please provide a valid username.", + "Please provide a valid username (50 characters max).", document.getElementById("errorUsername"), - "Username looks good!", - document.getElementById("validUsername"), + // "Username looks good!", + // document.getElementById("validUsername"), isUsernameTaken, "This username is already taken.", document.getElementById("errorUsername") @@ -234,8 +273,8 @@ $(document).ready(function () { /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/, "Please provide a valid email address.", document.getElementById("errorEmailAddress"), - "Email address looks good!", - document.getElementById("validEmailAddress"), + // "Email address looks good!", + // document.getElementById("validEmailAddress"), isEmailTaken, "This email address is already taken.", document.getElementById("errorEmailAddress") @@ -247,9 +286,9 @@ $(document).ready(function () { this, /^[^\s]{8,20}$/, "Password must range 8-20 characters.", - document.getElementById("errorPassword"), - "Password looks good!", - document.getElementById("validPassword") + document.getElementById("errorPassword") + // "Password looks good!", + // document.getElementById("validPassword") ); }); diff --git a/src/javascript/login.js b/src/javascript/login.js index 8a0c58a..88751e0 100644 --- a/src/javascript/login.js +++ b/src/javascript/login.js @@ -1,5 +1,5 @@ (() => { - ("use strict"); + "use strict"; // Fetch all the forms we want to apply custom Bootstrap validation styles to const forms = document.querySelectorAll(".needs-validation"); @@ -37,11 +37,35 @@ function togglePassword() { } document.addEventListener("DOMContentLoaded", function () { - const sendButton = document.querySelector("#sendEmailBtn"); - const emailInput = document.querySelector("#email"); + const sendButton = $("#sendEmailBtn"); + const emailInput = $("#email"); + const usernameInput = $("#username"); + const passwordInput = $("#password"); + + function truncateExceedingCharacters() { + let emailValue = emailInput.val(); + let usernameValue = usernameInput.val(); + let passwordValue = passwordInput.val(); + + if (emailValue.length > 100) { + emailValue = emailValue.slice(0, 100); + emailInput.val(emailValue); + } + + if (usernameValue.length > 50) { + usernameValue = usernameValue.slice(0, 50); + usernameInput.val(usernameValue); + } + + if (passwordValue.length > 20) { + passwordValue = passwordValue.slice(0, 20); + passwordInput.val(passwordValue); + } + } $("#username, #password, #email").on("input", function (event) { preventSpaces(event); + truncateExceedingCharacters(); }); // Clear server-side error message @@ -67,10 +91,10 @@ document.addEventListener("DOMContentLoaded", function () { }); // Initially disable the Send button - sendButton.disabled = true; + sendButton.prop("disabled", true); const validateEmail = () => { - const email = emailInput.value; + const email = emailInput.val(); const isExistingEmail = existingEmails.includes(email); // Email format validation const isValid = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test( @@ -78,49 +102,42 @@ document.addEventListener("DOMContentLoaded", function () { ); if (!isValid) { - emailInput.classList.add("is-invalid"); - emailInput.classList.remove("was-validated"); - emailInput.classList.remove("is-valid"); - document.querySelector("#email-error").textContent = - "Please provide a valid email address."; - document.querySelector("#email-valid").textContent = ""; + emailInput.addClass("is-invalid").removeClass("was-validated is-valid"); + $("#email-error").text("Please provide a valid email address."); + $("#email-valid").text(""); } else if (!isExistingEmail) { - emailInput.classList.add("is-invalid"); - emailInput.classList.remove("was-validated"); - emailInput.classList.remove("is-valid"); - document.querySelector("#email-error").textContent = - "User with this email cannot be found."; - document.querySelector("#email-valid").textContent = ""; + emailInput.addClass("is-invalid").removeClass("was-validated is-valid"); + $("#email-error").text("We couldn't find your email address."); + $("#email-valid").text(""); } else { - emailInput.classList.remove("is-invalid"); - emailInput.classList.add("is-valid"); - emailInput.classList.add("was-validated"); - document.querySelector("#email-error").textContent = ""; - document.querySelector("#email-valid").textContent = "Looks right!"; + emailInput.removeClass("is-invalid").addClass("is-valid was-validated"); + $("#email-error").text(""); + // $("#email-valid").text("Looks right!"); } - sendButton.disabled = !isValid || !isExistingEmail; + sendButton.prop("disabled", !isValid || !isExistingEmail); }; // Validate the email input on input and change events - emailInput.addEventListener("input", validateEmail); - emailInput.addEventListener("change", validateEmail); + emailInput.on("input change", validateEmail); // Password Reset Link $("#sendEmailBtn").click(function (event) { event.preventDefault(); - const email = $("#email").val(); + const email = emailInput.val(); if (!/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(email)) { // Basic email format validation - const emailError = document.querySelector("#email-error"); - emailError.textContent = "Please provide a valid email address."; - emailInput.classList.add("is-invalid"); + $("#email-error").text("Please provide a valid email address."); + emailInput.addClass("is-invalid"); return; } // Disable the button while the request is being processed - sendButton.disabled = true; - sendButton.innerHTML = `Sending...`; + sendButton + .prop("disabled", true) + .html( + `Sending...` + ); $.ajax({ url: "includes/send-password-reset.php", @@ -140,10 +157,8 @@ document.addEventListener("DOMContentLoaded", function () { location.reload(); }); } else { - const emailError = document.querySelector("#email-error"); - emailError.textContent = response.message; - emailInput.classList.remove("is-valid"); - emailInput.classList.add("is-invalid"); + $("#email-error").text(response.message); + emailInput.removeClass("is-valid").addClass("is-invalid"); } }, error: function (xhr, status, error) { @@ -151,8 +166,7 @@ document.addEventListener("DOMContentLoaded", function () { }, complete: function () { // Reset the button content and enable it after the request is complete (whether success or error) - sendButton.innerHTML = "Send Link"; - sendButton.disabled = false; + sendButton.html("Send Link").prop("disabled", false); }, }); }); diff --git a/src/login.php b/src/login.php index 87d78c5..9a02d44 100644 --- a/src/login.php +++ b/src/login.php @@ -44,6 +44,13 @@ + + + + + + + @@ -86,7 +93,7 @@
-
+
- - - - - - - diff --git a/src/sales-prediction-algorithm/regression-model.py b/src/sales-prediction-algorithm/regression-model.py index 8f823b2..4f68a74 100644 --- a/src/sales-prediction-algorithm/regression-model.py +++ b/src/sales-prediction-algorithm/regression-model.py @@ -135,16 +135,16 @@ def main(): output_directory = 'src/sales-prediction-algorithm/' store_predictions(next_week_sales_pred, next_week_timestamps, output_directory) - # # Calculate Absolute Percentage Error (APE) - # ape = np.abs((regressor.predict(X_test) - y_test.values) / y_test.values) * 100 + # Calculate Absolute Percentage Error (APE) + ape = np.abs((regressor.predict(X_test) - y_test.values) / y_test.values) * 100 - # # Format MAPE to two decimal points only - # mape = np.mean(ape) + # Format MAPE to two decimal points only + mape = np.mean(ape) - # print(f"Mean Absolute Error of the model is : {metrics.mean_absolute_error(y_test, regressor.predict(X_test))}") - # print(f"Mean Squared Error of the model is : {metrics.mean_squared_error(y_test, regressor.predict(X_test))}") - # print(f"Root Mean Squared Error of the model is : {np.sqrt(metrics.mean_squared_error(y_test, regressor.predict(X_test)))}") - # print(f"Mean Absolute Percentage Error of the model is : {mape: .2f}%") + print(f"Mean Absolute Error of the model is : {metrics.mean_absolute_error(y_test, regressor.predict(X_test))}") + print(f"Mean Squared Error of the model is : {metrics.mean_squared_error(y_test, regressor.predict(X_test))}") + print(f"Root Mean Squared Error of the model is : {np.sqrt(metrics.mean_squared_error(y_test, regressor.predict(X_test)))}") + print(f"Mean Absolute Percentage Error of the model is : {mape: .2f}%") # # Visualising the Training and Testing set results # plt.scatter(X_train, y_train, color='green', label='Training points') diff --git a/src/sales.php b/src/sales.php index c8e8e45..e9a396f 100644 --- a/src/sales.php +++ b/src/sales.php @@ -165,7 +165,7 @@