diff --git a/package.json b/package.json
index 31bfeaf..2ffdb85 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"money": "^0.2.0",
"netlify-auth-js": "^0.5.2",
"react": "^15.4.1",
+ "react-date-range": "^0.9.4",
"react-dom": "^15.4.1",
"react-gravatar": "^2.6.1",
"semantic-ui-css": "^2.2.4",
diff --git a/src/Components/Order/Address.js b/src/Components/Order/Address.js
index 8f24b30..8e21a7f 100644
--- a/src/Components/Order/Address.js
+++ b/src/Components/Order/Address.js
@@ -11,7 +11,7 @@ export default function({title, address, href, onLink}: args) {
{address &&
- {address.first_name} {address.last_name}
+ {address.name}
{address.company &&
{address.company}
}
{address.address1}
{address.address2 &&
{address.address2}
}
diff --git a/src/Components/Order/AddressEditor.js b/src/Components/Order/AddressEditor.js
index adaaee2..bbbb679 100644
--- a/src/Components/Order/AddressEditor.js
+++ b/src/Components/Order/AddressEditor.js
@@ -48,8 +48,7 @@ export default class AddressEditor extends Component {
return addr &&
-
-
+
diff --git a/src/Components/Order/index.js b/src/Components/Order/index.js
index e6b8f36..2063feb 100644
--- a/src/Components/Order/index.js
+++ b/src/Components/Order/index.js
@@ -9,6 +9,8 @@ import Address from './Address';
import AddressEditor from './AddressEditor';
import './styles.css';
+import { requiresShipping } from '../../helpers'
+
function formatId(id: string) {
return id.split("-").pop();
}
@@ -116,16 +118,15 @@ export default class OrderView extends Component {
handleReceipt = (e: SyntheticEvent) => {
e.preventDefault();
- const {commerce, config} = this.props;
const {order} = this.state;
if (!order) { return; }
-
- const openWindow = window.open("about:blank", "Receipt");
- console.log(config.receiptTemplate)
- commerce.orderReceipt(order.id, config.receiptTemplate).then((data) => {
- openWindow.document.body.innerHTML = data.data;
- });
-
+ let user = localStorage.getItem('netlify.auth.user')
+ try {
+ user = JSON.parse(user)
+ window.open(`https://smashingmagazine.com/receipts/?id=${order.id}&jwt=${user.jwt_token}`, "Receipt");
+ } catch (e) {
+ console.log(e)
+ }
}
render() {
@@ -135,7 +136,7 @@ export default class OrderView extends Component {
const item = params.item ? EditableItems[params.item] : null;
return
@@ -145,7 +146,7 @@ export default class OrderView extends Component {
- Order Details
+ Order #{order && order.invoice_number}
{params.id}
@@ -178,14 +179,17 @@ export default class OrderView extends Component {
/>
-
-
-
+
+
+ {requiresShipping(order) && (
+
+ )}
+
}
@@ -262,8 +266,8 @@ export default class OrderView extends Component {
Billing Status
- {order && order.payment_state}
- {order && order.payment_state === 'paid' && receipt}
+ {order && order.payment_state.toUpperCase()}
+ {order && order.payment_state === 'paid' && Show receipt
}
@@ -282,23 +286,26 @@ export default class OrderView extends Component {
}
-
-
- Shipping Status
- Shipping to {order && order.shipping_address && order.shipping_address.country}
-
+ {false && requiresShipping(order) && (
+
+
+ Shipping Status
+ Shipping to {order && order.shipping_address && order.shipping_address.country}
+
+
+
+
+
+ {order && newFullfilementState && newFullfilementState !== order.fulfillment_state && }
+
+
+ )}
-
-
-
- {order && newFullfilementState && newFullfilementState !== order.fulfillment_state && }
-
-
diff --git a/src/Components/Orders/index.js b/src/Components/Orders/index.js
index 6d9e1ec..f83c341 100644
--- a/src/Components/Orders/index.js
+++ b/src/Components/Orders/index.js
@@ -2,7 +2,7 @@
import type {Commerce, Pagination, Order, Address} from '../../Types';
import _ from 'lodash';
import React, {Component} from 'react';
-import {Button, Checkbox, Grid, Dimmer, Dropdown, Loader, Table, Input, Select} from 'semantic-ui-react';
+import {Button, Checkbox, Grid, Dimmer, Dropdown, Loader, Table, Icon, Header, Input, Select, Modal} from 'semantic-ui-react';
import Layout from '../Layout';
import PaginationView, {pageFromURL} from '../Pagination';
import ErrorMessage from '../Messages/Error';
@@ -10,6 +10,10 @@ import distanceInWordsToNow from 'date-fns/distance_in_words_to_now';
import countries from '../../data/countries.json';
import 'csvexport/dist/Export.min';
import './Orders.css';
+import { defaultRanges, Calendar, DateRange } from 'react-date-range'
+import moment from 'moment'
+
+import { requiresShipping, formatDateInterval } from '../../helpers'
const STORED_FIELDS_KEY = 'commerce.admin.orderFields';
@@ -32,11 +36,20 @@ function formatLineItems(order: Order, csv: boolean) {
)
}
+function formatName(order: Order, csv: boolean) {
+
+ return _.get(order, 'billing_address.name') || _.get(order, 'shipping_address.name')
+}
+
function formatLineItemTypes(order: Order, csv: boolean) {
let types = [];
(order.line_items || []).map(item => !types.includes(item.type) && types.push(item.type))
+ if (csv) {
+ return types.map(t => `${t}`).join(', ').replace(/,\s*$/, '')
+ }
+
return types.map(t => {t}
)
}
@@ -80,9 +93,10 @@ function formatDateField(field: 'created_at' | 'updated_at') {
}
const fields = {
- ID: {},
+ ID: { fn: (order) => order.invoice_number },
Email: {sort: "email"},
Items: {fn: formatLineItems},
+ Name: {fn: formatName},
Type: {fn: formatLineItemTypes},
"Shipping Address": {fn: formatAddress("shipping_address")},
"Shipping Country": {fn: (order) => order.shipping_address.country},
@@ -90,7 +104,7 @@ const fields = {
"Billing Country": {fn: (order) => order.billing_address.country},
Taxes: {sort: "taxes", fn: formatPriceField("taxes")},
Subtotal: {sort: "subtotal", fn: formatPriceField("subtotal")},
- "Shipping State": {fn: (order) => order.fulfillment_state},
+ "Shipping State": {fn: (order) => requiresShipping(order) ? order.fulfillment_state : null},
"Payment State": {},
Total: {sort: "total", fn: formatPriceField("total")},
"Created At": {sort: "created_at", fn: formatDateField("created_at")},
@@ -98,15 +112,16 @@ const fields = {
};
const enabledFields = {
- ID: false,
+ ID: true,
Items: true,
Type: true,
+ Name: true,
Email: true,
"Shipping Address": false,
"Shipping Country": false,
"Billing Address": false,
"Billing Country": false,
- "Shipping State": true,
+ //"Shipping State": false,
"Payment State": true,
Taxes: false,
Subtotal: false,
@@ -141,7 +156,6 @@ class OrderDetail extends Component {
render() {
const {order, enabledFields} = this.props;
-
return
@@ -190,7 +204,7 @@ export default class Orders extends Component {
error: null,
filters: [],
page: pageFromURL(),
- enabledFields: storedFields ? JSON.parse(storedFields) : Object.assign({}, enabledFields),
+ enabledFields: Object.assign({}, enabledFields, storedFields ? JSON.parse(storedFields) : {}),
tax: false,
shippingCountries: null,
orders: null,
@@ -267,7 +281,7 @@ export default class Orders extends Component {
const addr = formatField(field, order);
console.log(addr, field, order)
addressFields.forEach((field) => {
- formattedOrder[`${match[1]} ${field}`] = addr[field];
+ formattedOrder[`${match[1]} ${field}`] = (field === 'zip') ? `="${addr[field]}"` : addr[field];
})
} else {
formattedOrder[field] = fields[field].fn ? fields[field].fn(order, true) : formatField(field, order);
@@ -344,15 +358,23 @@ export default class Orders extends Component {
});
}
- orderQuery(page: ?number) {
- const query: Object = {
+ orderQuery(page: ?number, per_page: ?number) {
+ const { startDate, endDate } = this.state
+ let query: Object = {
user_id: "all",
- per_page: PER_PAGE,
- page: page || this.state.page
+ per_page: per_page || PER_PAGE,
+ page: page || this.state.page,
+ payment_state: 'paid',
};
this.state.filters.forEach((filter) => {
query[filter] = OrdersFilters[filter](this.state);
});
+
+ if (startDate && endDate) {
+ query.from = startDate.unix()
+ query.to = endDate.unix()
+ }
+
return query;
}
@@ -362,7 +384,7 @@ export default class Orders extends Component {
return Promise.resolve(selected);
}
- return this.props.commerce.orderHistory(this.orderQuery(page || 1))
+ return this.props.commerce.orderHistory(this.orderQuery(page || 1, 1000))
.then(({orders, pagination}) => (
pagination.last === pagination.current ? orders : this.downloadAll(pagination.next).then(o => orders.concat(o))
));
@@ -403,21 +425,57 @@ export default class Orders extends Component {
handleReceipts = (e: SyntheticEvent) => {
e.preventDefault();
- const {commerce} = this.props;
const {orders} = this.state;
- const openWindow = window.open("about:blank", "Receipts");
+ const selected = (orders || []).filter((o) => o.selected && o.payment_state === 'paid')
+ let user = localStorage.getItem('netlify.auth.user')
- Promise.all((orders || []).filter((o) => o.selected && o.payment_state === 'paid').map((order) => commerce.orderReceipt(order.id)))
- .then((receipts) => {
- openWindow.document.body.innerHTML = receipts.map((data) => data.data).join("");
- });
+ console.log(selected.length)
+ user = JSON.parse(user)
+ selected.forEach((order, i) => {
+ setTimeout(() => window.open(`https://smashingmagazine.com/receipts/?id=${order.id}&jwt=${user.jwt_token}`, `Receipt ${i + 1}`), i * 100)
+ })
}
+ handleDatePicker = (isReset, isApply) => this.setState({
+ openDatePicker: !this.state.openDatePicker,
+ startDate: !isReset ? this.state.startDate : null,
+ endDate: !isReset ? this.state.endDate : null,
+ }, () => (isReset || isApply) && this.loadOrders())
+
render() {
const {onLink} = this.props;
- const {loading, allSelected, downloading, error, orders, pagination, tax, enabledFields, searchScope, selection} = this.state;
+ const {loading, startDate, endDate, allSelected, openDatePicker, downloading, error, orders, pagination, tax, enabledFields, searchScope, selection} = this.state;
+ const interval = formatDateInterval(startDate, endDate)
+
return
+
+
+
+ this.setState({ startDate, endDate })}
+ onChange={ ({ startDate, endDate }) => this.setState({ startDate, endDate })}
+ theme={{
+ DateRange: { width: 850 },
+ Calendar : { width: 350 },
+ PredefinedRanges : { marginLeft: 10, marginTop: 10 }
+ }}
+ />
+
+
+
+
+
+
+
@@ -440,6 +498,12 @@ export default class Orders extends Component {
+
+
+
+
diff --git a/src/helpers/index.js b/src/helpers/index.js
new file mode 100644
index 0000000..8b8e8ea
--- /dev/null
+++ b/src/helpers/index.js
@@ -0,0 +1,33 @@
+import get from 'lodash/get'
+import isArray from 'lodash/isArray'
+import moment from 'moment'
+
+const requiresShipping = order => {
+ const items = isArray(order) ? order : (get(order, 'line_items') || [])
+ return !!items.filter(i => i.type === 'Book')[0]
+}
+
+export { requiresShipping }
+
+
+const formatDateInterval = (startDate, endDate) => {
+ let interval = null
+ if (startDate && endDate) {
+ interval = startDate.format('DD/MM/YY') + '–' + endDate.format('DD/MM/YY')
+
+ if (startDate.isSame(endDate, 'year')) {
+ interval = startDate.format('MMM DD') + '–' + endDate.format('MMM DD, YYYY')
+ if (startDate.isSame(endDate, 'month')) {
+ interval = startDate.format('MMM DD') + '–' + endDate.format('DD, YYYY')
+ if (startDate.isSame(endDate, 'day')) {
+ interval = startDate.format('MMM DD, YYYY')
+ }
+ }
+ if (endDate.isSame(moment(), 'year')) interval = interval.replace(endDate.format(', YYYY'), '')
+ }
+ }
+
+ return interval
+}
+
+export { formatDateInterval }
diff --git a/yarn.lock b/yarn.lock
index b263ac9..50c8130 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1104,7 +1104,7 @@ clap@^1.0.9:
dependencies:
chalk "^1.1.3"
-classnames@^2.1.5:
+classnames@^2.1.5, classnames@^2.2.1:
version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
@@ -2117,6 +2117,18 @@ fb-watchman@^1.8.0, fb-watchman@^1.9.0:
dependencies:
bser "1.0.2"
+fbjs@^0.8.16:
+ version "0.8.16"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db"
+ dependencies:
+ core-js "^1.0.0"
+ isomorphic-fetch "^2.1.1"
+ loose-envify "^1.0.0"
+ object-assign "^4.1.0"
+ promise "^7.1.1"
+ setimmediate "^1.0.5"
+ ua-parser-js "^0.7.9"
+
fbjs@^0.8.9:
version "0.8.12"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.12.tgz#10b5d92f76d45575fd63a217d4ea02bea2f8ed04"
@@ -3351,7 +3363,7 @@ longest@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
-loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
dependencies:
@@ -3498,6 +3510,10 @@ minimist@^1.1.1, minimist@^1.2.0:
dependencies:
minimist "0.0.8"
+moment@^2.10.6:
+ version "2.21.0"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a"
+
money@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/money/-/money-0.2.0.tgz#7eada2df1009df935fa18d4fb1d620ddacce02c2"
@@ -3685,7 +3701,7 @@ oauth-sign@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
-object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0:
+object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -4198,6 +4214,14 @@ promise@7.1.1, promise@^7.1.1:
dependencies:
asap "~2.0.3"
+prop-types@^15.5.10:
+ version "15.6.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca"
+ dependencies:
+ fbjs "^0.8.16"
+ loose-envify "^1.3.1"
+ object-assign "^4.1.1"
+
prop-types@^15.5.7, prop-types@~15.5.7:
version "15.5.8"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394"
@@ -4274,6 +4298,14 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-date-range@^0.9.4:
+ version "0.9.4"
+ resolved "https://registry.yarnpkg.com/react-date-range/-/react-date-range-0.9.4.tgz#d97515545a28edc717b674e169a50a215d69ec15"
+ dependencies:
+ classnames "^2.2.1"
+ moment "^2.10.6"
+ prop-types "^15.5.10"
+
react-dev-utils@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-0.5.2.tgz#50d0b962d3a94b6c2e8f2011ed6468e4124bc410"