diff --git a/package-lock.json b/KaizenLAN/package-lock.json similarity index 100% rename from package-lock.json rename to KaizenLAN/package-lock.json diff --git a/package.json b/KaizenLAN/package.json similarity index 100% rename from package.json rename to KaizenLAN/package.json diff --git a/public/css/index.css b/KaizenLAN/public/css/index.css similarity index 100% rename from public/css/index.css rename to KaizenLAN/public/css/index.css diff --git a/public/habit.html b/KaizenLAN/public/habit.html similarity index 100% rename from public/habit.html rename to KaizenLAN/public/habit.html diff --git a/public/index.html b/KaizenLAN/public/index.html similarity index 100% rename from public/index.html rename to KaizenLAN/public/index.html diff --git a/public/js/habit.js b/KaizenLAN/public/js/habit.js similarity index 100% rename from public/js/habit.js rename to KaizenLAN/public/js/habit.js diff --git a/public/js/index.js b/KaizenLAN/public/js/index.js similarity index 100% rename from public/js/index.js rename to KaizenLAN/public/js/index.js diff --git a/public/js/profile.js b/KaizenLAN/public/js/profile.js similarity index 100% rename from public/js/profile.js rename to KaizenLAN/public/js/profile.js diff --git a/public/js/settings.js b/KaizenLAN/public/js/settings.js similarity index 100% rename from public/js/settings.js rename to KaizenLAN/public/js/settings.js diff --git a/public/js/water.js b/KaizenLAN/public/js/water.js similarity index 100% rename from public/js/water.js rename to KaizenLAN/public/js/water.js diff --git a/public/js/weight.js b/KaizenLAN/public/js/weight.js similarity index 100% rename from public/js/weight.js rename to KaizenLAN/public/js/weight.js diff --git a/old/kaizen_icon.png b/KaizenLAN/public/kaizen_icon.png similarity index 100% rename from old/kaizen_icon.png rename to KaizenLAN/public/kaizen_icon.png diff --git a/old/kaizen_icon_outline.png b/KaizenLAN/public/kaizen_icon_outline.png similarity index 100% rename from old/kaizen_icon_outline.png rename to KaizenLAN/public/kaizen_icon_outline.png diff --git a/old/kaizen_logo.png b/KaizenLAN/public/kaizen_logo.png similarity index 100% rename from old/kaizen_logo.png rename to KaizenLAN/public/kaizen_logo.png diff --git a/public/lib/graph/habitLoader.js b/KaizenLAN/public/lib/graph/habitLoader.js similarity index 100% rename from public/lib/graph/habitLoader.js rename to KaizenLAN/public/lib/graph/habitLoader.js diff --git a/KaizenLAN/public/lib/graph/kaizenGraphInterface.js b/KaizenLAN/public/lib/graph/kaizenGraphInterface.js new file mode 100644 index 0000000..bb3a1d5 --- /dev/null +++ b/KaizenLAN/public/lib/graph/kaizenGraphInterface.js @@ -0,0 +1,24 @@ +const GRAPH_ENDPOINT = "http://192.168.0.35:8080/graphql"; + +async function request(query) { + const options = { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({query}) + }; + try { + const response = await fetch(GRAPH_ENDPOINT, options); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + var responseBody = await response.json(); + return responseBody.data + } catch (error) { + console.error('Error fetching data:', error); + alert("An unexpected error occurred when querying kaizen graph - are the APIs running?") + } +} + +export { request } \ No newline at end of file diff --git a/public/lib/graph/kaizenGraphInterface.js b/KaizenLAN/public/lib/graph/kaizenGraphInterface.js.bak similarity index 100% rename from public/lib/graph/kaizenGraphInterface.js rename to KaizenLAN/public/lib/graph/kaizenGraphInterface.js.bak diff --git a/public/lib/graph/profileLoader.js b/KaizenLAN/public/lib/graph/profileLoader.js similarity index 100% rename from public/lib/graph/profileLoader.js rename to KaizenLAN/public/lib/graph/profileLoader.js diff --git a/public/lib/graph/waterLoader.js b/KaizenLAN/public/lib/graph/waterLoader.js similarity index 100% rename from public/lib/graph/waterLoader.js rename to KaizenLAN/public/lib/graph/waterLoader.js diff --git a/public/lib/graph/weightTrackLoader.js b/KaizenLAN/public/lib/graph/weightTrackLoader.js similarity index 100% rename from public/lib/graph/weightTrackLoader.js rename to KaizenLAN/public/lib/graph/weightTrackLoader.js diff --git a/public/lib/habitWidget.js b/KaizenLAN/public/lib/habitWidget.js similarity index 100% rename from public/lib/habitWidget.js rename to KaizenLAN/public/lib/habitWidget.js diff --git a/public/lib/profileWidget.js b/KaizenLAN/public/lib/profileWidget.js similarity index 100% rename from public/lib/profileWidget.js rename to KaizenLAN/public/lib/profileWidget.js diff --git a/public/lib/utils/utils.js b/KaizenLAN/public/lib/utils/utils.js similarity index 100% rename from public/lib/utils/utils.js rename to KaizenLAN/public/lib/utils/utils.js diff --git a/public/lib/waterWidget.js b/KaizenLAN/public/lib/waterWidget.js similarity index 100% rename from public/lib/waterWidget.js rename to KaizenLAN/public/lib/waterWidget.js diff --git a/public/lib/weightWidget.js b/KaizenLAN/public/lib/weightWidget.js similarity index 100% rename from public/lib/weightWidget.js rename to KaizenLAN/public/lib/weightWidget.js diff --git a/public/profile.html b/KaizenLAN/public/profile.html similarity index 100% rename from public/profile.html rename to KaizenLAN/public/profile.html diff --git a/public/res/manage_habits.png b/KaizenLAN/public/res/manage_habits.png similarity index 100% rename from public/res/manage_habits.png rename to KaizenLAN/public/res/manage_habits.png diff --git a/public/res/manage_hydrate.png b/KaizenLAN/public/res/manage_hydrate.png similarity index 100% rename from public/res/manage_hydrate.png rename to KaizenLAN/public/res/manage_hydrate.png diff --git a/public/res/manage_journal.png b/KaizenLAN/public/res/manage_journal.png similarity index 100% rename from public/res/manage_journal.png rename to KaizenLAN/public/res/manage_journal.png diff --git a/public/res/manage_lists.png b/KaizenLAN/public/res/manage_lists.png similarity index 100% rename from public/res/manage_lists.png rename to KaizenLAN/public/res/manage_lists.png diff --git a/public/res/manage_weight.png b/KaizenLAN/public/res/manage_weight.png similarity index 100% rename from public/res/manage_weight.png rename to KaizenLAN/public/res/manage_weight.png diff --git a/public/res/placeholder.png b/KaizenLAN/public/res/placeholder.png similarity index 100% rename from public/res/placeholder.png rename to KaizenLAN/public/res/placeholder.png diff --git a/public/res/settings.png b/KaizenLAN/public/res/settings.png similarity index 100% rename from public/res/settings.png rename to KaizenLAN/public/res/settings.png diff --git a/public/res/view_profile.png b/KaizenLAN/public/res/view_profile.png similarity index 100% rename from public/res/view_profile.png rename to KaizenLAN/public/res/view_profile.png diff --git a/public/settings.html b/KaizenLAN/public/settings.html similarity index 100% rename from public/settings.html rename to KaizenLAN/public/settings.html diff --git a/public/water.html b/KaizenLAN/public/water.html similarity index 100% rename from public/water.html rename to KaizenLAN/public/water.html diff --git a/public/weight.html b/KaizenLAN/public/weight.html similarity index 100% rename from public/weight.html rename to KaizenLAN/public/weight.html diff --git a/server.js b/KaizenLAN/server.js similarity index 100% rename from server.js rename to KaizenLAN/server.js diff --git a/README.md b/README.md index 5c59aea..02539ea 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ # Kaizen LAN -> [!NOTE] -> This README is currently a **plan** for Kaizen LAN. There are no current releases at this time and the first version is in development. - ### Frontend ![Express.js](https://img.shields.io/badge/express.js-%23404d59.svg?style=for-the-badge&logo=express&logoColor=%2361DAFB) ![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white) @@ -23,17 +20,21 @@ **Kaizen LAN**: Continuously improve your life with helpful widgets - accessible around your home! This application offers a interface that contains many different self improvement tools. The goal is to provide the user a customized experience to help continuously improve their lives through the use of small and simple tools. The following tools are planned to be included in Kaizen LAN: -- **Kaizen profile** (planned for v1.0.0) -- **Weight tracking** (planned for v1.0.0) -- **Water/hydration tracking** (planned for v1.0.0) -- **Habit tracking** (planned for v1.0.0) + +### Currently Implemented +- **Kaizen profile** (v1.0.0) +- **Weight tracking** (v1.0.0) +- **Water/hydration tracking** (v1.0.0) +- **Habit tracking** (v1.0.0) + +### Planned to be Implemented - **Routine checklists** (planned for v1.1.0) - **Text/CSV editor** (planned for v1.1.0) - **Time blocking** (planned for v1.1.0) - **Journal** (planned for v1.1.0) - **Food calorie tracking** (planned for v1.2.0) - **Todo list** (planned for v1.2.0) - **Countdown workout** (planned for v1.2.0) +- **Countdown workout** (planned for v1.2.0) # Concept View @@ -51,12 +52,11 @@ This application offers a interface that contains many different self improvemen To utilize all of the features of Kaizen LAN, you will need to designate a computer system to run each part of the Kaizen LAN application. This includes the Kaizen LAN server, Kaizen GraphQL API, each microservice, and a MySQL database. To be able to run all of these, you must have the following: - **[Node.js](https://nodejs.org/en) version 18 or higher** (used to run Kaizen LAN server and Kaizen Profile API) -- **[Java](https://openjdk.org/projects/jdk/) version 17 or higher** and **Maven version 3 or higher** (used to build and run each microservice) +- **[Java](https://openjdk.org/projects/jdk/) version 17 or higher** (used to build and run each API microservice) - **[MySQL](https://www.mysql.com/) version 8 or higher** (used to run the MySQL database) - **Bash or related terminal interface** - macOS testing using [Zsh](https://en.wikipedia.org/wiki/Z_shell) (preinstalled on macOS) - Linux (Ubuntu) testing using [GNOME](https://en.wikipedia.org/wiki/GNOME_Terminal) (preinstalled on Ubuntu 22) - - Windows testing using [Git Bash](https://git-scm.com/downloads) (NOT preinstalled) ## Dependencies @@ -82,34 +82,43 @@ You can download the latest release of the application from the **[releases page ### Initial Setup -For initial setup, you must have your MySQL instance running on your machine. Open the `setup.sh` file to configure with your MySQL credentials: +For initial setup, you must have your MySQL instance running on your machine. Verify that you can open MySQL through the terminal by using the command and signing in with your MySQL password: ```bash -#!/bin/bash - -# MySQL credentials -MYSQL_USER="your_mysql_username" -MYSQL_PASSWORD="your_mysql_password" -MYSQL_HOST="localhost" -MYSQL_DB="your_database_name" +mysql -u {your_mysql_username} -p ``` -Specifically, you will need to modify the `MYSQL_USER`, `MYSQL_PASSWORD`, and `MYSQL_DB` values. Kaizen LAN was designed to run on the local machine, so there is no need to modify the host value. -Running this script will create and configure the MySQL database along with each table utilized in this application. If the setup was successful, you will see a message that reads "`SUCCESS: Kaizen LAN setup complete`". If the setup was unsuccessful, you will see a message that reads "`FAILURE: Setup was unable to complete`". +If you are able to login with a username and password like this, you are ready to move forward with installing Kaizen. This README does not serve the purpose of showing users how to install MySQL on their device. -### Run the application +Run the `setup.sh` script in a bash-supported terminal. +- You will be prompted to sign into your MySQL using the script. This script will create all of the tables used in KaizenLAN. It will also create a **secrets** folder which stores the MySQL credentials and LAN address in the user's `Documents/narlock/secrets/mysql.properties` file. The APIs that KaizenLAN utilizes will read from this properties file so that it can communicate with the MySQL database. +- Next, you will setup your profile. The script will prompt you to create a Kaizen username and enter various information for your profile. After this is completed, a row in the Profile and Health tables for the Kaizen Profile will be added to the MySQL database and the setup will be completed. + +> [!NOTE] +> If you are interested in viewing the contents of the bash script, you can open the script in a text editor, or view it online on [GitHub](https://github.com/narlock/KaizenLAN/blob/main/setup.sh) - + +### Run the application Once the setup is complete, you can run the `start.sh` script in a new terminal. This will launch the Kaizen LAN server, Kaizen GraphQL API, and each microservice utilized by this application. > [!WARNING] -> By running this application, you are running roughly 10+ applications on your system. RAM usage may vary. +> By running this application, you are running roughly 6 applications on your system. RAM usage may vary. + +When you run the application, you will receive the messages indicating which applications are running on which port number: +```sh +Starting Kaizen Profile API{} on port 8079 +Starting Narlock Habit API{} on port 8089 +Starting Narlock Water Track API{} on port 8083 +Starting Narlock Weight Track API{} on port 8081 +Starting Narlock GraphQL API{} on port 8080 +Starting Kaizen LAN{} on port 3000 +``` -Once the script completes, you can choose to exit the terminal if you wish. Next, you can navigate to **http://localhost:3000/** to access Kaizen LAN. +Once the script completes, you can choose to exit the terminal if you wish. Next, you can navigate to **http://localhost:3000/** to access Kaizen LAN. On other devices within your local network, you can navigate to your LAN **http://{lan_address}:3000/** on any of the devices connected to your network to use the application. You can find the exact address in the secrets properties folder that was created during the setup if you cannot find this address. ### Stopping the application -When the start script is ran, it will run all of the required applications for Kaizen LAN in the background. The stop script will end each process that was opened by the start script. Simply just run the `stop.sh` script in a terminal. +When the start script is ran, it will run all of the required applications for Kaizen LAN in the background. The stop script will end each process that was opened by the start script. Simply just run the `stop.sh` script in a terminal. This will kill each process that is running on the ports above. # Concept Idea @@ -119,9 +128,7 @@ Based off of [Kaizen](https://github.com/narlock/Kaizen), which is a local Java ![First Iteration](./readme%20assets/Interface.png) -The first iteration of Kaizen LAN introduces a simple interface utilizing the checklist api, water tracking api, profile api, and weight tracking api. The navigation bar at the top of the screen expands on each of the widgets that appear on the home screen. +The first iteration of Kaizen LAN introduces a simple interface utilizing the habit api, water tracking api, profile api, and weight tracking api. The navigation bar at the top of the screen expands on each of the widgets that appear on the home screen. # Future Enhancements -- Multiprofile: require users to "login" to their profile. This allows multiple users to have a profile to utilize Kaizen LAN. - - This includes the functionality of providing a password (or not) to sign in to a profile. -- Anti Habit API integration +- Multiprofile: require users to "login" to their profile. This allows multiple users to have a profile to utilize Kaizen LAN. This includes the functionality of providing a password (or not) to sign in to a profile. diff --git a/old/css/index.css b/old/css/index.css deleted file mode 100644 index c8d23da..0000000 --- a/old/css/index.css +++ /dev/null @@ -1,291 +0,0 @@ -/* styles.css */ - -body { - background-color: #484848; - /* Grey background color */ - font-family: 'Fira Code', monospace; - /* Set Fira Code as the default font */ - color: #9c9c9c; - /* Set off-white text color for elements with the class 'off-white-text' */ -} - -footer { - padding-top: 20px; - text-align: center; -} - -footer a { - text-decoration: none; /* Remove underline */ - color: inherit; /* Inherit text color from parent */ -} - -footer a:hover { - color: #00a657; /* Change color on hover */ -} - -h2, h3, b { - color: #ffffff; -} - -p { - color: #9c9c9c; -} - -.special { - color: #00eb7b; -} - -h1 { - font-size: 64px; -} - -button { - margin-left: 10px; -} - -p { - /* Additional styling for paragraphs if needed */ - font-size: 16px; - /* Adjust font size as needed */ -} - -.topnav a { - float: left; - position: relative; - color: #f2f2f2; - text-align: center; - padding: 10px 10px; - text-decoration: none; - font-size: 17px; - -} - -.topnav-right { - float: right; - position: relative; - color: #f2f2f2; - text-align: center; - padding: 10px 10px; - padding-top: 50px; - text-decoration: none; - font-size: 17px; -} - -/* Add the tooltip styling */ -.tooltip { - position: absolute; - background-color: #000; - color: #fff; - padding: 5px; - border-radius: 5px; - visibility: hidden; - opacity: 0; - transition: opacity 0.3s; - z-index: 1; -} - -/* Position the tooltip above the link */ -.tooltip.top { - bottom: calc(100% + 5px); - left: 50%; - transform: translateX(-50%); -} - -/* Position the tooltip above the right-aligned links */ -.tooltip.right { - top: 50%; - left: calc(100% + 5px); - transform: translateY(-50%); -} - -.menuLink img { - transition: filter 0.3s; /* Add transition for smooth effect */ -} - -.menuLink:hover img { - filter: brightness(100%) sepia(100%) hue-rotate(120deg); -} - - -#homeLink img { - content: url('../kaizen_logo.png'); - width: 325px; -} - -.container { - display: flex; - flex-wrap: wrap; - width: 100%; /* Set a specific width for consistency */ - justify-content: space-around; /* Adjust as needed */ -} - -.center-container { - display: flex; - justify-content: center; - align-items: center; - margin-top: 30px; -} - -.add-button { - margin: 20px; - padding-top: 4px; - padding-left: 10px; - padding-right: 10px; - padding-bottom: 4px; - font-size: 25px; - background-color: #00eb7b; - color: black; - font-weight: bold; -} - -.checkBoxLabel { - margin-bottom: 12px; - cursor: pointer; - font-size: 22px; -} - -.checkBoxLabel input { - width: 24px; - height: 24px; - margin-right: 20px; - margin-bottom: 20px; -} - -.checkBoxIncomplete { - color: white; -} - -.blockDiv { - display: block; -} - -.box { - flex: 1; - min-width: 300px; - margin: 20px; - padding: 20px; - box-sizing: border-box; - border: 1px solid #ccc; -} - -.boxNoBorder { - flex: 1; - min-width: 300px; - margin: 20px; - padding: 20px; - box-sizing: border-box; -} - -.hiddenBox { - flex: 1; - min-width: 300px; - margin: 20px; - padding: 20px; - box-sizing: border-box; -} - -#profile img { - float: left; - margin-right: 20px; - width: 200px; - height: 200px; -} - -#xpBarProgress { - width: 100%; - max-width: 400px; - background-color: grey; - border: 1px solid #ccc; -} - -#xpBar { - width: 1%; - height: 30px; - background-color: #00eb7b; -} - -.bmi.underweight { - color: rgb(0, 145, 255); -} - -.bmi.normal { - color: #00eb7b; -} - -.bmi.overweight { - color: orange; -} - -.bmi.obese { - color: red; -} - -@media only screen and (min-width: 901px) { - /* Show the tooltip on hover */ - .topnav a:hover .tooltip { - visibility: visible; - opacity: 1; - } - - /* Customize tooltip content for each link */ - .topnav a[href="/profile"] .tooltip::before { - content: 'View Profile'; - } - - .topnav a[href="/lists"] .tooltip::before { - content: 'Manage Lists'; - } - - .topnav a[href="/schedule"] .tooltip::before { - content: 'Manage Schedule'; - } - - .topnav a[href="/weight"] .tooltip::before { - content: 'Manage Weight'; - } - - .topnav a[href="/water"] .tooltip::before { - content: 'Manage Hydration'; - } - - .topnav a[href="/journal"] .tooltip::before { - content: 'Manage Journal'; - } - - .topnav a[href="/settings"] .tooltip::before { - content: 'Change Settings'; - } -} - -@media only screen and (max-width: 900px) { - - /* Adjust the size for screens with a maximum width of 600px (typical for phones) */ - #homeLink img { - content: url('../kaizen_icon_outline.png'); - width: 32px; - } - - .menuLink img { - width: 20px; - height: 20px; - } - - .topnav-right { - padding-top: 5px; - } - - .box { - flex-basis: 100%; /* Set the basis to 100% for stacking */ - margin: auto; - margin-top: 20px; - } - - .hiddenBox { - display: none; - } - - #profile img { - width: 175px; - height: 175px; - } -} \ No newline at end of file diff --git a/old/hydration.html b/old/hydration.html deleted file mode 100644 index a17e6a5..0000000 --- a/old/hydration.html +++ /dev/null @@ -1,58 +0,0 @@ - - - -
- - -Today's weight: ${TODAY_ENTRY.weight}
` - - element.appendChild(displayWeightDiv); - getGraphEntries(7); -} - -function getGraphEntries(daysAgo) { - if(myWeightChart) { - myWeightChart.destroy(); - myWeightChart = null; - } - - // Default to show Week View - var today = getCurrentDateString() - var daysAgo = getDaysAgoDateString(daysAgo) - console.log(`attempting to retrieve /weight/range?startDate=${daysAgo}&endDate=${today}`) - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - GRAPH_RESPONSE = JSON.parse(xmlhttp.response) - - const xValues = []; - const yValues = []; - - GRAPH_RESPONSE.entries.forEach(element => { - xValues.push(element.date) - yValues.push(element.weight) - }); - - displayGraph("myWeightChart", xValues, yValues); - } else if (this.readyState == 4) { - // Some error occurred` - var response = JSON.parse(xmlhttp.response) - console.error(`an unexpected error occurred when calling simple-time-block-api ${response.error}`) - } - }; - - xmlhttp.open("GET", `http://${HOST_ADDRESS}:8081/weight/range?startDate=${daysAgo}&endDate=${today}`, true) - xmlhttp.send(); -} - -function displayGraph(element, xValues, yValues) { - myWeightChart = new Chart(element, { - type: "line", - data: { - labels: xValues, - datasets: [{ - label: "Weight Trend", - fill: false, - lineTension: 0.2, - backgroundColor: "rgba(0,235,123,1.0)", - borderColor: "rgba(0,166,87,0.7)", - pointRadius: 8, - pointHoverRadius: 12, - data: yValues - }] - }, - options: { - plugins: { - legend: { - labels: { - color: "white", - } - } - }, - scales: { - y: { - title: { - display: true, - color: "white", - text: "Weight" - }, - ticks: { - color: "white" - } - }, - x: { - title: { - display: true, - color: "white", - text: "Date" - }, - ticks: { - color: "white" - } - } - } - } - }); -} - -function showCreateWeightInterface(elementId) { - var element = document.getElementById(elementId) - - var createWeightDiv = document.createElement('div') - createWeightDiv.id = 'createWeightDiv' - - // Create text box for entering weight - var weightEntryBox = document.createElement('input') - weightEntryBox.type = 'text' - weightEntryBox.id = 'createWeightEntry' - weightEntryBox.placeholder = 'Enter weight here...'; - - // Create a button for submitting the weight entry to database - var weightEntrySubmit = document.createElement('button') - weightEntrySubmit.innerText = 'Submit Entry' - weightEntrySubmit.id = 'createWeightButton' - weightEntrySubmit.addEventListener('click', handleCreateWeightClick); - - // add them to the dom - createWeightDiv.appendChild(weightEntryBox) - createWeightDiv.appendChild(weightEntrySubmit) - element.appendChild(createWeightDiv) - - // Recreate the graph view - based off of what is already there... - getGraphEntries(7); -} - -// Function to be called when the button is clicked -function handleCreateWeightClick() { - var entry = document.getElementById('createWeightEntry').value - console.log(`user entered ${entry} into the box`) - if(isFloatingPointNumber(entry)) { - // Make call to backend api - createWeightEntry(entry); - syncProfileCurrentWeight(entry); - } else { - alert(`Unexpected entry value: ${entry}, please enter a valid weight entry.`) - } -} - -function createWeightEntry(entry) { - console.log(`creating weight entry for today with ${entry}`) - - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("POST", `http://${HOST_ADDRESS}:8081/weight`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 201) { - console.log("successfully created, change to view") - TODAY_ENTRY = JSON.parse(xmlhttp.response) - removeCreateWeightInterface(); - showTodayWeightInterface("weight"); - } else if(this.readyState == 4) { - alert("An unexpected error occurred when creating an entry") - } - } - - var data = { - weight: entry, - date: getCurrentDateString() - }; - var jsonData = JSON.stringify(data) - - xmlhttp.send(jsonData); -} - -function syncProfileCurrentWeight(entry) { - var PROFILE_ENTRY = null; - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Show profile details - PROFILE_ENTRY = JSON.parse(xmlhttp.response) - console.log(PROFILE_ENTRY) - updateWeightOnProfile(PROFILE_ENTRY, entry); - } else if (this.readyState == 4 && this.status == 404) { - // Show create profile details - console.log("Profile not found, showing create profile interface") - } else if (this.readyState == 4) { - // Unknown error occurred - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8079/profile/1`); - xmlhttp.send(); -} - -function updateWeightOnProfile(profile, entry) { - profile.health.weight = entry; - // gain 10 xp points for entering in daily weight - profile.xp = profile.xp + 10; - - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("PUT", `http://${HOST_ADDRESS}:8079/profile/1`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - console.log("successfully updated profile") - } else if(this.readyState == 4) { - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - } - var jsonData = JSON.stringify(profile) - xmlhttp.send(jsonData); - - moveXpBar(profile.xp, mainProfileDiv); -} - -function removeCreateWeightInterface() { - var createWeightDiv = document.getElementById('createWeightDiv') - if (createWeightDiv) { - createWeightDiv.remove(); - } -} - -/** - * ================= - * HELPER METHODS - * ================= - */ - -function calculateLevel(experience) { - // Define the base experience required for level 1 and the experience growth factor - const baseExperience = 100; - const experienceGrowthFactor = 1.2; - - // Ensure the input is a non-negative integer - const validatedExperience = Math.max(0, Math.floor(experience)); - - // Calculate the level using the exponential formula - const level = Math.floor(Math.log(validatedExperience / baseExperience) / Math.log(experienceGrowthFactor)) + 1; - - return level; -} - -function calculateExperienceToNextLevel(currentExperience) { - // Define the base experience for level 1 and the experience growth factor - const baseExperience = 100; - const experienceGrowthFactor = 1.2; - - // Ensure the input is a non-negative integer - const validatedExperience = Math.max(0, Math.floor(currentExperience)); - - // Calculate the current level using the same formula as before - const currentLevel = Math.floor(Math.log(validatedExperience / baseExperience) / Math.log(experienceGrowthFactor)) + 1; - - // Calculate the experience required for the next level - const experienceForNextLevel = Math.ceil(baseExperience * Math.pow(experienceGrowthFactor, currentLevel)); - - // Calculate the difference between the experience for the next level and the current experience - const experienceNeededForNextLevel = Math.max(0, experienceForNextLevel - validatedExperience); - - return experienceNeededForNextLevel; -} - -function getCurrentDateString() { - const today = new Date(); - - // Get year, month, and day - const year = today.getFullYear(); - const month = String(today.getMonth() + 1).padStart(2, '0'); // Month is zero-based, so add 1 - const day = String(today.getDate()).padStart(2, '0'); - - // Concatenate them in the "YYYY-mm-dd" format - const dateString = `${year}-${month}-${day}`; - - return dateString; -} - -function getDaysAgoDateString(days) { - const today = new Date(); - const sevenDaysAgo = new Date(today); - - // Subtract seven days - sevenDaysAgo.setDate(today.getDate() - days); - - // Get year, month, and day - const year = sevenDaysAgo.getFullYear(); - const month = String(sevenDaysAgo.getMonth() + 1).padStart(2, '0'); // Month is zero-based, so add 1 - const day = String(sevenDaysAgo.getDate()).padStart(2, '0'); - - // Concatenate them in the "YYYY-mm-dd" format - const dateString = `${year}-${month}-${day}`; - - return dateString; -} - -function isFloatingPointNumber(input) { - // Use a regular expression to match a floating-point number - const floatingPointPattern = /^[-+]?[0-9]*\.?[0-9]+$/; - - // Test the input against the pattern - return floatingPointPattern.test(input); -} - -function areDatesEqual(date1, date2) { - console.log(date1); - console.log(date2); - if(date1 == null || date2 == null) { - return false; - } - - return date1.getFullYear() === date2.getFullYear() && - date1.getMonth() === date2.getMonth() && - date1.getDate() === date2.getDate(); -} - -function giveExperienceToProfile(profile, amount) { - profile.xp = profile.xp + amount; - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("PUT", `http://${HOST_ADDRESS}:8079/profile/1`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - console.log("successfully updated profile") - } else if(this.readyState == 4) { - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - } - var jsonData = JSON.stringify(profile) - xmlhttp.send(jsonData); - - moveXpBar(profile.xp, mainProfileDiv); -} \ No newline at end of file diff --git a/old/js/lists.js b/old/js/lists.js deleted file mode 100644 index b8a0b95..0000000 --- a/old/js/lists.js +++ /dev/null @@ -1,322 +0,0 @@ -HOST_ADDRESS = "192.168.0.129" - -var MORNING_ITEMS = null; -var DAILY_ITEMS = null; -var NIGHT_ITEMS = null; - -document.addEventListener("DOMContentLoaded", function () { - getProfileEntry(); - retrieveListInformation(); - addButtonsToDom(); -}); - -function retrieveListInformation() { - getMorningList(); - getDailyList(); - getNightList(); -} - -function addButtonsToDom() { - addButtonToDom(document.getElementById('morningChecklist'), 'morning'); - addButtonToDom(document.getElementById('dayChecklist'), 'daily'); - addButtonToDom(document.getElementById('nightChecklist'), 'night') -} - -function addButtonToDom(rootElement, checklistName) { - var addItemDiv = document.createElement('div'); - addItemDiv.id = `${checklistName}ButtonDiv`; - addItemDiv.classList.add("center-container"); - - var button = document.createElement('button'); - button.classList.add("add-button") - button.innerText = '+'; - var itemTextField = document.createElement('input'); - itemTextField.type = 'text'; - itemTextField.id = `${checklistName}TextField`; - addItemDiv.appendChild(button); - addItemDiv.appendChild(itemTextField); - rootElement.appendChild(addItemDiv); - - button.addEventListener('click', () => { - // input validation against textfield - // then add the item to the list on backend - // then call the getList again - // if success, make sure to set itemTextField's text to nothing - if(itemTextField.value.trim() == '') { - alert("Kaizen Message\n\nYou must enter a in the text field to add a new item to a checklist.") - } else { - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("POST", `http://${HOST_ADDRESS}:8085/checklist-item`, true); - xmlhttp.setRequestHeader("Content-Type", "application/json"); - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 201) { - - console.log(`Successfully created new item for ${checklistName} checklist`) - - // Refresh the list - resetChecklist(checklistName); - } - } - - var requestPayload = { - checklistName: checklistName, - name: itemTextField.value - }; - var jsonData = JSON.stringify(requestPayload); - xmlhttp.send(jsonData); - - itemTextField.value = ''; - } - }); -} - -function resetChecklist(name) { - // Refresh the list - if(name == 'morning') { - getMorningList(); - } else if(name == 'daily') { - getDailyList(); - } else { - getNightList(); - } -} - -function printMorningList() { - console.log(MORNING_ITEMS); -} - -/** - * ================= - * API METHODS - * ================= - */ - -function getMorningList() { - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Retrieved the list - MORNING_ITEMS = JSON.parse(xmlhttp.response); - console.log(`retrieved morning items: ${MORNING_ITEMS}`) - populateMorningChecklistItems(); - } else if(this.readyState == 4) { - console.error("An unexpected error occurred when calling simple-checklist-api. Is it running?") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8085/checklist-item?checklistName=morning`); - xmlhttp.send(); -} - -function populateMorningChecklistItems() { - var morningChecklistItemsDiv = document.getElementById('morningChecklistItems'); - - // Remove each dom child - they will be dynamically readded - while (morningChecklistItemsDiv.firstChild) { - morningChecklistItemsDiv.removeChild(morningChecklistItemsDiv.firstChild); - } - - MORNING_ITEMS.forEach(element => { - addItemToChecklistDiv(morningChecklistItemsDiv, element, 'morning'); - }); -} - -function getDailyList() { - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Retrieved the list - DAILY_ITEMS = JSON.parse(xmlhttp.response); - console.log(`retrieved daily items: ${DAILY_ITEMS}`) - populateDailyChecklistItems(); - } else if(this.readyState == 4) { - console.error("An unexpected error occurred when calling simple-checklist-api. Is it running?") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8085/checklist-item?checklistName=daily`); - xmlhttp.send(); -} - -function populateDailyChecklistItems() { - var dailyChecklistItemsDiv = document.getElementById('dayChecklistItems'); - - // Remove each dom child - they will be dynamically readded - while(dailyChecklistItemsDiv.firstChild) { - dailyChecklistItemsDiv.removeChild(dailyChecklistItemsDiv.firstChild); - } - - DAILY_ITEMS.forEach(element => { - addItemToChecklistDiv(dailyChecklistItemsDiv, element, 'daily'); - }); -} - -function getNightList() { - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Retrieved the list - NIGHT_ITEMS = JSON.parse(xmlhttp.response); - console.log(`retrieved night items: ${NIGHT_ITEMS}`) - populateNightChecklistItems(); - } else if(this.readyState == 4) { - console.error("An unexpected error occurred when calling simple-checklist-api. Is it running?") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8085/checklist-item?checklistName=night`); - xmlhttp.send(); -} - -function populateNightChecklistItems() { - var nightChecklistItemsDiv = document.getElementById('nightChecklistItems'); - - // Remove each dom child - they will be dynamically readded - while(nightChecklistItemsDiv.firstChild) { - nightChecklistItemsDiv.removeChild(nightChecklistItemsDiv.firstChild); - } - - NIGHT_ITEMS.forEach(element => { - addItemToChecklistDiv(nightChecklistItemsDiv, element, 'night'); - }); -} - -function addItemToChecklistDiv(checklistDiv, element, checklistName) { - var elementDiv = document.createElement('div') - elementDiv.classList.add('checklist-element') - - var label = document.createElement('label'); - label.classList.add('checkBoxLabel'); - var checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - label.appendChild(checkbox); - var checkmark = document.createElement('span') - checkmark.classList.add('checkmark'); - label.appendChild(checkmark); - if(element.streak != null && element.streak != 0) { - label.appendChild(document.createTextNode(`${element.name} [🔥 ${element.streak}]`)); - } else { - label.appendChild(document.createTextNode(`${element.name}`)); - } - elementDiv.appendChild(label); - checklistDiv.appendChild(elementDiv); - - // check completed date - if(element.lastCompletedDate) { - sameDay = areDatesEqual(new Date(), new Date(`${element.lastCompletedDate}T00:00:00`)); - if(sameDay) { - checkbox.checked = true; - checkbox.disabled = true; - } else { - // Not checked, we can complete this today - label.classList.add('checkBoxIncomplete'); - } - } else { - // Not checked, we can complete this today - label.classList.add('checkBoxIncomplete'); - } - - // action - checkbox.addEventListener('click', function(event) { - if(event.shiftKey) { - checkbox.checked = false; - var result = window.confirm(`Kaizen Message\n\nWould you like to remove item ${element.name}?`) - if(result) { - var xmlhttp = new XMLHttpRequest(); - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 204) { - console.log("successfully remove item"); - resetChecklist(checklistName); - } else if(this.readyState == 4) { - console.error("An unexpected error occurred when calling simple-checklist-api. Is it running?") - } - } - } - - xmlhttp.open("DELETE", `http://${HOST_ADDRESS}:8085/checklist-item/${element.id}`, true); - xmlhttp.send(); - } else { - // If checkbox is checked, disable it - if (checkbox.checked) { - checkbox.disabled = true; - } - label.classList.remove('checkBoxIncomplete'); - - // Call the streak endpoint to update date and streak - var xmlhttp = new XMLHttpRequest(); - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - console.log("Backend updated"); - giveExperienceToProfile(PROFILE_ENTRY, 5); - } else if(this.readyState == 4) { - console.error("An unexpected error occurred when calling simple-checklist-api. Is it running?") - } - } - - xmlhttp.open("PATCH", `http://${HOST_ADDRESS}:8085/checklist-item/${element.id}/streak`, true); - xmlhttp.send(); - } - }); -} - -/** - * ================= - * HELPER METHODS - * ================= - */ - -function areDatesEqual(date1, date2) { - console.log(date1); - console.log(date2); - if(date1 == null || date2 == null) { - return false; - } - - return date1.getFullYear() === date2.getFullYear() && - date1.getMonth() === date2.getMonth() && - date1.getDate() === date2.getDate(); -} - -function giveExperienceToProfile(profile, amount) { - profile.xp = profile.xp + amount; - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("PUT", `http://${HOST_ADDRESS}:8079/profile/1`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - console.log("successfully updated profile") - } else if(this.readyState == 4) { - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - } - var jsonData = JSON.stringify(profile) - xmlhttp.send(jsonData); -} - -let PROFILE_ENTRY = null; -function getProfileEntry() { - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Show profile details - PROFILE_ENTRY = JSON.parse(xmlhttp.response) - } else if (this.readyState == 4 && this.status == 404) { - // Show create profile details - console.log("Profile not found, showing create profile interface") - - // TODO add create profile logic - } else if (this.readyState == 4) { - // Unknown error occurred - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8079/profile/1`, true); - xmlhttp.send(); -} \ No newline at end of file diff --git a/old/js/profile.js b/old/js/profile.js deleted file mode 100644 index 5cb3e7a..0000000 --- a/old/js/profile.js +++ /dev/null @@ -1,164 +0,0 @@ -const HOST_ADDRESS = "192.168.0.129"; -let PROFILE_ENTRY = null; - -/** - * ================= - * ON LOAD FUNCTIONS - * ================= - */ - -document.addEventListener("DOMContentLoaded", function () { - getProfileEntry(); -}); - -/** - * ================= - * GET PROFILE ENTRY - * ================= - */ - -// At the moment, we only support one profile, so we will just search for /profile/1 -function getProfileEntry() { - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function () { - if(this.readyState == 4 && this.status == 200) { - // Show profile details - PROFILE_ENTRY = JSON.parse(xmlhttp.response) - console.log(PROFILE_ENTRY) - displayProfile(); - } else if (this.readyState == 4 && this.status == 404) { - // Show create profile details - console.log("Profile not found, showing create profile interface") - - // TODO add create profile logic - } else if (this.readyState == 4) { - // Unknown error occurred - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - }; - - xmlhttp.open('GET', `http://${HOST_ADDRESS}:8079/profile/1`, true); - xmlhttp.send(); -} - -/** - * ================= - * CREATE PROFILE ENTRY - * ================= - */ - -// TODO - -/** - * ================= - * DISPLAY PROFILE ENTRY - * ================= - */ - -function displayProfile() { - var profileDiv = document.getElementById('profile'); - - var mainDiv = document.createElement('div'); - mainDiv.classList.add("center-container"); - - var imageElement = document.createElement('img'); - imageElement.src = PROFILE_ENTRY.image_url; - - var contentElement = document.createElement('p'); - contentElement.innerHTML = ` - -BMI: ${bmi} [${bmiString}]
` - - element.appendChild(displayStatsDiv) - - var bmiElement = document.querySelector('.bmi'); - bmiElement.classList.remove('underweight', 'normal', 'overweight', 'obese'); - bmiElement.classList.add(bmiString.toLowerCase()); -} - -function getBmi() { - var heightInInches = PROFILE.health.height; - var weightInPounds = PROFILE.health.weight; - - // Convert height from inches to meters (1 inch = 0.0254 meters) - var heightInMeters = heightInInches * 0.0254; - - // Convert weight from pounds to kilograms (1 pound = 0.453592 kilograms) - var weightInKilograms = weightInPounds * 0.453592; - - // Calculate BMI - var bmi = weightInKilograms / (heightInMeters * heightInMeters); - - // Round the BMI to two decimal places - bmi = Math.round(bmi * 100) / 100; - - return bmi; -} - -function getBmiString(bmi) { - if (bmi < 18.5) { - return "Underweight"; - } else if (bmi >= 18.5 && bmi < 25) { - return "Normal"; - } else if (bmi >= 25 && bmi < 30) { - return "Overweight"; - } else { - return "Obese"; - } -} - -function updateStats() { - var displayStatsDiv = document.getElementById('displayStatsDiv') - var bmi = getBmi(); - var bmiString = getBmiString(bmi); - displayStatsDiv.innerHTML = `BMI: ${bmi} [${bmiString}]
` - - var bmiElement = document.querySelector('.bmi'); - bmiElement.classList.remove('underweight', 'normal', 'overweight', 'obese'); - bmiElement.classList.add(bmiString.toLowerCase()); -} - -/** - * ================= - * GRAPH - * ================= - */ - -let GRAPH_RESPONSE = null; - -function createWeekGraph() { - getGraphEntries(7); - document.getElementById('graphBoxTitle').innerText = 'Graph (Week View)' -} - -function createMonthGraph() { - getGraphEntries(30); - document.getElementById('graphBoxTitle').innerText = 'Graph (Month View)' -} - -function createYearGraph() { - getGraphEntries(365); - document.getElementById('graphBoxTitle').innerText = 'Graph (Year View)' -} - -function getGraphEntries(daysAgo) { - if(myChart) { - myChart.destroy(); - myChart = null; - } - - // Default to show Week View - var today = getCurrentDateString() - var daysAgo = getDaysAgoDateString(daysAgo) - console.log(`attempting to retrieve /weight/range?startDate=${daysAgo}&endDate=${today}`) - var xmlhttp = new XMLHttpRequest(); - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - GRAPH_RESPONSE = JSON.parse(xmlhttp.response) - - const xValues = []; - const yValues = []; - - GRAPH_RESPONSE.entries.forEach(element => { - xValues.push(element.date) - yValues.push(element.weight) - }); - - displayGraph("myChart", xValues, yValues); - } else if (this.readyState == 4) { - // Some error occurred` - var response = JSON.parse(xmlhttp.response) - console.error(`an unexpected error occurred when calling simple-time-block-api ${response.error}`) - } - }; - - xmlhttp.open("GET", `http://${HOST_ADDRESS}:8081/weight/range?startDate=${daysAgo}&endDate=${today}`, true) - xmlhttp.send(); -} - -function displayGraph(element, xValues, yValues) { - myChart = new Chart(element, { - type: "line", - data: { - labels: xValues, - datasets: [{ - label: "Weight Trend", - fill: false, - lineTension: 0.2, - backgroundColor: "rgba(0,235,123,1.0)", - borderColor: "rgba(0,166,87,0.7)", - pointRadius: 8, - pointHoverRadius: 12, - data: yValues - }] - }, - options: { - plugins: { - legend: { - labels: { - color: "white", - } - } - }, - scales: { - y: { - title: { - display: true, - color: "white", - text: "Weight" - }, - ticks: { - color: "white" - } - }, - x: { - title: { - display: true, - color: "white", - text: "Date" - }, - ticks: { - color: "white" - } - } - } - } - }); -} - -/** - * ================= - * CREATE WEIGHT FUNCTIONS - * ================= - */ - -function showCreateWeightInterface(elementId) { - var element = document.getElementById(elementId) - - var createWeightDiv = document.createElement('div') - createWeightDiv.id = 'createWeightDiv' - - // Create text box for entering weight - var weightEntryBox = document.createElement('input') - weightEntryBox.type = 'text' - weightEntryBox.id = 'createWeightEntry' - weightEntryBox.placeholder = 'Enter weight here...'; - - // Create a button for submitting the weight entry to database - var weightEntrySubmit = document.createElement('button') - weightEntrySubmit.innerText = 'Submit Entry' - weightEntrySubmit.id = 'createWeightButton' - weightEntrySubmit.addEventListener('click', handleCreateWeightClick); - - // add them to the dom - createWeightDiv.appendChild(weightEntryBox) - createWeightDiv.appendChild(weightEntrySubmit) - element.appendChild(createWeightDiv) - - // Recreate the graph view - based off of what is already there... - graph_text = document.getElementById('graphBoxTitle').innerText - if(graph_text.includes('Month')) { - createMonthGraph(); - } else if(graph_text.includes('Year')) { - createYearGraph(); - } else { - createWeekGraph(); - } - -} - -// Function to be called when the button is clicked -function handleCreateWeightClick() { - var entry = document.getElementById('createWeightEntry').value - console.log(`user entered ${entry} into the box`) - if(isFloatingPointNumber(entry)) { - // Make call to backend api - createWeightEntry(entry); - updateWeightOnProfile(entry); - } else { - alert(`Unexpected entry value: ${entry}, please enter a valid weight entry.`) - } -} - -function createWeightEntry(entry) { - console.log(`creating weight entry for today with ${entry}`) - - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("POST", `http://${HOST_ADDRESS}:8081/weight`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 201) { - console.log("successfully created, change to view") - TODAY_ENTRY = JSON.parse(xmlhttp.response) - removeCreateWeightInterface(); - showTodayWeightInterface("weight"); - } else if(this.readyState == 4) { - alert("An unexpected error occurred when creating an entry") - } - } - - var data = { - weight: entry, - date: getCurrentDateString() - }; - var jsonData = JSON.stringify(data) - - xmlhttp.send(jsonData); -} - -function updateWeightOnProfile(entry) { - PROFILE.health.weight = entry; - // gain 10 xp points for entering in daily weight - PROFILE.xp = PROFILE.xp + 10; - - var xmlhttp = new XMLHttpRequest(); - xmlhttp.open("PUT", `http://${HOST_ADDRESS}:8079/profile/1`, true) - xmlhttp.setRequestHeader("Content-Type", "application/json") - - xmlhttp.onreadystatechange = function() { - if(this.readyState == 4 && this.status == 200) { - console.log("successfully updated profile") - updateStats(); - } else if(this.readyState == 4) { - console.error("an unexpected error occurred when calling kaizen-profile-api (is it running?)") - } - } - var jsonData = JSON.stringify(PROFILE) - xmlhttp.send(jsonData); -} - -function removeCreateWeightInterface() { - var createWeightDiv = document.getElementById('createWeightDiv') - if (createWeightDiv) { - createWeightDiv.remove(); - } -} - -/** - * ================= - * SHOW WEIGHT FUNCTIONS - * ================= - */ - -function showTodayWeightInterface(elementId) { - console.log('showing today interface') - var element = document.getElementById(elementId) - - // TODO create a special div with an id that can be styled - var displayWeightDiv = document.createElement('div') - displayWeightDiv.id = 'displayWeightDiv' - displayWeightDiv.innerHTML = `Today's weight: ${TODAY_ENTRY.weight}
` - - element.appendChild(displayWeightDiv) - createWeekGraph() -} - -/** - * ================= - * HELPER FUNCTIONS - * ================= - */ - -function getCurrentDateString() { - const today = new Date(); - - // Get year, month, and day - const year = today.getFullYear(); - const month = String(today.getMonth() + 1).padStart(2, '0'); // Month is zero-based, so add 1 - const day = String(today.getDate()).padStart(2, '0'); - - // Concatenate them in the "YYYY-mm-dd" format - const dateString = `${year}-${month}-${day}`; - - return dateString; -} - -function getDaysAgoDateString(days) { - const today = new Date(); - const sevenDaysAgo = new Date(today); - - // Subtract seven days - sevenDaysAgo.setDate(today.getDate() - days); - - // Get year, month, and day - const year = sevenDaysAgo.getFullYear(); - const month = String(sevenDaysAgo.getMonth() + 1).padStart(2, '0'); // Month is zero-based, so add 1 - const day = String(sevenDaysAgo.getDate()).padStart(2, '0'); - - // Concatenate them in the "YYYY-mm-dd" format - const dateString = `${year}-${month}-${day}`; - - return dateString; -} - -function isFloatingPointNumber(input) { - // Use a regular expression to match a floating-point number - const floatingPointPattern = /^[-+]?[0-9]*\.?[0-9]+$/; - - // Test the input against the pattern - return floatingPointPattern.test(input); -} \ No newline at end of file diff --git a/old/lists.html b/old/lists.html deleted file mode 100644 index 6cc575c..0000000 --- a/old/lists.html +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - -