diff options
| author | Jules Laplace <jules@okfoc.us> | 2017-04-21 16:03:11 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2017-04-21 16:03:11 -0400 |
| commit | ef83dba4a83e23e38b67ee31b79e79c9e25a003d (patch) | |
| tree | be0e65ee556d215796f6c64e3df7d8adb5c51554 /client/components | |
| parent | 5028ad81845308f3b1954dcc1fde664077fa0fa9 (diff) | |
display orders per product, download as csv
Diffstat (limited to 'client/components')
| -rw-r--r-- | client/components/App.jsx | 44 | ||||
| -rw-r--r-- | client/components/OrderList.jsx | 121 | ||||
| -rw-r--r-- | client/components/ProductList.jsx | 31 |
3 files changed, 193 insertions, 3 deletions
diff --git a/client/components/App.jsx b/client/components/App.jsx index 26af681..1b58e24 100644 --- a/client/components/App.jsx +++ b/client/components/App.jsx @@ -1,12 +1,50 @@ import React from 'react' +import ProductList from './ProductList.jsx' +import OrderList from './OrderList.jsx' +import client from '../client' export default class App extends React.Component { constructor() { super() + this.state = { + ready: false, + products: null, + product: null, + orders: null, + } + this.load = this.load.bind(this) + this.pick = this.pick.bind(this) + client.fetch('/api/products').then(this.load) + } + load(products) { + this.setState({ + ready: true, + products: products, + }) + } + pick(product) { + this.setState({ + product: product, + orders: null + }) + client.fetch('/api/orders', {id: product.product_merchant_product_id}).then((orders) => this.setState({ orders: orders })) } render() { - return ( - <div>Loading...</div> - ) + if (! this.state.ready) { + return ( + <div className='loading'>Loading...</div> + ) + } + else { + const products = this.state.products + const product = this.state.product + const orders = this.state.orders + return ( + <div> + <ProductList products={products} handleSelect={(product) => this.pick(product)} /> + <OrderList product={product} orders={orders} /> + </div> + ) + } } }
\ No newline at end of file diff --git a/client/components/OrderList.jsx b/client/components/OrderList.jsx new file mode 100644 index 0000000..5b0380b --- /dev/null +++ b/client/components/OrderList.jsx @@ -0,0 +1,121 @@ +import React from 'react' +import state_lookup from '../state_lookup' +import saveAs from 'browser-saveas' +import csvStringify from 'csv-stringify' + +export default class OrderList extends React.Component { + constructor(props) { + super() + this.downloadCsv = this.downloadCsv.bind(this) + } + downloadCsv() { + const orders = this.parseOrders().map((order) => { + return [ + order.order_id, + order.order_date, + order.order_checkout_type, + order.order_ship_name, + order.order_company, + order.order_address1, + order.order_address2, + order.order_city, + state_lookup(order.order_state), + order.order_zip, + order.order_country !== 'United States' ? '' : order.order_country, + ] + }) + csvStringify(orders, (err, csv) => { + const blob = new Blob([csv], {type : 'text/plain;charset=utf-8'}) + saveAs(blob, this.props.product.product_name.replace(/\s+/g,"") +'.csv') + }) + } + parseOrders() { + return this.props.orders.filter( (order) => { + // also filter where order.order_status == 3 (paid in full) ? + // filter weird blank orders if found + return !! order.order_ship_name + }).map( (order, i) => { + const name = order.order_ship_name + .toUpperCase() + .replace(/(Sr|Jr|I|II|III|IV)\.?$/i, "") + .split(" ") + .reverse()[0] + return [ name, order ] + }).sort((a,b) => { + return a[0] < b[0] ? -1 : a[0] === b[0] ? 0 : 1 + }).map((pair, i) => { + return pair[1] + }) + } + render() { + if (! this.props.product) { + return ( <div></div> ) + } + if (! this.props.orders) { + return ( <div className='loading'>Loading...</div> ) + } + if (! this.props.orders.length) { + return ( <div className='notfound'>No orders found</div> ) + } + + const items = this.parseOrders().map((order, i) => { + const order_link = ( + <a href={'http://shopping.msana.com/cw4/admin/order-details.php?order_id=' + order.order_id}> + (order) + </a> + ) + const customer_link = order.order_checkout_type === 'guest' ? '' : ( + <a href={'http://shopping.msana.com/cw4/admin/customer-details.php?customer_id=' + order.order_customer_id}> + (customer) + </a> + ) + let order_name, order_address + if (order.order_company && order.order_company !== order.order_ship_name) { + order_name = ( + <span> + {order.order_ship_name}<br /> + {order.order_company} + </span> + ) + } + else { + order_name = order.order_ship_name + } + if (order.order_address2 && order.order_address2 !== order.order_address1) { + order_address = ( + <span> + {order.order_address1}<br /> + {order.order_address2} + </span> + ) + } + else { + order_address = order.order_address1 + } + + const country = order.order_country !== 'United States' ? order.order_country : "" + return ( + <div key={i}> + <div> + {order_link} {customer_link} + </div> + <div> + {order_name}<br /> + {order_address}<br /> + {order.order_city}, {state_lookup(order.order_state)} {order.order_zip} {country} + </div> + </div> + ) + }) + + return ( + <div className='orderList'> + <a href='#' onClick={() => this.downloadCsv()}>Download CSV</a> + {items} + <br /> + <br /> + <br /> + </div> + ) + } +}
\ No newline at end of file diff --git a/client/components/ProductList.jsx b/client/components/ProductList.jsx new file mode 100644 index 0000000..ab00e9f --- /dev/null +++ b/client/components/ProductList.jsx @@ -0,0 +1,31 @@ +import React from 'react' + +export default class ProductList extends React.Component { + constructor(props) { + super() + this.state = { value: -1 } + this.pick = this.pick.bind(this) + } + pick(event) { + const value = Number(event.target.value) + this.setState({ value: value }) + if (value === -1) return + const product = this.props.products[value] + this.props.handleSelect(product) + } + render() { + const items = this.props.products.map((product, i) => { + return ( + <option key={i} value={i}> + {product.product_name} ({product.product_merchant_product_id}) + </option> + ) + }) + items.unshift(<option key={-1} value={-1}>Select a product...</option>) + return ( + <select value={this.state.value} onChange={this.pick}> + {items} + </select> + ) + } +}
\ No newline at end of file |
