Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 5. Add Items to list #20

Merged
merged 7 commits into from
Feb 16, 2024
Merged

Issue 5. Add Items to list #20

merged 7 commits into from
Feb 16, 2024

Conversation

sillytsundere
Copy link
Collaborator

@sillytsundere sillytsundere commented Feb 12, 2024

Description

These code changes enable users to add items to their shopping lists via a form on the ManageLists view. The form uses semantic html elements to adhere to accessibility standards.

Related Issue

Closes #5

Acceptance Criteria

UI-related tasks:

  • The ManageList view displays a form that allows them to enter the name of the item and select how soon they anticipate needing to buy it again. There should be 3 choices for this:
    • “Soon”, corresponding to 7 days
    • “Kind of soon”, corresponding to 14 days
    • “Not soon”, corresponding to 30 days
  • The input that accepts the name of the item has a semantic label element associated with it
  • The user can submit this form with both the mouse and the Enter key
  • When the user submits the form, they see a message indicating that the item either was or was not saved to the database.

Data-related tasks:

  • The console.log in the addItem function in src/api/firebase.js is replaced with a function that adds the new document to the Firestore database. That function will be imported from the firebase/firestore module.
  • The user’s soon/not soon/kind of soon choice is used to calculate nextPurchasedDate

Type of Changes

enhancement

Updates

Before

localhost_3000_manage-list (1)

After

localhost_3000_manage-list

Testing Steps / QA Criteria

git pull
git checkout ja-pc-feature-add-item
npm ci
npm run start
Navigate to Manage List page to view form
Enter item and when you will next purchase item into form fields, submit form, view alert informing item was successfully saved
Navigate to List page to view newly added item

@sillytsundere sillytsundere added the enhancement New feature or request label Feb 12, 2024
Copy link

github-actions bot commented Feb 12, 2024

Visit the preview URL for this PR (updated for commit 078f475):

https://tcl-73-smart-shopping-list--pr20-ja-pc-feature-add-it-txa4cj02.web.app

