Skip to content

Instantly share code, notes, and snippets.

@jeffeb3
Last active December 31, 2018 23:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeffeb3/b8eb060a564ca767679c6baff7351854 to your computer and use it in GitHub Desktop.
Save jeffeb3/b8eb060a564ca767679c6baff7351854 to your computer and use it in GitHub Desktop.
Trying out a wine scoring thing using react and boostrap but not using npm...
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Flask React</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- styles -->
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div id="root"></div>
</div>
<!-- scripts -->
<!-- Reactstrap Required dependencies -->
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/prop-types/15.6.1/prop-types.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/react/16.3.2/umd/react.production.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.2/umd/react-dom.production.min.js"></script>
<!-- Reactstrap Optional dependencies -->
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/react-transition-group/2.2.1/react-transition-group.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/react-popper/0.10.4/umd/react-popper.min.js"></script>
<!-- Reactstrap -->
<script type="text/javascript" src="https://unpkg.com/reactstrap@6.0.1/dist/reactstrap.full.min.js"></script>
<!-- babel for converting the script -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel" charset="utf-8">
console.log("Hello, this is a log statement");
// "Import" the components from Reactstrap
const {
Button,
ButtonToolbar,
Card,
CardBody,
CardHeader,
CardText,
Collapse,
Form,
FormGroup,
ListGroup,
ListGroupItem,
} = Reactstrap;
class WineHeader extends React.Component {
render() {
return (
<div>
<h3>Hello {this.props.username}, You've tasted {this.props.tasted} wines and you have liked {this.props.liked} of them.</h3>
</div>
)
}
};
class WineFooter extends React.Component {
render() {
return (
<div>
<h3>When you're totally done, click this submit button</h3>
<Button color="primary">Submit Scores</Button>
</div>
)
}
};
class ScoreButton extends React.Component {
render() {
return (
<Button
color={this.props.chosenScore === this.props.value ? "primary" : "secondary"}
active={this.props.chosenScore === this.props.value}
onClick={() => this.props.doClick(this.props.value)}
>
{this.props.value}
</Button>
)
}
};
class WineScore extends React.Component {
constructor (props) {
super(props);
this.state = {
expanded: false,
};
this.onClick = this.onClick.bind(this);
}
onClick() {
this.setState({ expanded: !this.state.expanded });
}
render() {
let scores = Array(8).fill().map((_, i) => {
return (<ScoreButton value={i+1} chosenScore={this.props.currentScore} doClick={(score) => this.props.doClick(this.props.wineNum, score)}/>);
});
let activeClassName = "";
if (this.state.expanded) {
activeClassName = "active";
}
return (
<ListGroupItem>
<ListGroup>
<ListGroupItem className={activeClassName} onClick={this.onClick}>
<h5>Wine {this.props.wineNum + 1}</h5>
</ListGroupItem>
<Collapse isOpen={this.state.expanded}>
<ListGroupItem>
<ButtonToolbar>
{scores}
</ButtonToolbar>
</ListGroupItem>
</Collapse>
</ListGroup>
</ListGroupItem>
)
};
};
class WineList extends React.Component {
render() {
let wineScores = Array(this.props.numWines).fill().map((_,i) => {
return <WineScore wineNum={i} currentScore={this.props.scores[i]} doClick={this.props.doClick}/>
});
return (
<ListGroup>
{wineScores}
</ListGroup>
)
}
};
class UserPage extends React.Component {
constructor (props) {
super(props);
this.state = {
// This currentScore object is where the scores get filled at the beginning. This might
// be where you would populate it from the stored information in Python.
currentScore: Array(props.numWines).fill(0),
// These items are computed, so they may not belong in state, but it was an easy place
// to put them.
tasted: 0,
liked: 0,
};
this.setScore = this.setScore.bind(this);
}
// setScore gets called way down on each button, and it gets called with the wine number and
// the score written on the button. This updates the state, which causes things to be
// redrawn, and make it look like it's been selected. It also is where you would attach any
// external calls to ajax, or a post call, or whatever.
setScore(wineNum, score) {
// Set the score for this press.
this.state.currentScore[wineNum] = score;
// Compute some "stats"
this.state.tasted = 0;
this.state.liked = 0;
this.state.currentScore.forEach((score) => {
if (score !== 0) {
this.state.tasted += 1;
}
if (score > 4) {
this.state.liked += 1;
}
});
// Reset the "state", which will force a redraw.
this.setState({
currentScore: [...this.state.currentScore],
tasted: this.state.tasted,
liked: this.state.liked,
});
// Do whatever you want right here. The current scores just changed.
}
render() {
return (
<div>
<WineHeader username="Jeff" tasted={this.state.tasted} liked={this.state.liked}/>
<WineList numWines={4} scores={this.state.currentScore} doClick={this.setScore}/>
<WineFooter/>
</div>
)
};
};
// Render a Reactstrap Button element onto root
ReactDOM.render(
React.createElement(UserPage, null),
document.getElementById('root')
);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment