Heathercoraje / pomotris-vh

Pomodoro time tracker with colorful records, trust me. you'd love it :heart: Built with React

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Code Style Refactors

iwilsonq opened this issue Β· comments

One more thing! Most of the things I'd improve are things that your linter actually pick up, just be sure to get eslint working with your IDE πŸ‘

For example, using destructuring in Timers.jsx:

handleRecordSubmit = () => {
  const { category, title, startTime, duration, onRecordSubmit } = this.state;
  const id = uuid();
  onRecordSubmit({ category, title, startTime, duration, id });
};

Regarding the assignment of const id = uuid() here, this operation is usually done on the backend, sometimes even by the database you're using. In the spirit of keeping backend concerns separate from the client, I'd move this to your apiLocalStorage service that 'mocks' the backend, namely to the saveRecords method.

For now, saving the whole list of records works with smaller data, but I'd recommend creating a saveOne or insertOne method on the 'backend' service and just call that method multiple times. This'll make it easier to compose API calls on the backend; remember that each record might have dozens of fields, it would be quite a lot of work to save multiple records at a time. On top of that there might be a pipeline of 6 methods or hooks that need to be called on the backend for each insertOne call in order to keep the integrity all of the other data in order.

That tangent aside, I think for the scope of this project, you've implemented it pretty well πŸ˜„

Inside CategorySetting.jsx there are some concerns with naming. The Field component should be called CategoryColorForm or even CategoryColorGroup. For the fields field in CategorySetting state, I think that fields should be called categories and category should be renamed to name, since it feels like from an outsiders perspective that fields is pretty broad and can be interpreted for many different parts of this app.

To summarize that, ive updated the code of CategorySetting's render method

	render() {
		return (
			<div className="setting">
				<hr />
				<p className='setting-title'>Category Setting</p>
                                <form onSubmit={this.onSave}>
                                 {this.state.categories.map((category, i) => (
			           <CategoryColorGroup key={i} id={i} 
                                     data={category}
                                     onInputChange={this.onInputChange} 
                                   />
		                 ));}
                               </form>
				
				<button className="button-modal-save" onClick={this.onSave}>
					Save
				</button>
				<button className="button-modal-cancel" onClick={this.onCancelClick}>
					Cancel
				</button>
			</div>
		);
	}

By wrapping all of the category color groups in a form and giving that form an onSubmit prop, the user can submit it by pressing enter. They can also click the save button as it stands. The big thing to note is that there is only one form component and n inputs, one for each category. I think this makes sense with the current setup, I wouldn't expect n forms within the same modal after all.

I'll stop for now, comment if you have any questions πŸ”¨

handleRecordSubmit = () => {
  const { category, title, startTime, duration, onRecordSubmit } = this.state;
  const id = uuid();
  onRecordSubmit({ category, title, startTime, duration, id });
};

@iwilsonq But onRecordSubmit is a function, a prop from a parent component.
Do you mean to suggest adding onRecordSubmit in state of this component? and just use variable?

Oh I see my error, I meant to take onRecordSubmit from props! I intended to say that there are places where es6 destructuring can make it cleaner and easier to read πŸ˜… . Compare that snippet to this one

handleRecordSubmit = () => {
  const category = this.state.category;
  const task = this.state.task;
  const startTime = this.state.startTime;
  const duration = this.state.duration;
  const id = uuid();
  this.props.onRecordSubmit({ category, task, startTime, duration, id });
};

because jsx component has be inside a enclosing tag, so I am adding

as wrapper

class CategoryColorGroup extends Component {
	render() {
		const ID = this.props.id;
		const category = this.props.data.category;
		const color = this.props.data.color;
		return (
			<div className="category-color-form">
				<input
					id={ID}
					name="color"
					type="color"
					value={color}
					className="input-color"
					onChange={this.props.onInputChange}
				/>
				<input
					id={ID}
					name="category"
					value={category}
					className="input-category"
					placeholder="new category"
					onChange={this.props.onInputChange}
					autoComplete="off"
				/>
			</div>
		);
	}
}

Then, though I have only one form and also onSubmit fn() attached, when I press enter on CategoryColorGroup, function does not get invoked. Is it because I have div as wrapper?

	render() {
		return (
			<div className="setting">
				<hr />
				<p className="setting-title">Category Setting</p>
				<form onSubmit={this.onSaveClick}>
					{this.state.categories.map((category, i) => (
						<CategoryColorGroup
						key={i}
						id={i}
						data={category}
						onInputChange={this.onInputChange}
						/>
					))}
				</form>
				<button className="button-modal-save" onClick={this.onSaveClick}>
					Save
				</button>
				<button className="button-modal-cancel" onClick={this.onCancelClick}>
					Cancel
				</button>
			</div>
		);
	}
}

@iwilsonq also, did you mean to say to destruct ones that are not functions as such below?

handleRecordSubmit = () => {
		const { category, task, startTime, duration, onRecordSubmit} = this.state;
		const color = generateRandomColor(category, this.props.categories);
		const id = generateID();
		this.props.onRecordSubmit({ category, task, startTime, duration, color, id });
	};

Yes like that basically, or this

handleRecordSubmit = () => {
  const { category, task, startTime, duration} = this.state;
  const color = generateRandomColor(category, this.props.categories);
  const id = generateID();
  this.props.onRecordSubmit({ category, task, startTime, duration, color, id });
};

As for the form, it should work I think, can you use console.log and see if this.onSave is being called?

if you refer to this.onSaveClick it does not get invoked.

Well looking back, the categories probably dont need to be rendered from state, you should try to keep the state of your component as light as possible. There are two ways to do this here:

  1. Controlled component form input. You'll use component state in CategorySettings to store the currently entered values of the inputs. When onSubmit is called from the form, the onSave function takes those values out of state and submits them.

  2. Regular HTML form. You'll just have a bunch of tags under your form, when you hit submit, your form will have a reference to those inputs. This is more fragile/static since it doesnt rely on component state.

Basically, use state to hold the values you care about. Don't use state to render input fields at all, unless its like a showField boolean.

If I understood correctly, the first option is basically what the current codes are doing. onInputChange controls the input as it changes and stored them as state. then OnSaveClick, it submits category data inside state.

also still not understanding why it does not log out anything.

onSaveClick = () => {
  console.log('hello world')
  const data = this.state.categories;
  this.props.onSave(data);
  this.props.closeModal();
};

onCancelClick = () => {
  this.props.closeModal();
};
render() {
  return (
    <div className="setting">
      <hr />
      <p className="setting-title">Category Setting</p>
      <form onSubmit={this.onSaveClick}>
	  {this.state.categories.map((category, i) => (
	  <CategoryColorGroup
 	     key={i}
	     id={i}
	     data={category}
	     onInputChange={this.onInputChange}
	   />
	  ))}
       </form>
       <button className="button-modal-save" onClick={this.onSaveClick}>
          Save
       </button>
       <button className="button-modal-cancel" onClick={this.onCancelClick}>
	  Cancel
       </button>
     </div>
    ); 
  }
}