# Technical Specifications

<!--toc:start-->
- [Technical Specifications](#technical-specifications)
  - [Devices & Responsiveness](#devices-responsiveness)
  - [Page Requirements](#page-requirements)
      - [Home](#home)
        - [UI Requirements](#ui-requirements)
        - [API Requirements](#api-requirements)
      - [Favorites](#favorites)
      - [Create](#create)
      - [Shopping List](#shopping-list)
      - [Profile](#profile)
  - [Database Requirements](#database-requirements)
        - [Table ID Choice](#table-id-choice)
    - [Tables](#tables)
    - [Enums and Types](#enums-and-types)
<!--toc:end-->

Application specifications.

## Devices & Responsiveness

This application is a web app, however, it is built following a "mobile-first" pattern. Which 
means the desktop interface is lacking and will be designed after the completion of the mobile 
web interface.

## Page Requirements

This section outlines the specific technical requirements for the application. It is broken down
by page.


#### Home

The home page will server as the landing page where users can search recipes, filter their search, as
well as view lists of recently made recipes, recently viewed and trending recipes lists.

##### UI Requirements

- [x] Welcome Banner
    - [x] Video display with large text overhead
    - [x] Sub text below the video with a "Call to Action"
    - [ ] ~Interactive banner that can be hidden with a "Got it!" or "X"~

- [x] Message & Pills Banner
    - [x] Message with text like "Craving Something Specific?"
    - [ ] ~Pill buttons below which allow for a direct search for meal type~

- [x] Search bar
    - [x] Ability to search for recipes, meals, and tags

- [x] Filter drop down
    - [x] **Filter by meal** - *E_Meal enum type*
    - [x] **Filter by time requirements** - *15min, 30min, 1hr, 1.5hr, +1.5hr*
    - [x] **Filter by difficulty** - *1 to 5 stars*
    -  [x] **Filter by serving size** - *1 to 16*

- [x] Recipe of The Week
    - [x] **Single recipe display** of the best performing recipe, with spotlight effect
    - [x] **Display recipe details in depth** - Title, duration, **image***, meal category, simplified description
    - [x] **Make now** button to allow easy access to meal directions

- [x] Recently Viewed List
    - [x] Scrolling list of the most recent 5-10 recipes viewed
    - [x] **Display recipe details** - Title, duration, **image***, meal category, and a heart to like the recipe

- [x] Make Again List
    - [x] Scrolling list of the most recent 5-10 recipes made
    - [x] **Display recipe details** - Title, duration, **image***, meal category, and a heart to like the recipe

- [x] Create Recipe CTA (call-to-action)
    - [x] **Large CTA banner** with text prompting users to create a recipe
    - [x] **Button** to take the user to the create page

'*': Not sure yet, still under consideration


##### API Requirements

- [ ] ~Message & Pills Banner~
    - [ ] ~Search all recipes of a specific meal type~

- [x] Search bar
    - [x] Text search on titles based on search query
    - [x] Text search on tags based on search query
    - [x] Text search on **meal** based on search query

- [x] Filter drop down
    - [x] Update search to only contain meals from selected filter
    - [x] Update search to only contain means that meet the time requirement of the selected filter
    - [x] Update search to only contain meals that meet the difficulty level of the selected filter
    - [x] Update search to only contain meals that meet the serving size of the selected filter

- [ ] Recipe of The Week
    - [ ] Fetch the most performing recipe of the last 7 days and all of the required meta data
        - [ ] Most views (W: 0.1)
        - [ ] Most makes (W: 0.5)
        - [ ] Most likes (W: 0.3)
        - [ ] Most reviews (W: 0.4)
        - [ ] Highest avg rating (W: 0.2/star, 0.0 - 1.0)
    - [ ] Direct a user to the recipes display page
    - [ ] Telemetry data to collect clicks for each recipe

- [ ] Recently Viewed List
    - [ ] Fetch a list of recently viewed meals and all required meta data
    - [ ] Like a post and store it in user's liked posts list
    - [ ] Direct a user to the recipes display page
    - [ ] Telemetry data to collect clicks for each recipe

- [ ] Make Again List
    - [ ] Fetch a list of recently viewed meals and all required meta data
    - [ ] Like a post and store it in user's liked posts list
    - [ ] Direct a user to the recipes display page
    - [ ] Telemetry data to collect clicks for each recipe

'**': Not sure implementation



#### Favorites







#### Create

The create page will contain a page to create a new recipe. It will include
all of the required details without any need to move to other pages. The entire
creation process will take place here


##### UI Requirements

- [x] Create Recipe Heading Banner
    - [x] Large, simple text banner that displays a header
    - [x] Smaller text section that contains some useful information for using the wizard

- [x] Recipe Creation Wizard
     - [x] **Recipe Details:** required
         - [x] **Recipe title:** small text input (1 to 128)
         - [x] **Recipe description:** large text input
         - [x] **Meal category:** pill radio buttons or drop down*
         - [x] **Service size:** numeric input (1 to 16)
         - [x] **Difficulty rating:** star buttons that can be selected (up to 5)
         - [x] **Duration:** prep and cook time, individual numeric inputs
     - [x] **Ingredients:** required
        - [x] **Dynamic ingredient list:** List of each ingredient
            - [x] **Content:** name and quantity (both text inputs)
            - [ ] **Actions:** delete button and **reorder element***
        - [x] **Add ingredient button:** Simple button to add a blank ingredient row
    - [x] **Instructions:** required
        - [x] **Dynamic instructions list:** Numbered list of each instruction
            - [x] **Content:** number and large text instruction
                - [ ] **Rich text editor?***
            - [ ] **Actions:** delete button and **reorder element***
        - [x] **Add step button:** Simple button to add a blank instruction element
    - [x] **Media & Tags:** optional
        - [x] **Image Upload**
            - [x] Single image selector for the thumbnail image
            - [x] Small image display once one has been upload
            - [x] Remove button to remove the image
            - [x] Replace button to replace the image
        - [x] **Tags**
             - [x] Text input to add tags
             - [ ] Using list of existing tags, use a prefill while typing
             - [x] Tags that don't exist will be added
             - [x] Display a small list of added tags
             - [x] Clicking a tag will remove it from the list
    - [x] **Footer & Submit**
        - [x] Save recipe button to complete the form
        - [ ] Button is disabled until the minimum required fields are complete*

- [x] Input Validation
    - [x] Required elements should have a **required indicator**
    - [x] Required elements will be validated input
        - [ ] **Valid:** Green outline or indicator* maybe a small, green check mark
        - [x] **Invalid:** Red outline or indicator* maybe a red border with error text


'*': Not sure yet, still under consideration


##### API Requirements


- [x] Middleware
     - [x] **Authentication:** User must be logged in to access this page
     - [x] **Authentication:** User must be logged in to submit the creation of a recipe (fallback)

- [x] Recipe Creation Wizard
    - [x] Create a new recipe object in the database
    - [x] Recipe should be attached to a user (logged in)
    - [x] User should be directed to the view recipe page on a successful creation






#### Shopping List







#### Profile



##### UI Requirements

- [ ] User details section
    - [ ] Google details: profile picture, full name and email

- [ ] User recipe section
    - [ ] List of all the recipes created by the user
    - [ ] Paginated? **Maybe a max size and a button for seeing them all***
    - [ ] Short and sweet, not much data displayed, no image and no description
    - [ ] Different layout then used elsewhere, spanned across the entire page

- [ ] User saved recipe section
    - [ ] List of all the recipes liked/saved by the user
    - [ ] Max size of **x*** amount, a see all button will take the user to their favorites page
    - [ ] Should look the like section above

- [ ] User activity section
     - [ ] List of all recent "engagement" the user has created
     - [ ] Just a message and a date


'*': Not sure yet, still under consideration


##### API Requirements




## Database Requirements

This section outlines the specific technical requirements for the database store for 
this application. It will describe the required tables, fields, and other expectations.


##### Table ID Choice

Typically, I like to use UUID's for ID's. However, after some research I have concluded that for this 
application, the use of the `SERIAL` or `SERIAL` type will work sufficiently. Security is not a huge
concern with this application since no major data will be stored, however, measures will still be in 
place (of course).

One of the biggest reasons **I** choose UUID's is their obscurity which provides some basic security 
against specific attack styles (enumeration attacks, etc.), however, I do not anticipate that being a 
large concern, so the simplicity of using an integer will surpass the small, niche benefits of using 
UUID's.


### Tables

Below is a breakdown of the required tables and their respective fields. The fields will
also have a list of attributes which are to be implemented at the database level. **JSONB**
data fields will also have a small example object. A more in-depth data structure can be 
found in **OTHER** section.

- [x] Recipes: Represents a single recipe.
    - [x] ID (PK) Serial
    - [x] Title (Required) string(128)
    - [x] Description (Required) text
    - [x] Instructions (Required) string(1024)[]
    - [x] Serves (Required) int(0..16)
    - [x] Difficulty (Required) int(1..5)
    - [x] Duration (Required) JSONB({ "total": int, "prep": int, "cook": int })
    - [x] Category (Required) E_Meal (defined in the [enums](#enums-and-types) section)
    - [x] Ingredients (Required) JSONB({ "item_a": [{ "name": string, "quantity": string }], "item_b": ... })
    - [x] UserId (FK: User.Id) Serial
    - [x] Modified () date/time stamp
    - [x] Created (Required) date/time stamp

- [x] Users: Represents a single user.
    - [x] ID (PK) Serial
    - [x] GoogleId (Unique, Required) text
    - [x] Name (Required) string(64)
    - [x] Email (Unique, Required) string(128)
    - [x] ImageURL () text
    - [x] GoogleRefreshToken () text
    - [x] Created (Required) date/time stamp

- [x] Engagements: Represents a single engagement from a single user.
    - [x] ID (PK) Serial
    - [x] Type (Required) E_Engagement
    - [x] Message () text (Used to store any relevant notes, if needed)
    - [x] Entity (Serial) Serial (Used to relate an entity, if needed)
    - [x] UserId (FK: User.Id)  Serial, optional for not logged in users
    - [x] Created (Required) date/time stamp

- [x] Favorites: **Many-to-many** table to represent a list of recipes favorites by a user.
    - [x] ID (PK) *Composite key***
    - [x] UserId (FK: User.Id, Required)  Serial
    - [x] RecipeId (FK: Recipe.Id, Required)  Serial
    - [x] Created (Required) date/time stamp

- [x] Tags: Represents a single tag that can be had by many recipes.
    - [x] ID (PK) Serial
    - [x] Name (Unique, Required) string(32)
    - [x] Created (Required) date/time stamp

- [x] RecipeTags: **Many-to-many** table to represent a list of tags on a recipe.
    - [x] ID (PK) Serial
    - [x] RecipeId (FK: Recipe.Id, Required)  Serial
    - [x] TagId (FK: Tag.Id, Required)  Serial
    - [x] Created (Required) date/time stamp

- [ ] Lists: Represents a single users shopping list.
    - [ ] ID (PK) Serial
    - [ ] UserId (FK: User.Id, Required)  Serial
    - [ ] Content (Required) JSONB([ { "name": string, "quantity": string }, ... ])
    - [ ] Created (Required) date/time stamp

- [ ] Images: Represents a single image used by a single recipe.
    - [ ] ID (PK) Serial
    - [ ] RecipeId (FK: Recipe.Id, Required) Serial
    - [ ] Alt (Required) string(128) (alt text for accessibility, same as recipe title)
    - [ ] Url (Required) text
    - [ ] Created (Required) date/time stamp

- [ ] Reviews: Represents a single review on a recipe from a single author.
    - [ ] ID (PK) Serial
    - [ ] Comment (Required) text
    - [ ] Rating () int(0..5) (Optional b/c nested replies don't need a rating)
    - [ ] ReviewId (FK: Review.Id) Serial (This is used for nested replies)
    - [ ] RecipeId (FK: Recipe.Id, Required) Serial
    - [ ] UserId (FK: User.Id, Required) Serial
    - [ ] Created (Required) date/time stamp

- [ ] Notifications: Represents a single user notification.
    - [ ] ID (PK) Serial
    - [ ] UserId (FK: User.Id, Required) Serial
    - [ ] Type (Required) E_Notification
    -  [ ] Message (Required) text
    - [ ] Entity (Serial) Serial (Used to relate an entity, if needed)
    - [ ] Read (Required, Default: F) boolean
    - [ ] Created (Required) date/time stamp

- [x] RecipeOfTheWeek: Represents the recipe of the week.
    - [x] ID (PK) Serial
    - [x] RecipeId (FK: Recipe.Id, Required) Serial
    - [x] Score (Required) float (Computed score)
    - [x] Created (Required) date/time stamp (serves as the validity)


'**': Not sure implementation

### Enums and Types

Below is a breakdown of the required enumerated types that should be stored in the database.
Various tables will reference these types.

- [x] E_Meal: Type to represent the type of meal of a recipe.
    - [x] breakfast: string
    - [x] lunch: string
    - [x] dinner: string
    - [x] dessert: string
    - [x] snack: string
    - [x] side: string
    - [x] other: string

- [ ] E_Notification: Type to represent a type of user notification.
    - [ ] comment: string
    - [ ] like: string
    - [ ] system: string

- [x] E_Engagement: Type to represent a type of user engagement.
     - [x] made: string
     - [x] liked: string
     - [x] viewed: string
     - [x] shared: string
     - [x] reviewed: string
     - [x] rated: string
