@fleetbase/storefront-engine 0.3.18 → 0.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/components/customer-panel/orders.hbs +107 -104
- package/addon/components/customer-panel/orders.js +52 -45
- package/addon/components/modals/incoming-order.hbs +208 -199
- package/addon/components/modals/order-ready-assign-driver.hbs +1 -1
- package/addon/components/order-panel/details.js +0 -2
- package/addon/components/order-panel.hbs +314 -1
- package/addon/components/order-panel.js +51 -3
- package/addon/components/widget/customers.hbs +75 -51
- package/addon/components/widget/customers.js +29 -41
- package/addon/components/widget/orders.hbs +278 -119
- package/addon/components/widget/orders.js +75 -80
- package/addon/components/widget/storefront-metrics.hbs +3 -6
- package/addon/components/widget/storefront-metrics.js +25 -41
- package/addon/controllers/orders/index.js +214 -105
- package/addon/controllers/settings/gateways.js +1 -1
- package/addon/helpers/get-tip-amount.js +13 -2
- package/addon/routes/application.js +2 -4
- package/addon/services/order-actions.js +248 -0
- package/addon/services/storefront.js +2 -0
- package/addon/styles/storefront-engine.css +48 -0
- package/addon/templates/home.hbs +2 -1
- package/addon/templates/orders/index/view.hbs +1 -1
- package/addon/templates/orders/index.hbs +26 -3
- package/addon/templates/products/index/index.hbs +28 -28
- package/addon/templates/settings.hbs +1 -1
- package/app/services/order-actions.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/migrations/2023_05_03_025307_create_carts_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_checkouts_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_gateways_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_network_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_networks_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_notification_channels_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_payment_methods_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_addon_categories_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_addons_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_variant_options_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_variants_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_products_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_reviews_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_store_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_votes_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_carts_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_checkouts_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_gateways_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_network_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_networks_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_notification_channels_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_payment_methods_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addon_categories_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addons_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variant_options_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variants_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_products_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_reviews_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_votes_table.php +1 -1
- package/server/src/Http/Controllers/ActionController.php +2 -1
- package/server/src/Http/Controllers/OrderController.php +15 -2
- package/server/src/Http/Controllers/v1/CheckoutController.php +11 -12
- package/server/src/Http/Controllers/v1/CustomerController.php +11 -3
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +5 -5
- package/server/src/Http/Requests/CreateCustomerRequest.php +4 -0
- package/server/src/Http/Requests/InitializeCheckoutRequest.php +2 -1
- package/server/src/Models/Store.php +2 -2
- package/server/src/Observers/OrderObserver.php +7 -1
- package/server/src/Rules/IsValidLocation.php +2 -2
- package/server/src/Support/Storefront.php +34 -0
- package/translations/en-us.yaml +6 -1
|
@@ -1,18 +1,15 @@
|
|
|
1
|
-
<div class="storefront-metrics-widget"
|
|
1
|
+
<div class="storefront-metrics-widget" ...attributes>
|
|
2
2
|
<div class="flex items-center justify-between">
|
|
3
3
|
<div class="flex items-center">
|
|
4
4
|
<h3 class="text-lg leading-6 font-medium text-gray-900 dark:text-gray-100 mr-2">
|
|
5
5
|
{{t "storefront.component.widget.storefront-metrics.last-day"}}
|
|
6
6
|
</h3>
|
|
7
|
-
{{#if this.
|
|
7
|
+
{{#if this.loadMetrics.isRunning}}
|
|
8
8
|
<div>
|
|
9
9
|
<Spinner class="text-sky-400" />
|
|
10
10
|
</div>
|
|
11
11
|
{{/if}}
|
|
12
12
|
</div>
|
|
13
|
-
<div>
|
|
14
|
-
|
|
15
|
-
</div>
|
|
16
13
|
</div>
|
|
17
14
|
<dl class="mt-4 grid grid-cols-2 gap-5 sm:grid-cols-4">
|
|
18
15
|
<div class="px-4 py-5 border border-gray-200 dark:border-gray-900 bg-gray-50 dark:bg-gray-700 shadow-sm dark:shadow rounded-lg overflow-hidden sm:p-6">
|
|
@@ -35,7 +32,7 @@
|
|
|
35
32
|
|
|
36
33
|
<div class="px-4 py-5 border border-gray-200 dark:border-gray-900 bg-gray-50 dark:bg-gray-700 shadow-sm dark:shadow rounded-lg overflow-hidden sm:p-6">
|
|
37
34
|
<dt class="text-sm font-medium text-gray-500 dark:text-gray-100 truncate">
|
|
38
|
-
{{t "storefront.common.
|
|
35
|
+
{{pluralize this.metrics.stores_count (t "storefront.common.store") without-count=true}}
|
|
39
36
|
</dt>
|
|
40
37
|
<dd class="mt-1 text-3xl font-semibold text-gray-800 dark:text-white">
|
|
41
38
|
{{this.metrics.stores_count}}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
|
-
import {
|
|
4
|
+
import { get } from '@ember/object';
|
|
5
|
+
import { debug } from '@ember/debug';
|
|
5
6
|
import { startOfMonth, endOfMonth, format } from 'date-fns';
|
|
7
|
+
import { task } from 'ember-concurrency';
|
|
6
8
|
|
|
7
9
|
export default class WidgetStorefrontMetricsComponent extends Component {
|
|
8
10
|
@service fetch;
|
|
9
11
|
@service storefront;
|
|
10
|
-
|
|
12
|
+
@tracked title = 'This Month';
|
|
13
|
+
@tracked start = format(startOfMonth(new Date()), 'yyyy-MM-dd');
|
|
14
|
+
@tracked end = format(endOfMonth(new Date()), 'yyyy-MM-dd');
|
|
11
15
|
@tracked metrics = {
|
|
12
16
|
orders_count: 0,
|
|
13
17
|
customers_count: 0,
|
|
@@ -15,47 +19,27 @@ export default class WidgetStorefrontMetricsComponent extends Component {
|
|
|
15
19
|
earnings_sum: 0,
|
|
16
20
|
};
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.storefront.on('order.broadcasted', this.reloadMetrics);
|
|
30
|
-
this.storefront.on('storefront.changed', this.reloadMetrics);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@action async reloadMetrics() {
|
|
34
|
-
this.metrics = await this.fetchMetrics(this.start, this.end);
|
|
22
|
+
constructor(owner, { title = 'This Month' }) {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this.title = title;
|
|
25
|
+
this.loadMetrics.perform(this.start, this.end);
|
|
26
|
+
this.storefront.on('order.broadcasted', () => {
|
|
27
|
+
this.loadMetrics.perform();
|
|
28
|
+
});
|
|
29
|
+
this.storefront.on('storefront.changed', () => {
|
|
30
|
+
this.loadMetrics.perform();
|
|
31
|
+
});
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
@
|
|
38
|
-
this.
|
|
34
|
+
@task *loadMetrics(start, end) {
|
|
35
|
+
const store = get(this.storefront, 'activeStore.id');
|
|
39
36
|
|
|
40
|
-
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.fetch
|
|
49
|
-
.get('actions/metrics', { start, end, store }, { namespace: 'storefront/int/v1' })
|
|
50
|
-
.then((metrics) => {
|
|
51
|
-
this.isLoading = false;
|
|
52
|
-
resolve(metrics);
|
|
53
|
-
})
|
|
54
|
-
.catch(() => {
|
|
55
|
-
this.isLoading = false;
|
|
56
|
-
|
|
57
|
-
resolve(this.metrics);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
37
|
+
try {
|
|
38
|
+
const metrics = yield this.fetch.get('actions/metrics', { start, end, store }, { namespace: 'storefront/int/v1' });
|
|
39
|
+
this.metrics = metrics;
|
|
40
|
+
return metrics;
|
|
41
|
+
} catch (err) {
|
|
42
|
+
debug('Error loading storefront metrics:', err);
|
|
43
|
+
}
|
|
60
44
|
}
|
|
61
45
|
}
|
|
@@ -1,60 +1,39 @@
|
|
|
1
|
-
import { action } from '@ember/object';
|
|
2
|
-
import { inject as service } from '@ember/service';
|
|
3
|
-
import { isBlank } from '@ember/utils';
|
|
4
1
|
import BaseController from '@fleetbase/storefront-engine/controllers/base-controller';
|
|
5
2
|
import { tracked } from '@glimmer/tracking';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { action, get } from '@ember/object';
|
|
4
|
+
import { inject as service } from '@ember/service';
|
|
5
|
+
import { isBlank } from '@ember/utils';
|
|
6
|
+
import { isArray } from '@ember/array';
|
|
7
|
+
import { timeout, task } from 'ember-concurrency';
|
|
8
8
|
|
|
9
9
|
export default class OrdersIndexController extends BaseController {
|
|
10
|
-
/**
|
|
11
|
-
* Inject the `notifications` service
|
|
12
|
-
*
|
|
13
|
-
* @var {Service}
|
|
14
|
-
*/
|
|
15
10
|
@service notifications;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Inject the `intl` service
|
|
19
|
-
*
|
|
20
|
-
* @var {Service}
|
|
21
|
-
*/
|
|
22
11
|
@service intl;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Inject the `modals-manager` service
|
|
26
|
-
*
|
|
27
|
-
* @var {Service}
|
|
28
|
-
*/
|
|
29
12
|
@service modalsManager;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Inject the `crud` service
|
|
33
|
-
*
|
|
34
|
-
* @var {Service}
|
|
35
|
-
*/
|
|
36
13
|
@service crud;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Inject the `fetch` service
|
|
40
|
-
*
|
|
41
|
-
* @var {Service}
|
|
42
|
-
*/
|
|
43
14
|
@service fetch;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Inject the `filters` service
|
|
47
|
-
*
|
|
48
|
-
* @var {Service}
|
|
49
|
-
*/
|
|
50
15
|
@service filters;
|
|
16
|
+
@service hostRouter;
|
|
17
|
+
@service storefront;
|
|
18
|
+
@tracked page = 1;
|
|
19
|
+
@tracked limit;
|
|
20
|
+
@tracked query;
|
|
21
|
+
@tracked sort = '-created_at';
|
|
22
|
+
@tracked public_id;
|
|
23
|
+
@tracked internal_id;
|
|
24
|
+
@tracked tracking;
|
|
25
|
+
@tracked facilitator;
|
|
26
|
+
@tracked customer;
|
|
27
|
+
@tracked driver;
|
|
28
|
+
@tracked payload;
|
|
29
|
+
@tracked pickup;
|
|
30
|
+
@tracked dropoff;
|
|
31
|
+
@tracked updated_by;
|
|
32
|
+
@tracked created_by;
|
|
33
|
+
@tracked status;
|
|
34
|
+
@tracked currency = 'USD';
|
|
51
35
|
|
|
52
|
-
|
|
53
|
-
* Queryable parameters for this controller's model
|
|
54
|
-
*
|
|
55
|
-
* @var {Array}
|
|
56
|
-
*/
|
|
57
|
-
queryParams = [
|
|
36
|
+
@tracked queryParams = [
|
|
58
37
|
'page',
|
|
59
38
|
'limit',
|
|
60
39
|
'sort',
|
|
@@ -73,33 +52,17 @@ export default class OrdersIndexController extends BaseController {
|
|
|
73
52
|
'status',
|
|
74
53
|
];
|
|
75
54
|
|
|
76
|
-
@tracked page = 1;
|
|
77
|
-
@tracked limit;
|
|
78
|
-
@tracked query;
|
|
79
|
-
@tracked sort = '-created_at';
|
|
80
|
-
@tracked public_id;
|
|
81
|
-
@tracked internal_id;
|
|
82
|
-
@tracked tracking;
|
|
83
|
-
@tracked facilitator;
|
|
84
|
-
@tracked customer;
|
|
85
|
-
@tracked driver;
|
|
86
|
-
@tracked payload;
|
|
87
|
-
@tracked pickup;
|
|
88
|
-
@tracked dropoff;
|
|
89
|
-
@tracked updated_by;
|
|
90
|
-
@tracked created_by;
|
|
91
|
-
@tracked status;
|
|
92
|
-
|
|
93
55
|
@tracked columns = [
|
|
94
56
|
{
|
|
95
57
|
label: this.intl.t('storefront.common.id'),
|
|
96
58
|
valuePath: 'public_id',
|
|
97
|
-
width: '
|
|
59
|
+
width: '130px',
|
|
98
60
|
cellComponent: 'table/cell/anchor',
|
|
99
61
|
onClick: this.viewOrder,
|
|
100
62
|
resizable: true,
|
|
101
63
|
sortable: true,
|
|
102
64
|
filterable: true,
|
|
65
|
+
filterComponent: 'filter/string',
|
|
103
66
|
},
|
|
104
67
|
{
|
|
105
68
|
label: this.intl.t('storefront.orders.index.internal-id'),
|
|
@@ -108,27 +71,38 @@ export default class OrdersIndexController extends BaseController {
|
|
|
108
71
|
resizable: true,
|
|
109
72
|
sortable: true,
|
|
110
73
|
filterable: true,
|
|
74
|
+
hidden: true,
|
|
111
75
|
filterComponent: 'filter/string',
|
|
112
76
|
},
|
|
113
77
|
{
|
|
114
78
|
label: this.intl.t('storefront.orders.index.customer'),
|
|
115
79
|
valuePath: 'customer.name',
|
|
116
80
|
cellComponent: 'table/cell/base',
|
|
117
|
-
width: '
|
|
81
|
+
width: '100px',
|
|
118
82
|
resizable: true,
|
|
119
83
|
sortable: true,
|
|
120
|
-
hidden:
|
|
84
|
+
hidden: false,
|
|
121
85
|
filterable: true,
|
|
122
86
|
filterComponent: 'filter/model',
|
|
123
87
|
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-order-customer'),
|
|
124
88
|
filterParam: 'customer',
|
|
125
89
|
model: 'customer',
|
|
126
90
|
},
|
|
91
|
+
{
|
|
92
|
+
label: this.intl.t('storefront.orders.index.total'),
|
|
93
|
+
cellComponent: 'table/cell/currency',
|
|
94
|
+
currency: this.currency,
|
|
95
|
+
valuePath: 'meta.total',
|
|
96
|
+
width: '100px',
|
|
97
|
+
resizable: true,
|
|
98
|
+
hidden: false,
|
|
99
|
+
sortable: true,
|
|
100
|
+
},
|
|
127
101
|
{
|
|
128
102
|
label: this.intl.t('storefront.common.pickup'),
|
|
129
103
|
valuePath: 'pickupName',
|
|
130
104
|
cellComponent: 'table/cell/base',
|
|
131
|
-
width: '
|
|
105
|
+
width: '150px',
|
|
132
106
|
resizable: true,
|
|
133
107
|
sortable: true,
|
|
134
108
|
filterable: true,
|
|
@@ -141,7 +115,7 @@ export default class OrdersIndexController extends BaseController {
|
|
|
141
115
|
label: this.intl.t('storefront.common.dropoff'),
|
|
142
116
|
valuePath: 'dropoffName',
|
|
143
117
|
cellComponent: 'table/cell/base',
|
|
144
|
-
width: '
|
|
118
|
+
width: '150px',
|
|
145
119
|
resizable: true,
|
|
146
120
|
sortable: true,
|
|
147
121
|
filterable: true,
|
|
@@ -150,15 +124,34 @@ export default class OrdersIndexController extends BaseController {
|
|
|
150
124
|
filterParam: 'dropoff',
|
|
151
125
|
model: 'place',
|
|
152
126
|
},
|
|
127
|
+
{
|
|
128
|
+
label: this.intl.t('storefront.orders.index.driver-assigned'),
|
|
129
|
+
cellComponent: 'table/cell/driver-name',
|
|
130
|
+
valuePath: 'driver_assigned',
|
|
131
|
+
modelPath: 'driver_assigned',
|
|
132
|
+
width: '150px',
|
|
133
|
+
resizable: true,
|
|
134
|
+
sortable: true,
|
|
135
|
+
filterable: true,
|
|
136
|
+
filterComponent: 'filter/model',
|
|
137
|
+
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-driver-for-order'),
|
|
138
|
+
filterParam: 'driver',
|
|
139
|
+
model: 'driver',
|
|
140
|
+
query: {
|
|
141
|
+
// no model, serializer, adapter for relations
|
|
142
|
+
without: ['fleets', 'vendor', 'vehicle', 'currentJob'],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
153
145
|
{
|
|
154
146
|
label: this.intl.t('storefront.orders.index.scheduled-at'),
|
|
155
147
|
valuePath: 'scheduledAt',
|
|
156
148
|
sortParam: 'scheduled_at',
|
|
157
149
|
filterParam: 'scheduled_at',
|
|
158
|
-
width: '
|
|
150
|
+
width: '125px',
|
|
159
151
|
resizable: true,
|
|
160
152
|
sortable: true,
|
|
161
153
|
filterable: true,
|
|
154
|
+
hidden: true,
|
|
162
155
|
filterComponent: 'filter/date',
|
|
163
156
|
},
|
|
164
157
|
{
|
|
@@ -169,43 +162,16 @@ export default class OrdersIndexController extends BaseController {
|
|
|
169
162
|
hidden: true,
|
|
170
163
|
width: '50px',
|
|
171
164
|
},
|
|
172
|
-
{
|
|
173
|
-
label: this.intl.t('storefront.orders.index.transaction-total'),
|
|
174
|
-
cellComponent: 'table/cell/base',
|
|
175
|
-
valuePath: 'transaction_amount',
|
|
176
|
-
width: '50px',
|
|
177
|
-
resizable: true,
|
|
178
|
-
hidden: true,
|
|
179
|
-
sortable: true,
|
|
180
|
-
},
|
|
181
165
|
{
|
|
182
166
|
label: this.intl.t('storefront.orders.index.tracking-number'),
|
|
183
167
|
cellComponent: 'table/cell/base',
|
|
184
168
|
valuePath: 'tracking_number.tracking_number',
|
|
185
|
-
width: '
|
|
169
|
+
width: '160px',
|
|
186
170
|
resizable: true,
|
|
187
171
|
sortable: true,
|
|
188
172
|
filterable: true,
|
|
189
173
|
filterComponent: 'filter/string',
|
|
190
174
|
},
|
|
191
|
-
{
|
|
192
|
-
label: this.intl.t('storefront.orders.index.driver-assigned'),
|
|
193
|
-
cellComponent: 'table/cell/driver-name',
|
|
194
|
-
valuePath: 'driver_assigned',
|
|
195
|
-
modelPath: 'driver_assigned',
|
|
196
|
-
width: '170px',
|
|
197
|
-
resizable: true,
|
|
198
|
-
sortable: true,
|
|
199
|
-
filterable: true,
|
|
200
|
-
filterComponent: 'filter/model',
|
|
201
|
-
filterComponentPlaceholder: this.intl.t('storefront.orders.index.select-driver-for-order'),
|
|
202
|
-
filterParam: 'driver',
|
|
203
|
-
model: 'driver',
|
|
204
|
-
query: {
|
|
205
|
-
// no model, serializer, adapter for relations
|
|
206
|
-
without: ['fleets', 'vendor', 'vehicle', 'currentJob'],
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
175
|
{
|
|
210
176
|
label: this.intl.t('storefront.common.type'),
|
|
211
177
|
cellComponent: 'cell/humanize',
|
|
@@ -219,7 +185,7 @@ export default class OrdersIndexController extends BaseController {
|
|
|
219
185
|
label: this.intl.t('storefront.common.status'),
|
|
220
186
|
valuePath: 'status',
|
|
221
187
|
cellComponent: 'table/cell/status',
|
|
222
|
-
width: '
|
|
188
|
+
width: '140px',
|
|
223
189
|
resizable: true,
|
|
224
190
|
sortable: true,
|
|
225
191
|
filterable: true,
|
|
@@ -228,10 +194,10 @@ export default class OrdersIndexController extends BaseController {
|
|
|
228
194
|
},
|
|
229
195
|
{
|
|
230
196
|
label: this.intl.t('storefront.orders.index.created-at'),
|
|
231
|
-
valuePath: '
|
|
197
|
+
valuePath: 'createdAtShort',
|
|
232
198
|
sortParam: 'created_at',
|
|
233
199
|
filterParam: 'created_at',
|
|
234
|
-
width: '
|
|
200
|
+
width: '100px',
|
|
235
201
|
resizable: true,
|
|
236
202
|
sortable: true,
|
|
237
203
|
filterable: true,
|
|
@@ -239,7 +205,7 @@ export default class OrdersIndexController extends BaseController {
|
|
|
239
205
|
},
|
|
240
206
|
{
|
|
241
207
|
label: this.intl.t('storefront.orders.index.updated-at'),
|
|
242
|
-
valuePath: '
|
|
208
|
+
valuePath: 'updatedAtShort',
|
|
243
209
|
sortParam: 'updated_at',
|
|
244
210
|
filterParam: 'updated_at',
|
|
245
211
|
width: '125px',
|
|
@@ -282,25 +248,35 @@ export default class OrdersIndexController extends BaseController {
|
|
|
282
248
|
ddMenuLabel: 'Order Actions',
|
|
283
249
|
cellClassNames: 'overflow-visible',
|
|
284
250
|
wrapperClass: 'flex items-center justify-end mx-2',
|
|
285
|
-
width: '
|
|
251
|
+
width: '90px',
|
|
286
252
|
actions: [
|
|
287
253
|
{
|
|
288
|
-
label: this.intl.t('
|
|
254
|
+
label: this.intl.t('fleet-ops.operations.orders.index.view-order'),
|
|
289
255
|
icon: 'eye',
|
|
290
256
|
fn: this.viewOrder,
|
|
257
|
+
permission: 'fleet-ops view order',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
label: this.intl.t('fleet-ops.operations.orders.index.dispatch-order'),
|
|
261
|
+
icon: 'paper-plane',
|
|
262
|
+
fn: this.dispatchOrder,
|
|
263
|
+
permission: 'fleet-ops dispatch order',
|
|
264
|
+
isVisible: (order) => order.canBeDispatched,
|
|
291
265
|
},
|
|
292
266
|
{
|
|
293
|
-
label: this.intl.t('
|
|
267
|
+
label: this.intl.t('fleet-ops.operations.orders.index.cancel-order'),
|
|
294
268
|
icon: 'ban',
|
|
295
269
|
fn: this.cancelOrder,
|
|
270
|
+
permission: 'fleet-ops cancel order',
|
|
296
271
|
},
|
|
297
272
|
{
|
|
298
273
|
separator: true,
|
|
299
274
|
},
|
|
300
275
|
{
|
|
301
|
-
label: this.intl.t('
|
|
276
|
+
label: this.intl.t('fleet-ops.operations.orders.index.delete-order'),
|
|
302
277
|
icon: 'trash',
|
|
303
278
|
fn: this.deleteOrder,
|
|
279
|
+
permission: 'fleet-ops delete order',
|
|
304
280
|
},
|
|
305
281
|
],
|
|
306
282
|
sortable: false,
|
|
@@ -310,6 +286,11 @@ export default class OrdersIndexController extends BaseController {
|
|
|
310
286
|
},
|
|
311
287
|
];
|
|
312
288
|
|
|
289
|
+
constructor() {
|
|
290
|
+
super(...arguments);
|
|
291
|
+
this.currency = get(this.storefront, 'activeStore.currency');
|
|
292
|
+
}
|
|
293
|
+
|
|
313
294
|
/**
|
|
314
295
|
* The search task.
|
|
315
296
|
*
|
|
@@ -337,4 +318,132 @@ export default class OrdersIndexController extends BaseController {
|
|
|
337
318
|
@action viewOrder(order) {
|
|
338
319
|
return this.transitionToRoute('orders.index.view', order);
|
|
339
320
|
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Cancels a specific order after confirmation.
|
|
324
|
+
* @param {Object} order - The order to cancel.
|
|
325
|
+
* @param {Object} [options={}] - Additional options for the modal.
|
|
326
|
+
* @action
|
|
327
|
+
* @memberof OperationsOrdersIndexController
|
|
328
|
+
*/
|
|
329
|
+
@action cancelOrder(order, options = {}) {
|
|
330
|
+
this.modalsManager.confirm({
|
|
331
|
+
title: this.intl.t('fleet-ops.operations.orders.index.cancel-title'),
|
|
332
|
+
body: this.intl.t('fleet-ops.operations.orders.index.cancel-body'),
|
|
333
|
+
order,
|
|
334
|
+
confirm: async (modal) => {
|
|
335
|
+
modal.startLoading();
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
await this.fetch.patch('orders/cancel', { order: order.id });
|
|
339
|
+
order.set('status', 'canceled');
|
|
340
|
+
this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.cancel-success', { orderId: order.public_id }));
|
|
341
|
+
modal.done();
|
|
342
|
+
} catch (error) {
|
|
343
|
+
this.notifications.serverError(error);
|
|
344
|
+
modal.stopLoading();
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
...options,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@action dispatchOrder(order, options = {}) {
|
|
352
|
+
this.modalsManager.confirm({
|
|
353
|
+
title: this.intl.t('fleet-ops.operations.orders.index.dispatch-title'),
|
|
354
|
+
body: this.intl.t('fleet-ops.operations.orders.index.dispatch-body'),
|
|
355
|
+
acceptButtonScheme: 'primary',
|
|
356
|
+
acceptButtonText: 'Dispatch',
|
|
357
|
+
acceptButtonIcon: 'paper-plane',
|
|
358
|
+
order,
|
|
359
|
+
confirm: async (modal) => {
|
|
360
|
+
modal.startLoading();
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await this.fetch.patch('orders/dispatch', { order: order.id });
|
|
364
|
+
order.set('status', 'dispatched');
|
|
365
|
+
this.notifications.success(this.intl.t('fleet-ops.operations.orders.index.dispatch-success', { orderId: order.public_id }));
|
|
366
|
+
modal.done();
|
|
367
|
+
} catch (error) {
|
|
368
|
+
this.notifications.serverError(error);
|
|
369
|
+
modal.stopLoading();
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
...options,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@action deleteOrder(order, options = {}) {
|
|
377
|
+
this.crud.delete(order, {
|
|
378
|
+
onSuccess: () => {
|
|
379
|
+
return this.hostRouter.refresh();
|
|
380
|
+
},
|
|
381
|
+
...options,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
@action bulkDeleteOrders(selected = []) {
|
|
386
|
+
selected = selected.length > 0 ? selected : this.table.selectedRows;
|
|
387
|
+
|
|
388
|
+
this.crud.bulkDelete(selected, {
|
|
389
|
+
modelNamePath: `public_id`,
|
|
390
|
+
acceptButtonText: 'Delete Orders',
|
|
391
|
+
onSuccess: async () => {
|
|
392
|
+
await this.hostRouter.refresh();
|
|
393
|
+
this.table.untoggleSelectAll();
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
@action bulkCancelOrders(selected = []) {
|
|
399
|
+
selected = selected.length > 0 ? selected : this.table.selectedRows;
|
|
400
|
+
|
|
401
|
+
if (!isArray(selected) || selected.length === 0) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
this.crud.bulkAction('cancel', selected, {
|
|
406
|
+
acceptButtonText: 'Cancel Orders',
|
|
407
|
+
acceptButtonScheme: 'danger',
|
|
408
|
+
acceptButtonIcon: 'ban',
|
|
409
|
+
modelNamePath: `public_id`,
|
|
410
|
+
actionPath: `orders/bulk-cancel`,
|
|
411
|
+
actionMethod: `PATCH`,
|
|
412
|
+
onConfirm: (canceledOrders) => {
|
|
413
|
+
canceledOrders.forEach((order) => {
|
|
414
|
+
order.set('status', 'canceled');
|
|
415
|
+
});
|
|
416
|
+
},
|
|
417
|
+
onSuccess: async () => {
|
|
418
|
+
await this.hostRouter.refresh();
|
|
419
|
+
this.table.untoggleSelectAll();
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
@action bulkDispatchOrders(selected = []) {
|
|
425
|
+
selected = selected.length > 0 ? selected : this.table.selectedRows;
|
|
426
|
+
|
|
427
|
+
if (!isArray(selected) || selected.length === 0) {
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
this.crud.bulkAction('dispatch', selected, {
|
|
432
|
+
acceptButtonText: 'Dispatch Orders',
|
|
433
|
+
acceptButtonScheme: 'magic',
|
|
434
|
+
acceptButtonIcon: 'rocket',
|
|
435
|
+
modelNamePath: 'public_id',
|
|
436
|
+
actionPath: 'orders/bulk-dispatch',
|
|
437
|
+
actionMethod: 'POST',
|
|
438
|
+
onConfirm: (dispatchedOrders) => {
|
|
439
|
+
dispatchedOrders.forEach((order) => {
|
|
440
|
+
order.set('status', 'dispatched');
|
|
441
|
+
});
|
|
442
|
+
},
|
|
443
|
+
onSuccess: async () => {
|
|
444
|
+
await this.hostRouter.refresh();
|
|
445
|
+
this.table.untoggleSelectAll();
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
}
|
|
340
449
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { helper } from '@ember/component/helper';
|
|
2
|
+
import formatCurrency from '@fleetbase/ember-ui/utils/format-currency';
|
|
3
|
+
import numbersOnly from '@fleetbase/ember-ui/utils/numbers-only';
|
|
4
|
+
import calculatePercentage from '@fleetbase/ember-core/utils/calculate-percentage';
|
|
2
5
|
|
|
3
|
-
export default helper(function getTipAmount(
|
|
4
|
-
|
|
6
|
+
export default helper(function getTipAmount([tip, subtotal, currency]) {
|
|
7
|
+
let amount = tip;
|
|
8
|
+
if (typeof tip === 'string' && tip.endsWith('%')) {
|
|
9
|
+
amount = calculatePercentage(numbersOnly(tip), subtotal);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
amount = parseInt(amount);
|
|
13
|
+
amount = isNaN(amount) ? 0 : amount;
|
|
14
|
+
|
|
15
|
+
return formatCurrency(amount, currency);
|
|
5
16
|
});
|
|
@@ -45,10 +45,8 @@ export default class ApplicationRoute extends Route {
|
|
|
45
45
|
return this.store.query('store', { limit: 300, sort: '-updated_at' });
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
afterModel(
|
|
49
|
-
|
|
50
|
-
// this.storefront.listenForIncomingOrders();
|
|
51
|
-
}
|
|
48
|
+
afterModel() {
|
|
49
|
+
this.storefront.listenForIncomingOrders();
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
disableSandbox() {
|