reacts-test-lmbuffetti
Version:
Simple starter package for Redux with React and Babel support
322 lines (294 loc) • 10.7 kB
JavaScript
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
// component that renders a single product
var ProductRow = React.createClass({
render: function() {
return (
<tr>
<td>{this.props.product.name}</td>
<td>{this.props.product.description}</td>
<td>€ {parseFloat(this.props.product.price).toFixed(2)}</td>
<td>{this.props.product.category_name}</td>
<td>
<a href='#'
onClick={() => this.props.changeAppMode('readOne', this.props.product.id)}
className='btn btn-info m-r-1em'> Read
</a>
<a href='#'
onClick={() => this.props.changeAppMode('update', this.props.product.id)}
className='btn btn-primary m-r-1em'> Edit
</a>
<a
onClick={() => this.props.changeAppMode('delete', this.props.product.id)}
className='btn btn-danger'> Delete
</a>
</td>
</tr>
);
}
});
// component for the whole products table
var ProductsTable = React.createClass({
render: function() {
var rows = this.props.products
.map(function(product, i) {
return (
<ProductRow
key={i}
product={product}
changeAppMode={this.props.changeAppMode} />
);
}.bind(this));
return(
!rows.length
? <div className='alert alert-danger'>No products found.</div>
:
<table className='table table-bordered table-hover'>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Price</th>
<th>Category</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{rows}
</tbody>
</table>
);
}
});
// component that contains all the logic and other smaller components
// that form the Read Products view
var TopActionsComponent = React.createClass({
render: function() {
return (
<div>
<a href='#'
onClick={() => this.props.changeAppMode('create')}
className='btn btn-primary margin-bottom-1em'> Create product
</a>
</div>
);
}
});
var ReadProductsComponent = React.createClass({
getInitialState: function() {
return {
products: []
};
},
// on mount, fetch all products and stored them as this component's state
componentDidMount: function() {
this.serverRequest = $.get("api/read_all_products.php", function (products) {
this.setState({
products: JSON.parse(products)
});
}.bind(this));
},
// on unmount, kill product fetching in case the request is still pending
componentWillUnmount: function() {
this.serverRequest.abort();
},
render: function() {
// list of products
var filteredProducts = this.state.products;
$('.page-header h1').text('Read Products');
return (
<div className='overflow-hidden'>
<TopActionsComponent changeAppMode={this.props.changeAppMode} />
<ProductsTable
products={filteredProducts}
changeAppMode={this.props.changeAppMode} />
</div>
);
}
});
var MainApp = React.createClass({
getInitialState: function() {
return {
currentMode: 'read',
productId: null
};
},
changeAppMode: function(newMode, productId){
this.setState({currentMode: newMode});
if(productId !== undefined){
this.setState({productId: productId});
}
},
render: function() {
var modeComponent =
<ReadProductsComponent
changeAppMode={this.changeAppMode} />;
switch(this.state.currentMode){
case 'read':
break;
case 'create':
modeComponent = <CreateProductComponent changeAppMode={this.changeAppMode}/>;
break;
default:
break;
}
return modeComponent;
}
});
var CreateProductComponent = React.createClass({
getInitialState: function() {
return {
categories: [],
selectedCategoryId: -1,
name: '',
description: '',
price: '',
successCreation: null
};
},
componentDidMount: function() {
this.serverRequest = $.get("api/read_all_categories.php", function (categories) {
this.setState({
categories: JSON.parse(categories)
});
}.bind(this));
$('.page-header h1').text('Create product');
},
componentWillUnmount: function() {
this.serverRequest.abort();
},
// handle category change
onCategoryChange: function(e) {
this.setState({selectedCategoryId: e.target.value});
},
// handle name change
onNameChange: function(e) {
this.setState({name: e.target.value});
},
// handle description change
onDescriptionChange: function(e) {
this.setState({description: e.target.value});
},
// handle price change
onPriceChange: function(e) {
this.setState({price: e.target.value});
},
onSave: function(e){
$.post("api/create_product.php", {
name: this.state.name,
description: this.state.description,
price: this.state.price,
category_id: this.state.selectedCategoryId
},
function(res){
this.setState({successCreation: res});
this.setState({name: ""});
this.setState({description: ""});
this.setState({price: ""});
this.setState({selectedCategoryId: -1});
}.bind(this)
);
e.preventDefault();
},
render: function() {
// make categories as option for the select tag.
var categoriesOptions = this.state.categories.map(function(category){
return (
<option key={category.id} value={category.id}>{category.name}</option>
);
});
/*
- tell the user if a product was created
- tell the user if unable to create product
- button to go back to products list
- form to create a product
*/
return (
<div>
{
this.state.successCreation == "true" ?
<div className='alert alert-success'>
Product was saved.
</div>
: null
}
{
this.state.successCreation == "false" ?
<div className='alert alert-danger'>
Unable to save product. Please try again.
</div>
: null
}
<a href='#'
onClick={() => this.props.changeAppMode('read')}
className='btn btn-primary margin-bottom-1em'> Read Products
</a>
<form onSubmit={this.onSave}>
<table className='table table-bordered table-hover'>
<tbody>
<tr>
<td>Name</td>
<td>
<input
type='text'
className='form-control'
value={this.state.name}
required
onChange={this.onNameChange} />
</td>
</tr>
<tr>
<td>Description</td>
<td>
<textarea
type='text'
className='form-control'
required
value={this.state.description}
onChange={this.onDescriptionChange}>
</textarea>
</td>
</tr>
<tr>
<td>Price ($)</td>
<td>
<input
type='number'
step="0.01"
className='form-control'
value={this.state.price}
required
onChange={this.onPriceChange}/>
</td>
</tr>
<tr>
<td>Category</td>
<td>
<select
onChange={this.onCategoryChange}
className='form-control'
value={this.state.selectedCategoryId}>
<option value="-1">Select category...</option>
{categoriesOptions}
</select>
</td>
</tr>
<tr>
<td></td>
<td>
<button
className='btn btn-primary'
onClick={this.onSave}>Save</button>
</td>
</tr>
</tbody>
</table>
</form>
</div>
);
}
});
ReactDOM.render(
<MainApp />,
document.getElementById('content')
);