This is the last class of our Gallery Of Horns. You have horned creatures displaying on the page. When you click on a beast, you increase its favorites and display it as a modal. We will be adding one more piece of functionality: filtering by numbers of horns.
Time Estimate For each of the features listed below, make an estimate of the time it will take you to complete the feature, and record your start and finish times for that feature:
Overview Read this overview. Reading
Video Watch the video for this class from the demo playlist.
Demonstration Look through these sample problems.
Challenges Navigate to the javascript folder within your data-structures-and-algorithms repository.
git checkout -b sort
npm run get-challenge 04
In your terminal, from the javascript folder, run npm test 04 to execute the tests in this file for this challenge.
At this point, you will see the failed tests scroll through your terminal window with a brief report of the number of failed tests at the bottom.
If you do not see this, verify your installation of Jest by typing npx jest –version in your terminal. Filename typos can make things break!
Write code to make the tests pass, one at a time. Let the error messages guide you.
Once the test is passing, refactor as needed, then move on to the next challenge.
Submission When you have completed the entire set of code challenges and all tests pass, create a pull request from your current branch to the main branch and merge it into main.
You will be able to see a test coverage report in GitHub on the Actions tab of your data-structures-and-algorithms repository. It should match what you saw on your terminal in the above steps. Your graders will be looking at this as well.
Submit a link to your pull request.
App.jsx
// useState is a "hook"
// It's a function that returns state and an update function
import { useState } from 'react'
import 'bootstrap/dist/css/bootstrap.min.css';
import People from './components/People.jsx';
import SelectedPerson from './components/SelectedPerson.jsx';
import originalFamilyData from "./assets/family.json";
function App() {
const [family, setFamily] = useState(originalFamilyData);
const [selectedPerson, setSelectedPerson] = useState({});
const [isSelectedPersonVisible, setIsSelectedPersonVisible] = useState(false);
function addFamilyMember() {
let newPerson = {
_id: Math.random(),
name: "Fred",
hair: "Grey",
pets: [],
age: 42,
votes: 0
};
setFamily([...family, newPerson]);
}
function selectPerson(person) {
setSelectedPerson(person);
setIsSelectedPersonVisible(true);
}
function handleCloseModal() {
setIsSelectedPersonVisible(false);
}
function handleVote(data) {
let newFamily = family.map(person => {
if (data._id === person._id) {
person.votes++;
}
return person;
});
setFamily(newFamily);
handleCloseModal();
}
return (
<>
<div>Family Members: {family.length}</div>
<button onClick={addFamilyMember}>Add One</button>
<People handleSelectPerson={selectPerson} list={family} />
<SelectedPerson
show={isSelectedPersonVisible}
handleClose={handleCloseModal}
handleVote={handleVote}
person={selectedPerson}
/>
</>
);
}
export default App;
People.jsx
import React from 'react';
import CardGroup from 'react-bootstrap/CardGroup';
import Form from 'react-bootstrap/Form';
import Person from './Person.jsx';
class People extends React.Component {
constructor(props) {
super(props);
this.state = {
name: 'The Cokos Clan',
address: 'Lynnwood, Wa',
family: props.list,
displayFamily: props.list,
};
}
changeAddress = () => {
this.setState({ ...this.state, address: "Wenatchee, WA" });
}
handleFilter = (e) => {
let age = e.target.value;
let filteredFamily = this.state.family.filter(person => person.age >= age);
this.setState({ ...this.state, displayFamily: filteredFamily });
}
render() {
return (
<>
<h2>Meet {this.state.name} from {this.state.address}</h2>
<div>
<button onClick={this.changeAddress}>Change</button>
</div>
<Form>
<Form.Label htmlFor="inputPassword5">
Password</Form.Label>
<Form.Control
type="number"
id="age"
placeholder="Enter Age"
onChange={this.handleFilter}
aria-describedby="passwordHelpBlock"
/>
</Form>
<CardGroup>
{this.state.displayFamily.map(person =>
<Person
handleSelectPerson={this.props.handleSelectPerson}
key={person._id}
person={person}
/>
)}
</CardGroup>
</>
)
}
}
export default People;
Person.jsx
import React from 'react';
import Card from 'react-bootstrap/Card';
import Button from 'react-bootstrap/Button';
function Person(props) {
function handleClick() {
props.handleSelectPerson(props.person);
}
return (
<Card style=>
<Card.Body>
<Card.Title>{props.person.name}</Card.Title>
<Card.Text>
Votes: {props.person.votes}
</Card.Text>
{
props.person.votes >= 1 ? null : <Button variant="primary" onClick={handleClick}>Pick Me!</Button>
}
</Card.Body>
</Card>
)
}
export default Person;
SelectedPerson.jsx
import React from 'react';
import Card from 'react-bootstrap/Card';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
function SelectedPerson(props) {
return (
<Modal show={props.show} onHide={props.handleClose}>
<Modal.Header closeButton>
<Modal.Title>{props.person.name}</Modal.Title>
</Modal.Header>
<Modal.Body>Votes: {props.person.votes}</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={props.handleClose}>
Close
</Button>
<Button variant="primary" onClick={() => props.handleVote(props.person)}>
Vote For Me
</Button>
</Modal.Footer>
</Modal>
)
}
export default SelectedPerson;
Statement on why this topic matters as it relates to what I’m studying in this module:
React forms enable efficient management of user input and state, and the ternary operator simplifies conditional rendering.
<input>, <textarea>, or <select>, whose value is controlled by React state. The component maintains its own state and updates it based on user input, allowing React to be the “single source of truth” for the form’s data.event.target.value property. This value represents the current content of the input field and can be used to update the React state accordingly.condition ? value if true : value if falseif(x===y){
console.log(true);
} else {
console.log(false);
}
x === y ? console.log(true) : console.log(false);Retrospectives are a critical part of Agile and typically take the form of meetings held by a team at the end of a sprint cycle. To get us acclimated to that process, we will use the format of retrospectives to guide today’s reflection.
This article gives a nice overview of the role of retrospectives.