Merge pull request #90 from cse110-fa22-group29/sprint-3

Sprint 3
This commit is contained in:
Arthur Lu 2022-12-03 12:39:42 -08:00 committed by GitHub
commit e9d33edf00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 2859 additions and 1811 deletions

View File

@ -5,29 +5,16 @@
"node": true "node": true
}, },
"extends": "eslint:recommended", "extends": "eslint:recommended",
"overrides": [ "overrides": [],
],
"parserOptions": { "parserOptions": {
"ecmaVersion": "latest", "ecmaVersion": "latest",
"sourceType": "module" "sourceType": "module"
}, },
"rules": { "rules": {
"indent": [ "indent": ["error", "tab"],
"error", "linebreak-style": ["error", "unix"],
"tab" "quotes": ["error", "double"],
], "semi": ["error", "always"],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"double"
],
"semi": [
"error",
"always"
],
"no-global-assign": 0 "no-global-assign": 0
} }
} }

View File

@ -47,7 +47,7 @@ jobs:
uses: actions/upload-pages-artifact@v1 uses: actions/upload-pages-artifact@v1
with: with:
# Upload only the src repository # Upload only the src repository
path: './source/' path: "./source/"
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v1 uses: actions/deploy-pages@v1

27
.github/workflows/prettier-linting.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: Prettier
on:
pull_request:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
# Single deploy job since we're just deploying
test:
runs-on: ubuntu-latest
steps:
- name: Install apt updates
run: sudo apt -y update; sudo apt -y upgrade;
- name: Install prerequisites
uses: actions/setup-node@v3
with:
node-version: 18
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
run: sudo npm install
- name: Run tests
run: sudo npm run lint-prettier

View File

@ -1,29 +0,0 @@
name: Prettier
on:
pull_request:
branches:
- main
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
# Single deploy job since we're just deploying
test:
runs-on: ubuntu-latest
steps:
- name: Install apt updates
run: sudo apt -y update; sudo apt -y upgrade;
- name: Install prerequisites
uses: actions/setup-node@v3
with:
node-version: 18
- name: Checkout
uses: actions/checkout@v3
- name: Install dependencies
run: sudo npm install
- name: Start local http server
run: sudo npm run http-server &
- name: Run tests
run: sudo npm lint-prettier

5
.prettierrc.json Normal file
View File

@ -0,0 +1,5 @@
{
"printWidth": 160,
"tabWidth": 4,
"useTabs": true
}

View File

@ -1,9 +1,13 @@
# Meeting Minutes (11/07/2022) # Meeting Minutes (11/07/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: First Sprint ## Meeting Topic: First Sprint
Meeting notes for the first sprint Meeting notes for the first sprint
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -15,13 +19,16 @@ Meeting notes for the first sprint
9. Arthur Lu 9. Arthur Lu
## Absentees ## Absentees
1. Isaac Otero 1. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/07/2022 at 6:00PM - When: 11/07/2022 at 6:00PM
- Where: CSE Building Second Floor - Where: CSE Building Second Floor
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
@ -32,10 +39,9 @@ Meeting notes for the first sprint
- ### Next Meeting's Business - ### Next Meeting's Business
## Decisions Made ## Decisions Made
- Linting details decided (TABS NOT SPACES) - Linting details decided (TABS NOT SPACES)
## End Time ## End Time
- 11/07/2022 at 8:00PM - 11/07/2022 at 8:00PM

View File

@ -15,6 +15,7 @@ We've identified 5 major features which we definitely want to implement in the C
- Manual Validation - Manual Validation
We also identified some features which are nice to have: We also identified some features which are nice to have:
- Automatic documentation publishing - Automatic documentation publishing
- Minification - Minification
- HTML Validation and accessibility scoring - HTML Validation and accessibility scoring

View File

@ -1,8 +1,13 @@
# Meeting Minutes (10/12/2022) # Meeting Minutes (10/12/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Kickoff Meeting ## Meeting Topic: Kickoff Meeting
This meeting is being held to kickoff the start of many meetings to come during the quarter. This meeting is being held to kickoff the start of many meetings to come during the quarter.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -14,13 +19,16 @@ This meeting is being held to kickoff the start of many meetings to come during
9. Daniel Hernandez 9. Daniel Hernandez
## Absentees ## Absentees
1. Arthur Lu 1. Arthur Lu
## Meeting Details ## Meeting Details
- When: 10/12/2022 at 3:30PM - When: 10/12/2022 at 3:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
@ -36,12 +44,11 @@ This meeting is being held to kickoff the start of many meetings to come during
- complete any remaining assignments - complete any remaining assignments
## Decisions Made ## Decisions Made
- went over github organizations and reviewed the assignments - went over github organizations and reviewed the assignments
- went through the rules and agreed on the contract - went through the rules and agreed on the contract
- figured out the brand name - figured out the brand name
## End Time ## End Time
- 10/12/2022 at 4:30PM - 10/12/2022 at 4:30PM

View File

@ -1,8 +1,13 @@
# Meeting Minutes (10/12/2022) # Meeting Minutes (10/12/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly Check-In Meeting ## Meeting Topic: Weekly Check-In Meeting
This meeting is the first weekly meeting with TA This meeting is the first weekly meeting with TA
## Attendance ## Attendance
1. Gagan Gopalaiah 1. Gagan Gopalaiah
2. Rhea Bhutada 2. Rhea Bhutada
3. Kara Hoagland 3. Kara Hoagland
@ -10,10 +15,12 @@ This meeting is the first weekly meeting with TA
5. Arthur 5. Arthur
## Meeting Details ## Meeting Details
- When: 10/12/2022 at 8:00PM - When: 10/12/2022 at 8:00PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
- ### Reviewed Project Details - ### Reviewed Project Details
- building CRUD app - building CRUD app
- utilizing HTML, CSS, JavaScript - utilizing HTML, CSS, JavaScript
@ -25,8 +32,10 @@ This meeting is the first weekly meeting with TA
- familiarize yourself with GitHub Actions - familiarize yourself with GitHub Actions
## Important Information ## Important Information
- Gagan OH (6:30PM-7:30PM on Wednesday) in CSE Basement - Gagan OH (6:30PM-7:30PM on Wednesday) in CSE Basement
- Reserved the room if any of us want to meet there. TA not going to present unless required. - Reserved the room if any of us want to meet there. TA not going to present unless required.
## End Time ## End Time
- 10/12/2022 at 8:30PM - 10/12/2022 at 8:30PM

View File

@ -1,9 +1,13 @@
# Meeting Minutes (10/19/2022) # Meeting Minutes (10/19/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly Check-In Meeting ## Meeting Topic: Weekly Check-In Meeting
This meeting is the second weekly meeting with TA. This meeting is the second weekly meeting with TA.
## Attendance ## Attendance
1. Gagan Gopalaiah 1. Gagan Gopalaiah
2. Rhea Bhutada 2. Rhea Bhutada
3. George Dubinin 3. George Dubinin
@ -14,19 +18,24 @@ This meeting is the second weekly meeting with TA.
8. Isaac Otero 8. Isaac Otero
## Meeting Details ## Meeting Details
- When: 10/19/2022 at 8:00PM - When: 10/19/2022 at 8:00PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
- ### Recap of last week - ### Recap of last week
- went over assignments - went over assignments
- discussed feelings on the midterm - discussed feelings on the midterm
- ### New Potential Meeting Time - ### New Potential Meeting Time
- without TA unless necessary - without TA unless necessary
- before lecture on Monday in CSE Basement - before lecture on Monday in CSE Basement
- ### Upcoming Assignments - ### Upcoming Assignments
- two coming up - two coming up
- brainstorm activity (due 10/23) - brainstorm activity (due 10/23)
- continue brainstorming throughout the week - continue brainstorming throughout the week
@ -35,11 +44,13 @@ This meeting is the second weekly meeting with TA.
- initial draft by 10/25 - 10/26 - initial draft by 10/25 - 10/26
- ### Tips on Designing - ### Tips on Designing
- user center design - user center design
- define the problem first, then the tools/techniques - define the problem first, then the tools/techniques
- finalize on the product and its features, then decide on how to build it - finalize on the product and its features, then decide on how to build it
- ### Standup - ### Standup
- not expected everyday - not expected everyday
- once every two days is ideal - once every two days is ideal
- doesn't have to be too descriptive - doesn't have to be too descriptive
@ -47,4 +58,5 @@ This meeting is the second weekly meeting with TA.
- ### Review of Recent Brainstorming Session - ### Review of Recent Brainstorming Session
## End Time ## End Time
- 10/19/2022 at 3:50PM - 10/19/2022 at 3:50PM

View File

@ -1,8 +1,13 @@
# Meeting Minutes (10/21/2022) # Meeting Minutes (10/21/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Application Brainstorming ## Meeting Topic: Application Brainstorming
This meeting is held to help the group decide on what application. We will also discuss preliminary designs. This meeting is held to help the group decide on what application. We will also discuss preliminary designs.
## Attendance ## Attendance
1. George Dubinin 1. George Dubinin
2. Gavyn Ezell 2. Gavyn Ezell
3. Henry Feng 3. Henry Feng
@ -15,15 +20,18 @@ This meeting is held to help the group decide on what application. We will also
10. Daniel Hernandez 10. Daniel Hernandez
## Absentees ## Absentees
N/A N/A
## Meeting Details ## Meeting Details
- When: - When:
- 10/21/2022 at 10:00AM - 10/21/2022 at 10:00AM
- 10/21/2022 at 1:30PM - 10/21/2022 at 1:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
@ -34,11 +42,13 @@ N/A
- Discuss design features for the chosen app - Discuss design features for the chosen app
## Decisions Made ## Decisions Made
- Added UCSD Food Reviewer App idea to the brainstorming doc - Added UCSD Food Reviewer App idea to the brainstorming doc
- The 10AM group cast 3 votes for the Social Media Auxilary and 1 vote for the UCSD Food Reviewer App (one participant voted twice) - The 10AM group cast 3 votes for the Social Media Auxilary and 1 vote for the UCSD Food Reviewer App (one participant voted twice)
- The 1:30PM group cast 7 votes for the UCSD Food Reviewer App and 5 votes for the Copy/Paste App - The 1:30PM group cast 7 votes for the UCSD Food Reviewer App and 5 votes for the Copy/Paste App
- We will move forward with the UCSD Food Reviewer App - We will move forward with the UCSD Food Reviewer App
## End Time ## End Time
- 10/21/2022 at 11:00AM - 10/21/2022 at 11:00AM
- 10/21/2022 at 2:30PM - 10/21/2022 at 2:30PM

View File

@ -1,8 +1,13 @@
# Meeting Minutes (10/23/2022) # Meeting Minutes (10/23/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Application Final Decision ## Meeting Topic: Application Final Decision
This meeting is held to help the group decide on which kind of app to build. This meeting is held to help the group decide on which kind of app to build.
## Attendance ## Attendance
1. George Dubinin 1. George Dubinin
2. Henry Feng 2. Henry Feng
3. Arthur Lu 3. Arthur Lu
@ -12,16 +17,19 @@ This meeting is held to help the group decide on which kind of app to build.
7. Isaac Otero 7. Isaac Otero
## Absentees ## Absentees
1. Sanjit Joseph 1. Sanjit Joseph
2. Gavyn Ezell 2. Gavyn Ezell
3. Daniel Hernandez 3. Daniel Hernandez
## Meeting Details ## Meeting Details
- When: - When:
- 10/23/2022 at 1:00PM - 10/23/2022 at 1:00PM
- Where: Zoom (Rhea's Meeting Room) - Where: Zoom (Rhea's Meeting Room)
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
@ -30,11 +38,13 @@ This meeting is held to help the group decide on which kind of app to build.
- Discuss design features for the chosen app - Discuss design features for the chosen app
## Decisions Made ## Decisions Made
- Maybe for the food reviewer app. Presenting possible writeup to Gagan - Maybe for the food reviewer app. Presenting possible writeup to Gagan
- Maybe for the resume builder. Presenting possible writeup to Gagan https://docs.google.com/document/d/1zdvVxd47Ivdz-D0rZGNJqc3D9GiQj0n_xMJKapOV39A/edit?usp=sharing - Maybe for the resume builder. Presenting possible writeup to Gagan https://docs.google.com/document/d/1zdvVxd47Ivdz-D0rZGNJqc3D9GiQj0n_xMJKapOV39A/edit?usp=sharing
- Maybe for Social Media Local Archive. Presenting possible writeup to Gagan https://docs.google.com/document/d/1upNr6lneB2uzCoQ12_aa1CMg1W8p2NBFb6xmP7i4-z4/edit?usp=sharing - Maybe for Social Media Local Archive. Presenting possible writeup to Gagan https://docs.google.com/document/d/1upNr6lneB2uzCoQ12_aa1CMg1W8p2NBFb6xmP7i4-z4/edit?usp=sharing
- No to the copy/paste app (not local first) - No to the copy/paste app (not local first)
## End Time ## End Time
- When: - When:
- 10/23/2022 at 2:00PM - 10/23/2022 at 2:00PM

View File

@ -1,10 +1,15 @@
# Meeting Minutes (10/26/2022) # Meeting Minutes (10/26/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly Check-In Meeting ## Meeting Topic: Weekly Check-In Meeting
This is our third weekly meeting with Gagan. This is our third weekly meeting with Gagan.
## Attendance ## Attendance
TA. Gagan Gopalaiah TA. Gagan Gopalaiah
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Sanjit Joseph 3. Sanjit Joseph
@ -12,17 +17,20 @@ TA. Gagan Gopalaiah
5. Gavyn Ezell 5. Gavyn Ezell
## Meeting Details ## Meeting Details
- When: 10/26/2022 at 3:00 PM - When: 10/26/2022 at 3:00 PM
- Where: Zoom (Gagan's Zoom room: https://ucsd.zoom.us/j/5177090642) - Where: Zoom (Gagan's Zoom room: https://ucsd.zoom.us/j/5177090642)
## Agenda: ## Agenda:
- ### Present our ideas to Gagan - ### Present our ideas to Gagan
- All ideas seem to be doable - All ideas seem to be doable
- Consider a few tweaks to "CRUDify" apps - Consider a few tweaks to "CRUDify" apps
- Gagan is partial to food review app idea, but any of them can work - Gagan is partial to food review app idea, but any of them can work
- ### Tips for projects - ### Tips for projects
- SOCIAL MEDIA ORGANIZER: avoid API integration if possible/only make it a small part, not a main feature - SOCIAL MEDIA ORGANIZER: avoid API integration if possible/only make it a small part, not a main feature
- RESUME BUILDER: try to "CRUDify" it more if we're going for this - RESUME BUILDER: try to "CRUDify" it more if we're going for this
@ -31,7 +39,9 @@ TA. Gagan Gopalaiah
- Perhaps make a separate slack channel for these to avoid clutter - Perhaps make a separate slack channel for these to avoid clutter
## Moving forward: ## Moving forward:
- ### BY FRIDAY: - ### BY FRIDAY:
- Try and meet tomorrow (10/27) to make a final decision - Try and meet tomorrow (10/27) to make a final decision
- Let Gagan know what we've decided on - Let Gagan know what we've decided on
- Complete project pitch assignment - need to present to Gagan tomorrow 10/27, due on canvas 11/1 - Complete project pitch assignment - need to present to Gagan tomorrow 10/27, due on canvas 11/1
@ -39,6 +49,6 @@ TA. Gagan Gopalaiah
- ### OVER WEEKEND: - ### OVER WEEKEND:
- (If possible) Start on CI/CD pipeline (basic js app/unit tests, use Github actions to set up) - (If possible) Start on CI/CD pipeline (basic js app/unit tests, use Github actions to set up)
## End Time ## End Time
- 10/26/2022 at 4:00 PM - 10/26/2022 at 4:00 PM

View File

@ -1,9 +1,13 @@
# Meeting Minutes (10/27/2022) # Meeting Minutes (10/27/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Final Project Decision ## Meeting Topic: Final Project Decision
We're figuring out what project we're going to do, and figure out what we need for the starting pitch. We're figuring out what project we're going to do, and figure out what we need for the starting pitch.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. Sanjit Joseph 2. Sanjit Joseph
3. Arthur Lu 3. Arthur Lu
@ -15,16 +19,20 @@ We're figuring out what project we're going to do, and figure out what we need f
9. Isaac Otero 9. Isaac Otero
## Meeting Details ## Meeting Details
- When: 10/27/2022 at 5:00 PM - When: 10/27/2022 at 5:00 PM
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343) - Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
## Agenda: ## Agenda:
- ### Decide which project we're doing - ### Decide which project we're doing
- Gagan seemed to like the food review app idea best in their current states - Gagan seemed to like the food review app idea best in their current states
- We all seem to agree that the food review app is acceptable - We all seem to agree that the food review app is acceptable
- Made a couple clarifications, no major changes or objections to the app - Made a couple clarifications, no major changes or objections to the app
- ### Start project pitch - ### Start project pitch
- Created google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing** - Created google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
- Prof recommends skimming the book: **https://basecamp.com/shapeup** (esp. ch.5 on risks and rabbit holes) - Prof recommends skimming the book: **https://basecamp.com/shapeup** (esp. ch.5 on risks and rabbit holes)
- Finishing Risks + Rabbit holes here in the meeting - Finishing Risks + Rabbit holes here in the meeting
@ -36,9 +44,10 @@ We're figuring out what project we're going to do, and figure out what we need f
- Probably provides food suggestions based on where you've eaten (and liked) before - Probably provides food suggestions based on where you've eaten (and liked) before
- We're not going to try anything with external data atm. - We're not going to try anything with external data atm.
## Moving forward: ## Moving forward:
- ### BY TOMORROW: - ### BY TOMORROW:
- FINISH PITCH SLIDES - FINISH PITCH SLIDES
- MUST CHANGE DIAGRAM TO ALL RESTAURANTS (Isaac will change this) - MUST CHANGE DIAGRAM TO ALL RESTAURANTS (Isaac will change this)
- Daniel will update the pitch slides by adding images/graphics. - Daniel will update the pitch slides by adding images/graphics.
@ -55,6 +64,6 @@ We're figuring out what project we're going to do, and figure out what we need f
- ### LATER: - ### LATER:
- Have some people split off and work on the basic UI design. Technically Sanjit had the 'art role' according to the TA but not sure what that entails. More ppl would def be helpful. TBD who else is helping - Have some people split off and work on the basic UI design. Technically Sanjit had the 'art role' according to the TA but not sure what that entails. More ppl would def be helpful. TBD who else is helping
## End Time ## End Time
- 10/27/2022 at 6:15 PM - 10/27/2022 at 6:15 PM

View File

