diff --git a/content/docs/contributor/zotmeal/api/index.mdx b/content/docs/contributor/zotmeal/api/index.mdx new file mode 100644 index 0000000..eb99c9e --- /dev/null +++ b/content/docs/contributor/zotmeal/api/index.mdx @@ -0,0 +1,26 @@ +--- +title: API +--- + +import { ServerOff, Database } from "lucide-react"; + +ZotMeal implements its very own API for use with the project. Information on +how to extend the API and use it for ZotMeal can be found below. + + + } + href="/docs/contributor/zotmeal/api/serverless" + title="Serverless" + > + Cron jobs + + } + href="/docs/contributor/zotmeal/api/trpc" + title="tRPC" + > + Database tasks + + + \ No newline at end of file diff --git a/content/docs/contributor/zotmeal/api/meta.json b/content/docs/contributor/zotmeal/api/meta.json new file mode 100644 index 0000000..1fc4415 --- /dev/null +++ b/content/docs/contributor/zotmeal/api/meta.json @@ -0,0 +1,5 @@ +{ + "title": "API", + "icon": "Server", + "pages": ["serverless", "trpc"] +} diff --git a/content/docs/contributor/zotmeal/api/serverless.mdx b/content/docs/contributor/zotmeal/api/serverless.mdx new file mode 100644 index 0000000..807c7e1 --- /dev/null +++ b/content/docs/contributor/zotmeal/api/serverless.mdx @@ -0,0 +1,88 @@ +--- +title: Serverless Functions +--- + +import { File, Folder, Files } from "fumadocs-ui/components/files"; + +As opposed to managing a server backend, ZotMeal uses serverless functions that are ran on-demand in the cloud, with AWS Lambda as our cloud service. + +## Cron Jobs + +Inside the `./apps/server` folder you will see something like this: + + + + + + + + + + + + + +The `src/functions/trpc` directory is used for creating API endpoints for our tRPC functions (for future work). tRPC helps us write APIs with autocomplete and type checking. + +Inside the `src/functions/cron` folder we can find: + + + + + + + + +Each of these `.ts` functions corresponds to a specific **cron** job that +our app performs. + +- **Daily**: Fetches the menu from CampusDishAPI for the current day and inserts +it into the database. Runs every day at midnight to ensure the most up to date +menu information. + +- **Weekly**: Fetches all menus from CampusDishAPI for all days at most 2 week +away from today. Allows users to see future menus for up to 2 week away. + +## Server Functions + +The main functionality of these jobs can be found in the `./packages/api/src/server` subdirectory. + +#### server/daily + +Functions in `parse.ts`: + +`getCampusDishMenu` + Fetches and parses the CampusDish menu for a given date. +- Input: `Date`, `RestaurantName`, `string` (periodId) +- Returns: `CampusDishMenu` + +`upsertMenusForDate` + Fetches and upserts the CampusDish menu for all periods of a given date. +- Input: `Date`, `RestaurantName` +- Returns: None + +Functions in `index.ts` + +`daily` + Performs the daily cron job action: Fetches the menu for the current date and upserts it into the database. +- Input: `Date`, `RestaurantName` +- Returns: None + +#### server/weekly + +`weekly` + Performs the weekly cron job action: Fetches the menu for all 14 days after the current date and upserts them into the database. +- Input: `Date`, `RestaurantName` +- Returns: None + +#### Server/scrapeEvents + +`getHTML` + Fetches the raw HTML of the page from the URL provided +- Input: `string` (URL) +- Returns: `string` (HTML) + +`scrapeEvents` + Scrapes the events from the events page URL provided to create a list of all upcoming events. +- Input: `string` (HTML) +- Returns: `Event[]` \ No newline at end of file diff --git a/content/docs/contributor/zotmeal/api/trpc.mdx b/content/docs/contributor/zotmeal/api/trpc.mdx new file mode 100644 index 0000000..341119d --- /dev/null +++ b/content/docs/contributor/zotmeal/api/trpc.mdx @@ -0,0 +1,138 @@ +--- +title: tRPC +--- + +import { File, Folder, Files } from "fumadocs-ui/components/files"; + +Taking a look inside the `./packages/api/src` folder we find something like this: + + + + + + + + + + + + + + +Each folder corresponds to a set of tRPC procedures that handles one major feature. + +Within each subfolder, we find 2-4 `.ts` files that looks something like this: + + + + + + + + + + +- The `router.ts` file contains tRPC procedures that exported via the tRPC router. +- The `services.ts` file contains helper functions that are used in the tRPC procedures mentioned above +- The files with extension `.test.ts` contain tests that run when running `turbo test`. See ***creating tests*** for more information. +- For our tRPC functions, we use Zod to define and validate schemas for input variables at runtime. + +We will now go into detail about each individual tRPC procedure. + +## Dishes + +#### Procedures + +`dish/get` (`getDishProcedure`) + Queries the `dishes` table for a dish +- Input: `string` (dishId) + +`dish/rate` (`RateDishProcedure`) + Updates the rating of a given dish when users submit a rating +- Input: `RatingSchema` + +#### Services + +`upsertDish` + Attempts to insert one dish entry into the `dishes` table, along with its `NutritionInfo` and `DietRestrictions`. Upon conflict with `dishes.id`, the old entry is updated with new info. +- Input: `DishWithRelations` +- Returns upserted dish on success + +`upsertDishToMenu` + Attempts to insert a relation in the `dishesToMenu` table. Upon conflict with (`dishesId`, `menusId`) the old relation is updated. +- Input: `DishToMenu` +## Events + +#### Procedures + +`event/upcoming` + Queries the `events` table for all events that are happening today or later. +- Input: None +#### Services + +`upsertEvent` + Attempts to insert one event entry into the `events` table. Upon conflict with (`events.title`, `events.start`, `events.restaurantId`), the old entry is updated with new info. +- Input: `Event` + +`upsertEvents` + Attempts to insert multiple events into the `events` table. Upon conflict old entries are updated. +- Input: `DishToMenu` +- Returns list of successfully upserted events +## Menus + +#### Services + +`upsertMenu` + Attempts to insert one menu entry into the `menus` table. Upon conflict with `menus.id`, the old entry is updated with new info. +- Input: `Menu` + +## Periods + +#### Services + +`upsertPeriod` + Attempts to insert one period entry into the `periods` table. Upon conflict with `periods.id`, the old entry is updated with new info. +- Input: `Period` + +## Ratings + +#### Services + +`upsertRatings` + Attempts to insert one rating entry into the `ratings` table. Upon conflict with (`ratings.userId`, `ratings.dishId`), the old entry is updated with new info. +- Input: `Rating` + +## Restaurants + +#### Services + +`upsertRestaurant` + Attempts to insert one restaurant entry into the `restaurants` table. Upon conflict with `restaurants.id`, the old entry is updated with new info. +- Input: `Restaurant` + +`getRestaurantsByDate` + Queries the database for information on both restaurants corresponding to a given date. +- Input: `Date` +- Returns: `ZotmealData` +## Stations + +#### Services + +`upsertStation` + Attempts to insert one station entry into the `stations` table. Upon conflict with `stations.id`, the old entry is updated with new info. +- Input: `Station` + +## Users + +#### Services + +`getUser` + Queries the `users` table for a user along with their ratings and pins +- Input: `string` (userId) +- Returns: \{`User`, `Pin[]`, `Rating[]`\} + +`upsertUser` + Attempts to insert one user entry into the `users` table. Upon conflict with `users.id`, the old entry is updated with new info. +- Input: `User` + +You may also notice there is `api/src/server` subfolder in this directory. This subfolder contains components relating the the Lambda serverless functions this app performs (see Serverless Functions) diff --git a/content/docs/contributor/zotmeal/getting-started.md b/content/docs/contributor/zotmeal/getting-started.md deleted file mode 100644 index f15cbd3..0000000 --- a/content/docs/contributor/zotmeal/getting-started.md +++ /dev/null @@ -1,3 +0,0 @@ ---- -title: Getting Started ---- diff --git a/content/docs/contributor/zotmeal/getting-started.mdx b/content/docs/contributor/zotmeal/getting-started.mdx new file mode 100644 index 0000000..e8aee86 --- /dev/null +++ b/content/docs/contributor/zotmeal/getting-started.mdx @@ -0,0 +1,184 @@ +--- +title: Getting Started +icon: GraduationCap +--- + +import { Steps, Step } from "fumadocs-ui/components/steps"; +import { File, Folder, Files } from "fumadocs-ui/components/files"; + +## Prerequisites + + + +Install `Node.js`. This allows you to run JavaScript on your computer (outside of a browser). +This is best done with a version manager that allows you to easily switch between +Node.js versions based on the requirements of different projects. +Try using any of the following: + +- [nvm](https://github.com/nvm-sh/nvm) - node-version-manager +- [fnm](https://github.com/Schniz/fnm) - fast-node-manager +- [nvm-widows](https://github.com/coreybufler/nvm-windows) - node-version-manager for Windows machines + +If none of those work for any reason, you can defer to your Operating System's +package manager or [the downloads from the official website](https://nodejs.org/en/download). +We will be using the latest LTS version of Node. + + + +Install `pnpm`. This is our package manager of choice for this project. +It's responsible for installing, uninstalling, and keeping track of the app's dependencies. + +```bash +npm install --global pnpm +``` + + + +Make sure to have `docker` installed, which can be installed from [the official website](https://www.docker.com/get-started/). It will allow you to: + - Run the local postgres database required for backend functions + - Run backend tests that rely on Testcontainers + + + +## Developing + + + +Clone the ZotMeal repository from GitHub: +```bash +git clone https://github.com/icssc/ZotMeal.git +``` + + + +Navigate to the root directory and change your node version to the one specified in the .nvmrc by running `nvm use` or `fnm use`. + + + +While still in the root directory, install the dependencies by running `cd ZotMeal && pnpm install`. + + + +To start a local Postgres container database, run the `docker compose up` in the root directory. This will automatically set up and run a test database using docker. + + + +Create a `.env` in the root directory based on the example given in `.env.development`. + + + +Run `pnpm db:push` to push the schema to the docker database. + + + +Start local development by running `pnpm dev:next` in the root directory. +The tRPC procedures are available on `http://localhost:3000/router.procedure?input={field: value}` + +```sh + # example of getting events from tRPC + http://localhost:3000/events.get +``` + + + +Pull the latest CampusDish data into your local database by `cd`'ing into the `apps/server` directory and running `pnpm run test:daily` or `pnpm run test:weekly`. + + + +View the local website at [http://localhost:8080](http://localhost:8080) +As you make changes to the Next.js application, those changes will be automatically +reflected on the local website. + + + + +## Troubleshooting + +Sometimes, you may run into errors when trying to run some of the commands listed above. Here are some things that can help fix this: + + + +### Reinstall Packages +Reinstall all packages in the project: +```bash +rm -force node_modules +pnpm install +``` + + + + +### Ensure Node is Correct Version +Check by running `node -v` (v20). + +- If not, download/switch to v20, by running: +```bash +fnm install v20 +fnm use 20 +``` +**OR** +```bash +nvm install v20 +nvm use 20 +``` + + + +## Structure Overview + +The following directory tree outlines the major folders in the ZotMeal repository: + + + + + + + + + + + + + + + + + +The `node_modules` folder contains all ***Node.js*** packages that the repository uses. + +The `apps` folder contains major endpoints that ZotMeal uses: +- `apps/next` contains all of the frontend components and scripts used to build the web app, written in **Next.js**. +- `apps/server` contains the scripts used to connect backend functions to AWS Lambda Serverless procedures. + +The `packages` folder contains all the functionality of the backend of ZotMeal. +- `packages/api` contains all the ***tRPC** procedures used +- `packages/db` contains the database schema (written using ***DrizzleORM***) +- `packages/validators` contains information used for type verification of API schemas used in the backend (written using ***Zod***) + +## Testing + +Run `turbo test` at the root of the project. + +**Database** + +Run the following commands to pull data into your local database. Your local website may display no meals without this step. + +```sh +cd apps/server + +# For daily test +pnpm test:daily + +# For weekly test +pnpm test:weekly +``` + +If you want to check the contents of the database, run the following command (while the server is not running). + +```sh +pnpm db:studio +``` + +## Adding Workspaces + +To add a new package run `turbo gen workspace` and follow the prompts. \ No newline at end of file diff --git a/content/docs/contributor/zotmeal/index.md b/content/docs/contributor/zotmeal/index.md index 8d8bf87..c608f8c 100644 --- a/content/docs/contributor/zotmeal/index.md +++ b/content/docs/contributor/zotmeal/index.md @@ -1,3 +1,44 @@ --- title: ZotMeal --- + +## About + +Navigating UCI's dining options at Brandywine and the Anteatery is now simpler and more informed with ZotMeal. This comprehensive menu viewer, available as a website and mobile app, is designed to enhance your campus dining experience. UCI students use ZotMeal to plan their daily meals and track progress toward their nutritional goals. + +Key features of ZotMeal include: + +- **_Detailed Menu Viewer_**: Browse current and upcoming menus, allowing you +to strategically plan your meal swipes and never miss your favorite dishes. +- **_Allergen and Dietary Information_**: Make informed choices with easy +access to comprehensive ingredient and allergen details for every meal. +- **_Event Calendar_**: Stay updated on special dining hall events and limited-time offerings. +- **_Dish Ratings_**: Contribute your own feedback to help fellow Anteaters discover the best of campus dining. + +![A screenshot of the ZotMeal website homepage.](./zotmeal-screenshot.jpg) + +## Technology + +ZotMeal consists of a Next.JS frontend with a shared backend. A summary of the libraries used in each are listed below. + +### Frontend + +- [Next.js](https://nextjs.org) - Full-stack React framework used for the website. +- [shad/cn](https://ui.shadcn.com/) - A library of fully customizable, plug-n-play components for use with React. +- [Zustand](https://github.com/pmndrs/zustand) - State management library for React apps. + +### Backend +- [Drizzle](https://drizzle.dev/) - ORM for Postgres. +- [AWS](https://aws.amazon.com/) - RDS and Lambda. +- [Serverless Framework](https://www.serverless.com/) - Framework for cloud resources such as AWS Lambda. +- [tRPC](https://trpc.io/) - Typesafe remote procedure calls to access the underlying Postgres database. + +### Tooling + +- [Turborepo](https://turborepo.com) - High-performance build system for monorepo scaling. +- [Tailwind](https://tailwindcss.com) - A utility-first CSS framework. +- [TypeScript](https://www.typescriptlang.org) - JavaScript with type-checking. + +## Contributing + +We'd be happy to have your contributions to ZotMeal -- we're always looking to grow and change! Please see [Getting Started](/docs/contributor/zotmeal/getting-started) to learn how to contribute effectively. \ No newline at end of file diff --git a/content/docs/contributor/zotmeal/meta.json b/content/docs/contributor/zotmeal/meta.json index d0fc514..0162e64 100644 --- a/content/docs/contributor/zotmeal/meta.json +++ b/content/docs/contributor/zotmeal/meta.json @@ -1,5 +1,5 @@ { "title": "ZotMeal", "icon": "UtensilsCrossed", - "pages": ["getting-started"] + "pages": ["getting-started", "ui", "api"] } diff --git a/content/docs/contributor/zotmeal/ui.mdx b/content/docs/contributor/zotmeal/ui.mdx new file mode 100644 index 0000000..412201a --- /dev/null +++ b/content/docs/contributor/zotmeal/ui.mdx @@ -0,0 +1,108 @@ +--- +title: UI +--- + +import { File, Folder, Files } from "fumadocs-ui/components/files"; + +ZotMeal's frontend -- written in the [Next.js](https://nextjs.org) framework. + + +# App Structure + +The web app is contained in apps/next, which should look something like: + + + + + + + + + + + + + + + + +> A quick aside about `📂node_modules` and `📂public`: +> - `📂public` is for static data that needs serving, like images. +> - `📂node_modules` is a folder that Node.js automatically generates for the packages used in development. + +We will now go into detail about each subdirectory of `📂src`, which +comprise the whole of the frontend. + +## 📂 App +In `📂app`, we use the Next.js page router to establish **pages**, which are web +pages rendered individually from one another, each with a unique URL. + + + + + + + + + + + + +Without going too far into the weeds of the [Next.js page router](https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts), +let's breakdown each element: + +- `📂about` & `📂events`: Each folder in Next (if containing a `page.tsx`) +represents a page. In this case, `/about` and `/events`. +- `favicon.ico`: The favicon of the website (the little image that appears +next to the tab name). +- `globals.css`: The global stylesheet for all pages, used by tailwindcss. +- `page.tsx`: The homepage for the web app. + +## 📂 Components + +All of the components used in ZotMeal's web app are defined in +`📂components`. + +ZotMeal extends a lot of the [shad/cn](https://ui.shadcn.com/) library's +components. As such, you may be better off looking at their documentation to +implement your own component for ZotMeal. + +See the components in this folder for more details on each unique component. + +## 📂 Context + +All of the [contexts](https://react.dev/learn/passing-data-deeply-with-context) +used in ZotMeal's webapp are defined in `📂context`. + +Essentially, a context is a method of passing information between components +without having to **prop drill**, or pass props deeply into children that may +or may not use those props. See the link above for React context information. + +## 📂 Hooks + +All of the [hooks](https://react.dev/reference/react/hooks) used in ZotMeal's +webapp are defined in `📂hooks`. + +See the link above for more information on React hooks. + +## 📂 Utils + +Functions, types, constants, and other static information/tools used across +ZotMeal's webapp are defined in `📂utils`. + +## Defining Your Own Folder + +If for some reason you find yourself writing a file that doesn't fit within the +predefined folders above, please reach out to a current ZotMeal lead to figure +out whether a new folder needs to be created for organization. + +# Backend Integration + +ZotMeal leverages a tRPC backend, which queries a local Postgres database. +This database has cron jobs run on it that pull CampusDish data daily and +weekly for dishes and events. + +Most of the tRPC calls in the frontend (as of writing) are performed in the +`side.tsx` file (Side component). For more information on the tRPC functions, +check out `docs/Serverless Functions.md`, `docs/tRPC Procedures`, and the +`packages/api/src` folder. \ No newline at end of file diff --git a/content/docs/contributor/zotmeal/zotmeal-screenshot.jpg b/content/docs/contributor/zotmeal/zotmeal-screenshot.jpg new file mode 100644 index 0000000..ac01e6c Binary files /dev/null and b/content/docs/contributor/zotmeal/zotmeal-screenshot.jpg differ