reusable components SelectInput and TextInput + CourseForm
parent
2fe0b6c647
commit
528c5715f3
|
@ -0,0 +1,49 @@
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
const SelectInput = ({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
onChange,
|
||||||
|
defaultOption,
|
||||||
|
value,
|
||||||
|
error,
|
||||||
|
options
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor={name}>{label}</label>
|
||||||
|
<div className="field">
|
||||||
|
{/* Note, value is set here rather than on the option - docs: https://facebook.github.io/react/docs/forms.html */}
|
||||||
|
<select
|
||||||
|
name={name}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
className="form-control"
|
||||||
|
>
|
||||||
|
<option value="">{defaultOption}</option>
|
||||||
|
{options.map((option) => {
|
||||||
|
return (
|
||||||
|
<option key={option.value} value={option.value}>
|
||||||
|
{option.text}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
{error && <div className="alert alert-danger">{error}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SelectInput.propTypes = {
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
defaultOption: PropTypes.string,
|
||||||
|
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
error: PropTypes.string,
|
||||||
|
options: PropTypes.arrayOf(PropTypes.object)
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectInput;
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
|
||||||
|
const TextInput = ({ name, label, onChange, placeholder, value, error }) => {
|
||||||
|
let wrapperClass = "form-group";
|
||||||
|
if (error && error.length > 0) {
|
||||||
|
wrapperClass += " " + "has-error";
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={wrapperClass}>
|
||||||
|
<label htmlFor={name}>{label}</label>
|
||||||
|
<div className="field">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name={name}
|
||||||
|
className="form-control"
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
{error && <div className="alert alert-danger">{error}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TextInput.propTypes = {
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
error: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TextInput;
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import TextInput from "../common/TextInput";
|
||||||
|
import SelectInput from "../common/SelectInput";
|
||||||
|
|
||||||
|
const CourseForm = ({
|
||||||
|
course,
|
||||||
|
authors,
|
||||||
|
onSave,
|
||||||
|
onChange,
|
||||||
|
saving = false,
|
||||||
|
errors = {}
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<form onSubmit={onSave}>
|
||||||
|
<h2>{course.id ? "Edit" : "Add"} Course</h2>
|
||||||
|
{errors.onSave && (
|
||||||
|
<div className="alert alert-danger" role="alert">
|
||||||
|
{errors.onSave}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<TextInput
|
||||||
|
name="title"
|
||||||
|
label="Title"
|
||||||
|
value={course.title}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.title}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectInput
|
||||||
|
name="authorId"
|
||||||
|
label="Author"
|
||||||
|
value={course.authorId || ""}
|
||||||
|
defaultOption="Select Author"
|
||||||
|
options={authors.map((author) => ({
|
||||||
|
value: author.id,
|
||||||
|
text: author.name
|
||||||
|
}))}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.author}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TextInput
|
||||||
|
name="category"
|
||||||
|
label="Category"
|
||||||
|
value={course.category}
|
||||||
|
onChange={onChange}
|
||||||
|
error={errors.category}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button type="submit" disabled={saving} className="btn btn-primary">
|
||||||
|
{saving ? "Saving..." : "Save"}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
CourseForm.propTypes = {
|
||||||
|
authors: PropTypes.array.isRequired,
|
||||||
|
course: PropTypes.object.isRequired,
|
||||||
|
errors: PropTypes.object,
|
||||||
|
onSave: PropTypes.func.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
saving: PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CourseForm;
|
Loading…
Reference in New Issue