@ -1,15 +1,20 @@
# Meeting Minutes (10/28/2022) # Meeting Minutes (10/28/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Project Pitch ## Meeting Topic: Project Pitch
We finished up the project pitch docs and presenting them to Gagan. We finished up the project pitch docs and presenting them to Gagan.
Google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing** Google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQUuFKsgvewOCOkdeMHFRg4/edit?usp=sharing**
## Meeting Details ## Meeting Details
- When: 10/28/2022 at 2:30 PM - When: 10/28/2022 at 2:30 PM
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343) - Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
## Agenda: ## Agenda:
- ### Finish Project Pitch documents - ### Finish Project Pitch documents
- Finished user stories/diagrams and uploaded to github - Finished user stories/diagrams and uploaded to github
- Went over presentation before showing TA - Went over presentation before showing TA
@ -17,8 +22,10 @@ Google slides: **https://docs.google.com/presentation/d/1_XWihJGVChFtYS38RnYJtQU
- **Overall reaction - he liked our app! More feedback to come, but we can feel free to start some basic work.** - **Overall reaction - he liked our app! More feedback to come, but we can feel free to start some basic work.**
## Moving forward: ## Moving forward:
- I think we need to upload our project pitch to canvas by 11/1 - I think we need to upload our project pitch to canvas by 11/1
- Start on the really basic stuff as discussed in lecture (hello world for CI/CD setup, etc) - Start on the really basic stuff as discussed in lecture (hello world for CI/CD setup, etc)
## End Time ## End Time
- 10/28/2022 at 4:00 PM - 10/28/2022 at 4:00 PM

View File

