@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.
Files changed (67) hide show
  1. package/addon/components/customer-panel/orders.hbs +2 -2
  2. package/addon/components/customer-panel/orders.js +1 -1
  3. package/addon/components/modals/create-gateway.hbs +33 -12
  4. package/addon/components/modals/share-network.hbs +1 -1
  5. package/addon/components/network-category-picker.hbs +2 -1
  6. package/addon/components/network-category-picker.js +52 -22
  7. package/addon/components/order-panel.hbs +1 -1
  8. package/addon/components/widget/customers.hbs +5 -2
  9. package/addon/components/widget/customers.js +14 -6
  10. package/addon/components/widget/orders.hbs +30 -9
  11. package/addon/components/widget/orders.js +7 -1
  12. package/addon/components/widget/storefront-key-metrics.js +3 -3
  13. package/addon/components/widget/storefront-metrics.hbs +11 -1
  14. package/addon/components/widget/storefront-metrics.js +103 -1
  15. package/addon/controllers/customers/index.js +2 -2
  16. package/addon/controllers/networks/index/network/index.js +2 -0
  17. package/addon/controllers/networks/index/network/orders.js +1 -2
  18. package/addon/controllers/networks/index/network/stores.js +68 -64
  19. package/addon/controllers/networks/index.js +1 -2
  20. package/addon/controllers/products/index/category.js +1 -2
  21. package/addon/controllers/products/index/index.js +1 -2
  22. package/addon/controllers/settings/gateways.js +6 -1
  23. package/addon/controllers/settings/index.js +1 -0
  24. package/addon/controllers/settings/notifications.js +3 -5
  25. package/addon/models/network.js +1 -0
  26. package/addon/models/store.js +1 -0
  27. package/addon/routes/networks/index/network/index.js +5 -0
  28. package/addon/routes/networks/index/network/stores.js +6 -5
  29. package/addon/routes/settings/index.js +5 -0
  30. package/addon/services/order-actions.js +31 -0
  31. package/addon/styles/storefront-engine.css +29 -0
  32. package/addon/templates/networks/index/network/index.hbs +13 -0
  33. package/addon/templates/networks/index/network/stores.hbs +15 -1
  34. package/addon/templates/networks/index.hbs +1 -1
  35. package/addon/templates/settings/gateways.hbs +15 -4
  36. package/addon/templates/settings/index.hbs +13 -0
  37. package/addon/templates/settings/notifications.hbs +2 -2
  38. package/addon/utils/commerce-date-ranges.js +263 -0
  39. package/app/utils/commerce-date-ranges.js +1 -0
  40. package/composer.json +1 -1
  41. package/extension.json +1 -1
  42. package/package.json +2 -3
  43. package/server/migrations/2025_09_01_041353_add_default_order_config_column.php +110 -0
  44. package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +150 -0
  45. package/server/src/Expansions/OrderExpansion.php +43 -0
  46. package/server/src/Http/Controllers/NetworkController.php +20 -3
  47. package/server/src/Http/Controllers/OrderController.php +62 -9
  48. package/server/src/Http/Controllers/v1/CheckoutController.php +45 -48
  49. package/server/src/Http/Controllers/v1/ServiceQuoteController.php +19 -3
  50. package/server/src/Http/Middleware/SetStorefrontSession.php +8 -6
  51. package/server/src/Http/Resources/Customer.php +41 -17
  52. package/server/src/Http/Resources/Gateway.php +16 -11
  53. package/server/src/Http/Resources/Network.php +35 -34
  54. package/server/src/Http/Resources/NotificationChannel.php +17 -10
  55. package/server/src/Http/Resources/Store.php +36 -35
  56. package/server/src/Models/Customer.php +18 -2
  57. package/server/src/Models/FoodTruck.php +15 -0
  58. package/server/src/Models/Network.php +65 -2
  59. package/server/src/Models/Store.php +73 -10
  60. package/server/src/Notifications/StorefrontOrderAccepted.php +154 -0
  61. package/server/src/Observers/OrderObserver.php +6 -4
  62. package/server/src/Providers/StorefrontServiceProvider.php +1 -0
  63. package/server/src/Rules/IsValidLocation.php +12 -0
  64. package/server/src/Support/PushNotification.php +13 -4
  65. package/server/src/Support/Storefront.php +199 -37
  66. package/server/src/routes.php +2 -0
  67. 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.isPreparing}}
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.isPreparing}}
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-decorators';
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 class="w-full" @placeholder="Select gateway type" @options={{@options.schemaOptions}} @onSelect={{@options.selectSchema}} @humanize={{true}} />
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
- {{#each-in @options.schema as |key value|}}
34
- {{#if (is-bool-value value)}}
35
- <div class="input-group">
36
- <Checkbox @value={{value}} @label={{humanize key}} @onToggle={{fn @options.setConfigKey key}} />
37
- </div>
38
- {{else}}
39
- <InputGroup @name={{humanize key}}>
40
- <Input class="form-input w-full" placeholder={{humanize key}} @value={{value}} {{on "blur" (fn @options.setConfigKey key)}} />
41
- </InputGroup>
42
- {{/if}}
43
- {{/each-in}}
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-fgray-800 dark:bg-gray-800 p-4">
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.isLoading}}
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 isLoading = false;
15
- @tracked buttonTitle = null;
16
+ @tracked buttonTitle = 'Select Category';
16
17
 
17
- constructor() {
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 = this.args.network;
20
- this.category = this.args.category;
21
- this.setButtonTitle(this.category);
22
- this.loadCategories(this.category);
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
- @action loadCategories(parentCategory) {
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
- this.isLoading = true;
49
- this.store
50
- .query('category', queryParams)
51
- .then((categories) => {
52
- this.categories = categories.toArray();
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.selectedCategory = category;
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.isPreparing}}
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.customerId}}</a></td>
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></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.store.query('customer', {
38
- storefront,
39
- limit: 14,
40
- ...params,
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.isPreparing}}
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-ready"}}
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: 15%"}}>{{t "storefront.common.customer"}}</th>
230
- <th style={{"width: 15%"}}>{{t "storefront.common.driver"}}</th>
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: 22%"}}></th>
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.isPreparing}}
279
+ {{#if (eq order.status "started")}}
268
280
  <Button
269
281
  @size="xs"
270
282
  @type="success"
271
- @icon="bell-concierge"
272
- @text={{t "storefront.component.widget.orders.mark-as-ready"}}
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-decorators';
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', {}, { namespace: 'storefront/int/v1' }).then((response) => {
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
- {{t "storefront.component.widget.storefront-metrics.last-day"}}
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
@@ -70,6 +70,8 @@ export default class NetworksIndexNetworkIndexController extends Controller {
70
70
  */
71
71
  @tracked isLoading = false;
72
72
 
73
+ @tracked orderConfigs = [];
74
+
73
75
  /**
74
76
  * Alias for model.gateways, representing the gateways associated with the network.
75
77
  *
@@ -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 {