Group Members (2020-2021): Nathan, Naglis, David, Aadi
Group Members (2021-2022): Grace, Jessica, Kasey, Owen
Group Members (2022-2023): Divya, Hansheng, Krish, Sophia
Group Members (2023-2024): Tavneet, Abby, Delilah, Eric
Group Members (2024-2025): Bennett, Emran, Jack, Ryan
Group Members (2025-2026): Nathan, Abhi, Christian, Alex
- Copilot is a great tool for solving problems and building features. However, it is important that you fully understand the code before you implement it. Blindly "vibe coding" will lead to bad code and a larger mess which will take even more time to resolve.
- Trello is very important. Even though it may seem tedious, it is necessary to ensure proper organization and teamwork.
- Pair programming is the greatest tool you have. Before asking copilot or google, ask your teammates. Additionally, if somebody doesn't have a task, they MUST be pair programming.
- It is important to follow these GitHub best practices: pull requests must be reviewed by another member who will then merge it. Branches should clearly explain the feature. Delete the branch after merging.
Install Node.js
- Clone this repository
- From a terminal in the repository's directory, run the following command to install all dependencies:
npm install
- Create a .env file in the root directory
CLIENT_ID= <find in trello>
MONGO_URI= <find in trello>
SESSION_SECRET= <secret key>
PORT_NUM = 8080 (can change)
VAPID_PUBLIC_KEY= <find in trello>
VAPID_PRIVATE_KEY= <find in trello>
- Download MongoDB Compass for your computer
- Use the URI from the Trello to connect to the database
- In Compass, edit one of the ADMIN users and change their email to your email
- Run the server from the VS Code debugger
- Go to a web browser and type in localhost:PORT_NUM or click the link displayed in terminal
- Go to Login and sign in with Google
- Now you are on the add user page so add everyone else in your group as a user
MongoDB - Database
Node.js - Server
Mongoose - Creates a connection between MongoDB and the Node.js JavaScript runtime environment
Javascript - Used both on client and server side
EJS - Embedded JS, similar to HTML, only client side
CSS - Styling, only client side
Three.js - Renders 3D models on the web
Chart.js - Renders charts in the metrics page
The image above shows the dependencies of the different classes in the dat structure. All of the models are written in js except temps.json (you can find the data model under assets/server/model). Download MongoDB Compass to easily access the database with the same URI written in your ejs file. You can look through Compass to see what the dependencies look like in the actual app.
To explain the image more, each arrow shows a different dependency. The beginning of the arrow starts at the property that needs information from a different class, which is where the head of the arrow points.
Enabled is on its own because it's a separate class. That is the boolean value that the app references to see if ordering is turned on or off. During passing periods or outside of the Half Caf's hours, the baristas and admin can turn ordering off to prevent people from ordering and waiting for a drink that's not being made. Enabled uses a Websocket to check and see if it's been updated every second, and if it has, it reloads every page to either disable ordering or to sync the slider on the admin and barista side. ** Enabled is mainly controlled by the scheduler. **
This Node.js application integrates Google Authentication using the Google Sign-In API. It ensures that only authenticated users can access specific routes based on their roles. The application comprises several components: server-side middleware for session handling, server-side and client-side handlers for Google Sign-In, and view templates for rendering the authentication UI.
This is the core of the application's backend. It includes middleware that checks if a user is logged in before allowing access to certain routes. If a user's session does not have an email stored (req.session.email is undefined), they are redirected to the /auth page for authentication. This prevents unauthorized access to sensitive routes. The middleware specifically allows unrestricted access to public endpoints like "/homePopularDrinks" and "/homeMenu", and routing now ensures users go straight to authentication when required.
The auth.js file handles the actual authentication process:
- It defines routes that the frontend can communicate with to perform authentication tasks.
- When the frontend sends the ID token (received from Google after a user logs in), auth.js verifies this token using Google's libraries.
- If the verification is successful, it stores the user's email in the session, effectively logging them in.
The auth2.js script runs in the user's browser and handles:
- The receipt of the authentication response from Google (which includes the ID token).
- It sends this token to the server (/auth route) via a POST request.
- Upon confirmation of successful authentication, it redirects the user to the /redirectUser route.
After authentication, router.js takes over:
- It defines a route /redirectUser which checks the user's role based on the email stored in the session.
- Depending on the role fetched from the database (admin, barista, teacher), it redirects the user to the appropriate route. The redirect flow has been tightened so the auth page is the first stop when a session is missing.
The auth.ejs file is the front-end component where users interact with Google's Sign-In service. It includes:
- An image placeholder.
- Google's JavaScript library for authentication.
- A div configured with
data-client_idanddata-callbackwhich triggershandleCredentialResponseafter successful authentication.
This file is crucial for initiating the authentication flow from the client's browser.
The app works as a mobile app as well as on the computer website. To get the app on phone, go to nnhshalfcaf.com on a browser(may have to be Safari if on iPhone) and follow the page instructions to add to home screen. Mobile works by converting the app into a PWA(progressive web app) which includes:
- Service worker
- Manifest
- Add to Home HTML Page
- App Icon
All of these files are within the 'public' folder -- needed for mobile setup to work.
Mobile Notifications are implemented with the service worker, and the subscription endpoints(the place where notifications are sent to) for every user are stored in the MongoDB database under user. When adding visual changes, check changes it causes on both mobile and computer screens. Period countdown warnings are now surfaced in the shared header, so test both layouts for timing visibility.
The inventory system is used to track all ingredients that go into each drink ordered. Each ingredient has two types: customizable and uncustomizable. If an ingredient is customizable, it means that a user can choose to add it (or remove it) from any drink they want to order. For each menu item, there is a list of ingredients and an amount of those ingredients. These are the default ingredients, meaning that they are automatically checked when a user goes to order (however they can be unchecked if the ingredient is customizable). Adding additional ingredient to a drink does not change the price of the drink for the user, although the increased expense will be noted in the inventory manager. Ingredient quantities are rounded consistently when recorded, and the ingredients manager includes expanded support for adding new items and defaults.
- User Visits the Site: They attempt to access a protected route.
- Middleware Check: server.js checks if the user is authenticated.
- Redirection: If not authenticated, the user is redirected to the /auth route, loading auth.ejs.
- User Action: The user clicks the Google Sign-In button on auth.ejs.
- Token Acquisition: Google returns an ID token upon successful login, which auth2.js captures.
- Token Verification: auth2.js sends this token to the server via the route defined in auth.js.
- Session Update: Upon successful token verification, the user’s email is stored in the session.
- Role-Based Redirection: The user is then redirected to /redirectUser, where router.js checks the user's role and redirects them accordingly.
- Ordering Context: The header provides a period countdown warning, and ordering views keep cart state stable when navigating back.