(expires Fri, 23 Feb 2024 23:47:09 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: 99eed22fcca8bd9874e77f7b7f7d1eeb554a1666

@rachelspencer
Copy link
Collaborator

rachelspencer commented Feb 13, 2024

Hi @sillytsundere and @jaguilar89!
This looks so neat and tidy! I pulled this branch down and ran the app.

I noticed I could submit an item when the input field and radio buttons were unselected. I could also submit an item with only a name and no date requirement, and also submit with no name and only a date requirement. When doing this I got the success alert.

To overcome this I added a <required> attribute to the <input> tags.

To enhance accessibility I also added an <id> tag who's value matches the <forHTML> attribute already existing on the <label> tags.

I could enter an item using the mouse and enter key! I am not sure if you want to enhance the accessibility more and add functionality for a user to select the radio buttons by using the tab and enter key also. Would definitely be extra challenge but might be fun!

The new item const on line 19 isn't used, not sure if you want to take it out to clean up the console.log, or if you have plans to use it later.

Great work!!

PS - I'm not sure if we should be seeing the items in Firebase DB with the extra functionality added for this issue. I couldn't see them, but I'm also still getting the hang of Firebase.

Copy link
Collaborator

@rachelspencer rachelspencer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @jaguilar89 and @sillytsundere,

This looks so cool!

I added some comments on the changes I made on the branch, as well as a couple additional non-blocking suggestions that I didn't implement.

name="itemName"
type="text"
id="item"
required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added required so form field can't be left blank on submit

name="daysUntilNextPurchase"
type="radio"
id="soon"
required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added required so form field can't be left blank on submit

name="daysUntilNextPurchase"
type="radio"
id="kind-of-soon"
required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added required so form field can't be left blank on submit

onChange={handleChangeDate}
name="daysUntilNextPurchase"
type="radio"
id="not-soon"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added id attribute to match forHTML attribute on <label> for accessibility

onChange={handleChangeDate}
name="daysUntilNextPurchase"
type="radio"
id="kind-of-soon"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added id attribute to match forHTML attribute on <label> for accessibility

onChange={handleChangeDate}
name="daysUntilNextPurchase"
type="radio"
id="soon"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added id attribute to match forHTML attribute on <label> for accessibility

<li>
<label htmlFor="soon"> Soon (7 days)</label>
<input
value={7}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider making this your default value, to enhance accessibility. This can be achieved by adding another attribute here. If you chose to do this, you'll also need to update the initial state value to be "7".

Copy link
Collaborator

@jaguilar89 jaguilar89 Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We initially leave this part of the form unselected to account for accidental form submissions where an item name would be provided but the first radio button would already be selected, before the user has a chance to select it on their own. Whereas if there is no default radio button value, the user would see an error message, asking them to select an option first. See below screenshot.

image

As an alternative, we added a clear "Please select option" instruction to make it clear that the user must make a selection before submitting the form. See below screenshot.

image

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@trushmi What do you think?

src/views/ManageList.jsx Outdated Show resolved Hide resolved
@sillytsundere
Copy link
Collaborator Author

Jose and I made more changes, we agree with the changes suggested and implemented by Rachel to make the items of the form required so as to prevent items with no name or next purchase date to be entered into the list. Also Jose refactored the code to eliminate the need for useState and refactored the multiple hooks into one handleSubmit hook. This also removes the const newItem, an unused variable, calling the await directly without saving it in a variable.

Copy link
Member

@trushmi trushmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, but I think we can make a few improvements.

src/views/ManageList.jsx Outdated Show resolved Hide resolved
src/views/ManageList.jsx Outdated Show resolved Hide resolved
Hello from the <code>/manage-list</code> page!
</p>
<div>
<form id="item-form" onSubmit={handleSubmit}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend moving this form to a separate component in case we use it in the future. For example, we can create a component called RadioInput. The component should use props to receive the options, like this:

const options = [{label: "Soon (7 days)", value: 7, id: "soon"}, {label: "Kind of soon (14 days)", value: 14, id:"kind-of-soon"}];


...

<RadioInput name="daysUntilNextPurchase" options={options}/>

and inside of the component we can use those props:

function RadioInput({name, options}) {

  return (
    <ul>
      {options.map((option) => (
          <li>
             <label htmlFor={option.id}>{option.label}</label>
             <input value={option.value} name={name}... >
          </li>
        )
      )}
    <ul/>
  ) 
}

Copy link
Collaborator

@jaguilar89 jaguilar89 Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good suggestion. However, Paige and I think it's unnecessary for now simply because we don't think a radio button component will be needed in the future, based on the acceptance criteria of future issues. But, we can always keep this suggestion in mind in case it does become a necessary change in the future.

src/views/ManageList.jsx Outdated Show resolved Hide resolved
Copy link
Collaborator

@rachelspencer rachelspencer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

@trushmi trushmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed and tested. Looks good to me!

Copy link
Collaborator

@timothy-taylor timothy-taylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job completing this one! I left a few thoughts: feel to make any small changes you want or just make note of any changes you want to make moving forward (you can definitely leave the custom validation + status stuff for the future) and get this merged in!

const handleSubmit = async (e) => {
e.preventDefault();

const formData = new FormData(e.target);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool approach here using the FormData api in conjunction with default form/input functionality to access necessary data. You don't see this often in client-side React apps, but totally legit thing to do so that's cool to see.

alert('There was a problem');
}

formRef.current.reset();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether this reset() should be inside of the try branch of the try ... catch .... If there is an error that means that the item wasn't saved, so we probably don't want to clear the form on people (in case they want to try again?)

Copy link
Collaborator

@jaguilar89 jaguilar89 Feb 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense, clearing a form after a successful submit is expected behavior, not clearing it would clearly indicate there was a problem. I added this change.


alert('Item saved successfully');
} catch (error) {
alert('There was a problem');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't necessarily have to fully display the error in this catch statement, but I do think we could make this error status more specific.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified the catch block to display a more detailed error message.

try {
...
} catch (error) {
   alert(`There was a problem: ${error.message}`);
};

name="daysUntilNextPurchase"
type="radio"
id="soon"
required
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I said this to the other group as well, but the built in HTML validations actually aren't as accessible as one would hope. So I think down the road we should build our own validation + status displaying logic.

import { useRef } from 'react';

export function ManageList({ listPath }) {
const formRef = useRef();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the best practice recommendation by the React team is to declare this as const formRef = useRef(null) if you are going to assign the reference to a DOM element. I'm honestly not sure the different null vs undefined makes in the initial declaration in reality, but I would still recommend doing it so that your code can be as consistent as possible.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I will add this change. Thanks!

…e for useRef, moved form reset into try block so it only resets upon successful submission
@sillytsundere sillytsundere merged commit 98a596b into main Feb 16, 2024
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5. As a user, I want to add a new item to my shopping list so I can start recording purchases
5 participants