@ -1,13 +1,18 @@
# Meeting Minutes (11/01/2022) # Meeting Minutes (11/01/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Work going forward ## Meeting Topic: Work going forward
We're trying to figure out what our goals are for the project and how to get started. We're trying to figure out what our goals are for the project and how to get started.
## Meeting Details ## Meeting Details
- When: 11/01/2022 at 7:00 PM - When: 11/01/2022 at 7:00 PM
- Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343) - Where: Zoom (Rhea's Zoom room: https://ucsd.zoom.us/j/8054288343)
## Attendance ## Attendance
1. Rhea 1. Rhea
2. Gavyn 2. Gavyn
3. Isaac 3. Isaac
@ -18,6 +23,7 @@ We're trying to figure out what our goals are for the project and how to get sta
8. Sanjit 8. Sanjit
## Notes: ## Notes:
- Gagan suggests we have a feature backlog and pull stuff from that - Gagan suggests we have a feature backlog and pull stuff from that
- Using Github Issues for our feature backlog - Using Github Issues for our feature backlog
@ -26,9 +32,11 @@ We're trying to figure out what our goals are for the project and how to get sta
- Created figma sketch for app design, uploaded to github and google slides - Created figma sketch for app design, uploaded to github and google slides
## Moving forward: ## Moving forward:
- ### BY TONIGHT: - ### BY TONIGHT:
- We'll submit our pitch files - We'll submit our pitch files
- ### LATER: - ### LATER:
- Sanjit will upload a basic hello world program in order to test deployment/github actions - Sanjit will upload a basic hello world program in order to test deployment/github actions
- Arthur will start figuring out how to configure github actions - Arthur will start figuring out how to configure github actions
@ -38,4 +46,5 @@ We're trying to figure out what our goals are for the project and how to get sta
- NO PREFERENCE: Daniel, Marc, Rhea, Sanjit - NO PREFERENCE: Daniel, Marc, Rhea, Sanjit
## End Time ## End Time
- 11/01/2022 at 9:00 PM - 11/01/2022 at 9:00 PM

View File

@ -1,20 +1,26 @@
# Meeting Minutes (11/02/2022) # Meeting Minutes (11/02/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly TA Catchup with Gagan ## Meeting Topic: Weekly TA Catchup with Gagan
We are meeting with Gagan to discuss early phase design concepts and decisions we need to think about as we start the early coding phase. We are meeting with Gagan to discuss early phase design concepts and decisions we need to think about as we start the early coding phase.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gagan Gopalaiah 3. Gagan Gopalaiah
## Meeting Details ## Meeting Details
- When: 11/02/2022 at 3:30PM - When: 11/02/2022 at 3:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
## Discussion Points by Gagan ## Discussion Points by Gagan
- Now that we finished designs stage there are 2 approaches - Now that we finished designs stage there are 2 approaches
- The first is to just start coding without thinking about design (cowboy coding). It works but can get bumpy down the road - The first is to just start coding without thinking about design (cowboy coding). It works but can get bumpy down the road
- The second is to look at the project from a birds eye view and break it down into milestones and tasks. First break it down into weeks and then decide on what to do each day of the week. This will make it easier to keep things organized. - The second is to look at the project from a birds eye view and break it down into milestones and tasks. First break it down into weeks and then decide on what to do each day of the week. This will make it easier to keep things organized.
@ -29,6 +35,5 @@ We are meeting with Gagan to discuss early phase design concepts and decisions w
- We need to create the ADR and place it in the brainstorming section of the repo. This will contain details about specific project decisions that we made like database decisions (for example). - We need to create the ADR and place it in the brainstorming section of the repo. This will contain details about specific project decisions that we made like database decisions (for example).
## End Time ## End Time
- 11/02/2022 at 4:00PM - 11/02/2022 at 4:00PM

View File

@ -1,9 +1,13 @@
# Meeting Minutes (11/03/2022) # Meeting Minutes (11/03/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Technologies Discussion ## Meeting Topic: Technologies Discussion
We're deciding on what web technologies we will incorporate into our food blog application. We're deciding on what web technologies we will incorporate into our food blog application.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. Sanjit Joseph 2. Sanjit Joseph
3. Arthur Lu 3. Arthur Lu
@ -15,10 +19,12 @@ We're deciding on what web technologies we will incorporate into our food blog a
9. Isaac Otero 9. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/03/2022 at 3:00PM - When: 11/03/2022 at 3:00PM
- Where: In-person (CSE Basement B250) and George's Zoom room - Where: In-person (CSE Basement B250) and George's Zoom room
## Agenda: ## Agenda:
- ### Answer the questions that Gagan's asked the team leads yesterday - ### Answer the questions that Gagan's asked the team leads yesterday
- What high level approach will we have to coding? - What high level approach will we have to coding?
- Slow approach with diagrams and short sprints of around 3 days. Biweekly meetings where we catch up with what happened end of each sprint. - Slow approach with diagrams and short sprints of around 3 days. Biweekly meetings where we catch up with what happened end of each sprint.
@ -30,15 +36,13 @@ We're deciding on what web technologies we will incorporate into our food blog a
- We will be creating branches for different features and be submitting PRs direclty to the master branch. Forks will only be created for large overhaul type changes - We will be creating branches for different features and be submitting PRs direclty to the master branch. Forks will only be created for large overhaul type changes
- How will PRs be approved - How will PRs be approved
- The team will be split up into groups for different aspects of the app (front end, ui, database for example) and PRs will be reviewed and approved by 1 other member of the respective group - The team will be split up into groups for different aspects of the app (front end, ui, database for example) and PRs will be reviewed and approved by 1 other member of the respective group
- Introduce the ADR and discuss how we will create it - ## Introduce the ADR and discuss how we will create it
-
## Assignments: ## Assignments:
- ### By X point in time: - ### By X point in time:
- -
## End Time ## End Time
- 11/03/2022 at 4:00 PM - 11/03/2022 at 4:00 PM

View File

@ -1,32 +1,41 @@
# Meeting Minutes (11/04/2022) # Meeting Minutes (11/04/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Technologies Discussion ## Meeting Topic: Technologies Discussion
We're planning out our first sprint and breaking up the project into tasks. Tasks will be assigned to groups and GitHub issues will be created We're planning out our first sprint and breaking up the project into tasks. Tasks will be assigned to groups and GitHub issues will be created
for each task and assigned to a group. for each task and assigned to a group.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. Sanjit Joseph 2. Sanjit Joseph
3. Arthur Lu 3. Arthur Lu
4. Marc Reta 4. Marc Reta
6. Kara Hoagland 5. Kara Hoagland
7. Daniel Hernandez 6. Daniel Hernandez
8. Gavyn Ezell 7. Gavyn Ezell
9. Isaac Otero 8. Isaac Otero
10. Henry Feng 9. Henry Feng
## Meeting Details ## Meeting Details
- When: 11/04/2022 at 10:00AM - When: 11/04/2022 at 10:00AM
- Where: George's Zoom room - Where: George's Zoom room
## Agenda: ## Agenda:
## Sprint 1 Categories and Assignments ## Sprint 1 Categories and Assignments
Frontend: Isaac, Sanjit, and Daniel Frontend: Isaac, Sanjit, and Daniel
Backend: Rhea, George, Gavyn, Kara, Backend: Rhea, George, Gavyn, Kara,
- Save to database - Save to database
- Load from database - Load from database
- Clear database - Clear database
Unit Testing: Arthur, Marc Unit Testing: Arthur, Marc
## End Time ## End Time
- 11/03/2022 at 10:30 AM - 11/03/2022 at 10:30 AM

View File

@ -1,9 +1,13 @@
# Meeting Minutes (11/08/2022) # Meeting Minutes (11/08/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: In-Person First Sprint Day 2 ## Meeting Topic: In-Person First Sprint Day 2
Meeting notes for the first sprint Meeting notes for the first sprint
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -12,10 +16,12 @@ Meeting notes for the first sprint
6. Daniel Hernandez 6. Daniel Hernandez
## Meeting Details ## Meeting Details
- When: 11/08/2022 at 2:00PM - When: 11/08/2022 at 2:00PM
- Where: Mike's Red Tacos - Where: Mike's Red Tacos
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
@ -24,16 +30,16 @@ Meeting notes for the first sprint
- ### Next Meeting's Business - ### Next Meeting's Business
## App Progress ## App Progress
- The landing page is closer - The landing page is closer
- Review card css file entered - Review card css file entered
- Review Card javascript logic implemented (thanks Gavin) - Review Card javascript logic implemented (thanks Gavin)
- -
## Decisions Made ## Decisions Made
- Linting details decided (TABS NOT SPACES) - Linting details decided (TABS NOT SPACES)
## End Time ## End Time
- 11/07/2022 at 8:00PM - 11/07/2022 at 8:00PM

View File

@ -1,21 +1,27 @@
# Meeting Minutes (11/09/2022) # Meeting Minutes (11/09/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly TA Catchup with Gagan ## Meeting Topic: Weekly TA Catchup with Gagan
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing. We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gagan Gopalaiah 3. Gagan Gopalaiah
4. Sanjit Joseph 4. Sanjit Joseph
## Meeting Details ## Meeting Details
- When: 11/09/2022 at 3:30PM - When: 11/09/2022 at 3:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
## Discussion Points by Gagan ## Discussion Points by Gagan
- Provided updates on first sprint - Provided updates on first sprint
- Testing Tips - Testing Tips
- functionality testing - functionality testing
@ -33,4 +39,5 @@ We are meeting with Gagan to discuss progress made on Sprint 1 and testing strat
- JS Docs - JS Docs
## End Time ## End Time
- 11/09/2022 at 4:00PM - 11/09/2022 at 4:00PM

View File

@ -1,8 +1,11 @@
# Sprint 1 Retrospective (11/14/2022) # Sprint 1 Retrospective (11/14/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 1 Retrospective ## Meeting Topic: Sprint 1 Retrospective
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Sanjit Joseph 3. Sanjit Joseph
@ -15,54 +18,64 @@
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/14/2022 at 4:30PM - When: 11/14/2022 at 4:30PM
- Where: On Campus - Where: On Campus
## Agenda: ## Agenda:
Discuss the review, share more detailed thoughts on sprint 1, and create some resolutions for sprint 2 Discuss the review, share more detailed thoughts on sprint 1, and create some resolutions for sprint 2
## Sprint 1 Review Below (for convenience) ## Sprint 1 Review Below (for convenience)
## Sprint 1 REVIEW ## Sprint 1 REVIEW
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below: In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
### What do you think worked well in the first sprint? ### What do you think worked well in the first sprint?
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be. We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
### What can we improve on for the next sprint? ### What can we improve on for the next sprint?
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process. We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
### What was your contribution to the sprint? ### What was your contribution to the sprint?
* Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
* Gavyn Etzel: Helped with javascript side of things for website - Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
* Henry Feng: Local image store and meeting support - Gavyn Etzel: Helped with javascript side of things for website
* Sanjit: Default photo design and frontend star rating css - Henry Feng: Local image store and meeting support
* Daniel: Helped modify html, added upload file feature - Sanjit: Default photo design and frontend star rating css
* Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action - Daniel: Helped modify html, added upload file feature
* Marc Rheta: Added HTML Linting and CSS Linting - Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
* Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html - Marc Rheta: Added HTML Linting and CSS Linting
* George Dubinin: Meeting notes, Repo organization, cookies - Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
* Kara Hoagland: CRUD backend functionality - George Dubinin: Meeting notes, Repo organization, cookies
- Kara Hoagland: CRUD backend functionality
### Was there anything blocking your progress in the sprint? ### Was there anything blocking your progress in the sprint?
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues. Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break. Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
## Resolutions ## Resolutions
* Divide up tasks and assign tasks to members
* Define objectives for team groups (frontend, backend, and unit testing) - Divide up tasks and assign tasks to members
* Scheduled meetings with more notice and keep meetings at a more central location so that more members can attend - Define objectives for team groups (frontend, backend, and unit testing)
* Get the unit testing modules up to date - Scheduled meetings with more notice and keep meetings at a more central location so that more members can attend
* To-do: create a style guide - Get the unit testing modules up to date
* Heed the styles and documentation (to avoid linter issues) - To-do: create a style guide
- Heed the styles and documentation (to avoid linter issues)
## Early Issues ## Early Issues
* restructure local storage to store individual (key, review) pairs rather than storing data under one key (current schema)
* implement a file upload system (think canvas file upload) - restructure local storage to store individual (key, review) pairs rather than storing data under one key (current schema)
* add a cuisine attribute for tagging and filtering - implement a file upload system (think canvas file upload)
* Create UI buttons and low fidelity css - add a cuisine attribute for tagging and filtering
* Unit test all the above - Create UI buttons and low fidelity css
- Unit test all the above
## End Time ## End Time
- 11/14/2022 at 5:00PM - 11/14/2022 at 5:00PM

View File

@ -1,9 +1,13 @@
# Sprint 1 Review Meeting Minutes (11/13/2022) # Sprint 1 Review Meeting Minutes (11/13/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 1 Review ## Meeting Topic: Sprint 1 Review
We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing. We are meeting with Gagan to discuss progress made on Sprint 1 and testing strategies that we need to keep in mind as we continue developing.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Sanjit Joseph 3. Sanjit Joseph
@ -16,37 +20,45 @@ We are meeting with Gagan to discuss progress made on Sprint 1 and testing strat
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/13/2022 at 1:00PM - When: 11/13/2022 at 1:00PM
- Where: Capital One Cafe and Zoom - Where: Capital One Cafe and Zoom
## Agenda: ## Agenda:
Review the week 7 sprint and get the writeup for the Agile review assignemnt Review the week 7 sprint and get the writeup for the Agile review assignemnt
## Sprint 1 REVIEW ## Sprint 1 REVIEW
In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below: In collecting feedback during our final sprint the leads decided to ask members individually about their experience during sprint 1 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
### What do you think worked well in the first sprint? ### What do you think worked well in the first sprint?
We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be. We resolved to hold each of our sprint 1 meetings in person with a remote option available to members that couldn't attend. We really liked hanging out at the restaurants before working on the sprint and these experiences encouraged psychological safety in the group. We made some noticeable progress which was very encouraging for the group. Specifically, we figured out quite a bit of the CI/CD pipeline details which will help us going forward and we got a solid grasp of what the visual aspects and feel of the website will be.
### What can we improve on for the next sprint? ### What can we improve on for the next sprint?
We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process. We ran into trouble early on due to some lack of planning for specific tasks. The members agreed that we should have spent more time defining tasks for specific members and defining goals for our different teams (frontend, backend, and unit testing). There was some concern over members not being able to attend all meetings and we think this could have been fixed with regularly scheduled meetings. Some technical concerns were the Javascript unit testing pipeline development lagging behind code development and pipeline requirements being unclear. Perhaps we should write out a style document to guide the automated linting process.
### What was your contribution to the sprint? ### What was your contribution to the sprint?
* Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
* Gavyn Etzel: Helped with javascript side of things for website - Rhea Bhutada: Worked on the backend features including how to get create new review card page to open in a new window
* Henry Feng: Local image store and meeting support - Gavyn Etzel: Helped with javascript side of things for website
* Sanjit: Default photo design and frontend star rating css - Henry Feng: Local image store and meeting support
* Daniel: Helped modify html, added upload file feature - Sanjit: Default photo design and frontend star rating css
* Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action - Daniel: Helped modify html, added upload file feature
* Marc Rheta: Added HTML Linting and CSS Linting - Arthur Lu: Added JS Linting, Unit testing pipeline actions and rote a few simple unit tests; added deployment pipeline action
* Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html - Marc Rheta: Added HTML Linting and CSS Linting
* George Dubinin: Meeting notes, Repo organization, cookies - Isaac Otero: Low and mid fidelity wireframes of how our page will look like, Started working on homepage.html
* Kara Hoagland: CRUD backend functionality - George Dubinin: Meeting notes, Repo organization, cookies
- Kara Hoagland: CRUD backend functionality
### Was there anything blocking your progress in the sprint? ### Was there anything blocking your progress in the sprint?
Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues. Communication was challenging especially for members that would attend over Zoom and it was a challenge keeping track of each member's progress. We ran into some issues with the branching strategy with branches rapidly multiplying at points and the GitHub tags not working. The biggest technical issue we experienced involved Node and ES6 compatibility issues.
Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break. Overall we feel that sprint 1 was a success with many lessons learned. Our enthusiasm for the project is only building and we are excited to get back into it with sprint 2 after a much needed short break.
## End Time ## End Time
- 11/13/2022 at 3:00PM - 11/13/2022 at 3:00PM

View File

@ -1,21 +1,27 @@
# Meeting Minutes (11/16/2022) # Meeting Minutes (11/16/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly TA Catchup with Gagan ## Meeting Topic: Weekly TA Catchup with Gagan
We are meeting with Gagan to discuss Checkpoint 1 and Sprint 2 resolutions. We are meeting with Gagan to discuss Checkpoint 1 and Sprint 2 resolutions.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gagan Gopalaiah 3. Gagan Gopalaiah
4. Kara Hoagland 4. Kara Hoagland
## Meeting Details ## Meeting Details
- When: 11/16/2022 at 3:30PM - When: 11/16/2022 at 3:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
## Discussion Points by Gagan ## Discussion Points by Gagan
- Updated Gagan on Sprint 1 - Updated Gagan on Sprint 1
- looked at Girhub actions - looked at Girhub actions
- looked at the published page so far - looked at the published page so far
@ -30,4 +36,5 @@ We are meeting with Gagan to discuss Checkpoint 1 and Sprint 2 resolutions.
- Gagan sees Netlify as more professional and not to difficult to implement - Gagan sees Netlify as more professional and not to difficult to implement
## End Time ## End Time
- 11/16/2022 at 3:45PM - 11/16/2022 at 3:45PM

View File

@ -1,9 +1,13 @@
# Meeting Minutes (11/07/2022) # Meeting Minutes (11/07/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: First Sprint ## Meeting Topic: First Sprint
Meeting notes for the first sprint Meeting notes for the first sprint
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -16,16 +20,20 @@ Meeting notes for the first sprint
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/17/2022 at 11:30PM - When: 11/17/2022 at 11:30PM
- Where: Design & Innovation Building - Where: Design & Innovation Building
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
- Second sprint commences! - Second sprint commences!
- Focus on design progress for the project showoff - Focus on design progress for the project showoff
- Cuisine vs Tag identifiers for reviews (both?) - Cuisine vs Tag identifiers for reviews (both?)
- localStorage will hold: - localStorage will hold:
- list of active IDs which is updated for very create operation. An ID uniquely identifies a review - list of active IDs which is updated for very create operation. An ID uniquely identifies a review
- value, "nextId" denoting the index of the next available slot for an Id - value, "nextId" denoting the index of the next available slot for an Id
@ -33,15 +41,19 @@ Meeting notes for the first sprint
- a list for every tag that denotes which Ids belong to reviews containing this tag - a list for every tag that denotes which Ids belong to reviews containing this tag
End2end tests will rely on specific html element names which include the following: End2end tests will rely on specific html element names which include the following:
- "create-btn" (located on homepage and used to create a new review) - "create-btn" (located on homepage and used to create a new review)
- "submit-btn" (located on form and used to post review) - "submit-btn" (located on form and used to post review)
- "update-btn" (located on a specific review page) - "update-btn" (located on a specific review page)
- "delete-btn" (located on a specific review page) - "delete-btn" (located on a specific review page)
- "tag-add-btn" (located on the review create form) - "tag-add-btn" (located on the review create form)
- ### Next Meeting's Business - ### Next Meeting's Business
## Decisions Made ## Decisions Made
- -
## End Time ## End Time
- 11/17/2022 at 1:00PM - 11/17/2022 at 1:00PM

View File

@ -1,8 +1,11 @@
# Meeting Minutes (11/20/2022) # Meeting Minutes (11/20/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Second Sprint Meeting 3 ## Meeting Topic: Second Sprint Meeting 3
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -15,25 +18,31 @@
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/20/2022 at 1:00PM - When: 11/20/2022 at 1:00PM
- Where: CSE Building Second Floor - Where: CSE Building Second Floor
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- N/A - N/A
- ### New Business - ### New Business
- Planning for the Agile Steam Status Video - Planning for the Agile Steam Status Video
- *Present the status of your software*
- _Present the status of your software_
- Show off the preliminary design of index.html - Show off the preliminary design of index.html
- Walk through the process of creating a journal entry - Walk through the process of creating a journal entry
- *Description of current challenges to development* - _Description of current challenges to development_
- *Preview of the next sprint and what to look forward to* - _Preview of the next sprint and what to look forward to_
- Front end redo for home page including semantic restructuring and enhanced CSS - Front end redo for home page including semantic restructuring and enhanced CSS
- Documentation session for JS, CSS, and HTML files - Documentation session for JS, CSS, and HTML files
- Pipeline details have largely been ironed out - Pipeline details have largely been ironed out
- ### Next Meeting's Business - ### Next Meeting's Business
- Creation of team status video - Creation of team status video
## End Time ## End Time
- 11/20/2022 at 3:00PM - 11/20/2022 at 3:00PM

View File

@ -1,18 +1,24 @@
# Meeting Minutes (11/23/2022) # Meeting Minutes (11/23/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly TA Catchup with Gagan ## Meeting Topic: Weekly TA Catchup with Gagan
We are meeting with Gagan to discuss status video and general updates on project. We are meeting with Gagan to discuss status video and general updates on project.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gagan Gopalaiah 3. Gagan Gopalaiah
## Meeting Details ## Meeting Details
- When: 11/23/2022 at 3:30PM - When: 11/23/2022 at 3:30PM
- Where: Zoom - Where: Zoom
## Discussion Points by Gagan ## Discussion Points by Gagan
- progress looks good!! - progress looks good!!
- deadline for project - deadline for project
- december 3rd/4th code freeze - december 3rd/4th code freeze
@ -30,4 +36,5 @@ We are meeting with Gagan to discuss status video and general updates on project
- quickly discussed team roles - quickly discussed team roles
## End Time ## End Time
- 11/23/2022 at 3:52PM - 11/23/2022 at 3:52PM

View File

@ -1,9 +1,13 @@
# Sprint 2 Review Meeting Minutes (11/27/2022) # Sprint 2 Review Meeting Minutes (11/27/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 2 Review ## Meeting Topic: Sprint 2 Review
We are reviewing the second sprint 2 progress made and highlights We are reviewing the second sprint 2 progress made and highlights
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Sanjit Joseph 3. Sanjit Joseph
@ -16,48 +20,58 @@ We are reviewing the second sprint 2 progress made and highlights
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/27/2022 at 4:30PM - When: 11/27/2022 at 4:30PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
Review the second sprint and discuss assiget the writeup for the Agile review assignemnt Review the second sprint and discuss assiget the writeup for the Agile review assignemnt
## Sprint 2 REVIEW ## Sprint 2 REVIEW
In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below: In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
### ➼ What do you think worked well in the first sprint? ### ➼ What do you think worked well in the first sprint?
Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort. Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort.
### ➼ What can we improve on for the next sprint? ### ➼ What can we improve on for the next sprint?
With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2. With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2.
### ➼ What was your contribution to the sprint? ### ➼ What was your contribution to the sprint?
* Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
* Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files - Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
- Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files
Helped work through the storage revamp for our review cards Helped work through the storage revamp for our review cards
Also helped integrate our first design/style setup with functionality Also helped integrate our first design/style setup with functionality
* Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles. - Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles.
* Sanjit: I reimplemented the star ratings since they had some issues and werent merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon - Sanjit: I reimplemented the star ratings since they had some issues and werent merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon
* Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group. - Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group.
Helped in styling suggestions. Helped in styling suggestions.
* Arthur Lu: Worked on fixing some CI/CD pipeline issues - Arthur Lu: Worked on fixing some CI/CD pipeline issues
Implemented e2e testing for basic update and delete functionality Implemented e2e testing for basic update and delete functionality
Helped with fixing the homepage and review page layout Helped with fixing the homepage and review page layout
Helped with fixing the article tag overflow issue Helped with fixing the article tag overflow issue
* Marc Rheta: Implemented the e2e testing for reading and create - Marc Rheta: Implemented the e2e testing for reading and create
Allowed tabs for CSS/HTML linters Allowed tabs for CSS/HTML linters
* Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html - Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html
* George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video. - George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video.
* Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page - Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page
### ➼ Was there anything blocking your progress in the sprint? ### ➼ Was there anything blocking your progress in the sprint?
A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall. A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall.
## Next Sprint Goals ## Next Sprint Goals
- Resolve the 4 issues open on GitHub right now - Resolve the 4 issues open on GitHub right now
- Make the project "local first" by creating a cache - Make the project "local first" by creating a cache
- Bug fixes and final product adjustments possibly pushed to sprint 4 - Bug fixes and final product adjustments possibly pushed to sprint 4
- We aim to keep sprint 3 short (a few days max) - We aim to keep sprint 3 short (a few days max)
- JS docs (we can potentially leave this out with an explanation of where our documentation is) - JS docs (we can potentially leave this out with an explanation of where our documentation is)
## End Time ## End Time
- 11/27/2022 at 5:00PM - 11/27/2022 at 5:00PM

View File

@ -1,8 +1,11 @@
# Sprint 1 Retrospective (11/28/2022) # Sprint 1 Retrospective (11/28/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 1 Retrospective ## Meeting Topic: Sprint 1 Retrospective
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Sanjit Joseph 3. Sanjit Joseph
@ -15,44 +18,52 @@
10. Isaac Otero 10. Isaac Otero
## Meeting Details ## Meeting Details
- When: 11/28/2022 at 4:00PM - When: 11/28/2022 at 4:00PM
- Where: Zoom - Where: Zoom
## Agenda: ## Agenda:
Discuss the review, share more detailed thoughts on sprint 2, and create some resolutions for sprint 3 Discuss the review, share more detailed thoughts on sprint 2, and create some resolutions for sprint 3
## Sprint 3 Review Below (for convenience) ## Sprint 3 Review Below (for convenience)
In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below: In collecting feedback for the sprint the leads decided to ask members individually about their experience during sprint 2 to then summarize these responses. Each member was asked 4 questions with their summarized responses below:
### ➼ What do you think worked well in the first sprint? ### ➼ What do you think worked well in the first sprint?
Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort. Communication within the group was improved and our joint study sessions where more productive. The design team got the support they needed to accomplish the majority of their work on the project. The push to emphasize the sub-teams responsible for different tasks turned out to be a great idea and everyone put in a good effort.
### ➼ What can we improve on for the next sprint? ### ➼ What can we improve on for the next sprint?
With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2. With the vast majority of feature implementation underway the rapid progress created a lot of bugs which otherwise could have been avoid with more careful planning. Some members felt that even though they made a great effort they weren't able to contribute as much as they wanted to. Some of the code documentation fell behind and some design discussions were circumvented because some members where busy. One consequence was that relatively few ADRs were created even though we made many important design decisions during sprint 2.
### ➼ What was your contribution to the sprint? ### ➼ What was your contribution to the sprint?
* Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
* Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files - Rhea Bhutada: I mainly helped implement the backend for the CRUD features of the app and documentation related to this. This mainly entailed changing the way that we were storing user data in local storage. Additionally, I helped design the form and homepage.
- Gavyn Etzel: Helped with JavaScript functionality (CRUD Features), and also did a lot of the documentation for the script files
Helped work through the storage revamp for our review cards Helped work through the storage revamp for our review cards
Also helped integrate our first design/style setup with functionality Also helped integrate our first design/style setup with functionality
* Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles. - Henry Feng: Worked on implementing local image uploading and storing features for updating and creating profiles.
* Sanjit: I reimplemented the star ratings since they had some issues and werent merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon - Sanjit: I reimplemented the star ratings since they had some issues and werent merged with sprint 1. I fixed a bunch of linting issues that popped up from that as well. I did a fair bit of color palette brainstorming with the team. I also went over our app design for the sprint video and edited that together. Most importantly I put a chef hat on the raccoon
* Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group. - Daniel: Helped in initial CreatePage and HomePage design which improved through feedback from the rest of the group.
Helped in styling suggestions. Helped in styling suggestions.
* Arthur Lu: Worked on fixing some CI/CD pipeline issues - Arthur Lu: Worked on fixing some CI/CD pipeline issues
Implemented e2e testing for basic update and delete functionality Implemented e2e testing for basic update and delete functionality
Helped with fixing the homepage and review page layout Helped with fixing the homepage and review page layout
Helped with fixing the article tag overflow issue Helped with fixing the article tag overflow issue
* Marc Rheta: Implemented the e2e testing for reading and create - Marc Rheta: Implemented the e2e testing for reading and create
Allowed tabs for CSS/HTML linters Allowed tabs for CSS/HTML linters
* Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html - Isaac Otero: I was able to help out with the sprint video for the last sprint and thought of how our page will look like, Started working on homepage.html
* George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video. - George Dubinin: Meeting notes, Repo organization, Front-end (a little), Project Status Review video.
* Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page - Kara Hoagland: I helped set up the new local storage design, reimplemented the CRUD features using the new local storage design, contributed to the styling, added a default img, backend on the details page
### ➼ Was there anything blocking your progress in the sprint? ### ➼ Was there anything blocking your progress in the sprint?
A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall. A few members got sick over the break and with midterms picking up for other classes some members had trouble dedicting time for the project but everyone still put in a great effort overall.
## Next Sprint Goals ## Next Sprint Goals
- Resolve the 4 issues open on GitHub right now - Resolve the 4 issues open on GitHub right now
- Make the project "local first" by creating a cache - Make the project "local first" by creating a cache
- Bug fixes and final product adjustments possibly pushed to sprint 4 - Bug fixes and final product adjustments possibly pushed to sprint 4
@ -60,12 +71,14 @@ A few members got sick over the break and with midterms picking up for other cla
- JS docs (we can potentially leave this out with an explanation of where our documentation is) - JS docs (we can potentially leave this out with an explanation of where our documentation is)
## Resolutions ## Resolutions
* Sprint 3 first meeting happening 11-29 at 5:00PM
* Make sure that there's enough communication between front-end and back-end - Sprint 3 first meeting happening 11-29 at 5:00PM
* Focus on meeting with your subgroup and then touch base with the main group - Make sure that there's enough communication between front-end and back-end
* Keep documentation up to date with the rest of the project - Focus on meeting with your subgroup and then touch base with the main group
* We need to finalize the home page design (this has been open for a while). - Keep documentation up to date with the rest of the project
* Fix image sizing issues by focusing on supporting 300x300 pixel images with sizes of around 2-5 megabytes - We need to finalize the home page design (this has been open for a while).
- Fix image sizing issues by focusing on supporting 300x300 pixel images with sizes of around 2-5 megabytes
## End Time ## End Time
- 11/14/2022 at 5:00PM - 11/14/2022 at 5:00PM

View File

@ -1,8 +1,11 @@
# Meeting Minutes (11/29/2022) # Meeting Minutes (11/29/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 3 Debut Meeting ## Meeting Topic: Sprint 3 Debut Meeting
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gavyn Ezell 3. Gavyn Ezell
@ -14,10 +17,12 @@
9. Arthur Lu (remote) 9. Arthur Lu (remote)
## Meeting Details ## Meeting Details
- When: 11/29/2022 at 5:00PM - When: 11/29/2022 at 5:00PM
- Where: Design and Innovation Building - Where: Design and Innovation Building
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- Resolve pretty print linting PR - Resolve pretty print linting PR
- Resolve documentation not being merged to main PR - Resolve documentation not being merged to main PR
@ -32,4 +37,5 @@
- Creation of team status video - Creation of team status video
## End Time ## End Time
- 11/20/2022 at 3:00PM - 11/20/2022 at 3:00PM

View File

@ -1,20 +1,25 @@
# Meeting Minutes (11/30/2022) # Meeting Minutes (11/30/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Sprint 3 Continued ## Meeting Topic: Sprint 3 Continued
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
4. Henry Feng 3. Henry Feng
5. Kara Hoagland 4. Kara Hoagland
7. Sanjit Joseph 5. Sanjit Joseph
9. Arthur Lu 6. Arthur Lu
## Meeting Details ## Meeting Details
- When: 11/30/2022 at 2:00PM - When: 11/30/2022 at 2:00PM
- Where: Design and Innovation Building - Where: Design and Innovation Building
## Agenda: ## Agenda:
- ### Old/Unresolved Business - ### Old/Unresolved Business
- Fix empty page for no-tag search - Fix empty page for no-tag search
- Catch testing up with what we implemented yesterday - Catch testing up with what we implemented yesterday
@ -27,4 +32,5 @@
- Creation of team status video - Creation of team status video
## End Time ## End Time
- 11/30/2022 at 2:00PM - 11/30/2022 at 2:00PM

View File

@ -1,22 +1,29 @@
# Meeting Minutes (12/1/2022) # Meeting Minutes (12/1/2022)
## Team 29: Hackers1995 ## Team 29: Hackers1995
## Meeting Topic: Weekly TA Catchup with Gagan ## Meeting Topic: Weekly TA Catchup with Gagan
We are meeting with Gagan to discuss status video and general updates on project. We are meeting with Gagan to discuss status video and general updates on project.
## Attendance ## Attendance
1. Rhea Bhutada 1. Rhea Bhutada
2. George Dubinin 2. George Dubinin
3. Gagan Gopalaiah 3. Gagan Gopalaiah
## Meeting Details ## Meeting Details
- When: 12/1/2022 at 12:00PM - When: 12/1/2022 at 12:00PM
- Where: Zoom - Where: Zoom
## Discussion Points by Gagan ## Discussion Points by Gagan
- Don't code up anything after Sunday. Reserve the time for bug fixes - Don't code up anything after Sunday. Reserve the time for bug fixes
- Final Interview is a 4-5 minute interview about general course specific topics - Final Interview is a 4-5 minute interview about general course specific topics
- Live demo of the app for Gagan - Live demo of the app for Gagan
- Gagan asks us to evaluate instructional assistants - Gagan asks us to evaluate instructional assistants
## End Time ## End Time
- 12/1/2022 at 12:20PM - 12/1/2022 at 12:20PM

View File

@ -1,13 +1,18 @@
# Team Working Agreement # Team Working Agreement
## Term: Fall 2022 ## Term: Fall 2022
## Creation: 10/12/2022; Revised: N/A ## Creation: 10/12/2022; Revised: N/A
## Group Identification ## Group Identification
- Team 29 - Team 29
- TA: Gagan Gopalaiah - TA: Gagan Gopalaiah
- Instructor: Professor Thomas Powell - Instructor: Professor Thomas Powell
- Team Name: Hackers1995 - Team Name: Hackers1995
## Team member info (name/email) ## Team member info (name/email)
1. Rhea Bhutada, rbhutada@ucsd.edu 1. Rhea Bhutada, rbhutada@ucsd.edu
2. George Dubinin, gdubinin@ucsd.edu 2. George Dubinin, gdubinin@ucsd.edu
3. Gavyn Ezell, gezell@ucsd.edu 3. Gavyn Ezell, gezell@ucsd.edu
@ -20,12 +25,15 @@
10. Daniel Hernandez, d7hernan@ucsd.edu 10. Daniel Hernandez, d7hernan@ucsd.edu
## RULES: ## RULES:
#### 1) Primary Means of Communication and Expectations #### 1) Primary Means of Communication and Expectations
- All members will communicate via Slack. - All members will communicate via Slack.
- All members will be expected to read messages from group chats and direct messages, and respond in no more than 4 hours and no later than 10PM. - All members will be expected to read messages from group chats and direct messages, and respond in no more than 4 hours and no later than 10PM.
- All pull requests require 3 people to review the code being pushed to main. - All pull requests require 3 people to review the code being pushed to main.
#### 2) Scheduling Meetings (Schedule at least one meeting as part of constructing your team agreement.) #### 2) Scheduling Meetings (Schedule at least one meeting as part of constructing your team agreement.)
- Members are expected to meet at least once a week with the group either in-person or on Zoom. Future meeting details will be determined within a 24 hours window. - Members are expected to meet at least once a week with the group either in-person or on Zoom. Future meeting details will be determined within a 24 hours window.
- Team members hosting the meeting will send out a reminder of the meeting with an agenda 2 hours before the meeting. - Team members hosting the meeting will send out a reminder of the meeting with an agenda 2 hours before the meeting.
@ -54,4 +62,5 @@
## Team Signatures ## Team Signatures
#### Print Name: #### Print Name:
#### Signature: #### Signature:

View File

@ -1,9 +1,11 @@
# **Hackers1995** # **Hackers1995**
## **Brand** ## **Brand**
![poster](./branding/teamposter.jpg) ![poster](./branding/teamposter.jpg)
## **Values** ## **Values**
- Openness - Openness
- Honesty - Honesty
- Respect - Respect
@ -11,63 +13,64 @@
- Diversity/Inclusion - Diversity/Inclusion
## **Roster** ## **Roster**
### **TA: Gagan Gopalaiah** ### **TA: Gagan Gopalaiah**
### **Team Lead: Rhea Bhutada** ### **Team Lead: Rhea Bhutada**
- #### About Me: - #### About Me:
- My name is Rhea Bhutada and I am currently a CS major and CogSci minor at ERC. The intersection between neuroscience and computer science really fascinates me and I generally try to apply myself to projects that deal with the overlap of both of these fields. This year I'm working as an undergraduate researcher at the Swartz Center for Computational Neuroscience, which has been an extremely cool experience. Other than that I love to stay active. I used to play basketball in high school and was in an NCAA commercial with Shaq. But lately, Ive been really into running. Overall, I'm excited to contribute to this project! Although I haven't had too much industry experience, I am interested to see how I can apply my previous course work to backend or frontend design. - My name is Rhea Bhutada and I am currently a CS major and CogSci minor at ERC. The intersection between neuroscience and computer science really fascinates me and I generally try to apply myself to projects that deal with the overlap of both of these fields. This year I'm working as an undergraduate researcher at the Swartz Center for Computational Neuroscience, which has been an extremely cool experience. Other than that I love to stay active. I used to play basketball in high school and was in an NCAA commercial with Shaq. But lately, Ive been really into running. Overall, I'm excited to contribute to this project! Although I haven't had too much industry experience, I am interested to see how I can apply my previous course work to backend or frontend design.
- #### Link to Github: https://github.com/rheabhutada02 - #### Link to Github: https://github.com/rheabhutada02
### **Team Lead: George Dubinin** ### **Team Lead: George Dubinin**
- #### About Me: - #### About Me:
- Hello World! I'm a fifth year (3rd year transfer) computer science major from the North Bay Area. Web development has been a big focus of mine since taking Prof Powell's 134B last winter and I'm stoked to be back in the "full stack" developer seat for 110. I am the second the team lead and in addition to my love for leading and working on team projects I am also fascinated by web development technologies including containerization, infrastructure as code (IaC), software as a service (SAAS), and web-based encryption (security). I am also an avid DJ and the traininer manmager for the DJ club on campus. This quarter is shaping up to be a memorable one! - Hello World! I'm a fifth year (3rd year transfer) computer science major from the North Bay Area. Web development has been a big focus of mine since taking Prof Powell's 134B last winter and I'm stoked to be back in the "full stack" developer seat for 110. I am the second the team lead and in addition to my love for leading and working on team projects I am also fascinated by web development technologies including containerization, infrastructure as code (IaC), software as a service (SAAS), and web-based encryption (security). I am also an avid DJ and the traininer manmager for the DJ club on campus. This quarter is shaping up to be a memorable one!
- #### Link to Github: https://github.com/look-its-ashton - #### Link to Github: https://github.com/look-its-ashton
### **Gavyn Ezell** ### **Gavyn Ezell**
- #### About Me: - #### About Me:
- My name is Gavyn Ezell and Im from Hawaii. Currently a 3rd year CS Major at Muir. I love video games, playing piano, and going to the gym. For SWE, backend interests me most (I am not good with design and visuals), and Im hoping to learn a lot more backend from this project! - My name is Gavyn Ezell and Im from Hawaii. Currently a 3rd year CS Major at Muir. I love video games, playing piano, and going to the gym. For SWE, backend interests me most (I am not good with design and visuals), and Im hoping to learn a lot more backend from this project!
- #### Link to Github: https://github.com/gavyn-ezell - #### Link to Github: https://github.com/gavyn-ezell
### **Daniel Hernandez** ### **Daniel Hernandez**
- #### About Me: - #### About Me:
- My name is Daniel Hernandez and I am a 3rd year Computer Science major and music minor. Some of my interests in the CS field are ML, AI, and Cybersecurity. Outside of school, I play drums for a local band. For SE, the backend aspect appeals to me the most since I am able to utilize more of what I learned from my past classes. However, I would want to try frontend since I do enjoy design to some extent. - My name is Daniel Hernandez and I am a 3rd year Computer Science major and music minor. Some of my interests in the CS field are ML, AI, and Cybersecurity. Outside of school, I play drums for a local band. For SE, the backend aspect appeals to me the most since I am able to utilize more of what I learned from my past classes. However, I would want to try frontend since I do enjoy design to some extent.
- #### Link to Github: https://github.com/d7hernan - #### Link to Github: https://github.com/d7hernan
### **Henry Feng** ### **Henry Feng**
- #### About Me: - #### About Me:
- My name is Henry, and I am a 3rd year CS major. I was born in China and grew up in New Zealand. I wrote my first line of code, in Python during my second year of high school. My favourite foods are ramen, steak and pasta. Some of my hobbies include playing guitar, hiking, cooking, video games, and music (from the Persona series). I am excited to start this project and hope to contribute to both frontend and backend. - My name is Henry, and I am a 3rd year CS major. I was born in China and grew up in New Zealand. I wrote my first line of code, in Python during my second year of high school. My favourite foods are ramen, steak and pasta. Some of my hobbies include playing guitar, hiking, cooking, video games, and music (from the Persona series). I am excited to start this project and hope to contribute to both frontend and backend.
- #### Link to Github: https://github.com/dusk-moon - #### Link to Github: https://github.com/dusk-moon
### **Kara Hoagland** ### **Kara Hoagland**
- #### About Me: - #### About Me:
- My name is Kara Hoagland and I am a 3rd year Computer Engineering major. CS-wise, I'm interested in topics such as computer vision and RFID, but it's hard to limit oneself because there's so many interesting topics out there. Outside of CS, I enjoy D&D, biking, and reading. I got some industry experience over summer and love getting to see how that experience and my previous classes all apply to this project. I'm interested in full stack but more so the backend of things. - My name is Kara Hoagland and I am a 3rd year Computer Engineering major. CS-wise, I'm interested in topics such as computer vision and RFID, but it's hard to limit oneself because there's so many interesting topics out there. Outside of CS, I enjoy D&D, biking, and reading. I got some industry experience over summer and love getting to see how that experience and my previous classes all apply to this project. I'm interested in full stack but more so the backend of things.
- #### Link to Github: https://github.com/KH-Cl - #### Link to Github: https://github.com/KH-Cl
### **Marc Reta** ### **Marc Reta**
- #### About Me: My name is Marc Reta and I am a 3rd year Computer Engineering major in Warren College. I love exploring San Diego and going on adventures. I have a huge interest in Public Transportation. I'm looking foward to working with everyone in my group and learn how to create an application. - #### About Me: My name is Marc Reta and I am a 3rd year Computer Engineering major in Warren College. I love exploring San Diego and going on adventures. I have a huge interest in Public Transportation. I'm looking foward to working with everyone in my group and learn how to create an application.
- #### Link to Github: https://github.com/Graydogminer - #### Link to Github: https://github.com/Graydogminer
### **Sanjit Joseph** ### **Sanjit Joseph**
- #### About Me: - #### About Me:
- Hi! My name is Sanjit Joseph and I'm a 3rd year CE major at Sixth. I'm from the Bay Area, so I've been surrounded by technology most of my life. I'm into building computers and I waste a lot of time (and money) messing with my PC and playing video games on it. I enjoy things outside of tech, though--as an Eagle Scout, I've done tons of backpacking throughout California and the US. I also hold a black belt in Shotokan Karate. As for this class, I'm pretty excited about all the different aspects of software engineering; frontend and backend both appeal to me, but I'm really just excited to work on a long class project in a team setting. - Hi! My name is Sanjit Joseph and I'm a 3rd year CE major at Sixth. I'm from the Bay Area, so I've been surrounded by technology most of my life. I'm into building computers and I waste a lot of time (and money) messing with my PC and playing video games on it. I enjoy things outside of tech, though--as an Eagle Scout, I've done tons of backpacking throughout California and the US. I also hold a black belt in Shotokan Karate. As for this class, I'm pretty excited about all the different aspects of software engineering; frontend and backend both appeal to me, but I'm really just excited to work on a long class project in a team setting.
- #### Link to Github: https://github.com/sm-joseph - #### Link to Github: https://github.com/sm-joseph
### **Isaac Otero** ### **Isaac Otero**
- #### About Me: - #### About Me:
- My name is Isaac Otero, I am a 5th year Cog Sci major. I am interested in front end development. I want to implement what Ive learned from my design classes into my projects for front end development. - My name is Isaac Otero, I am a 5th year Cog Sci major. I am interested in front end development. I want to implement what Ive learned from my design classes into my projects for front end development.
- #### Link to Github: https://github.com/Isaac-Otero - #### Link to Github: https://github.com/Isaac-Otero
### **Arthur Lu** ### **Arthur Lu**
- #### About Me: - #### About Me:
- My name is Arthur Lu and I am a 3rd year CE major. I am primarily interested in low level systems design, hardware development and optimization, and HPC architecture. I work as an undergraduate research assistant for Prof. Turakhia developing hardware accelerators for long length genome alignment. When Im not busy, I like to relax with some retro video games. - My name is Arthur Lu and I am a 3rd year CE major. I am primarily interested in low level systems design, hardware development and optimization, and HPC architecture. I work as an undergraduate research assistant for Prof. Turakhia developing hardware accelerators for long length genome alignment. When Im not busy, I like to relax with some retro video games.
- #### Link to Github: https://github.com/ltcptgeneral - #### Link to Github: https://github.com/ltcptgeneral

View File

@ -10,7 +10,6 @@
"lint-css": "stylelint **/*.css", "lint-css": "stylelint **/*.css",
"fix-css": "stylelint --fix **/*.css", "fix-css": "stylelint --fix **/*.css",
"http-server": "http-server source", "http-server": "http-server source",
"js-doc": "jsdoc -d source/docs/ -r source/",
"lint-prettier": "prettier --check .", "lint-prettier": "prettier --check .",
"fix-prettier": "prettier --write ." "fix-prettier": "prettier --write ."
}, },
@ -18,12 +17,11 @@
"eslint": "^8.27.0", "eslint": "^8.27.0",
"htmlhint": "1.1.4", "htmlhint": "1.1.4",
"http-server": "", "http-server": "",
"jsdoc": "^4.0.0",
"mocha": "10", "mocha": "10",
"mock-local-storage": "^1.1.23", "mock-local-storage": "^1.1.23",
"prettier": "2.8.0",
"puppeteer": "^18.2.1", "puppeteer": "^18.2.1",
"stylelint": "14.14.1", "stylelint": "14.14.1",
"stylelint-config-standard": "^29.0.0", "stylelint-config-standard": "^29.0.0"
"prettier": "2.8.0"
} }
} }

