Skip to content

Conversation

@CalebLItalien
Copy link

Starting modal rewrites.

@CharlieMcVicker
Copy link
Member

closes #81

@CharlieMcVicker CharlieMcVicker self-requested a review May 21, 2023 18:29
Copy link
Member

@CharlieMcVicker CharlieMcVicker left a comment

Choose a reason for hiding this comment

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

This is awesome and you have clearly learned so much!!

There are a couple things I'd love to see changed before we merge:

  1. Names from copy/pasted code should be updated
  2. We should look at useState calls and figure out if they are needed or are just creating the possibility for invalid state
  3. I'm not convinced your "WHERE_FOUND" action actually makes it to the user state and updates the database. Also an action type like "SET_WHERE_FOUND" would be more in keeping with naming conventions.
  4. The "exitWizard" and "exitAtEnd" functions are weird. I think that the steps/wizard abstraction is sort of borked at this point, and maybe we need to stop pretending that it is more general than it is.

onChange = {onRadioChanged}
checked = {collectionId == collection.id}
/>
<label htmlFor={collection.id}>{collection.title} ({totalTerms(collection.sets)} terms) </label>
Copy link
Member

Choose a reason for hiding this comment

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

This is good for now, but I wonder if we should write short descriptions of the sets to put here instead of just # of terms.

goToNextStep,
goToPreviousStep,
}: StepProps): ReactElement {
const [enabled, setEnbabled] = useState(collectionId != undefined);
Copy link
Member

Choose a reason for hiding this comment

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

  1. I think it's best practice to use !== here.

  2. Maybe "canGoToNextStep" would be a better name for this. It's not clear what is enabled/disabled by this until the last line of the function. Also, is this state, or a function of state? Ie. should enabled always be equal to collectionId != undefined? Is there any time when we want to have the button enabled even though the collectionId isn't set? If it's actually a function of another field and not its own data, you could remove the "useState" call and just do:

const canGoToNextStep = collectionId !== undefined;

Copy link
Author

Choose a reason for hiding this comment

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

Yes this was a misunderstanding of state. I've changed this to use a global variable instead.

Comment on lines 56 to 73
<fieldset>
<legend>Email Address</legend>
<input
type = "email"
name = "email"
value = {email}
onChange = {onEmailChanged}
/>
</fieldset>
<fieldset>
<legend>Where did you find us?</legend>
<input
type = "whereFound"
name = "whereFound"
value = {whereFound}
onChange = {onWhereFoundChanged}
/>
</fieldset>
Copy link
Member

Choose a reason for hiding this comment

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

So this is a weird HTML moment, but I don't think it's semantically correct to use fieldset and legend with a single input. The input is supposed to have a label that explains what it is, not a legend.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset

Maybe these two text inputs should be in a fieldset together and then each have their own label? That or they should be loose in the form or in divs.

Copy link
Author

Choose a reason for hiding this comment

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

This has been changed to make sense within the context of a fieldset.

Comment on lines 29 to 35
<br></br>
- Filler text 1.
<br></br>
- Filler text 2.
<br></br>
- Filler text 3.
<br></br>
Copy link
Member

Choose a reason for hiding this comment

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

I know this is filler, but unordered lists should be written with the ul (Unordered List) and li (List item) tags, FWIW.

Copy link
Member

Choose a reason for hiding this comment

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

Also, this many <br/>s is scary -- maybe we need some components with padding/margins?

Copy link
Author

Choose a reason for hiding this comment

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

I temporarily changed it to the unordered list, do you want me to add a component for the code of conduct?

/*
* Defines css for steps.
*/
export const StepIndicator = styled.h4`
Copy link
Member

Choose a reason for hiding this comment

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

Is this used by multiple files? If not, maybe it can just live in the file that uses it.

Copy link
Author

Choose a reason for hiding this comment

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

This has been moved to the only file that uses it, index.tsx.

// TODO: perform any necessary cleanup or finalization
} else {
// if any required fields are missing, show an error message or prevent the user from exiting
alert("Please fill out all required fields.");
Copy link
Member

Choose a reason for hiding this comment

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

Is this code reachable? If not, why?

Form validation is a pain in the ass to do, but if we have this branch here that surfaces an error to the user, the user should have the information they need to solve the problem. If that's too much work, we need to report an error somehow.

Eg. If we are pretty sure this code never runs, leaving a line like the below would let future developers know that we never want to hit this branch.

throw new Error("Expected required fields to be filled out before attempting to exit");

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this line can be reached and can be thrown to the user. I have added it to the exitWizardAtEnd function as well.

Comment on lines 91 to 101
function exitWizardAtEnd() {
// any part of wizard state could be undefined, so unpack it all
const { groupId, email, phoneticsPreference, collectionId, whereFound} = wizardState;
// add checks here to make sure fields are defined
if (groupId !== undefined && email !== undefined && phoneticsPreference !== undefined && collectionId != undefined && whereFound !== undefined) {
// reassemble state here (without Partial<>)
const fullState: WizardState = { groupId, email, phoneticsPreference, collectionId, whereFound};
// dispatch the actions for each step
steps.forEach((step) => step.commitState(fullState, userStateContext));
}
}
Copy link
Member

Choose a reason for hiding this comment

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

how is this different from exitWizard? When does each get called?

Copy link
Author

Choose a reason for hiding this comment

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

One exits upon filling out all required fields, the other ends after advanced features have been filled out. I have updated exitWizard to exitWizardNoAdvanced to make this more clear.

return (
<userStateContext.Provider value={{ ...state, ...interactors, dispatch }}>
{children}
{(state.config.userEmail === null || state.config.groupId === null) && (
Copy link
Member

Choose a reason for hiding this comment

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

Should whereFound be on this list?

Maybe we should put this into a memo or something -- the condition is sort of complex to just shove inline like this (I know this is my code 👼)

Copy link
Author

Choose a reason for hiding this comment

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

I added the condition, could you help me with the memoization step? I'm confused on where to declare the memo of it all.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe this should just be a constant defined earlier in the function.

Eg. add this earlier in the func near where you are doing hooks n stuff

const userNeedsSetup = (state.config.userEmail === null || state.config.groupId === null)

Then replace the inline condition with

(userNeedsSetup && (...Modal...))

Copy link
Author

Choose a reason for hiding this comment

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

I've made this change to the above suggestion. It might also be useful to define an array which defines necessary information from the user (ie, state.config.userEmail, state.config.groupId, etc.) and just looping threw those elements.

Copy link
Member

@CharlieMcVicker CharlieMcVicker left a comment

Choose a reason for hiding this comment

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

World's smallest most annoying nitpick

goToNextStep,
goToPreviousStep,
}: StepProps): ReactElement {
var canGoToNextStep = collectionId !== undefined;
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be const -- var is evil and has terrible behavior!

Copy link
Author

Choose a reason for hiding this comment

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

I changed it to let so we'll be able to reassign it later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants