code from amapei
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
package react.order;
|
||||
import react.ReactDOM;
|
||||
import react.ReactComponent;
|
||||
import react.ReactMacro.jsx;
|
||||
import Common;
|
||||
import utils.HttpUtil;
|
||||
import react.product.ProductSelect;
|
||||
import react.router.Redirect;
|
||||
import react.router.Link;
|
||||
|
||||
|
||||
/**
|
||||
* A box to add an order to a member
|
||||
* @author fbarbut
|
||||
*/
|
||||
class InsertOrder extends react.ReactComponentOfPropsAndState<{contractId:Int,userId:Int,distributionId:Int,onInsert:UserOrder->Void},{products:Array<ProductInfo>,error:String,selected:Int}>
|
||||
{
|
||||
|
||||
public function new(props)
|
||||
{
|
||||
super(props);
|
||||
state = {products:[],error:null,selected:null};
|
||||
}
|
||||
|
||||
override function componentDidMount()
|
||||
{
|
||||
//load product list
|
||||
HttpUtil.fetch("/api/product/get/", GET, {contractId:props.contractId},PLAIN_TEXT)
|
||||
.then(function(data:String) {
|
||||
|
||||
/*var data : {products:Array<ProductInfo>} = haxe.Json.parse(data);
|
||||
for( p in data.products) {
|
||||
p.unitType = Type.createEnumIndex(UnitType,untyped p.unitType);
|
||||
}*/
|
||||
|
||||
var data : {products:Array<ProductInfo>} = tink.Json.parse(data);
|
||||
setState({products:data.products, error:null,selected:null});
|
||||
|
||||
}).catchError(function(data) {
|
||||
var data = Std.string(data);
|
||||
trace("Error",data);
|
||||
if(data.substr(0,1)=="{"){
|
||||
//json error from server
|
||||
var data : ErrorInfos = haxe.Json.parse(data);
|
||||
setState(cast {error:data.error.message} );
|
||||
}else{
|
||||
//js error
|
||||
setState(cast {error:data} );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
override public function render(){
|
||||
//redirect to orderBox if a product is selected
|
||||
var redirect = if(state.selected!=null) jsx('<$Redirect to="/" />') else null;
|
||||
|
||||
return jsx('
|
||||
<div>
|
||||
$redirect
|
||||
<h3>Choisissez le produit à ajouter</h3>
|
||||
<$Link className="btn btn-default" to="/"><span className="glyphicon glyphicon-chevron-left"></span> Retour</$Link>
|
||||
<$Error error="${state.error}" />
|
||||
<hr />
|
||||
<$ProductSelect onSelect=$onSelectProduct products=${state.products} />
|
||||
</div>
|
||||
');
|
||||
}
|
||||
|
||||
function onSelectProduct(p:ProductInfo){
|
||||
var uo : UserOrder = cast {
|
||||
id:null,
|
||||
product:p,
|
||||
quantity:1,
|
||||
productId:p.id,
|
||||
productPrice:p.price,
|
||||
paid:false,
|
||||
invert:false,
|
||||
user2:null
|
||||
};
|
||||
props.onInsert(uo);
|
||||
setState(cast {selected:p.id});
|
||||
|
||||
//do not insert order now, just warn the OrderBox
|
||||
/*
|
||||
//insert order
|
||||
var data = [{id:null,productId:p.id,qt:1,paid:false,invert:false,user2:null} ];
|
||||
var req = {
|
||||
orders:haxe.Json.stringify(data),
|
||||
distributionId : props.distributionId,
|
||||
contractId : props.contractId
|
||||
};
|
||||
var r = HttpUtil.fetch("/api/order/update/"+props.userId, POST, req, JSON);
|
||||
r.then(function(d:Dynamic) {
|
||||
|
||||
if (Reflect.hasField(d, "error")) {
|
||||
setState(cast {error:d.error.message});
|
||||
}else{
|
||||
//WOOT
|
||||
//trace("OK");
|
||||
//go to OrderBox with a redirect
|
||||
setState(cast {selected:p.id});
|
||||
}
|
||||
}).catchError(function(d) {
|
||||
trace("PROMISE ERROR", d);
|
||||
setState(cast {error:d.error.message});
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package react.order;
|
||||
import react.ReactDOM;
|
||||
import react.ReactComponent;
|
||||
import react.ReactMacro.jsx;
|
||||
import Common;
|
||||
import react.product.Product;
|
||||
|
||||
/**
|
||||
* A User order
|
||||
* @author fbarbut
|
||||
*/
|
||||
class Order extends react.ReactComponentOfPropsAndState<{order:UserOrder,onUpdate:UserOrder->Void,parentBox:react.order.OrderBox},{order:UserOrder,inputValue:String}>
|
||||
{
|
||||
var hasPayments :Bool;
|
||||
var currency : String;
|
||||
|
||||
public function new(props)
|
||||
{
|
||||
super(props);
|
||||
state = {order:props.order,inputValue:null};
|
||||
hasPayments = props.parentBox.props.hasPayments;
|
||||
currency = props.parentBox.props.currency;
|
||||
|
||||
if (state.order.productUnit == null) state.order.productUnit = Piece;
|
||||
if (state.order.productQt == null) state.order.productQt = 1;
|
||||
|
||||
state.inputValue = if ( isSmartQtInput(state.order) ){
|
||||
Std.string(round(state.order.quantity * state.order.productQt));
|
||||
}else{
|
||||
Std.string(state.order.quantity);
|
||||
}
|
||||
}
|
||||
|
||||
override public function render(){
|
||||
var o = state.order;
|
||||
/*var unit = if (o.productHasFloatQt || o.productHasVariablePrice){
|
||||
jsx('<div className="col-md-1">${Formatting.unit(o.productUnit)}</div>');
|
||||
}else{
|
||||
jsx('<div className="col-md-1"></div>');
|
||||
}*/
|
||||
|
||||
/*
|
||||
//use smart qt only if hasFloatQt
|
||||
var productName = if (o.productHasFloatQt || o.productHasVariablePrice){
|
||||
jsx('<div className="col-md-3">${o.productName}</div>');
|
||||
}else{
|
||||
jsx('<div className="col-md-3">${o.productName} ${o.productQt} ${Formatting.unit(o.productUnit)}</div>');
|
||||
}
|
||||
*/
|
||||
/*var productName = if (o.productHasFloatQt || o.productHasVariablePrice){
|
||||
jsx('<div className="col-md-3">${o.productName}</div>');*/
|
||||
|
||||
var input = if (isSmartQtInput(o)){
|
||||
jsx('<div className="input-group">
|
||||
<input type="text" className="form-control input-sm text-right" value="${state.inputValue}" onChange=${onChange} onKeyPress=${onKeyPress}/>
|
||||
<div className="input-group-addon">${Formatting.unit(o.productUnit)}</div>
|
||||
</div>');
|
||||
}else{
|
||||
jsx('<div className="input-group">
|
||||
<input type="text" className="form-control input-sm text-right" value="${state.inputValue}" onChange=${onChange} onKeyPress=${onKeyPress}/>
|
||||
</div>');
|
||||
}
|
||||
|
||||
var alternated = if(props.parentBox.props.contractType==0 && props.parentBox.state.users!=null){
|
||||
//constant orders
|
||||
var options = props.parentBox.state.users.map(function(x) return jsx('<option key=${x.id} value=${x.id}>${x.name}</option>') );
|
||||
|
||||
var checkbox = if(o.invertSharedOrder){
|
||||
jsx('<input data-toggle="tooltip" title="Inverser l\'alternance" checked="checked" type="checkbox" value="1" onChange=$onChangeInvert />');
|
||||
}else{
|
||||
jsx('<input data-toggle="tooltip" title="Inverser l\'alternance" type="checkbox" value="1" onChange=$onChangeInvert />');
|
||||
}
|
||||
|
||||
jsx('<div>
|
||||
<select className="form-control input-sm" style=${{width:"150px",display:"inline-block"}} onChange=${onChangeUser2} value=${o.userId2}>
|
||||
<option value="0">-</option>
|
||||
$options
|
||||
</select>
|
||||
$checkbox
|
||||
</div>');
|
||||
}else{
|
||||
null;
|
||||
}
|
||||
|
||||
return jsx('<div className="productOrder row">
|
||||
<div className="col-md-4">
|
||||
<$Product productInfo=${o.product} />
|
||||
</div>
|
||||
|
||||
<div className="col-md-1 ref">
|
||||
${o.productRef}
|
||||
</div>
|
||||
|
||||
<div className="col-md-1">
|
||||
${round(o.quantity * o.productPrice)} ${currency}
|
||||
</div>
|
||||
|
||||
<div className="col-md-2">
|
||||
$input
|
||||
${makeInfos()}
|
||||
</div>
|
||||
|
||||
${paidInput()}
|
||||
|
||||
<div className="col-md-3">$alternated</div>
|
||||
|
||||
</div>');
|
||||
}
|
||||
|
||||
function round(f){
|
||||
return Formatting.formatNum(f);
|
||||
}
|
||||
|
||||
function paidInput(){
|
||||
if(hasPayments) return null;
|
||||
if(state.order.paid){
|
||||
return jsx('<div className="col-md-1"><input type="checkbox" name="paid" value="1" checked="checked" onChange=${onChangePaid} /></div>');
|
||||
}else{
|
||||
return jsx('<div className="col-md-1"><input type="checkbox" name="paid" value="1" onChange=${onChangePaid} /></div>');
|
||||
}
|
||||
}
|
||||
|
||||
function makeInfos(){
|
||||
var o = state.order;
|
||||
return if ( isSmartQtInput(o) ){
|
||||
jsx('<div className="infos">
|
||||
<b> ${round(o.quantity)} </b> x <b>${o.productQt} ${Formatting.unit(o.productUnit)}</b > ${o.productName}
|
||||
</div>');
|
||||
}else{
|
||||
null;
|
||||
}
|
||||
}
|
||||
|
||||
function isSmartQtInput(o:UserOrder):Bool{
|
||||
return o.product.hasFloatQt || o.product.variablePrice || o.product.wholesale;
|
||||
}
|
||||
|
||||
function onChange(e:js.html.Event){
|
||||
e.preventDefault();
|
||||
var value :String = untyped (e.target.value == "") ? "0" : e.target.value;
|
||||
state.inputValue = value;
|
||||
var v = Formatting.parseFloat(value);
|
||||
var o = state.order;
|
||||
if ( isSmartQtInput(o) ){
|
||||
//the value is a smart qt, so we need re-compute the quantity
|
||||
o.quantity = v / o.productQt;
|
||||
}else{
|
||||
o.quantity = v;
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
if (props.onUpdate != null) props.onUpdate(state.order);
|
||||
}
|
||||
|
||||
function onChangePaid(e:js.html.Event){
|
||||
state.order.paid = untyped e.target.checked;
|
||||
this.setState(state);
|
||||
if (props.onUpdate != null) props.onUpdate(state.order);
|
||||
}
|
||||
|
||||
function onChangeInvert(e:js.html.Event){
|
||||
state.order.invertSharedOrder = untyped e.target.checked;
|
||||
this.setState(state);
|
||||
if (props.onUpdate != null) props.onUpdate(state.order);
|
||||
}
|
||||
|
||||
function onChangeUser2(e:js.html.Event){
|
||||
var v = Std.parseInt(untyped e.target.value);
|
||||
state.order.userId2 = v==0 ? null : v;
|
||||
this.setState(state);
|
||||
if (props.onUpdate != null) props.onUpdate(state.order);
|
||||
}
|
||||
|
||||
function onKeyPress(event:js.html.KeyboardEvent){
|
||||
/*if(event.key == 'Enter'){
|
||||
trace('enter !');
|
||||
}*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package react.order;
|
||||
import react.ReactDOM;
|
||||
import react.ReactComponent;
|
||||
import react.ReactMacro.jsx;
|
||||
import Common;
|
||||
import utils.HttpUtil;
|
||||
import react.router.HashRouter;
|
||||
import react.router.Route;
|
||||
import react.router.Switch;
|
||||
import react.router.Link;
|
||||
|
||||
typedef OrderBoxState = {
|
||||
orders:Array<UserOrder>,
|
||||
error:String,
|
||||
users:Null<Array<UserInfo>>,
|
||||
};
|
||||
typedef OrderBoxProps = {
|
||||
userId:Int,
|
||||
distributionId:Int,
|
||||
contractId:Int,
|
||||
contractType:Int,
|
||||
date:String,
|
||||
place:String,
|
||||
userName:String,
|
||||
onValidate:Void->Void,
|
||||
currency:String,
|
||||
hasPayments:Bool
|
||||
};
|
||||
|
||||
/**
|
||||
* A box to edit/add orders of a member
|
||||
* @author fbarbut
|
||||
*/
|
||||
class OrderBox extends react.ReactComponentOfPropsAndState<OrderBoxProps,OrderBoxState>
|
||||
{
|
||||
|
||||
public function new(props)
|
||||
{
|
||||
super(props);
|
||||
state = { orders : [], error : null, users:null };
|
||||
}
|
||||
|
||||
override function componentDidMount()
|
||||
{
|
||||
|
||||
//request api avec user + distrib
|
||||
HttpUtil.fetch("/api/order/get/"+props.userId, GET, {distributionId:props.distributionId,contractId:props.contractId}, PLAIN_TEXT)
|
||||
.then(function(data:String) {
|
||||
|
||||
var data : {orders:Array<UserOrder>} = tink.Json.parse(data);
|
||||
/*for( o in orders){
|
||||
//convert ints to enums, enums have been lost in json serialization
|
||||
o.productUnit = Type.createEnumIndex(Unit, cast o.productUnit );
|
||||
}*/
|
||||
setState({orders:data.orders, error:null});
|
||||
|
||||
if(props.contractType==0) loadUsers();
|
||||
|
||||
}).catchError(function(data) {
|
||||
var data = Std.string(data);
|
||||
trace("Error",data);
|
||||
if(data.substr(0,1)=="{"){
|
||||
//json error from server
|
||||
var data : ErrorInfos = haxe.Json.parse(data);
|
||||
setState( cast {error:data.error.message} );
|
||||
}else{
|
||||
//js error
|
||||
setState( cast {error:data} );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* load user list when contract is constant orders
|
||||
*/
|
||||
function loadUsers(){
|
||||
HttpUtil.fetch("/api/user/getFromGroup/", GET, {}, PLAIN_TEXT)
|
||||
.then(function(data:String) {
|
||||
|
||||
var data : {users:Array<UserInfo>} = tink.Json.parse(data);
|
||||
setState({users:data.users, error:null});
|
||||
|
||||
}).catchError(function(data) {
|
||||
|
||||
var data = Std.string(data);
|
||||
if(data.substr(0,1)=="{"){
|
||||
//json error from server
|
||||
var data : ErrorInfos = haxe.Json.parse(data);
|
||||
setState( cast {error:data.error.message} );
|
||||
}else{
|
||||
//js error
|
||||
setState( cast {error:data} );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
override public function render(){
|
||||
|
||||
//edit orders
|
||||
|
||||
|
||||
var renderOrders = this.state.orders.map(function(o){
|
||||
var k :String = if(o.id!=null) {
|
||||
Std.string(o.id);
|
||||
} else {
|
||||
o.productId+"-"+Std.random(99999);
|
||||
};
|
||||
return jsx('<$Order key="$k" order="$o" onUpdate=$onUpdate parentBox=${this} />') ;
|
||||
} );
|
||||
|
||||
|
||||
var delivery = if(props.date==null){
|
||||
null;
|
||||
}else{
|
||||
jsx('<p>Pour la livraison du <b>${props.date}</b> à <b>${props.place}</b></p>');
|
||||
}
|
||||
|
||||
var renderOrderBox = function() return jsx('
|
||||
<div onKeyPress=${onKeyPress}>
|
||||
<h3>Commandes de ${props.userName}</h3>
|
||||
$delivery
|
||||
<$Error error="${state.error}" />
|
||||
<hr/>
|
||||
<div className="row tableHeader">
|
||||
<div className="col-md-4">Produit</div>
|
||||
<div className="col-md-1">Ref.</div>
|
||||
<div className="col-md-1">Prix</div>
|
||||
<div className="col-md-2">Qté</div>
|
||||
<div className="col-md-1">Payé</div>
|
||||
<div className="col-md-3">Alterné avec</div>
|
||||
</div>
|
||||
${renderOrders}
|
||||
<div>
|
||||
<a onClick=${onClick} className="btn btn-primary">
|
||||
<span className="glyphicon glyphicon-chevron-right"></span> Valider
|
||||
</a>
|
||||
|
||||
<$Link className="btn btn-default" to="/insert"><span className="glyphicon glyphicon-plus-sign"></span> Ajouter un produit</$Link>
|
||||
</div>
|
||||
</div>
|
||||
');
|
||||
|
||||
|
||||
var onProductSelected = function(uo:UserOrder){
|
||||
|
||||
var existingOrder = Lambda.find(state.orders,function(x) return x.productId==uo.productId );
|
||||
if(existingOrder!=null){
|
||||
existingOrder.quantity += uo.quantity;
|
||||
this.setState(this.state);
|
||||
}else{
|
||||
this.state.orders.push(uo);
|
||||
this.setState(this.state);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//insert product box
|
||||
var renderInsertBox = function(){
|
||||
return jsx('<$InsertOrder contractId="${props.contractId}" userId="${props.userId}" distributionId="${props.distributionId}" onInsert=$onProductSelected/>');
|
||||
}
|
||||
|
||||
return jsx('<$HashRouter>
|
||||
<$Switch>
|
||||
<$Route path="/" exact=$true render=$renderOrderBox />
|
||||
<$Route path="/insert" exact=$true render=$renderInsertBox />
|
||||
</$Switch>
|
||||
</$HashRouter>');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* called when an order is updated
|
||||
*/
|
||||
function onUpdate(data:UserOrder){
|
||||
/*trace("ON UPDATE : " + data);
|
||||
for ( o in state.orders){
|
||||
if (o.id == data.id) {
|
||||
o.quantity = data.quantity;
|
||||
o.paid = data.paid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setState(this.state);*/
|
||||
}
|
||||
|
||||
/**
|
||||
* submit updated orders to the API
|
||||
*/
|
||||
function onClick(?_){
|
||||
|
||||
var data = new Array<{id:Int,productId:Int,qt:Float,paid:Bool,invertSharedOrder:Bool,userId2:Int}>();
|
||||
for ( o in state.orders) data.push({id:o.id, productId : o.productId, qt: o.quantity, paid : o.paid, invertSharedOrder:o.invertSharedOrder, userId2:o.userId2});
|
||||
|
||||
var req = { orders:data };
|
||||
|
||||
var p = HttpUtil.fetch("/api/order/update/"+props.userId+"?distributionId="+props.distributionId+"&contractId="+props.contractId, POST, req, JSON);
|
||||
p.then(function(data:Dynamic) {
|
||||
|
||||
//WOOT
|
||||
if (props.onValidate != null) props.onValidate();
|
||||
|
||||
}).catchError(function(data) {
|
||||
var data = Std.string(data);
|
||||
trace("Error",data);
|
||||
if(data.substr(0,1)=="{"){
|
||||
//json error from server
|
||||
var data : ErrorInfos = haxe.Json.parse(data);
|
||||
setState( cast {error:data.error.message} );
|
||||
}else{
|
||||
//js error
|
||||
setState( cast {error:data} );
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function onKeyPress(e:js.html.KeyboardEvent){
|
||||
if(e.key=="Enter") onClick();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user