View File

@ -1,6 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
@ -8,12 +7,11 @@
<title>Food Journal</title> <title>Food Journal</title>
<!--Add Favicon--> <!--Add Favicon-->
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico"> <link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
<!-- Review Card Custom Element --> <!-- Review Card Custom Element -->
<script src="assets/scripts/ReviewCard.js" type="module"></script> <script src="assets/scripts/ReviewCard.js" type="module"></script>
<!-- Create Page Stylesheets & Scripts --> <!-- Create Page Stylesheets & Scripts -->
<link rel="stylesheet" href="./static/CreatePage.css" /> <link rel="stylesheet" href="./static/CreatePage.css" />
<link rel="stylesheet" href="./static/Form.css" /> <link rel="stylesheet" href="./static/Form.css" />
@ -34,31 +32,34 @@
<h1>New Entry</h1> <h1>New Entry</h1>
<form id="new-food-entry"> <form id="new-food-entry">
<fieldset> <fieldset>
<legend>PICTURE:</legend> <legend>PICTURE:</legend>
<select id="select" name="select"> <select id="select" name="select">
<option value="file">File Upload</option> <option value="file">File Upload</option>
<option value="url">From an URL</option> <option value="photo">Take a Photo</option>
</select> </select>
<label for="mealImage" id="source"> <input type="file" accept="image/*" id="mealImg" name="mealImg" />
<input type="file" accept="image/*" id="mealImg" name="mealImg"> </fieldset>
</label>
<fieldset>
<video id="player" width="320" height="240" autoplay hidden></video>
<canvas id="photoCanvas" width="320" height="240" hidden></canvas>
<button type="button" id="photoButton" hidden>Take Photo</button>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>MEAL NAME:</legend> <legend>MEAL NAME:</legend>
<label for="Name: "> <input type="text" id="mealName" name="mealName" required> </label> <label for="Name: "> <input type="text" id="mealName" name="mealName" required /> </label>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>RESTAURANT NAME:</legend> <legend>RESTAURANT NAME:</legend>
<label for="Name:"> <input type="text" id="restaurant" name="restaurant" required> </label> <label for="Name:"> <input type="text" id="restaurant" name="restaurant" required /> </label>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>RATING:</legend> <legend>RATING:</legend>
<div style="display: flex; justify-content: flex-start; align-items: center;"> <div style="display: flex; justify-content: flex-start; align-items: center">
<div class="rating"> <div class="rating">
<input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label> <input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label>
<input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label> <input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label>
@ -71,24 +72,22 @@
<fieldset> <fieldset>
<legend>COMMENTS:</legend> <legend>COMMENTS:</legend>
<textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%;"></textarea> <textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%"></textarea>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>TAGS: (ex. cuisine, distance, cost, etc)</legend> <legend>TAGS: (ex. cuisine, distance, cost, etc)</legend>
<input type="text" id="tag-form" name="tag-form"> <input type="text" id="tag-form" name="tag-form" />
<div class='tag-container' id="tag-container-form"> <div class="tag-container" id="tag-container-form"></div>
</div>
<button type="button" id="tag-add-btn">+</button> <button type="button" id="tag-add-btn">+</button>
</fieldset> </fieldset>
<button type="submit" id="save-btn" value="Submit">Save</button> <button type="submit" id="save-btn" value="Submit">Save</button>
<!-- Button that allows user to go back to the homepage --> <!-- Button that allows user to go back to the homepage -->
<input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')"> <input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')" />
</form> </form>
</div> </div>
</body> </body>
</html> </html>

View File

