@fleetbase/storefront-engine 0.3.31 → 0.4.1
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 +2 -2
- package/addon/components/customer-panel/orders.js +1 -1
- package/addon/components/modals/create-gateway.hbs +33 -12
- package/addon/components/modals/share-network.hbs +1 -1
- package/addon/components/network-category-picker.hbs +2 -1
- package/addon/components/network-category-picker.js +52 -22
- package/addon/components/order-panel.hbs +1 -1
- package/addon/components/widget/customers.hbs +5 -2
- package/addon/components/widget/customers.js +14 -6
- package/addon/components/widget/orders.hbs +30 -9
- package/addon/components/widget/orders.js +7 -1
- package/addon/components/widget/storefront-key-metrics.js +3 -3
- package/addon/components/widget/storefront-metrics.hbs +11 -1
- package/addon/components/widget/storefront-metrics.js +103 -1
- package/addon/controllers/customers/index.js +2 -2
- package/addon/controllers/networks/index/network/index.js +2 -0
- package/addon/controllers/networks/index/network/orders.js +1 -2
- package/addon/controllers/networks/index/network/stores.js +68 -64
- package/addon/controllers/networks/index.js +1 -2
- package/addon/controllers/products/index/category.js +1 -2
- package/addon/controllers/products/index/index.js +1 -2
- package/addon/controllers/settings/gateways.js +6 -1
- package/addon/controllers/settings/index.js +1 -0
- package/addon/controllers/settings/notifications.js +3 -5
- package/addon/models/network.js +1 -0
- package/addon/models/store.js +1 -0
- package/addon/routes/networks/index/network/index.js +5 -0
- package/addon/routes/networks/index/network/stores.js +6 -5
- package/addon/routes/settings/index.js +5 -0
- package/addon/services/order-actions.js +31 -0
- package/addon/styles/storefront-engine.css +29 -0
- package/addon/templates/networks/index/network/index.hbs +13 -0
- package/addon/templates/networks/index/network/stores.hbs +15 -1
- package/addon/templates/networks/index.hbs +1 -1
- package/addon/templates/settings/gateways.hbs +15 -4
- package/addon/templates/settings/index.hbs +13 -0
- package/addon/templates/settings/notifications.hbs +2 -2
- package/addon/utils/commerce-date-ranges.js +263 -0
- package/app/utils/commerce-date-ranges.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +2 -3
- package/server/migrations/2025_09_01_041353_add_default_order_config_column.php +110 -0
- package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +150 -0
- package/server/src/Expansions/OrderExpansion.php +43 -0
- package/server/src/Http/Controllers/NetworkController.php +20 -3
- package/server/src/Http/Controllers/OrderController.php +62 -9
- package/server/src/Http/Controllers/v1/CheckoutController.php +45 -48
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +19 -3
- package/server/src/Http/Middleware/SetStorefrontSession.php +8 -6
- package/server/src/Http/Resources/Customer.php +41 -17
- package/server/src/Http/Resources/Gateway.php +16 -11
- package/server/src/Http/Resources/Network.php +35 -34
- package/server/src/Http/Resources/NotificationChannel.php +17 -10
- package/server/src/Http/Resources/Store.php +36 -35
- package/server/src/Models/Customer.php +18 -2
- package/server/src/Models/FoodTruck.php +15 -0
- package/server/src/Models/Network.php +65 -2
- package/server/src/Models/Store.php +73 -10
- package/server/src/Notifications/StorefrontOrderAccepted.php +154 -0
- package/server/src/Observers/OrderObserver.php +6 -4
- package/server/src/Providers/StorefrontServiceProvider.php +1 -0
- package/server/src/Rules/IsValidLocation.php +12 -0
- package/server/src/Support/PushNotification.php +13 -4
- package/server/src/Support/Storefront.php +199 -37
- package/server/src/routes.php +2 -0
- package/translations/en-us.yaml +8 -0
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
@onClick={{fn this.acceptOrder order}}
|
|
42
42
|
/>
|
|
43
43
|
{{/if}}
|
|
44
|
-
{{#if order.
|
|
44
|
+
{{#if (eq order.status "accepted")}}
|
|
45
45
|
<Button
|
|
46
46
|
@size="xs"
|
|
47
47
|
@type="success"
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
@onClick={{fn this.acceptOrder order}}
|
|
103
103
|
/>
|
|
104
104
|
{{/if}}
|
|
105
|
-
{{#if order.
|
|
105
|
+
{{#if (eq order.status "accepted")}}
|
|
106
106
|
<Button @size="xs" @type="success" @icon="bell-concierge" @text={{t "storefront.component.widget.orders.mark-as-mark"}} @onClick={{fn this.markAsReady order}} />
|
|
107
107
|
{{/if}}
|
|
108
108
|
{{#if order.isPickupReady}}
|
|
@@ -3,7 +3,7 @@ import { tracked } from '@glimmer/tracking';
|
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
4
|
import { action, get } from '@ember/object';
|
|
5
5
|
import { debug } from '@ember/debug';
|
|
6
|
-
import { task } from 'ember-concurrency
|
|
6
|
+
import { task } from 'ember-concurrency';
|
|
7
7
|
|
|
8
8
|
export default class CustomerPanelOrdersComponent extends Component {
|
|
9
9
|
@service store;
|
|
@@ -2,7 +2,14 @@
|
|
|
2
2
|
<div class="modal-body-container">
|
|
3
3
|
<div class="mb-4 w-full">
|
|
4
4
|
<InputGroup @name={{t "storefront.component.modals.create-getaway.getaway"}} @helpText={{t "storefront.component.modals.create-getaway.getaway-text"}}>
|
|
5
|
-
<Select
|
|
5
|
+
<Select
|
|
6
|
+
@value={{@options.gateway.code}}
|
|
7
|
+
class="w-full"
|
|
8
|
+
@placeholder="Select gateway type"
|
|
9
|
+
@options={{@options.schemaOptions}}
|
|
10
|
+
@onSelect={{@options.selectSchema}}
|
|
11
|
+
@humanize={{true}}
|
|
12
|
+
/>
|
|
6
13
|
</InputGroup>
|
|
7
14
|
</div>
|
|
8
15
|
|
|
@@ -30,17 +37,31 @@
|
|
|
30
37
|
</div>
|
|
31
38
|
<div class="p-2 rounded-md my-2 border border-gray-200 dark:border-gray-800">
|
|
32
39
|
<h4 class="mb-2 font-semibold text-sm dark:text-white">Config</h4>
|
|
33
|
-
{{#
|
|
34
|
-
{{#
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
{{#if @options.gateway.isNew}}
|
|
41
|
+
{{#each-in @options.schema as |key value|}}
|
|
42
|
+
{{#if (is-bool-value value)}}
|
|
43
|
+
<div class="input-group">
|
|
44
|
+
<Checkbox @value={{value}} @label={{humanize key}} @onToggle={{fn @options.setConfigKey key}} />
|
|
45
|
+
</div>
|
|
46
|
+
{{else}}
|
|
47
|
+
<InputGroup @name={{humanize key}}>
|
|
48
|
+
<Input class="form-input w-full" placeholder={{humanize key}} @value={{value}} {{on "blur" (fn @options.setConfigKey key)}} />
|
|
49
|
+
</InputGroup>
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{/each-in}}
|
|
52
|
+
{{else}}
|
|
53
|
+
{{#each-in @options.gateway.config as |key value|}}
|
|
54
|
+
{{#if (is-bool-value value)}}
|
|
55
|
+
<div class="input-group">
|
|
56
|
+
<Checkbox @value={{value}} @label={{humanize key}} @onToggle={{fn @options.setConfigKey key}} />
|
|
57
|
+
</div>
|
|
58
|
+
{{else}}
|
|
59
|
+
<InputGroup @name={{humanize key}}>
|
|
60
|
+
<Input class="form-input w-full" placeholder={{humanize key}} @value={{value}} {{on "blur" (fn @options.setConfigKey key)}} />
|
|
61
|
+
</InputGroup>
|
|
62
|
+
{{/if}}
|
|
63
|
+
{{/each-in}}
|
|
64
|
+
{{/if}}
|
|
44
65
|
</div>
|
|
45
66
|
{{/if}}
|
|
46
67
|
</div>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
32
|
-
<div class="rounded-md border dark:border-
|
|
32
|
+
<div class="rounded-md border dark:border-gray-800 dark:bg-gray-800 p-4">
|
|
33
33
|
<h4 class="dark:text-gray-50 mb-4 font-semibold">{{t "storefront.component.modals.share-network.get-link"}}</h4>
|
|
34
34
|
<div class="input-group mb-0i">
|
|
35
35
|
<Toggle
|
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
@buttonClass={{concat "w-full truncate w-48" " " @buttonClass}}
|
|
9
9
|
@buttonWrapperClass={{concat "w-full" " " @buttonWrapperClass}}
|
|
10
10
|
@wrapperClass={{@wrapperClass}}
|
|
11
|
+
{{did-update this.updateArgs @category}}
|
|
11
12
|
as |dd|
|
|
12
13
|
>
|
|
13
14
|
<div role="menu" class="store-selector-dropdown-menu next-dd-menu py-1">
|
|
14
15
|
<div role="group" class="px-1 overflow-y-scroll max-h-72">
|
|
15
|
-
{{#if this.
|
|
16
|
+
{{#if this.loadCategories.isRunning}}
|
|
16
17
|
<div class="text-sm flex flex-row items-center px-3 py-0.5 border-0 my-1">
|
|
17
18
|
<Spinner class="mr-2i" />
|
|
18
19
|
<span class="dark:text-gray-100 test-sm">{{t "storefront.common.loading"}}</span>
|
|
@@ -2,6 +2,8 @@ import Component from '@glimmer/component';
|
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
4
|
import { action } from '@ember/object';
|
|
5
|
+
import { debug } from '@ember/debug';
|
|
6
|
+
import { task } from 'ember-concurrency';
|
|
5
7
|
import isModel from '@fleetbase/ember-core/utils/is-model';
|
|
6
8
|
|
|
7
9
|
export default class NetworkCategoryPickerComponent extends Component {
|
|
@@ -11,20 +13,27 @@ export default class NetworkCategoryPickerComponent extends Component {
|
|
|
11
13
|
@tracked categories = [];
|
|
12
14
|
@tracked selectedCategory;
|
|
13
15
|
@tracked network;
|
|
14
|
-
@tracked
|
|
15
|
-
@tracked buttonTitle = null;
|
|
16
|
+
@tracked buttonTitle = 'Select Category';
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
context = {
|
|
19
|
+
loadCategories: this.loadCategories,
|
|
20
|
+
loadParentCategories: this.loadParentCategories,
|
|
21
|
+
onSelectCategory: this.onSelectCategory,
|
|
22
|
+
onCreateNewCategory: this.onCreateNewCategory,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
constructor(owner, { network, category, onReady }) {
|
|
18
26
|
super(...arguments);
|
|
19
|
-
this.network =
|
|
20
|
-
this.category
|
|
21
|
-
|
|
22
|
-
|
|
27
|
+
this.network = network;
|
|
28
|
+
this.setCategory(category);
|
|
29
|
+
|
|
30
|
+
if (typeof onReady === 'function') {
|
|
31
|
+
onReady(this.context);
|
|
32
|
+
}
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
setButtonTitle(selectedCategory) {
|
|
26
36
|
let buttonTitle = this.args.buttonTitle ?? 'Select Category';
|
|
27
|
-
|
|
28
37
|
if (selectedCategory) {
|
|
29
38
|
buttonTitle = selectedCategory.name;
|
|
30
39
|
}
|
|
@@ -32,7 +41,7 @@ export default class NetworkCategoryPickerComponent extends Component {
|
|
|
32
41
|
this.buttonTitle = buttonTitle;
|
|
33
42
|
}
|
|
34
43
|
|
|
35
|
-
@
|
|
44
|
+
@task *loadCategories(parentCategory) {
|
|
36
45
|
const queryParams = {
|
|
37
46
|
owner_uuid: this.network.id,
|
|
38
47
|
parents_only: parentCategory ? false : true,
|
|
@@ -45,26 +54,20 @@ export default class NetworkCategoryPickerComponent extends Component {
|
|
|
45
54
|
queryParams.with_parent = true;
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.finally(() => {
|
|
55
|
-
this.isLoading = false;
|
|
56
|
-
});
|
|
57
|
+
try {
|
|
58
|
+
const categories = yield this.store.query('category', queryParams);
|
|
59
|
+
this.categories = categories.toArray();
|
|
60
|
+
} catch (error) {
|
|
61
|
+
debug(`Unable to load categories : ${error.message}`);
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
65
|
@action onSelectCategory(category) {
|
|
60
|
-
this.
|
|
61
|
-
this.setButtonTitle(category);
|
|
66
|
+
this.setCategory(category);
|
|
62
67
|
|
|
63
68
|
if (typeof this.args.onSelect === 'function') {
|
|
64
69
|
this.args.onSelect(category);
|
|
65
70
|
}
|
|
66
|
-
|
|
67
|
-
this.loadCategories(category);
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
@action onCreateNewCategory() {
|
|
@@ -80,4 +83,31 @@ export default class NetworkCategoryPickerComponent extends Component {
|
|
|
80
83
|
|
|
81
84
|
this.onSelectCategory(null);
|
|
82
85
|
}
|
|
86
|
+
|
|
87
|
+
@action updateArgs(el, [category]) {
|
|
88
|
+
this.setCategory(category);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async setCategoryById(categoryId) {
|
|
92
|
+
const category = this.store.peekRecord('category', categoryId);
|
|
93
|
+
if (category) {
|
|
94
|
+
this.setCategory(category);
|
|
95
|
+
} else {
|
|
96
|
+
// load from server if possible
|
|
97
|
+
const categoryRecord = await this.store.findRecord('category', categoryId);
|
|
98
|
+
if (categoryRecord) {
|
|
99
|
+
this.onSelectCategory(categoryRecord);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
setCategory(category) {
|
|
105
|
+
if (typeof category === 'string') {
|
|
106
|
+
return this.setCategoryById(category);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this.selectedCategory = category;
|
|
110
|
+
this.setButtonTitle(category);
|
|
111
|
+
this.loadCategories.perform(category);
|
|
112
|
+
}
|
|
83
113
|
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
@onClick={{fn this.acceptOrder this.order}}
|
|
19
19
|
/>
|
|
20
20
|
{{/if}}
|
|
21
|
-
{{#if this.order.
|
|
21
|
+
{{#if (eq this.order.status "accepted")}}
|
|
22
22
|
<Button @size="xs" @type="success" @icon="bell-concierge" @text={{t "storefront.component.widget.orders.mark-as-ready"}} @onClick={{fn this.markAsReady this.order}} />
|
|
23
23
|
{{/if}}
|
|
24
24
|
{{#if this.order.isPickupReady}}
|
|
@@ -30,6 +30,9 @@
|
|
|
30
30
|
@pad={{false}}
|
|
31
31
|
@wrapperClass={{@wrapperClass}}
|
|
32
32
|
>
|
|
33
|
+
<div class="flex justify-end px-4 py-2 space-x-2">
|
|
34
|
+
<Button @icon="refresh" @size="xs" @onClick={{perform this.loadCustomers}} />
|
|
35
|
+
</div>
|
|
33
36
|
{{#if (media "isMobile")}}
|
|
34
37
|
<div class="flex flex-col p-3 space-y-3">
|
|
35
38
|
{{#each this.customers as |customer|}}
|
|
@@ -63,11 +66,11 @@
|
|
|
63
66
|
<tbody>
|
|
64
67
|
{{#each this.customers as |customer|}}
|
|
65
68
|
<tr class="h-12">
|
|
66
|
-
<td><a href="javascript:;" {{on "click" (fn this.viewCustomer customer)}}>{{customer.
|
|
69
|
+
<td><a href="javascript:;" {{on "click" (fn this.viewCustomer customer)}}>{{customer.public_id}}</a></td>
|
|
67
70
|
<td>{{n-a customer.name}}</td>
|
|
68
71
|
<td>{{n-a customer.phone}}</td>
|
|
69
72
|
<td>{{n-a customer.email}}</td>
|
|
70
|
-
<td
|
|
73
|
+
<td>{{n-a customer.orders 0}}</td>
|
|
71
74
|
<td></td>
|
|
72
75
|
</tr>
|
|
73
76
|
{{/each}}
|
|
@@ -7,6 +7,7 @@ import { task } from 'ember-concurrency';
|
|
|
7
7
|
|
|
8
8
|
export default class WidgetCustomersComponent extends Component {
|
|
9
9
|
@service store;
|
|
10
|
+
@service fetch;
|
|
10
11
|
@service storefront;
|
|
11
12
|
@service intl;
|
|
12
13
|
@service contextPanel;
|
|
@@ -34,17 +35,24 @@ export default class WidgetCustomersComponent extends Component {
|
|
|
34
35
|
const storefront = get(this.storefront, 'activeStore.public_id');
|
|
35
36
|
|
|
36
37
|
try {
|
|
37
|
-
const customers = yield this.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
const { customers } = yield this.fetch.get(
|
|
39
|
+
'customers',
|
|
40
|
+
{
|
|
41
|
+
storefront,
|
|
42
|
+
limit: 14,
|
|
43
|
+
...params,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
namespace: 'storefront/int/v1',
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
42
50
|
this.loaded = true;
|
|
43
51
|
this.customers = customers;
|
|
44
52
|
|
|
45
53
|
return customers;
|
|
46
54
|
} catch (err) {
|
|
47
|
-
debug('Error loading customers for widget:', err);
|
|
55
|
+
debug('Error loading customers for widget:', err.message);
|
|
48
56
|
}
|
|
49
57
|
}
|
|
50
58
|
}
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
@pad={{false}}
|
|
31
31
|
@wrapperClass={{@wrapperClass}}
|
|
32
32
|
>
|
|
33
|
-
<div class="flex justify-end px-4 py-2">
|
|
33
|
+
<div class="flex justify-end px-4 py-2 space-x-2">
|
|
34
|
+
<Button @icon="refresh" @size="xs" @onClick={{perform this.loadOrders}} />
|
|
34
35
|
<Toggle @label="Active Orders Filter" @isToggled={{this.activeFilter}} @onToggle={{this.toggleActiveFilter}} />
|
|
35
36
|
</div>
|
|
36
37
|
{{#if (media "isMobile")}}
|
|
@@ -86,14 +87,25 @@
|
|
|
86
87
|
@onClick={{fn this.acceptOrder order}}
|
|
87
88
|
/>
|
|
88
89
|
{{/if}}
|
|
89
|
-
{{#if order.
|
|
90
|
+
{{#if (eq order.status "started")}}
|
|
90
91
|
<Button
|
|
91
92
|
@wrapperClass="w-full"
|
|
92
93
|
class="btn-block w-full"
|
|
93
94
|
@size="xs"
|
|
94
95
|
@type="success"
|
|
95
96
|
@icon="bell-concierge"
|
|
96
|
-
@text={{t "storefront.component.widget.orders.mark-as-
|
|
97
|
+
@text={{t "storefront.component.widget.orders.mark-as-preparing"}}
|
|
98
|
+
@onClick={{fn this.markAsPreparing order}}
|
|
99
|
+
/>
|
|
100
|
+
{{/if}}
|
|
101
|
+
{{#if (eq order.status "accepted")}}
|
|
102
|
+
<Button
|
|
103
|
+
@wrapperClass="w-full"
|
|
104
|
+
class="btn-block w-full"
|
|
105
|
+
@size="xs"
|
|
106
|
+
@type={{if order.meta.is_pickup "success" "magic"}}
|
|
107
|
+
@icon={{if order.meta.is_pickup "bell-concierge" "paper-plane"}}
|
|
108
|
+
@text={{if order.meta.is_pickup (t "storefront.component.widget.orders.mark-as-ready") (t "storefront.component.widget.orders.dispatch")}}
|
|
97
109
|
@onClick={{fn this.markAsReady order}}
|
|
98
110
|
/>
|
|
99
111
|
{{/if}}
|
|
@@ -226,11 +238,11 @@
|
|
|
226
238
|
<tr class="h-12 text-left py-1">
|
|
227
239
|
<th style={{"width: 15%"}}>{{t "storefront.component.widget.orders.id-column"}}</th>
|
|
228
240
|
<th style={{"width: 10%"}}>{{t "storefront.common.amount"}}</th>
|
|
229
|
-
<th style={{"width:
|
|
230
|
-
<th style={{"width:
|
|
241
|
+
<th style={{"width: 14%"}}>{{t "storefront.common.customer"}}</th>
|
|
242
|
+
<th style={{"width: 14%"}}>{{t "storefront.common.driver"}}</th>
|
|
231
243
|
<th style={{"width: 10%"}}>{{t "storefront.common.created"}}</th>
|
|
232
244
|
<th style={{"width: 15%"}}>{{t "storefront.common.status"}}</th>
|
|
233
|
-
<th style={{"width:
|
|
245
|
+
<th style={{"width: 24%"}}></th>
|
|
234
246
|
</tr>
|
|
235
247
|
</thead>
|
|
236
248
|
<tbody>
|
|
@@ -264,12 +276,21 @@
|
|
|
264
276
|
@onClick={{fn this.acceptOrder order}}
|
|
265
277
|
/>
|
|
266
278
|
{{/if}}
|
|
267
|
-
{{#if order.
|
|
279
|
+
{{#if (eq order.status "started")}}
|
|
268
280
|
<Button
|
|
269
281
|
@size="xs"
|
|
270
282
|
@type="success"
|
|
271
|
-
@icon="
|
|
272
|
-
@text={{t "storefront.component.widget.orders.mark-as-
|
|
283
|
+
@icon="hourglass-start"
|
|
284
|
+
@text={{t "storefront.component.widget.orders.mark-as-preparing"}}
|
|
285
|
+
@onClick={{fn this.markAsPreparing order}}
|
|
286
|
+
/>
|
|
287
|
+
{{/if}}
|
|
288
|
+
{{#if (eq order.status "accepted")}}
|
|
289
|
+
<Button
|
|
290
|
+
@size="xs"
|
|
291
|
+
@type={{if order.meta.is_pickup "success" "magic"}}
|
|
292
|
+
@icon={{if order.meta.is_pickup "bell-concierge" "paper-plane"}}
|
|
293
|
+
@text={{if order.meta.is_pickup (t "storefront.component.widget.orders.mark-as-ready") (t "storefront.component.widget.orders.dispatch")}}
|
|
273
294
|
@onClick={{fn this.markAsReady order}}
|
|
274
295
|
/>
|
|
275
296
|
{{/if}}
|
|
@@ -66,7 +66,7 @@ export default class WidgetOrdersComponent extends Component {
|
|
|
66
66
|
|
|
67
67
|
return orders;
|
|
68
68
|
} catch (err) {
|
|
69
|
-
debug('Error loading orders for widget:', err);
|
|
69
|
+
debug('Error loading orders for widget:', err.message);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -113,6 +113,12 @@ export default class WidgetOrdersComponent extends Component {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
@action markAsPreparing(order) {
|
|
117
|
+
this.orderActions.markAsPreparing(order, () => {
|
|
118
|
+
this.loadOrders.perform();
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
116
122
|
@action markAsCompleted(order) {
|
|
117
123
|
this.orderActions.markAsCompleted(order, () => {
|
|
118
124
|
this.loadOrders.perform();
|
|
@@ -1,7 +1,7 @@
|
|
|
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 { task } from 'ember-concurrency
|
|
4
|
+
import { task } from 'ember-concurrency';
|
|
5
5
|
|
|
6
6
|
export default class WidgetStorefrontKeyMetricsComponent extends Component {
|
|
7
7
|
/**
|
|
@@ -39,8 +39,8 @@ export default class WidgetStorefrontKeyMetricsComponent extends Component {
|
|
|
39
39
|
*
|
|
40
40
|
* @memberof WidgetKeyMetricsComponent
|
|
41
41
|
*/
|
|
42
|
-
@task *getDashboardMetrics() {
|
|
43
|
-
this.metrics = yield this.fetch.get('metrics',
|
|
42
|
+
@task *getDashboardMetrics(params = {}) {
|
|
43
|
+
this.metrics = yield this.fetch.get('metrics', params, { namespace: 'storefront/int/v1' }).then((response) => {
|
|
44
44
|
return this.createMetricsMapFromResponse(response);
|
|
45
45
|
});
|
|
46
46
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
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
|
+
Metrics
|
|
6
6
|
</h3>
|
|
7
7
|
{{#if this.loadMetrics.isRunning}}
|
|
8
8
|
<div>
|
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
{{/if}}
|
|
12
12
|
</div>
|
|
13
|
+
<div class="storefront-datepicker">
|
|
14
|
+
<DatePicker
|
|
15
|
+
@value={{concat this.start "," this.end}}
|
|
16
|
+
@range={{true}}
|
|
17
|
+
@buttons={{this.datePickerButtons}}
|
|
18
|
+
@onSelect={{this.selectDates}}
|
|
19
|
+
placeholder="Select date range"
|
|
20
|
+
class="min-w-250px"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
13
23
|
</div>
|
|
14
24
|
<dl class="mt-4 grid grid-cols-2 gap-5 sm:grid-cols-4">
|
|
15
25
|
<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">
|
|
@@ -1,10 +1,11 @@
|
|
|
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 { get } from '@ember/object';
|
|
4
|
+
import { get, action } from '@ember/object';
|
|
5
5
|
import { debug } from '@ember/debug';
|
|
6
6
|
import { startOfMonth, endOfMonth, format } from 'date-fns';
|
|
7
7
|
import { task } from 'ember-concurrency';
|
|
8
|
+
import { getDateRangeByLabel } from '../../utils/commerce-date-ranges';
|
|
8
9
|
|
|
9
10
|
export default class WidgetStorefrontMetricsComponent extends Component {
|
|
10
11
|
@service fetch;
|
|
@@ -18,6 +19,98 @@ export default class WidgetStorefrontMetricsComponent extends Component {
|
|
|
18
19
|
stores_count: 0,
|
|
19
20
|
earnings_sum: 0,
|
|
20
21
|
};
|
|
22
|
+
@tracked datePickerButtons = [
|
|
23
|
+
{
|
|
24
|
+
content: 'Yesterday',
|
|
25
|
+
className: 'quick-select-btn',
|
|
26
|
+
onClick: (datepicker) => {
|
|
27
|
+
const thisMonthRange = getDateRangeByLabel('Yesterday');
|
|
28
|
+
if (thisMonthRange) {
|
|
29
|
+
datepicker.selectDate(thisMonthRange);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
content: 'Last 7 Days',
|
|
35
|
+
className: 'quick-select-btn',
|
|
36
|
+
onClick: (datepicker) => {
|
|
37
|
+
const thisMonthRange = getDateRangeByLabel('Last 7 Days');
|
|
38
|
+
if (thisMonthRange) {
|
|
39
|
+
datepicker.selectDate(thisMonthRange);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
content: 'Last Week',
|
|
45
|
+
className: 'quick-select-btn',
|
|
46
|
+
onClick: (datepicker) => {
|
|
47
|
+
const thisMonthRange = getDateRangeByLabel('Last Week');
|
|
48
|
+
if (thisMonthRange) {
|
|
49
|
+
datepicker.selectDate(thisMonthRange);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
content: 'This Month',
|
|
55
|
+
className: 'quick-select-btn',
|
|
56
|
+
onClick: (datepicker) => {
|
|
57
|
+
const thisMonthRange = getDateRangeByLabel('This Month');
|
|
58
|
+
if (thisMonthRange) {
|
|
59
|
+
datepicker.selectDate(thisMonthRange);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
content: 'Last Month',
|
|
65
|
+
className: 'quick-select-btn',
|
|
66
|
+
onClick: (datepicker) => {
|
|
67
|
+
const thisMonthRange = getDateRangeByLabel('Last Month');
|
|
68
|
+
if (thisMonthRange) {
|
|
69
|
+
datepicker.selectDate(thisMonthRange);
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
content: 'This Quarter',
|
|
75
|
+
className: 'quick-select-btn',
|
|
76
|
+
onClick: (datepicker) => {
|
|
77
|
+
const thisMonthRange = getDateRangeByLabel('This Quarter');
|
|
78
|
+
if (thisMonthRange) {
|
|
79
|
+
datepicker.selectDate(thisMonthRange);
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
content: 'Last Quarter',
|
|
85
|
+
className: 'quick-select-btn',
|
|
86
|
+
onClick: (datepicker) => {
|
|
87
|
+
const thisMonthRange = getDateRangeByLabel('Last Quarter');
|
|
88
|
+
if (thisMonthRange) {
|
|
89
|
+
datepicker.selectDate(thisMonthRange);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
content: 'This Year',
|
|
95
|
+
className: 'quick-select-btn',
|
|
96
|
+
onClick: (datepicker) => {
|
|
97
|
+
const thisMonthRange = getDateRangeByLabel('This Year');
|
|
98
|
+
if (thisMonthRange) {
|
|
99
|
+
datepicker.selectDate(thisMonthRange);
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
content: 'Last Year',
|
|
105
|
+
className: 'quick-select-btn',
|
|
106
|
+
onClick: (datepicker) => {
|
|
107
|
+
const thisMonthRange = getDateRangeByLabel('Last Year');
|
|
108
|
+
if (thisMonthRange) {
|
|
109
|
+
datepicker.selectDate(thisMonthRange);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
];
|
|
21
114
|
|
|
22
115
|
constructor(owner, { title = 'This Month' }) {
|
|
23
116
|
super(...arguments);
|
|
@@ -42,4 +135,13 @@ export default class WidgetStorefrontMetricsComponent extends Component {
|
|
|
42
135
|
debug('Error loading storefront metrics:', err);
|
|
43
136
|
}
|
|
44
137
|
}
|
|
138
|
+
|
|
139
|
+
@action selectDates({ formattedDate }) {
|
|
140
|
+
const [start, end] = formattedDate;
|
|
141
|
+
this.start = start;
|
|
142
|
+
this.end = end;
|
|
143
|
+
if (start && end) {
|
|
144
|
+
this.loadMetrics.perform(start, end);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
45
147
|
}
|
|
@@ -2,9 +2,9 @@ import { inject as service } from '@ember/service';
|
|
|
2
2
|
import { isBlank } from '@ember/utils';
|
|
3
3
|
import BaseController from '@fleetbase/storefront-engine/controllers/base-controller';
|
|
4
4
|
import { tracked } from '@glimmer/tracking';
|
|
5
|
-
import { timeout } from 'ember-concurrency';
|
|
6
|
-
import { task } from 'ember-concurrency-decorators';
|
|
5
|
+
import { timeout, task } from 'ember-concurrency';
|
|
7
6
|
import { action } from '@ember/object';
|
|
7
|
+
|
|
8
8
|
export default class CustomersIndexController extends BaseController {
|
|
9
9
|
/**
|
|
10
10
|
* Inject the `notifications` service
|
|
@@ -2,8 +2,7 @@ import Controller from '@ember/controller';
|
|
|
2
2
|
import { inject as service } from '@ember/service';
|
|
3
3
|
import { tracked } from '@glimmer/tracking';
|
|
4
4
|
import { isBlank } from '@ember/utils';
|
|
5
|
-
import { timeout } from 'ember-concurrency';
|
|
6
|
-
import { task } from 'ember-concurrency-decorators';
|
|
5
|
+
import { timeout, task } from 'ember-concurrency';
|
|
7
6
|
import { action } from '@ember/object';
|
|
8
7
|
|
|
9
8
|
export default class NetworksIndexNetworkOrdersController extends Controller {
|