@ -7,7 +7,7 @@
<title>Food Journal</title> <title>Food Journal</title>
<!--Add Favicon--> <!--Add Favicon-->
<link rel="icon" type="image/x-icon" href="./assets/images/icons/favicon.ico"> <link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
<!-- Review Card Custom Element --> <!-- Review Card Custom Element -->
<script src="assets/scripts/ReviewCard.js" type="module"></script> <script src="assets/scripts/ReviewCard.js" type="module"></script>
@ -32,32 +32,54 @@
<div class="journal-form" id="review-details"> <div class="journal-form" id="review-details">
<form> <form>
<fieldset class="meal-name"> <fieldset class="meal-name">
<h1 id="d-mealName" style="font-family: Century Gothic;"></h1> <h1 id="d-meal-name" style="font-family: Century Gothic"></h1>
<h1 id="d-restaurant" style="font-family: Century Gothic; font-size: 30px;"></h1> <h1 id="d-restaurant" style="font-family: Century Gothic; font-size: 30px"></h1>
</fieldset> </fieldset>
<fieldset class="meal-pics"> <fieldset class="meal-pics">
<!-- image source --> <!-- image source -->
<img width=40% height=40% id="d-mealImg" style="margin-left: auto; margin-right: auto; display: block;"/> <img width="40%" height="40%" id="d-meal-img" style="margin-left: auto; margin-right: auto; display: block" />
</fieldset> </fieldset>
<fieldset class = "stars-and-comments" style="text-align: center;"> <fieldset class="stars-and-comments" style="text-align: center">
<img width=30% height=30% id="d-rating" style="margin-left: auto; margin-right: auto; display: block;"/> <img width="30%" height="30%" id="d-rating" style="margin-left: auto; margin-right: auto; display: block" />
<p id="d-comments"></p> <p id="d-comments"></p>
</fieldset> </fieldset>
<fieldset class="meal-tags"> <fieldset class="meal-tags">
<div class = "tag-container" id="d-tags" style="justify-content: center;"></div> <div class="tag-container" id="d-tags" style="justify-content: center"></div>
</fieldset> </fieldset>
</form> </form>
</div> </div>
<!---Navigation Buttons--> <!---Navigation Buttons-->
<div style="display: flex; justify-content: center;"> <div style="display: flex; justify-content: center">
<img src="./assets/images/home_button_for_interface.png" style="margin: 20px 10px 20px 10px;" id="home-btn" onclick="window.location.assign('./index.html')" height="50" width="50"/> <img
<img src ="./assets/images/edit_button_for_interface.png" style="margin: 20px 10px 20px 10px;" id="update-btn" height="50" width="50"/> src="./assets/images/home_button_for_interface.png"
<img src ="./assets/images/delete_icon_for_interface.png" style="margin: 20px 10px 20px 10px;" id="delete-btn" class="danger" height="50" width="50"/> style="margin: 20px 10px 20px 10px"
id="home-btn"
title="Home Page"
onclick="window.location.assign('./index.html')"
height="50"
width="50"
/>
<img
src="./assets/images/edit_button_for_interface.png"
style="margin: 20px 10px 20px 10px"
id="update-btn"
title="Edit Review"
height="50"
width="50"
/>
<img
src="./assets/images/delete_icon_for_interface.png"
style="margin: 20px 10px 20px 10px"
id="delete-btn"
title="Delete Review"
class="danger"
height="50"
width="50"
/>
</div> </div>
</main> </main>
@ -65,31 +87,34 @@
<h1>Update Entry</h1> <h1>Update Entry</h1>
<form id="new-food-entry"> <form id="new-food-entry">
<fieldset> <fieldset>
<legend>PICTURE:</legend> <legend>PICTURE:</legend>
<select id="select" name="select"> <select id="select" name="select">
<option value="file">File Upload</option> <option value="file">File Upload</option>
<option value="url">From an URL</option> <option value="photo">Take a Photo</option>
</select> </select>
<label for="mealImage" id="source"> <input type="file" accept="image/*" id="mealImg" name="mealImg" />
<input type="file" accept="image/*" id="mealImg" name="mealImg"> </fieldset>
</label>
<fieldset>
<video id="player" width="320" height="240" autoplay hidden></video>
<canvas id="photoCanvas" width="320" height="240" hidden></canvas>
<button type="button" id="photoButton" hidden>Take Photo</button>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>MEAL NAME:</legend> <legend>MEAL NAME:</legend>
<label for="Name: "> <input type="text" id="mealName" name="mealName" required> </label> <label for="Name: "> <input type="text" id="mealName" name="mealName" required /> </label>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>RESTAURANT NAME:</legend> <legend>RESTAURANT NAME:</legend>
<label for="Name:"> <input type="text" id="restaurant" name="restaurant" required> </label> <label for="Name:"> <input type="text" id="restaurant" name="restaurant" required /> </label>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>RATING:</legend> <legend>RATING:</legend>
<div style="display: flex; justify-content: flex-start; align-items: center;"> <div style="display: flex; justify-content: flex-start; align-items: center">
<div class="rating"> <div class="rating">
<input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label> <input type="radio" id="s5" name="rating" value="5" /> <label for="s5" id="s5-select"> 5 stars </label>
<input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label> <input type="radio" id="s4" name="rating" value="4" /> <label for="s4" id="s4-select"> 4 stars </label>
@ -102,20 +127,19 @@
<fieldset> <fieldset>
<legend>COMMENTS:</legend> <legend>COMMENTS:</legend>
<textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%;"></textarea> <textarea name="comments" id="comments" rows="5" style="resize: none; width: 100%"></textarea>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>TAGS: (ex. cuisine, distance, cost, etc)</legend> <legend>TAGS: (ex. cuisine, distance, cost, etc)</legend>
<input type="text" id="tag-form" name="tag-form"> <input type="text" id="tag-form" name="tag-form" />
<div class='tag-container' id="tag-container-form"> <div class="tag-container" id="tag-container-form"></div>
</div>
<button type="button" id="tag-add-btn">+</button> <button type="button" id="tag-add-btn">+</button>
</fieldset> </fieldset>
<button type="submit" id="save-btn" value="Submit">Save</button> <button type="submit" id="save-btn" value="Submit">Save</button>
<input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')"> <input type="button" value="Cancel" id="home-btn" onclick="window.location.assign('./index.html')" />
</form> </form>
</div> </div>
</body> </body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 KiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -6,58 +6,103 @@ window.addEventListener("DOMContentLoaded", init);
* Delegates the functionality for creating review cards. * Delegates the functionality for creating review cards.
*/ */
function init() { function init() {
initFormHandler(); initFormHandler();
} }
/** /**
* Creates a form and associates a new ID with the new review card. * Creates a form and associates a new ID with the new review card.
*/ */
function initFormHandler() { function initFormHandler() {
// Accesses form components // Accesses form components
let tagContainer = document.getElementById("tag-container-form"); let tagContainer = document.getElementById("tag-container-form");
let form = document.querySelector("form"); let form = document.querySelector("form");
// Event listener for reading form data // Declaring variable storing image data url
let select = document.getElementById("select"); let imgDataURL = "";
select.addEventListener("change", function() {
const input = document.getElementById("source");
// Accessing components related to taking photo
let videoMode = true;
let player = document.getElementById("player");
let canvas = document.getElementById("photoCanvas");
let photoButton = document.getElementById("photoButton");
let context = canvas.getContext("2d");
// Event listener for the photo taking/reset button
photoButton.addEventListener("click", () => {
// capturing the current video frame
if (videoMode) {
videoMode = false;
// setting up the appropriate components for displaying the photo preview
photoButton.innerText = "Retake";
player.setAttribute("hidden", "");
canvas.removeAttribute("hidden", "");
// displaying the captured snapshot on a canvas and saving it as a data url
context.drawImage(player, 0, 0, canvas.width, canvas.height);
imgDataURL = canvas.toDataURL();
}
// returning to displaying the video stream
else {
videoMode = true;
// setting up the appropriate components for the video stream
photoButton.innerText = "Take Photo";
canvas.setAttribute("hidden", "");
player.removeAttribute("hidden", "");
}
});
// Event listener for reading image form different data
let select = document.getElementById("select");
const input = document.getElementById("mealImg");
select.addEventListener("change", function () {
// Select a photo with HTML file selector // Select a photo with HTML file selector
if (select.value == "file") { if (select.value == "file") {
input.innerHTML = ` // enabling file upload components and hiding photo taking components
Source: input.removeAttribute("hidden", "");
<input type="file" accept="image/*" id="mealImg" name="mealImg"> player.setAttribute("hidden", "");
`; canvas.setAttribute("hidden", "");
photoButton.setAttribute("hidden", "");
// stopping the video stream
player.srcObject.getVideoTracks()[0].stop();
} }
// Upload text URL input // Take a photo
else { else {
input.innerHTML = ` // enabling photo taking components and hiding file upload components
Source: videoMode = true;
<input type="text" id="mealImg" name="mealImg"> photoButton.innerText = "Take Photo";
`; input.setAttribute("hidden", "");
player.removeAttribute("hidden", "");
photoButton.removeAttribute("hidden", "");
// getting video stream from user's camera then displaying it on a video element
navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
player.srcObject = stream;
});
} }
}); });
// Addresses sourcing image from local file // Addresses sourcing image from local file
let imgDataURL = "";
document.getElementById("mealImg").addEventListener("change", function () { document.getElementById("mealImg").addEventListener("change", function () {
const reader = new FileReader(); const reader = new FileReader();
// Store image data URL after successful image load // Store image data URL after successful image load
reader.addEventListener("load", ()=>{ reader.addEventListener(
"load",
() => {
imgDataURL = reader.result; imgDataURL = reader.result;
}, false); },
false
);
// Convert image file into data URL for local storage // Convert image file into data URL for local storage
reader.readAsDataURL(document.getElementById("mealImg").files[0]); reader.readAsDataURL(document.getElementById("mealImg").files[0]);
}); });
form.addEventListener("submit", function (e) { form.addEventListener("submit", function (e) {
// Create reviewObject and put in storage // Create reviewObject and put in storage
e.preventDefault(); e.preventDefault();
let formData = new FormData(form); let formData = new FormData(form);
@ -70,14 +115,13 @@ function initFormHandler() {
if (`${key}` !== "tag-form") { if (`${key}` !== "tag-form") {
reviewObject[`${key}`] = `${value}`; reviewObject[`${key}`] = `${value}`;
} }
if (`${key}` === "mealImg" && select.value == "file") { if (`${key}` === "mealImg" && imgDataURL !== "") {
reviewObject["mealImg"] = imgDataURL; reviewObject["mealImg"] = imgDataURL;
} }
} }
// Makes sure that ratings is filled // Makes sure that ratings is filled
if (reviewObject["rating"] != null) { if (reviewObject["rating"] != null) {
//Adds rags separately as an array //Adds rags separately as an array
reviewObject["tags"] = []; reviewObject["tags"] = [];
@ -99,30 +143,33 @@ function initFormHandler() {
else { else {
window.alert("NO! FILL IN STARS"); window.alert("NO! FILL IN STARS");
} }
}); });
// Event listener for tag functionality // Event listener for tag functionality
let tagAddBtn = document.getElementById("tag-add-btn"); let tagAddBtn = document.getElementById("tag-add-btn");
//Set used to track tags and ensure no duplicates
let tagSet = new Set();
tagAddBtn.addEventListener("click", () => { tagAddBtn.addEventListener("click", () => {
let tagField = document.getElementById("tag-form"); let tagField = document.getElementById("tag-form");
// If there is a tag, it'll display the tag // If there is a tag, it'll display the tag
if (tagField.value.length > 0) { if (tagField.value.length > 0) {
let tagSetVal = tagField.value.toLocaleLowerCase();
if (!tagSet.has(tagSetVal)) {
let tagLabel = document.createElement("label"); let tagLabel = document.createElement("label");
tagLabel.innerHTML = tagField.value; tagLabel.innerHTML = tagField.value;
tagLabel.setAttribute("class", "tag"); tagLabel.setAttribute("class", "tag");
tagSet.add(tagSetVal);
// Allows for user to delete the tag
tagLabel.addEventListener("click", () => { tagLabel.addEventListener("click", () => {
tagContainer.removeChild(tagLabel); tagContainer.removeChild(tagLabel);
tagSet.delete(tagSetVal);
}); });
// Adds the tag
tagContainer.append(tagLabel); tagContainer.append(tagLabel);
} else {
window.alert("No duplicate tags allowed");
}
tagField.value = ""; tagField.value = "";
} }
}); });
} }

View File

@ -16,7 +16,7 @@ class ReviewCard extends HTMLElement {
font-family: Century Gothic; font-family: Century Gothic;
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow-wrap: anywhere; cursor: pointer;
} }
a { a {
@ -31,18 +31,15 @@ class ReviewCard extends HTMLElement {
align-items: center; align-items: center;
border: 2px solid rgb(31, 41, 32); border: 2px solid rgb(31, 41, 32);
border-radius: 8px; border-radius: 8px;
display: grid;
grid-template-rows: 118px 56px 14px 18px 15px 36px;
height: auto; height: auto;
row-gap: 5px; row-gap: 5px;
padding: 0 16px 16px 16px; padding: 0 16px 16px 16px;
width: 178px; width: 200px;
margin: 8px 8px 8px 8px; margin: 8px 8px 8px 8px;
} }
div.rating { div.rating {
align-items: center; align-items: center;
column-gap: 5px;
display: flex; display: flex;
} }
@ -50,30 +47,30 @@ class ReviewCard extends HTMLElement {
height: auto; height: auto;
display: inline-block; display: inline-block;
object-fit: scale-down; object-fit: scale-down;
width: 78px;
} }
article>img { article>img {
border-top-left-radius: 6px; border-top-left-radius: 6px;
border-top-right-radius: 6px; border-top-right-radius: 6px;
height: 119px; height: 120px;
object-fit: cover; object-fit: cover;
margin-left: -16px; margin-left: -16px;
margin-right: -16px;
width: calc(100% + 32px); width: calc(100% + 32px);
} }
.meal-name-div {
height: 54px;
overflow: hidden;
}
label.restaurant-name { label.restaurant-name {
color: black !important; color: black !important;
} }
label.meal-name { label.meal-name {
display: -webkit-box; font-size: 24px;
font-size: 16px;
height: 36px; height: 36px;
line-height: 18px;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
} }
label:not(.meal-name), label:not(.meal-name),
@ -83,20 +80,27 @@ class ReviewCard extends HTMLElement {
font-size: 12px; font-size: 12px;
} }
.tag-container { .tag-container-div {
margin-top: 20px; margin-top: 20px;
height: 100px;
overflow: hidden;
}
.tag-container {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
height: fit-content;
} }
.a-tag { .a-tag {
background-color:#94da97; background-color:#94da97;
border-radius: 7px; border-radius: 6px;
color: #94da97; color: #94da97;
padding-right: 7px; padding: 0px 6px 2px 6px;
padding-left: 7px; margin: 2px 2px 2px 2px;
margin: 3px;
font-weight: bold; font-weight: bold;
overflow: hidden;
height: 14px;
} }
`; `;
articleEl.append(styleEl); articleEl.append(styleEl);
@ -145,19 +149,22 @@ class ReviewCard extends HTMLElement {
// Image setup // Image setup
let mealImg = document.createElement("img"); let mealImg = document.createElement("img");
mealImg.setAttribute("id", "a-mealImg"); mealImg.setAttribute("id", "a-meal-img");
mealImg.setAttribute("alt", "Meal Photo Corrupted"); mealImg.setAttribute("alt", "Meal Photo Corrupted");
mealImg.setAttribute("src", data["mealImg"]); mealImg.setAttribute("src", data["mealImg"]);
mealImg.addEventListener("error", function (e) { mealImg.addEventListener("error", function (e) {
mealImg.setAttribute("src", "./assets/images/plate_with_cutlery.png"); mealImg.setAttribute("src", "./assets/images/default_plate.png");
e.onerror = null; e.onerror = null;
}); });
// Meal name setup // Meal name setup
let meallabelDiv = document.createElement("div");
meallabelDiv.setAttribute("class", "meal-name-div");
let mealLabel = document.createElement("label"); let mealLabel = document.createElement("label");
mealLabel.setAttribute("id", "a-mealName"); mealLabel.setAttribute("id", "a-meal-name");
mealLabel.setAttribute("class", "meal-name"); mealLabel.setAttribute("class", "meal-name");
mealLabel.innerHTML = data["mealName"]; mealLabel.innerHTML = data["mealName"];
meallabelDiv.append(mealLabel);
// Restaurant name setup // Restaurant name setup
let restaurantLabel = document.createElement("label"); let restaurantLabel = document.createElement("label");
@ -182,6 +189,8 @@ class ReviewCard extends HTMLElement {
ratingDiv.append(starsImg); ratingDiv.append(starsImg);
// Tags setup // Tags setup
let tagContainerDiv = document.createElement("div");
tagContainerDiv.setAttribute("class", "tag-container-div");
let tagContainer = document.createElement("div"); let tagContainer = document.createElement("div");
tagContainer.setAttribute("class", "tag-container"); tagContainer.setAttribute("class", "tag-container");
tagContainer.setAttribute("id", "a-tags"); tagContainer.setAttribute("id", "a-tags");
@ -196,16 +205,15 @@ class ReviewCard extends HTMLElement {
tagContainer.append(newTag); tagContainer.append(newTag);
} }
} }
tagContainerDiv.append(tagContainer);
// Setting all the data to the review card // Setting all the data to the review card
articleEl.append(mealImg); articleEl.append(mealImg);
articleEl.append(mealLabel); articleEl.append(meallabelDiv);
articleEl.append(restaurantLabel); articleEl.append(restaurantLabel);
articleEl.append(ratingDiv); articleEl.append(ratingDiv);
articleEl.append(tagContainer); articleEl.append(tagContainerDiv);
articleEl.append(comments); articleEl.append(comments);
} }
/** /**
@ -228,18 +236,17 @@ class ReviewCard extends HTMLElement {
* } * }
*/ */
get data() { get data() {
let dataContainer = {}; let dataContainer = {};
// Getting the article elements for the review card // Getting the article elements for the review card
dataContainer["reviewID"] = this.reviewID; dataContainer["reviewID"] = this.reviewID;
// Get image //get image
let mealImg = this.shadowEl.getElementById("a-mealImg"); let mealImg = this.shadowEl.getElementById("a-meal-img");
dataContainer["mealImg"] = mealImg.getAttribute("src"); dataContainer["mealImg"] = mealImg.getAttribute("src");
// Get meal name //get meal name
let mealLabel = this.shadowEl.getElementById("a-mealName"); let mealLabel = this.shadowEl.getElementById("a-meal-name");
dataContainer["mealName"] = mealLabel.innerHTML; dataContainer["mealName"] = mealLabel.innerHTML;
// Get comment section // Get comment section

View File

@ -13,20 +13,23 @@ function init(){
setupUpdate(); setupUpdate();
} }
/**
* Populates the relevant data to the details from local storage review
*/
function setupInfo() { function setupInfo() {
let currID = JSON.parse(sessionStorage.getItem("currID")); let currID = JSON.parse(sessionStorage.getItem("currID"));
let currReview = getReviewFromStorage(currID); let currReview = getReviewFromStorage(currID);
//meal image //meal image
let mealImg = document.getElementById("d-mealImg"); let mealImg = document.getElementById("d-meal-img");
mealImg.setAttribute("src", currReview["mealImg"]); mealImg.setAttribute("src", currReview["mealImg"]);
mealImg.addEventListener("error", function (e) { mealImg.addEventListener("error", function (e) {
mealImg.setAttribute("src", "./assets/images/plate_with_cutlery.png"); mealImg.setAttribute("src", "./assets/images/default_plate.png");
e.onerror = null; e.onerror = null;
}); });
//meal name //meal name
let mealLabel = document.getElementById("d-mealName"); let mealLabel = document.getElementById("d-meal-name");
mealLabel.innerHTML = currReview["mealName"]; mealLabel.innerHTML = currReview["mealName"];
//restaurant name //restaurant name
@ -92,67 +95,128 @@ function setupUpdate(){
document.getElementById("s" + `${currReview["rating"]}`).checked = true; document.getElementById("s" + `${currReview["rating"]}`).checked = true;
document.getElementById("restaurant").defaultValue = currReview["restaurant"]; document.getElementById("restaurant").defaultValue = currReview["restaurant"];
//Set used to track tags and ensure no duplicates
let tagSet = new Set();
if (currReview["tags"]) { if (currReview["tags"]) {
while (tagContainer.firstChild) { while (tagContainer.firstChild) {
tagContainer.removeChild(tagContainer.firstChild); tagContainer.removeChild(tagContainer.firstChild);
} }
let tagSetVal;
for (let i = 0; i < currReview["tags"].length; i++) { for (let i = 0; i < currReview["tags"].length; i++) {
tagSetVal = currReview["tags"][i].toLocaleLowerCase();
tagSet.add(tagSetVal);
let newTag = document.createElement("label"); let newTag = document.createElement("label");
newTag.setAttribute("class", "tag"); newTag.setAttribute("class", "tag");
newTag.innerHTML = currReview["tags"][i]; newTag.innerHTML = currReview["tags"][i];
newTag.addEventListener("click", () => { newTag.addEventListener("click", () => {
tagContainer.removeChild(newTag); tagContainer.removeChild(newTag);
tagSet.delete(tagSetVal);
}); });
tagContainer.append(newTag); tagContainer.append(newTag);
} }
} }
// Declaring variable storing image data url
let imgDataURL = "";
// Accessing components related to taking photo
let videoMode = true;
let player = document.getElementById("player");
let canvas = document.getElementById("photoCanvas");
let photoButton = document.getElementById("photoButton");
let context = canvas.getContext("2d");
// Event listener for the photo taking/reset button
photoButton.addEventListener("click", () => {
// capturing the current video frame
if (videoMode) {
videoMode = false;
// setting up the appropriate components for displaying the photo preview
photoButton.innerText = "Retake";
player.setAttribute("hidden", "");
canvas.removeAttribute("hidden", "");
// displaying the captured snapshot on a canvas and saving it as a data url
context.drawImage(player, 0, 0, canvas.width, canvas.height);
imgDataURL = canvas.toDataURL();
}
// returning to displaying the video stream
else {
videoMode = true;
// setting up the appropriate components for the video stream
photoButton.innerText = "Take Photo";
canvas.setAttribute("hidden", "");
player.removeAttribute("hidden", "");
}
});
/* /*
* change the input source of the image between local file and URL * change the input source of the image between local file and taking photo
* depending on user's selection * depending on user's selection
*/ */
let select = document.getElementById("select"); let select = document.getElementById("select");
const input = document.getElementById("mealImg");
select.addEventListener("change", function () { select.addEventListener("change", function () {
const input = document.getElementById("source"); console.log("1");
// Select a photo with HTML file selector
if (select.value == "file") { if (select.value == "file") {
input.innerHTML = ` // enabling file upload components and hiding photo taking components
Source: input.removeAttribute("hidden", "");
<input type="file" accept="image/*" id="mealImg" name="mealImg"> player.setAttribute("hidden", "");
`; canvas.setAttribute("hidden", "");
photoButton.setAttribute("hidden", "");
// stopping the video stream
player.srcObject.getVideoTracks()[0].stop();
} }
//TODO: change to photo taking for sprint 3
// Take a photo
else { else {
input.innerHTML = ` // enabling photo taking components and hiding file upload components
Source: videoMode = true;
<input type="text" id="mealImg" name="mealImg"> photoButton.innerText = "Take Photo";
`; input.setAttribute("hidden", "");
player.removeAttribute("hidden", "");
photoButton.removeAttribute("hidden", "");
// getting video stream from user's camera then displaying it on a video element
navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => {
player.srcObject = stream;
});
} }
}); });
//addressing sourcing image from local file //addressing sourcing image from local file
let imgDataURL = "";
document.getElementById("mealImg").addEventListener("change", function () { document.getElementById("mealImg").addEventListener("change", function () {
console.log("reading used"); console.log("reading used");
const reader = new FileReader(); const reader = new FileReader();
//store image data URL after successful image load //store image data URL after successful image load
reader.addEventListener("load", ()=>{ reader.addEventListener(
"load",
() => {
imgDataURL = reader.result; imgDataURL = reader.result;
}, false); },
false
);
//convert image file into data URL for local storage //convert image file into data URL for local storage
reader.readAsDataURL(document.getElementById("mealImg").files[0]); reader.readAsDataURL(document.getElementById("mealImg").files[0]);
}); });
//Take formdata values as newData when submit //Take formdata values as newData when submit
form.addEventListener("submit", function () { form.addEventListener("submit", function () {
//We create reviewCard datea, replace it in in storage, and update tags /*
* User submits the form for their review.
* We create reviewCard data, replace in storage, and update tags
*/
let formData = new FormData(form); let formData = new FormData(form);
let newData = {}; let newData = {};
//iterate through formData and add to newData
// Iterate through formData an add to newData
for (let [key, value] of formData) { for (let [key, value] of formData) {
console.log(`${key}`); console.log(`${key}`);
console.log(`${value}`); console.log(`${value}`);
@ -160,10 +224,9 @@ function setupUpdate(){
newData[`${key}`] = `${value}`; newData[`${key}`] = `${value}`;
} }
// Account for the case where image is not updated // Account for the case where image is not updated
if (`${key}` === "mealImg" && document.getElementById("mealImg").value === "") { if (`${key}` === "mealImg" && imgDataURL === "") {
newData["mealImg"] = currReview["mealImg"]; newData["mealImg"] = currReview["mealImg"];
} } else if (`${key}` === "mealImg") {
else if (`${key}` === "mealImg" && select.value == "file") {
newData["mealImg"] = imgDataURL; newData["mealImg"] = imgDataURL;
} }
} }
@ -180,7 +243,6 @@ function setupUpdate(){
updateReviewToStorage(currID, newData); updateReviewToStorage(currID, newData);
updateDiv.classList.add("hidden"); updateDiv.classList.add("hidden");
}); });
// Adding tag to form functionality // Adding tag to form functionality
@ -188,14 +250,21 @@ function setupUpdate(){
tagAddBtn.addEventListener("click", () => { tagAddBtn.addEventListener("click", () => {
let tagField = document.getElementById("tag-form"); let tagField = document.getElementById("tag-form");
if (tagField.value.length > 0) { if (tagField.value.length > 0) {
let tagSetVal = tagField.value.toLocaleLowerCase();
if (!tagSet.has(tagSetVal)) {
let tagLabel = document.createElement("label"); let tagLabel = document.createElement("label");
tagLabel.innerHTML = tagField.value; tagLabel.innerHTML = tagField.value;
tagLabel.setAttribute("class", "tag"); tagLabel.setAttribute("class", "tag");
tagSet.add(tagSetVal);
tagLabel.addEventListener("click", () => { tagLabel.addEventListener("click", () => {
tagContainer.removeChild(tagLabel); tagContainer.removeChild(tagLabel);
tagSet.delete(tagSetVal);
}); });
tagContainer.append(tagLabel); tagContainer.append(tagLabel);
} else {
window.alert("No duplicate tags allowed");
}
tagField.value = ""; tagField.value = "";
} }
}); });

View File

@ -6,11 +6,10 @@ import {strict as assert} from "node:assert";
* @param {Object} review review data to input into the form * @param {Object} review review data to input into the form
*/ */
export async function setReviewForm(page, review) { export async function setReviewForm(page, review) {
// Set text fields // Set text fields
await page.$eval("#mealName", (el, value) => el.value = value, review.mealName); await page.$eval("#mealName", (el, value) => (el.value = value), review.mealName);
await page.$eval("#comments", (el, value) => el.value = value, review.comments); await page.$eval("#comments", (el, value) => (el.value = value), review.comments);
await page.$eval("#restaurant", (el, value) => el.value = value, review.restaurant); await page.$eval("#restaurant", (el, value) => (el.value = value), review.restaurant);
// Get all tag elements and click them to delete them // Get all tag elements and click them to delete them
let tag_items = await page.$$(".tag"); let tag_items = await page.$$(".tag");
@ -23,7 +22,7 @@ export async function setReviewForm(page, review) {
// Get the button needed to add new tags // Get the button needed to add new tags
let tag_btn = await page.$("#tag-add-btn"); let tag_btn = await page.$("#tag-add-btn");
for (let i = 0; i < review.tags.length; i++) { for (let i = 0; i < review.tags.length; i++) {
await page.$eval("#tag-form", (el, value) => el.value = value, review.tags[i]); await page.$eval("#tag-form", (el, value) => (el.value = value), review.tags[i]);
await tag_btn.click(); await tag_btn.click();
} }
@ -40,13 +39,13 @@ export async function setReviewForm(page, review) {
*/ */
export async function checkCorrectness(root, prefix, expected) { export async function checkCorrectness(root, prefix, expected) {
// Get the review image and check src // Get the review image and check src
let img = await root.$(`#${prefix}-mealImg`); let img = await root.$(`#${prefix}-meal-img`);
let imgSrc = await img.getProperty("src"); let imgSrc = await img.getProperty("src");
// Check src // Check src
assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc); assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc);
// Get the title, comment, and restaurant // Get the title, comment, and restaurant
let title = await root.$(`#${prefix}-mealName`); let title = await root.$(`#${prefix}-meal-name`);
let title_text = await title.getProperty("innerText"); let title_text = await title.getProperty("innerText");
let comment = await root.$(`#${prefix}-comments`); let comment = await root.$(`#${prefix}-comments`);
let comment_text = await comment.getProperty("innerText"); let comment_text = await comment.getProperty("innerText");

View File

@ -11,6 +11,17 @@ export function newReviewToStorage(review){
// set the review entry to the review object // set the review entry to the review object
localStorage.setItem(`review${nextReviewId}`, JSON.stringify(review)); localStorage.setItem(`review${nextReviewId}`, JSON.stringify(review));
// adding to the tag keys
addTagsToStorage(nextReviewId, review["tags"]);
//adding to the star storage
let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`));
if (!starArr) {
starArr = [];
}
starArr.push(nextReviewId);
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr));
//updating our activeIDS list //updating our activeIDS list
let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); let tempIdArr = JSON.parse(localStorage.getItem("activeIDS"));
tempIdArr.push(nextReviewId); tempIdArr.push(nextReviewId);
@ -37,6 +48,78 @@ export function getReviewFromStorage(ID){
* @param {Object} review to store * @param {Object} review to store
*/ */
export function updateReviewToStorage(ID, review) { export function updateReviewToStorage(ID, review) {
let oldReview = JSON.parse(localStorage.getItem(`review${ID}`));
let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`));
//activeID update recency
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
for (let i in activeIDS) {
if (activeIDS[i] == ID) {
activeIDS.splice(i, 1);
activeIDS.push(ID);
break;
}
}
localStorage.setItem("activeIDS", JSON.stringify(activeIDS));
//star local storage update
if (oldReview["rating"] !== review["rating"]) {
//first delete from previous rating array in storage
let oldStarArr = JSON.parse(localStorage.getItem(`star${oldReview["rating"]}`));
for (let i in oldStarArr) {
if (oldStarArr[i] == ID) {
//removing from corresponding rating array and updating local Storage
oldStarArr.splice(i, 1);
break;
}
}
if (oldStarArr.length != 0) {
localStorage.setItem(`star${oldReview["rating"]}`, JSON.stringify(oldStarArr));
} else {
localStorage.removeItem(`star${oldReview["rating"]}`);
}
//then add ID to array corresponding to new review rating
let newStarArr = starArr;
if (!newStarArr) {
newStarArr = [];
}
newStarArr.push(ID);
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(newStarArr));
} else if (starArr.length !== 1) {
//stars update recency if unchanged
for (let i in starArr) {
if (starArr[i] == ID) {
starArr.splice(i, 1);
starArr.push(ID);
break;
}
}
localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr));
}
//specifically the unchanged tags update recency
let repeatedTags = review["tags"].filter((x) => oldReview["tags"].includes(x));
let tagArr = [];
for (let i in repeatedTags) {
tagArr = JSON.parse(localStorage.getItem(`!${repeatedTags[i].toLocaleLowerCase()}`));
if (tagArr.length !== 1) {
for (let j in tagArr) {
if (tagArr[j] == ID) {
tagArr.splice(j, 1);
tagArr.push(ID);
break;
}
}
localStorage.setItem(`!${repeatedTags[i].toLocaleLowerCase()}`, JSON.stringify(tagArr));
}
}
//Get diff of tags and update storage
let deletedTags = oldReview["tags"].filter((x) => !review["tags"].includes(x));
let addedTags = review["tags"].filter((x) => !oldReview["tags"].includes(x));
deleteTagsFromStorage(ID, deletedTags);
addTagsToStorage(ID, addedTags);
// set the review entry with ID to the review object // set the review entry with ID to the review object
localStorage.setItem(`review${ID}`, JSON.stringify(review)); localStorage.setItem(`review${ID}`, JSON.stringify(review));
} }
@ -46,12 +129,31 @@ export function updateReviewToStorage(ID, review){
* @param {string} ID of the review to delete * @param {string} ID of the review to delete
*/ */
export function deleteReviewFromStorage(ID) { export function deleteReviewFromStorage(ID) {
//removing id number from activeIDS and star{rating}
let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
let reviewRating = JSON.parse(localStorage.getItem(`review${ID}`))["rating"];
let starArr = JSON.parse(localStorage.getItem(`star${reviewRating}`));
for (let i in starArr) {
if (starArr[i] == ID) {
//removing from corresponding rating array and updating local Storage
starArr.splice(i, 1);
break;
}
}
if (starArr.length != 0) {
localStorage.setItem(`star${reviewRating}`, JSON.stringify(starArr));
} else {
localStorage.removeItem(`star${reviewRating}`);
}
for (let i in activeIDS) { for (let i in activeIDS) {
if (activeIDS[i] == ID) { if (activeIDS[i] == ID) {
activeIDS.splice(i, 1); activeIDS.splice(i, 1);
localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); localStorage.setItem("activeIDS", JSON.stringify(activeIDS));
let currReview = JSON.parse(localStorage.getItem(`review${ID}`));
deleteTagsFromStorage(ID, currReview["tags"]);
localStorage.removeItem(`review${ID}`); localStorage.removeItem(`review${ID}`);
return; return;
} }
@ -60,9 +162,53 @@ export function deleteReviewFromStorage(ID){
console.error(`could not find review${ID} in localStorage`); console.error(`could not find review${ID} in localStorage`);
} }
// legacy function /**
* Delete ID from the specified tags' storage
* @param {string} ID to delete from lists
* @param {string[]} deletedTags to modify storage of
*/
function deleteTagsFromStorage(ID, deletedTags) {
for (let i in deletedTags) {
//get local storage of each tag and remove id from tag list
let tagName = "!" + deletedTags[i].toLocaleLowerCase();
let tagArr = JSON.parse(localStorage.getItem(tagName));
for (let j in tagArr) {
if (tagArr[j] == ID) {
tagArr.splice(j, 1);
break;
}
}
if (tagArr.length != 0) {
localStorage.setItem(tagName, JSON.stringify(tagArr));
} else {
localStorage.removeItem(tagName);
}
}
}
/**
* Add ID from the specified tags' storage
* @param {string} ID to add to lists
* @param {string[]} addedTags to modify storage of
*/
function addTagsToStorage(ID, addedTags) {
for (let i in addedTags) {
let tagName = "!" + addedTags[i].toLocaleLowerCase();
let tagArr = JSON.parse(localStorage.getItem(tagName));
if (!tagArr) {
tagArr = [];
}
tagArr.push(ID);
localStorage.setItem(tagName, JSON.stringify(tagArr));
}
}
/**
* Test Helper Function to get all reviews from local storage
* @returns {Object} all active reviews from local storage
*/
export function getAllReviewsFromStorage() { export function getAllReviewsFromStorage() {
if (!(localStorage.getItem("activeIDS"))) { if (!localStorage.getItem("activeIDS")) {
// we wanna init the active ID array and start the nextID count // we wanna init the active ID array and start the nextID count
localStorage.setItem("activeIDS", JSON.stringify([])); localStorage.setItem("activeIDS", JSON.stringify([]));
localStorage.setItem("nextID", JSON.stringify(0)); localStorage.setItem("nextID", JSON.stringify(0));
@ -76,3 +222,46 @@ export function getAllReviewsFromStorage() {
} }
return reviews; return reviews;
} }
/**
* Get all IDs of active reviews (order: most recent)
* @returns {number[]} list of all active IDs by recency
*/
export function getIDsFromStorage() {
if (!localStorage.getItem("activeIDS")) {
// we wanna init the active ID array and start the nextID count
localStorage.setItem("activeIDS", JSON.stringify([]));
localStorage.setItem("nextID", JSON.stringify(0));
}
let activeIDS = JSON.parse(localStorage.getItem("activeIDS"));
return activeIDS.reverse();
}
/**
* Returns all review IDs which contain the same tag specified (order: most recent)
* @param {string} tag to filter by
* @returns {number[]} list of IDs of reviews that all contain the specified tag by recency
*/
export function getIDsByTag(tag) {
let tagArr = JSON.parse(localStorage.getItem("!" + tag.toLocaleLowerCase()));
if (!tagArr) {
tagArr = [];
}
return tagArr.reverse();
}
/**
* Returns the top rated review IDs in order.
* @returns {number[]} list of IDs of reviews in order of top rating (most recent if equal rating)
*/
export function getTopIDsFromStorage() {
let resultArr = [];
for (let i = 5; i > 0; i--) {
let starArr = JSON.parse(localStorage.getItem(`star${i}`));
if (!starArr) {
continue;
}
resultArr = resultArr.concat(starArr.reverse());
}
return resultArr;
}

View File

@ -1,9 +1,16 @@
import { strict as assert } from "node:assert"; import { strict as assert } from "node:assert";
import { describe, it, before, after } from "mocha"; import { describe, it, before, after } from "mocha";
import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage} from "./localStorage.js"; import {
newReviewToStorage,
describe("test app localStorage interaction", () => { getReviewFromStorage,
updateReviewToStorage,
deleteReviewFromStorage,
getAllReviewsFromStorage,
getIDsByTag,
getTopIDsFromStorage,
} from "./localStorage.js";
describe("test CRUD localStorage interaction", () => {
before(() => { before(() => {
localStorage.clear(); localStorage.clear();
}); });
@ -16,11 +23,11 @@ describe("test app localStorage interaction", () => {
it("test localStorage state after adding one review", () => { it("test localStorage state after adding one review", () => {
let review = { let review = {
"imgSrc": "sample src", imgSrc: "sample src",
"mealName": "sample name", mealName: "sample name",
"restaurant": "sample restaurant", restaurant: "sample restaurant",
"rating": 5, rating: 5,
"tags": ["tag 1", "tag 2", "tag 3"] tags: ["tag 1", "tag 2", "tag 3"],
}; };
newReviewToStorage(review); newReviewToStorage(review);
@ -40,46 +47,45 @@ describe("test app localStorage interaction", () => {
for (let i = 1; i < 1000; i++) { for (let i = 1; i < 1000; i++) {
ids.push(i); ids.push(i);
let new_review = { let new_review = {
"imgSrc": `sample src ${i}`, imgSrc: `sample src ${i}`,
"mealName": `sample name ${i}`, mealName: `sample name ${i}`,
"restaurant": `sample restaurant ${i}`, restaurant: `sample restaurant ${i}`,
"rating": i, rating: i,
"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] tags: [`tag ${3 * i}`, `tag ${3 * i + 1}`, `tag ${3 * i + 2}`],
}; };
newReviewToStorage(new_review); new_review.reviewID = newReviewToStorage(new_review);
new_review.reviewID = i;
reviews.push(new_review); reviews.push(new_review);
assert.deepEqual(getAllReviewsFromStorage(), reviews); assert.deepEqual(getAllReviewsFromStorage(), reviews);
assert.deepEqual(getReviewFromStorage(i), new_review); assert.deepEqual(getReviewFromStorage(i), new_review);
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids);
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), (i+1)); assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), i + 1);
} }
}).timeout(5000); }).timeout(5000);
it("test localStorage state during updating 1000 reviews", () => { it("test localStorage state during updating 1000 reviews", () => {
let reviews = getAllReviewsFromStorage();
let ids = JSON.parse(localStorage.getItem("activeIDS"));
for (let i = 0; i < 1000; i++) { for (let i = 0; i < 1000; i++) {
let old_review = getReviewFromStorage(i);
let id = old_review.reviewID;
let new_review = { let new_review = {
"imgSrc": `updated sample src ${i}`, imgSrc: `updated sample src ${id}`,
"mealName": `updated sample name ${i}`, mealName: `updated sample name ${id}`,
"restaurant": `updated sample restaurant ${i}`, restaurant: `updated sample restaurant ${id}`,
"rating": i*2+i, reviewID: id,
"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] rating: (id % 5) + 1,
tags: [`tag ${3 * id}`, `tag ${3 * id + 1}`, `tag ${3 * id + 2}`],
}; };
new_review.reviewID = i;
reviews[i] = new_review; updateReviewToStorage(id, new_review);
updateReviewToStorage(i, new_review); let all_reviews = getAllReviewsFromStorage();
let active_ids = JSON.parse(localStorage.getItem("activeIDS"));
assert.deepEqual(getAllReviewsFromStorage(), reviews); assert.deepEqual(all_reviews[999], new_review);
assert.strictEqual(active_ids[999], id);
assert.deepEqual(getReviewFromStorage(i), new_review); assert.deepEqual(getReviewFromStorage(i), new_review);
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids);
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000);
} }
}).timeout(5000); }).timeout(5000);
@ -99,5 +105,215 @@ describe("test app localStorage interaction", () => {
} }
}).timeout(5000); }).timeout(5000);
it("test localStorage state after all deletes", () => {
assert.deepEqual(getAllReviewsFromStorage(), []);
});
after(() => {});
});
describe("test sort/filter localStorage interaction", () => {
before(() => {
localStorage.clear();
getAllReviewsFromStorage();
});
it("add sample data for sort and filter", () => {
for (let i = 0; i < 100; i++) {
let review = {
imgSrc: `sample src ${i}`,
mealName: `sample name ${i}`,
restaurant: `sample restaurant ${i}`,
rating: (i % 5) + 1,
tags: [`tag ${i % 3}`, `tag ${i < 50}`, "tag x"],
};
newReviewToStorage(review);
}
});
it("test getTopIDsFromStorage end behavior after create", () => {
let top_reviews = getTopIDsFromStorage();
let prev = Infinity;
for (let i = 0; i < top_reviews.length; i++) {
let review = getReviewFromStorage(top_reviews[i]);
assert.strictEqual(review.rating <= prev, true);
}
});
it("test getIDsByTag end behavior after create", () => {
let specific_tagged_reviews = [];
specific_tagged_reviews = getIDsByTag("tag 0");
assert.strictEqual(specific_tagged_reviews.length, 34);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 0"), true);
assert.strictEqual(review.reviewID % 3, 0);
}
specific_tagged_reviews = getIDsByTag("tag 1");
assert.strictEqual(specific_tagged_reviews.length, 33);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 1"), true);
assert.strictEqual(review.reviewID % 3, 1);
}
specific_tagged_reviews = getIDsByTag("tag 2");
assert.strictEqual(specific_tagged_reviews.length, 33);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 2"), true);
assert.strictEqual(review.reviewID % 3, 2);
}
specific_tagged_reviews = getIDsByTag("tag true");
assert.strictEqual(specific_tagged_reviews.length, 50);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag true"), true);
assert.strictEqual(review.reviewID < 50, true);
}
specific_tagged_reviews = getIDsByTag("tag false");
assert.strictEqual(specific_tagged_reviews.length, 50);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag false"), true);
assert.strictEqual(review.reviewID >= 50, true);
}
specific_tagged_reviews = getIDsByTag("tag x");
assert.strictEqual(specific_tagged_reviews.length, 100);
specific_tagged_reviews = getIDsByTag("tag y");
assert.deepEqual(specific_tagged_reviews, []);
});
it("update sample data for sort and filter", () => {
for (let i = 0; i < 100; i++) {
let old_review = getReviewFromStorage(i);
let new_review = {
imgSrc: `sample src ${i}`,
mealName: `sample name ${i}`,
restaurant: `sample restaurant ${i}`,
reviewID: old_review.reviewID,
rating: (i % 5) + 1,
tags: [`tag ${i % 4}`, `tag ${i < 37}`, "tag y"],
};
updateReviewToStorage(old_review.reviewID, new_review);
}
});
it("test getTopIDsFromStorage end behavior after create", () => {
let top_reviews = getTopIDsFromStorage();
let prev = Infinity;
for (let i = 0; i < top_reviews.length; i++) {
let review = getReviewFromStorage(top_reviews[i]);
assert.strictEqual(review.rating <= prev, true);
}
});
it("test getIDsByTag end behavior after update", () => {
let specific_tagged_reviews = [];
specific_tagged_reviews = getIDsByTag("tag 0");
assert.strictEqual(specific_tagged_reviews.length, 25);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 0"), true);
assert.strictEqual(review.reviewID % 4, 0);
}
specific_tagged_reviews = getIDsByTag("tag 1");
assert.strictEqual(specific_tagged_reviews.length, 25);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 1"), true);
assert.strictEqual(review.reviewID % 4, 1);
}
specific_tagged_reviews = getIDsByTag("tag 2");
assert.strictEqual(specific_tagged_reviews.length, 25);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 2"), true);
assert.strictEqual(review.reviewID % 4, 2);
}
specific_tagged_reviews = getIDsByTag("tag 3");
assert.strictEqual(specific_tagged_reviews.length, 25);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag 3"), true);
assert.strictEqual(review.reviewID % 4, 3);
}
specific_tagged_reviews = getIDsByTag("tag true");
assert.strictEqual(specific_tagged_reviews.length, 37);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag true"), true);
assert.strictEqual(review.reviewID < 37, true);
}
specific_tagged_reviews = getIDsByTag("tag false");
assert.strictEqual(specific_tagged_reviews.length, 63);
for (let i = 0; i < specific_tagged_reviews.length; i++) {
let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(review.tags.includes("tag false"), true);
assert.strictEqual(review.reviewID >= 37, true);
}
specific_tagged_reviews = getIDsByTag("tag x");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag y");
assert.strictEqual(specific_tagged_reviews.length, 100);
});
it("delete all sample data for sort and filter", () => {
for (let i = 0; i < 100; i++) {
deleteReviewFromStorage(i);
}
});
it("test getTopIDsFromStorage end behavior after delete", () => {
for (let i = 0; i <= 100; i++) {
let top_reviews = getTopIDsFromStorage(i);
assert.deepEqual(top_reviews, []);
}
});
it("test getIDsByTag end behavior after delete", () => {
let specific_tagged_reviews = [];
specific_tagged_reviews = getIDsByTag("tag 0");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag 1");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag 2");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag 3");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag true");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag false");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag x");
assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getIDsByTag("tag y");
assert.deepEqual(specific_tagged_reviews, []);
});
after(() => {}); after(() => {});
}); });

View File

@ -1,11 +1,9 @@
import { strict as assert } from "node:assert"; import { strict as assert } from "node:assert";
import { describe, it, before, after } from "mocha"; import { describe, it, before, after } from "mocha";
import puppeteer from "puppeteer-core"; import puppeteer from "puppeteer-core";
import {exit} from "node:process";
import { setReviewForm, checkCorrectness } from "./appTestHelpers.js"; import { setReviewForm, checkCorrectness } from "./appTestHelpers.js";
describe("test App end to end", async () => { describe("test App end to end", async () => {
let browser; let browser;
let page; let page;
@ -13,8 +11,7 @@ describe("test App end to end", async () => {
let root; let root;
try { try {
root = process.getuid() == 0; root = process.getuid() == 0;
} } catch (error) {
catch (error) {
root = false; root = false;
} }
@ -24,10 +21,8 @@ describe("test App end to end", async () => {
try { try {
await page.goto("http://localhost:8080", { timeout: 2000 }); await page.goto("http://localhost:8080", { timeout: 2000 });
await console.log(`✔ connected to localhost webserver as ${root ? "root" : "user"}`); await console.log(`✔ connected to localhost webserver as ${root ? "root" : "user"}`);
} } catch (error) {
catch (error) {
await console.log("❌ failed to connect to localhost webserver on port 8080"); await console.log("❌ failed to connect to localhost webserver on port 8080");
await exit(1);
} }
}); });
@ -38,7 +33,6 @@ describe("test App end to end", async () => {
}); });
describe("test CRUD on simple inputs and default image", () => { describe("test CRUD on simple inputs and default image", () => {
describe("test create 1 new review", async () => { describe("test create 1 new review", async () => {
it("create 1 new review", async () => { it("create 1 new review", async () => {
// Click the button to create a new review // Click the button to create a new review
@ -52,7 +46,7 @@ describe("test App end to end", async () => {
comments: "sample comment", comments: "sample comment",
restaurant: "sample restaurant", restaurant: "sample restaurant",
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
rating: 1 rating: 1,
}; };
await setReviewForm(page, review); await setReviewForm(page, review);
@ -65,12 +59,12 @@ describe("test App end to end", async () => {
it("check details page", async () => { it("check details page", async () => {
// check the details page for correctness // check the details page for correctness
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "sample name", mealName: "sample name",
comments: "sample comment", comments: "sample comment",
restaurant: "sample restaurant", restaurant: "sample restaurant",
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
rating: "http://localhost:8080/assets/images/1-star.svg" rating: "http://localhost:8080/assets/images/1-star.svg",
}; };
await checkCorrectness(page, "d", expected); await checkCorrectness(page, "d", expected);
}); });
@ -86,12 +80,12 @@ describe("test App end to end", async () => {
let shadowRoot = await review_card.getProperty("shadowRoot"); let shadowRoot = await review_card.getProperty("shadowRoot");
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "sample name", mealName: "sample name",
comments: "sample comment", comments: "sample comment",
restaurant: "sample restaurant", restaurant: "sample restaurant",
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
rating: "http://localhost:8080/assets/images/1-star.svg" rating: "http://localhost:8080/assets/images/1-star.svg",
}; };
await checkCorrectness(shadowRoot, "a", expected); await checkCorrectness(shadowRoot, "a", expected);
}); });
@ -111,12 +105,12 @@ describe("test App end to end", async () => {
// check the details page for correctness // check the details page for correctness
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "sample name", mealName: "sample name",
comments: "sample comment", comments: "sample comment",
restaurant: "sample restaurant", restaurant: "sample restaurant",
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
rating: "http://localhost:8080/assets/images/1-star.svg" rating: "http://localhost:8080/assets/images/1-star.svg",
}; };
await checkCorrectness(page, "d", expected); await checkCorrectness(page, "d", expected);
}); });
@ -133,21 +127,19 @@ describe("test App end to end", async () => {
// check the details page for correctness // check the details page for correctness
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "sample name", mealName: "sample name",
comments: "sample comment", comments: "sample comment",
restaurant: "sample restaurant", restaurant: "sample restaurant",
tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"],
rating: "http://localhost:8080/assets/images/1-star.svg" rating: "http://localhost:8080/assets/images/1-star.svg",
}; };
await checkCorrectness(shadowRoot, "a", expected); await checkCorrectness(shadowRoot, "a", expected);
}); });
}); });
describe("test update 1 review", async () => { describe("test update 1 review", async () => {
it("update 1 review", async () => { it("update 1 review", async () => {
// Get the only review card and click it // Get the only review card and click it
let review_card = await page.$("review-card"); let review_card = await page.$("review-card");
await review_card.click(); await review_card.click();
@ -163,7 +155,7 @@ describe("test App end to end", async () => {
comments: "updated comment", comments: "updated comment",
restaurant: "updated restaurant", restaurant: "updated restaurant",
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
rating: 5 rating: 5,
}; };
await setReviewForm(page, review); await setReviewForm(page, review);
@ -176,12 +168,12 @@ describe("test App end to end", async () => {
it("check details page", async () => { it("check details page", async () => {
// check the details page for correctness // check the details page for correctness
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "updated name", mealName: "updated name",
comments: "updated comment", comments: "updated comment",
restaurant: "updated restaurant", restaurant: "updated restaurant",
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
rating: "http://localhost:8080/assets/images/5-star.svg" rating: "http://localhost:8080/assets/images/5-star.svg",
}; };
await checkCorrectness(page, "d", expected); await checkCorrectness(page, "d", expected);
}); });
@ -198,16 +190,15 @@ describe("test App end to end", async () => {
// check the details page for correctness // check the details page for correctness
let expected = { let expected = {
imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", imgSrc: "http://localhost:8080/assets/images/default_plate.png",
mealName: "updated name", mealName: "updated name",
comments: "updated comment", comments: "updated comment",
restaurant: "updated restaurant", restaurant: "updated restaurant",
tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"],
rating: "http://localhost:8080/assets/images/5-star.svg" rating: "http://localhost:8080/assets/images/5-star.svg",
}; };
await checkCorrectness(shadowRoot, "a", expected); await checkCorrectness(shadowRoot, "a", expected);
}); });
}); });
describe("test delete 1 review", async () => { describe("test delete 1 review", async () => {
@ -217,7 +208,7 @@ describe("test App end to end", async () => {
await review_card.click(); await review_card.click();
await page.waitForNavigation(); await page.waitForNavigation();
page.on("dialog", async dialog => { page.on("dialog", async (dialog) => {
console.log(dialog.message()); console.log(dialog.message());
await dialog.accept(); await dialog.accept();
}); });

View File

@ -1,42 +1,156 @@
// main.js // main.js
import {getAllReviewsFromStorage} from "./localStorage.js"; import { getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage } from "./localStorage.js";
// Run the init() function when the page has loaded // Run the init() function when the page has loaded
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
function init() { function init() {
// Get the reviews from localStorage //initial population of review container
let reviews = getAllReviewsFromStorage(); sortAndFilter(false, null);
// Add each reviews to the <main> element //Add the event listeners to dropdown and search bar
addReviewsToDocument(reviews);
// Add the event listeners to the form elements
initFormHandler(); initFormHandler();
} }
/** /**
* @param {Array<Object>} reviews An array of reviews * @param {Array<Object>} reviews An array of reviews
*/ */
function addReviewsToDocument(reviews) { function addReviewsToDocument(reviews) {
let reviewBox = document.getElementById("review-container"); let reviewBox = document.getElementById("review-container");
reviews.forEach(review => { reviews.forEach((review) => {
let newReview = document.createElement("review-card"); let newReview = document.createElement("review-card");
newReview.data = review; newReview.data = review;
//TODO: want to append it to whatever the box is in layout
reviewBox.append(newReview); reviewBox.append(newReview);
}); });
} }
/** /**
* Adds the necessary event handlers to <form> and the clear storage * Adds the necessary event handlers to search-btn and sort
* <button>.
*/ */
function initFormHandler() { function initFormHandler() {
//grabbing search field
let searchField = document.getElementById("search-bar");
let searchBtn = document.getElementById("search-btn");
let searchTag = null;
//adding search functionality
//TODO: Add ability to enter without refresh of search bar
//filter by selected tag when button clicked
searchBtn.addEventListener("click", function () {
searchTag = searchField.value;
sortAndFilter(searchTag);
});
//btn to create form (could be its own function?) //for clearing tag filter
let createBtn = document.getElementById("create-btn"); let clearSearchBtn = document.getElementById("clear-search");
createBtn.addEventListener("click", function(){ clearSearchBtn.addEventListener("click", function () {
window.location.assign("./CreatePage.html"); searchTag = null;
searchField.value = "";
sortAndFilter(searchTag);
});
//sort by selected method
let sortMethod = document.getElementById("sort");
sortMethod.addEventListener("input", function () {
sortAndFilter(searchTag);
}); });
} }
/**
* Deciphers sort and filter to populate the review-container
* @param {string} searchTag tag name to filter by
*/
function sortAndFilter(searchTag) {
let reviewBox = document.getElementById("review-container");
let sortMethod = document.getElementById("sort");
//clear review container
while (reviewBox.firstChild) {
reviewBox.removeChild(reviewBox.firstChild);
}
let reviewIDs = [];
//sort method: most recent
if (sortMethod.value == "recent") {
//tag filtered most recent
if (searchTag) {
reviewIDs = getIDsByTag(searchTag);
}
//most recent
else {
reviewIDs = getIDsFromStorage();
}
//reversed for recency
loadReviews(0, reviewIDs);
}
//sort method: top rated
else if (sortMethod.value == "top") {
//tag filtered top rated
if (searchTag) {
//intersection of top ids list and ids by tag in top ids order
reviewIDs = getTopIDsFromStorage().filter((x) => getIDsByTag(searchTag).includes(x));
}
//top rated
else {
reviewIDs = getTopIDsFromStorage();
}
loadReviews(0, reviewIDs);
}
}
/**
* Populate review-container with 9 more reviews
* @param {number} index review index to begin with
* @param {number[]} reviewIDs ordered array of reviews
*/
function loadReviews(index, reviewIDs) {
let reviewBox = document.getElementById("review-container");
// label if there are no reviews to display
if (reviewIDs.length == 0) {
let emptyLabel = document.createElement("label");
emptyLabel.setAttribute("id", "empty");
emptyLabel.innerText = "No Reviews To Display";
reviewBox.append(emptyLabel);
} else {
let emptyLabel = document.getElementById("empty");
if (emptyLabel) {
reviewBox.removeChild(emptyLabel);
}
}
let moreBtn = document.getElementById("more-btn");
//delete load more button if exists
if (moreBtn) {
reviewBox.removeChild(moreBtn);
}
let reviewArr = [];
//check if there are more than 9 reviews left
if (index + 9 > reviewIDs.length - 1) {
//add remaining reviews to review container
for (let i = index; i < reviewIDs.length; i++) {
reviewArr.push(getReviewFromStorage(reviewIDs[i]));
}
addReviewsToDocument(reviewArr);
} else {
//add 9 more reviews to container
for (let i = index; i < index + 9; i++) {
reviewArr.push(getReviewFromStorage(reviewIDs[i]));
}
addReviewsToDocument(reviewArr);
//create and add load more button
moreBtn = document.createElement("button");
moreBtn.setAttribute("id", "more-btn");
moreBtn.innerText = "Load More";
//if load more clicked, load 9 more
moreBtn.addEventListener("click", function () {
loadReviews(index + 9, reviewIDs);
});
reviewBox.append(moreBtn);
}
}
const registerServiceWorker = async () => {
if ("serviceWorker" in navigator) {
try {
await navigator.serviceWorker.register("./sw.js", { scope: "./" });
} catch (error) {
console.error(`Registration failed with ${error}`);
}
}
};
registerServiceWorker();

View File

@ -1,4 +1,3 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -8,15 +7,18 @@
<title>Food Journal</title> <title>Food Journal</title>
<!--Add Favicon--> <!--Add Favicon-->
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico"> <link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico" />
<!-- Review Card Custom Element --> <!-- Recipe Card Custom Element -->
<script src="assets/scripts/ReviewCard.js" type="module"></script> <script src="assets/scripts/ReviewCard.js" type="module"></script>
<!-- Homepage Stylesheets & Scripts --> <!-- Main Stylesheets & Scripts -->
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
<link rel="stylesheet" href="./static/homepage.css" /> <link rel="stylesheet" href="./static/homepage.css" />
<script src="assets/scripts/main.js" type="module"></script> <script src="assets/scripts/main.js" type="module"></script>
</head> </head>
<body> <body>
<header> <header>
<div class="top-bar"> <div class="top-bar">
@ -27,28 +29,36 @@
</header> </header>
<main> <main>
<div class="body-container"> <div class="body-container">
<div style="width: 20%;"></div> <div style="width: 20%"></div>
<div style="width: 60%;"> <div style="width: 60%">
<div class="search-bar"> <div class="search-bar">
<form id="form"> <form id="form">
<input type="search" id="searching" name="searchBar" placeholder="Search journal..."> <label for="sort">Sorting Method:</label>
<button class="click" type="search"> Search </button> <select id="sort">
<div class="Filter-box"> <option value="recent">Most Recent</option>
<option value="top">Top Rated</option>
</div> </select>
<input type="search" id="search-bar" name="searchBar" placeholder="Search tags..." />
<button id="clear-search">Clear Search</button>
</form> </form>
<img src="./assets/images/search_button.png" alt="SEARCH BTN" id="search-btn" />
</div> </div>
<div class="center-display">
<img src ="./assets/images/Grouppink.png" alt="CREATE" style="opacity: 100%;" id="create-btn" onclick="window.location.assign('./CreatePage.html')"/>
<h2 id="recent-reviews-text"> Recent Reviews </h2>
<img src ="./assets/images/Grouppink.png" style="opacity:0;"/>
<div class="center-display">
<img
src="./assets/images/create_button.png"
alt="CREATE"
id="create-btn"
title="Add an entry!"
onclick="window.location.assign('./CreatePage.html')"
/>
<h2 id="recent-reviews-text">Recent Reviews</h2>
<img src="./assets/images/create_button.png" id="create-btn-invis" draggable="false" />
</div> </div>
<div class="review-container" id="review-container"></div> <div class="review-container" id="review-container"></div>
</div> </div>
<div style="width: 20%;"> <div style="width: 20%"></div>
</div>
</div> </div>
</main> </main>
</body> </body>

View File

@ -17,6 +17,12 @@
border: 2px solid rgb(31 41 32); border: 2px solid rgb(31 41 32);
border-radius: 8px; border-radius: 8px;
background-color: #f7dfd5; background-color: #f7dfd5;
word-break: break-all;
}
#d-meal-img {
border: 2px solid rgb(31 41 32);
border-radius: 8px;
} }
fieldset { fieldset {
@ -42,7 +48,8 @@ input[type="text"]:focus {
} }
.hidden, .hidden,
.rating:not(:checked) > input { /* Hide radio circles while star rating */ .rating:not(:checked) > input {
/* Hide radio circles while star rating */
display: none; display: none;
} }

View File

@ -52,18 +52,34 @@ body {
.search-bar { .search-bar {
display: flex; display: flex;
justify-content: center; justify-content: center;
font-family: "Century Gothic", sans-serif;
font-weight: bold;
color: #516754;
}
#sort {
margin-right: 1em;
} }
.search-bar > form { .search-bar > form {
float: right; float: right;
padding: 6px 10px; padding: 6px 10px;
/*
margin-top: 8px; margin-top: 8px;
margin-right: 16px; margin-right: 16px;
*/
background: rgb(239 183 183); background: rgb(239 183 183);
font-size: 17px; font-size: 17px;
border: none; border: none;
border-radius: 12px; border-radius: 12px;
cursor: pointer; }
#search-btn {
position: relative;
align-self: center;
width: 30px;
height: 30px;
} }
#recent-reviews-text { #recent-reviews-text {
@ -78,6 +94,17 @@ img#create-btn {
align-self: center; align-self: center;
padding-left: 2.5%; padding-left: 2.5%;
padding-right: 2.5%; padding-right: 2.5%;
cursor: pointer;
width: 10%;
height: 10%;
}
img#create-btn-invis {
opacity: 0;
padding-left: 2.5%;
padding-right: 2.5%;
width: 10%;
height: 10%;
} }
.review-container { .review-container {

67
source/sw.js Normal file
View File

@ -0,0 +1,67 @@
const CACHE_NAME = "food-journal-v1";
const ASSETS = [
"index.html",
"ReviewDetails.html",
"CreatePage.html",
"static/CoveredByYourGrace-Regular.ttf",
"static/CreatePage.css",
"static/Form.css",
"static/homepage.css",
"static/ReviewDetails.css",
"assets/images/0-star.svg",
"assets/images/1-star.svg",
"assets/images/2-star.svg",
"assets/images/3-star.svg",
"assets/images/4-star.svg",
"assets/images/5-star.svg",
"assets/images/create_button.png",
"assets/images/default_plate.png",
"assets/images/delete_icon_for_interface.png",
"assets/images/edit_button_for_interface.png",
"assets/images/home_button_for_interface.png",
"assets/images/favicon.ico",
"assets/images/Logo.png",
"assets/images/search_button.png",
"assets/scripts/CreatePage.js",
"assets/scripts/localStorage.js",
"assets/scripts/main.js",
"assets/scripts/ReviewCard.js",
"assets/scripts/ReviewDetails.js",
];
/**
* Adds the install listener where the app assets are added to the cache
*/
self.addEventListener("install", async () => {
// open the cace
const cache = await caches.open(CACHE_NAME);
// add all elements in ASSETS to the cache, these are all the files requried for the app to run
await cache.addAll(ASSETS);
});
/**
* Adds an event listener on fetch events to serve cached resources while offline
* Uses a network first structure to prioritize fetching from network in case of app updates.
* If there are important updates, we want the user to get those if possible.
*/
self.addEventListener("fetch", (event) => {
// add a response to the fetch event
event.respondWith(
caches.open(CACHE_NAME).then((cache) => {
// try to return a network fetch response
return fetch(event.request)
.then((fetchedResponse) => {
// if there is a response, add it to the cache
cache.put(event.request, fetchedResponse.clone());
// return the network response
return fetchedResponse;
})
.catch(() => {
// If there is not a network response, return the cached response
// The ignoreVary option is used here to fix an issue where the service worker
// would not serve certain requests unless the page was refreshed at least once
return cache.match(event.request, { ignoreVary: true, ignoreSearch: true });
});
})
);
});

View File

@ -1,16 +1,20 @@
# Final Project Topic Decision # Final Project Topic Decision
- Status: accept - Status: accept
- Deciders: team members and TA - Deciders: team members and TA
- Date: 10 / 27 / 22 - Date: 10 / 27 / 22
## Decision Drivers ## Decision Drivers
- Needed to develop a local-first, CRUD application that would be simple enough to implement in the next few weeks - Needed to develop a local-first, CRUD application that would be simple enough to implement in the next few weeks
## Considered Options: ## Considered Options:
- Social Media Archive - Social Media Archive
- Resume Builder - Resume Builder
- Copy/Paste - Copy/Paste
- Food Journal - Food Journal
## Decision Outcome ## Decision Outcome
Chosen Option: Food Journal, which allows users to hold their thoughts and ratings on meals and restaurants that they have been to. It is local-first, CRUD app, and fun. Therefore, we decided to choose this. Chosen Option: Food Journal, which allows users to hold their thoughts and ratings on meals and restaurants that they have been to. It is local-first, CRUD app, and fun. Therefore, we decided to choose this.

View File

@ -1,15 +1,19 @@
# Finalized App Design on Figma # Finalized App Design on Figma
- Status: accept - Status: accept
- Deciders: Isaac Otero - Deciders: Isaac Otero
- Date: 11 / 08 / 22 - Date: 11 / 08 / 22
## Decision Drivers: ## Decision Drivers:
- Needed to figure out the wireframe and flow of our app - Needed to figure out the wireframe and flow of our app
- Needed to visualize the different features - Needed to visualize the different features
## Considered Option: ## Considered Option:
- Different feature option - Different feature option
- Color Scheme, font, spacing, and other design options were discussed - Color Scheme, font, spacing, and other design options were discussed
## Decision Outcome: ## Decision Outcome:
- Chosen Option: Design can be found at this link: https://www.figma.com/file/Qhugp1Dd0gPnJTbmmUIvsa/Wireframe?node-id=36%3A2 - Chosen Option: Design can be found at this link: https://www.figma.com/file/Qhugp1Dd0gPnJTbmmUIvsa/Wireframe?node-id=36%3A2

View File

@ -10,6 +10,7 @@
- Need framework to perform unit testing quickly for immediate code feedback - Need framework to perform unit testing quickly for immediate code feedback
## Considered Options ## Considered Options
- JUnit5 - JUnit5
- Jest - Jest
- Mocha - Mocha

View File

@ -11,6 +11,7 @@
- Framework should be easy to implement end to end tests with - Framework should be easy to implement end to end tests with
## Considered Options ## Considered Options
- puppeteer - puppeteer
- selenium-webdriver - selenium-webdriver

View File

@ -10,6 +10,7 @@
- Already documentating infile using JSDoc style - Already documentating infile using JSDoc style
## Considered Options ## Considered Options
- JSDoc - JSDoc
## Decision Outcome ## Decision Outcome

View File

@ -10,6 +10,7 @@
- Need to enforce style on other files like markdown, json - Need to enforce style on other files like markdown, json
## Considered Options ## Considered Options
- Prettier - Prettier
## Decision Outcome ## Decision Outcome

View File

@ -1,15 +1,19 @@
# Backend Storage Structure # Backend Storage Structure
- Status: Accept - Status: Accept
- Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng - Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng
- Date: 11/29/2022 - Date: 11/29/2022
## Decision Drivers ## Decision Drivers
- Needed more efficient way of storing reviews that are created, for more efficient testing, updating, accessing, and deleting. - Needed more efficient way of storing reviews that are created, for more efficient testing, updating, accessing, and deleting.
## Considered Options ## Considered Options
- localStorage - localStorage
## Decision Outcome ## Decision Outcome
Using local storage to maintain the "local first" requirement. Using local storage to maintain the "local first" requirement.
Moved away from array of objects for storing reviews, reviews are stored individually as keys in localStorage, under the "review{id}" format. Each key Moved away from array of objects for storing reviews, reviews are stored individually as keys in localStorage, under the "review{id}" format. Each key
corresponds to object containing review data. We also have an array stored in local storage, named "activeIDs" which keeps track of id numbers that are attached corresponds to object containing review data. We also have an array stored in local storage, named "activeIDs" which keeps track of id numbers that are attached

View File

@ -1,15 +1,18 @@
# Opening Specific Reviews # Opening Specific Reviews
- Status: Accept - Status: Accept
- Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng - Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng
- Date: 11/29/2022 - Date: 11/29/2022
## Decision Drivers ## Decision Drivers
- When opening up a review, browser needs to know what review ID to use for loading the review page data - When opening up a review, browser needs to know what review ID to use for loading the review page data
## Considered Options ## Considered Options
- sessionStorage - sessionStorage
## Decision Outcome ## Decision Outcome
Review cards have event listeners that will add their associated review ID number to session storage so Review cards have event listeners that will add their associated review ID number to session storage so
when the review loads, the browser will use the id stored to pull exact data corresponding to the review. when the review loads, the browser will use the id stored to pull exact data corresponding to the review.

View File

@ -1,13 +1,17 @@
# Organizing Review Under Tags # Organizing Review Under Tags
- Status: Accept - Status: Accept
- Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng - Deciders: Rhea Bhutada, Kara Hoagland, Gavyn Ezell, George Dubinin, Henry Feng
- Date: 11/29/2022 - Date: 11/29/2022
## Decision Drivers ## Decision Drivers
- Needed to keep track of reviews under certain given tags for filtering feature. - Needed to keep track of reviews under certain given tags for filtering feature.
## Considered Options ## Considered Options
- localStorage - localStorage
## Decision Outcome ## Decision Outcome
For every tag create a key under that tag name in localStorage. They will store an array of IDs that correspond to reviews that contain that tag. For every tag create a key under that tag name in localStorage. They will store an array of IDs that correspond to reviews that contain that tag.

View File

@ -0,0 +1,20 @@
# Use a network first cache second for service worker architecture
- Status: in consideration
- Deciders: Arthur Lu, Kara Hoagland, Rhea Bhutada, George Dubinin
- Date: 12 / 01 / 22
## Decision Drivers
- Need to balance the need for user ease of use and local first priority
- Users should expect to update their app easily when they have network, but may not be expected to know how to perform a hard refresh
- Local first priority means we should avoid unnecessary network activity when possible
## Considered Options
- Network first cache second
- Cache first network second
## Decision Outcome
Chosen Option: Network first for automatic app updating.

View File

@ -1,2 +1,3 @@
# Overarching Decisions # Overarching Decisions
_We will eventually capture these as an ADR in markdown Links to an external site.(/specs/adrs will contain an individual document per major decision. There will be some initial ones that have to do with general project plan and approach, but more may be added as the project goes on. The main point of this capture is to explain why choices are made. As brainstorming may have your team settle on choices quickly capturing them in a document may be better than just mental consensus)_ _We will eventually capture these as an ADR in markdown Links to an external site.(/specs/adrs will contain an individual document per major decision. There will be some initial ones that have to do with general project plan and approach, but more may be added as the project goes on. The main point of this capture is to explain why choices are made. As brainstorming may have your team settle on choices quickly capturing them in a document may be better than just mental consensus)_

View File

@ -1,22 +1,26 @@
# App Pitch - Food Journal # App Pitch - Food Journal
## Summary ## Summary
<p> <p>
Our pitch is an app that allows users to store information about their recent restaurant experiences, including the restaurant name, location, date, dish, picture of the food, price, comments, ratings, etc. This app will allow individuals to document their food habits and track past meals. The app will then provide suggestions based on the users preferences and habits. Our pitch is an app that allows users to store information about their recent restaurant experiences, including the restaurant name, location, date, dish, picture of the food, price, comments, ratings, etc. This app will allow individuals to document their food habits and track past meals. The app will then provide suggestions based on the users preferences and habits.
</p> </p>
## Narrowing Down the Problem ## Narrowing Down the Problem
<p> <p>
People dont have a place to reflect on their food adventures. Whether its trying a new cuisine or looking into new restaurants, it is useful for people to have a place to record their restaurant experiences. In our research, we found that there is no app designed for people to journal their food related experiences and we feel that this app will offer a new and exciting avenue for people to enjoy and reflect on their meals. People dont have a place to reflect on their food adventures. Whether its trying a new cuisine or looking into new restaurants, it is useful for people to have a place to record their restaurant experiences. In our research, we found that there is no app designed for people to journal their food related experiences and we feel that this app will offer a new and exciting avenue for people to enjoy and reflect on their meals.
</p> </p>
## How is it CRUD? ## How is it CRUD?
* Create: Users create reviews of specific foods at any restaurant
* Read: Users read reviews that theyve created - Create: Users create reviews of specific foods at any restaurant
* Update: Users update their reviews when their ideas change about the food - Read: Users read reviews that theyve created
* Delete: Users may delete their reviews - Update: Users update their reviews when their ideas change about the food
- Delete: Users may delete their reviews
## Visual Representation ## Visual Representation
- User Flow Diagram: - User Flow Diagram:
<img src="./diagram.png"></img> <img src="./diagram.png"></img>
@ -34,31 +38,38 @@
<img src="./wireframes/new_entry_wireframe.PNG"></img> <img src="./wireframes/new_entry_wireframe.PNG"></img>
## User Personas ## User Personas
### Persona 1: Tom ### Persona 1: Tom
Tom would often face the issue of not knowing where he should go for his next meal. As someone who is new to the town, Tom does not know the restaurants around his place by heart, let alone the details on each restaurant like the price range, cuisine, and specific dishes likes and dislikes.<br>Toms problem is one that can be solved by our app. Whenever he visits a restaurant, he can use our app to note down any relevant information from that visit. And when Tom would need help on deciding where to eat, he can refer to the notes on his food journal to help him make that decision. Tom would often face the issue of not knowing where he should go for his next meal. As someone who is new to the town, Tom does not know the restaurants around his place by heart, let alone the details on each restaurant like the price range, cuisine, and specific dishes likes and dislikes.<br>Toms problem is one that can be solved by our app. Whenever he visits a restaurant, he can use our app to note down any relevant information from that visit. And when Tom would need help on deciding where to eat, he can refer to the notes on his food journal to help him make that decision.
### Persona 2: Ben ### Persona 2: Ben
Ben is trying to make sure that he watches what he eats. He doesnt mind eating somewhere unhealthy once in a while, but he wants to make sure the majority of his purchasing decisions are healthy.<br>If Ben uses our app, he can place tags on the meals he eats depending on whether theyre healthy or unhealthy. Then, he can look back over the past weeks and months and make sure he hasnt been eating at too many unhealthy places. If hes ever looking for something to eat, he can filter by tags on the app to find only healthy places that hes given high ratings to in the past. This way, he can stay consistent with his dieting goals. Ben is trying to make sure that he watches what he eats. He doesnt mind eating somewhere unhealthy once in a while, but he wants to make sure the majority of his purchasing decisions are healthy.<br>If Ben uses our app, he can place tags on the meals he eats depending on whether theyre healthy or unhealthy. Then, he can look back over the past weeks and months and make sure he hasnt been eating at too many unhealthy places. If hes ever looking for something to eat, he can filter by tags on the app to find only healthy places that hes given high ratings to in the past. This way, he can stay consistent with his dieting goals.
### Persona 3: Claire ### Persona 3: Claire
Claire noticed that shes spending more than she would like to on eating out and made a resolution to try to budget how much shes spending on restaurants. Claire has a general idea of the restaurants in her area, but its difficult to keep track of the details of each location.<br>If Claire uses this app, she can note down the price of each food she tries when eating out and how she thought that the quality compared to the price with her budget in mind. She can narrow down foods that she finds worth the price. When craving a certain type of food, Claire can also look for cheaper options in the same category of cuisine based on her previous entries. Claire noticed that shes spending more than she would like to on eating out and made a resolution to try to budget how much shes spending on restaurants. Claire has a general idea of the restaurants in her area, but its difficult to keep track of the details of each location.<br>If Claire uses this app, she can note down the price of each food she tries when eating out and how she thought that the quality compared to the price with her budget in mind. She can narrow down foods that she finds worth the price. When craving a certain type of food, Claire can also look for cheaper options in the same category of cuisine based on her previous entries.
# Similar Apps and Competition # Similar Apps and Competition
* Social media allows users to technically post their own food reviews (food accounts, food review posts), but sites are not specialized for food reviews
* Yelp known for specifically food, but still branches - Social media allows users to technically post their own food reviews (food accounts, food review posts), but sites are not specialized for food reviews
* Our app differs in scope (focus on food exclusively) - Yelp known for specifically food, but still branches
* Our app offers food review-specific features like specialized templates and formats - Our app differs in scope (focus on food exclusively)
- Our app offers food review-specific features like specialized templates and formats
# Statement of Purpose # Statement of Purpose
Ultimately, the purpose of this app is to allow users to keep a food diary. Having a place that allows individuals to journal their favorite meals, restaurants, cuisines, pictures, and more can be beneficial for people who are looking to know more about their eating habits and tendencies as well as try out new foods. Ultimately, the purpose of this app is to allow users to keep a food diary. Having a place that allows individuals to journal their favorite meals, restaurants, cuisines, pictures, and more can be beneficial for people who are looking to know more about their eating habits and tendencies as well as try out new foods.
# Risks and Rabbit Holes # Risks and Rabbit Holes
* Technical Unkowns
* How to implement CRUD related features? - Technical Unkowns
* Is there a limit to storage? How to store large amounts of data locally? - How to implement CRUD related features?
* Unsolved Design Problems: - Is there a limit to storage? How to store large amounts of data locally?
* What features we want to prioritize? - Unsolved Design Problems:
* How much data will be collecting? - What features we want to prioritize?
* How many fields should we have for each meal? - How much data will be collecting?
* Misunderstood Interdependencies: - How many fields should we have for each meal?
* N/A - Misunderstood Interdependencies:
- N/A