@fleetbase/storefront-engine 0.3.5 → 0.3.6

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 (83) hide show
  1. package/addon/components/context-panel.hbs +5 -0
  2. package/addon/components/context-panel.js +6 -0
  3. package/addon/components/customer-panel/details.hbs +34 -0
  4. package/addon/components/customer-panel/details.js +3 -0
  5. package/addon/components/customer-panel/orders.hbs +140 -0
  6. package/addon/components/customer-panel/orders.js +78 -0
  7. package/addon/components/customer-panel.hbs +70 -0
  8. package/addon/components/customer-panel.js +171 -0
  9. package/addon/components/display-place.hbs +52 -0
  10. package/addon/components/display-place.js +11 -0
  11. package/addon/components/modals/manage-addons.hbs +15 -52
  12. package/addon/components/modals/manage-addons.js +93 -43
  13. package/addon/components/modals/select-addon-category.hbs +1 -1
  14. package/addon/components/order-panel/details.hbs +245 -0
  15. package/addon/components/order-panel/details.js +189 -0
  16. package/addon/components/order-panel.hbs +1 -0
  17. package/addon/components/order-panel.js +38 -0
  18. package/addon/components/storefront-order-summary.hbs +9 -2
  19. package/addon/components/widget/customers.hbs +3 -1
  20. package/addon/components/widget/customers.js +5 -0
  21. package/addon/components/widget/orders.js +8 -146
  22. package/addon/controllers/customers/index/view.js +43 -0
  23. package/addon/controllers/customers/index.js +10 -6
  24. package/addon/controllers/networks/index/network/customers.js +68 -2
  25. package/addon/controllers/networks/index/network/orders.js +324 -1
  26. package/addon/controllers/networks/index/network/stores.js +0 -2
  27. package/addon/controllers/orders/index/view.js +13 -0
  28. package/addon/controllers/orders/index.js +10 -7
  29. package/addon/controllers/products/index/category/edit.js +12 -16
  30. package/addon/controllers/products/index/category/new.js +40 -45
  31. package/addon/controllers/products/index.js +8 -2
  32. package/addon/helpers/avatar-url.js +9 -0
  33. package/addon/models/product-variant-option.js +8 -1
  34. package/addon/models/product-variant.js +12 -2
  35. package/addon/models/product.js +62 -0
  36. package/addon/routes/customers/index/view.js +14 -0
  37. package/addon/routes/networks/index/network/customers.js +29 -0
  38. package/addon/routes/networks/index/network/orders.js +5 -0
  39. package/addon/routes/networks/index.js +1 -1
  40. package/addon/routes/orders/index/view.js +22 -1
  41. package/addon/routes/products/index/category/edit.js +6 -0
  42. package/addon/routes/products/index/category/new.js +3 -1
  43. package/addon/routes.js +1 -0
  44. package/addon/serializers/product-variant-option.js +14 -0
  45. package/addon/serializers/product-variant.js +27 -0
  46. package/addon/serializers/product.js +26 -4
  47. package/addon/services/context-panel.js +210 -0
  48. package/addon/styles/storefront-engine.css +6 -0
  49. package/addon/templates/application.hbs +3 -1
  50. package/addon/templates/customers/index/view.hbs +1 -0
  51. package/addon/templates/networks/index/network/customers.hbs +18 -1
  52. package/addon/templates/networks/index/network/orders.hbs +18 -1
  53. package/addon/templates/networks/index/network.hbs +1 -1
  54. package/addon/templates/orders/index/view.hbs +1 -1
  55. package/addon/templates/products/index/category/new.hbs +12 -67
  56. package/app/components/context-panel.js +1 -0
  57. package/app/components/customer-panel/details.js +1 -0
  58. package/app/components/customer-panel/orders.js +1 -0
  59. package/app/components/customer-panel.js +1 -0
  60. package/app/components/display-place.js +1 -0
  61. package/app/components/order-panel/details.js +1 -0
  62. package/app/components/order-panel.js +1 -0
  63. package/app/controllers/customers/index/view.js +1 -0
  64. package/app/controllers/orders/index/view.js +1 -0
  65. package/app/helpers/avatar-url.js +1 -0
  66. package/app/routes/customers/index/view.js +1 -0
  67. package/app/serializers/product-variant-option.js +1 -0
  68. package/app/services/context-panel.js +1 -0
  69. package/app/templates/customers/index/view.js +1 -0
  70. package/composer.json +3 -3
  71. package/extension.json +1 -1
  72. package/package.json +9 -3
  73. package/server/src/Http/Controllers/AddonCategoryController.php +90 -0
  74. package/server/src/Http/Controllers/v1/ReviewController.php +43 -52
  75. package/server/src/Http/Resources/Network.php +34 -32
  76. package/server/src/Http/Resources/NotificationChannel.php +32 -0
  77. package/server/src/Http/Resources/Product.php +10 -8
  78. package/server/src/Models/AddonCategory.php +37 -0
  79. package/server/src/Models/Product.php +6 -7
  80. package/server/src/Models/ProductAddon.php +3 -0
  81. package/server/src/Models/ProductAddonCategory.php +12 -2
  82. package/server/src/Providers/StorefrontServiceProvider.php +1 -1
  83. package/translations/en-us.yaml +101 -39
@@ -0,0 +1,189 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ import { action } from '@ember/object';
4
+ import { inject as service } from '@ember/service';
5
+ import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
6
+ import { tracked } from '@glimmer/tracking';
7
+
8
+ export default class OrderPanelDetailsComponent extends Component {
9
+ @service store;
10
+ @service storefront;
11
+ @service fetch;
12
+ @service intl;
13
+ @service appCache;
14
+ @service modalsManager;
15
+ @tracked isLoading = true;
16
+ @tracked orders = [];
17
+
18
+ constructor() {
19
+ super(...arguments);
20
+ }
21
+
22
+ /**
23
+ * Sets the overlay context.
24
+ *
25
+ * @action
26
+ * @param {OverlayContextObject} overlayContext
27
+ */
28
+ @action setOverlayContext(overlayContext) {
29
+ this.context = overlayContext;
30
+ contextComponentCallback(this, 'onLoad', ...arguments);
31
+ }
32
+
33
+ /**
34
+ * Handles the cancel action.
35
+ *
36
+ * @method
37
+ * @action
38
+ * @returns {Boolean} Indicates whether the cancel action was overridden.
39
+ */
40
+ @action onPressCancel() {
41
+ return contextComponentCallback(this, 'onPressCancel', this.customer);
42
+ }
43
+
44
+ @action async viewOrder(order) {
45
+ if (order.isFresh) {
46
+ return this.acceptOrder(order);
47
+ }
48
+
49
+ if (order.isPreparing) {
50
+ return this.markAsReady(order);
51
+ }
52
+
53
+ if (order.isPickupReady) {
54
+ return this.markAsCompleted(order);
55
+ }
56
+
57
+ return this.transitionToRoute('orders.index.view', order);
58
+ }
59
+
60
+ @action async acceptOrder(order) {
61
+ const activeStore = this.storefront.activeStore;
62
+
63
+ await order.loadPayload();
64
+ await order.loadCustomer();
65
+
66
+ this.modalsManager.show('modals/incoming-order', {
67
+ title: this.intl.t('storefront.component.widget.orders.accept-order'),
68
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.accept-order'),
69
+ acceptButtonScheme: 'success',
70
+ acceptButtonIcon: 'check',
71
+ order,
72
+ activeStore,
73
+ confirm: (modal) => {
74
+ modal.startLoading();
75
+
76
+ return this.fetch.post('orders/accept', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
77
+ return this.fetchOrders().then((orders) => {
78
+ this.orders = orders;
79
+ modal.stopLoading();
80
+ });
81
+ });
82
+ },
83
+ });
84
+ }
85
+
86
+ @action markAsReady(order) {
87
+ // for pickup orders
88
+ if (order.meta?.is_pickup === true) {
89
+ this.modalsManager.confirm({
90
+ title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-title'),
91
+ body: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-body'),
92
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-accept-button-text'),
93
+ acceptButtonIcon: 'check',
94
+ acceptButtonScheme: 'success',
95
+ confirm: (modal) => {
96
+ modal.startLoading();
97
+
98
+ return this.fetch.post('orders/ready', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
99
+ return this.fetchOrders().then((orders) => {
100
+ this.orders = orders;
101
+ modal.stopLoading();
102
+ });
103
+ });
104
+ },
105
+ });
106
+ }
107
+
108
+ if (!order.adhoc) {
109
+ // prompt to assign driver then dispatch
110
+ return this.modalsManager.show('modals/order-ready-assign-driver', {
111
+ title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-not-adhoc-title'),
112
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-not-adhoc-accept-button-text'),
113
+ acceptButtonScheme: 'success',
114
+ acceptButtonIcon: 'check',
115
+ adhoc: false,
116
+ driver: null,
117
+ order,
118
+ confirm: (modal) => {
119
+ modal.startLoading();
120
+
121
+ return this.fetch
122
+ .post('orders/ready', { order: order.id, driver: modal.getOption('driver.id'), adhoc: modal.getOption('adhoc') }, { namespace: 'storefront/int/v1' })
123
+ .then(() => {
124
+ return this.fetchOrders().then((orders) => {
125
+ this.orders = orders;
126
+ modal.stopLoading();
127
+ });
128
+ });
129
+ },
130
+ });
131
+ }
132
+
133
+ this.modalsManager.confirm({
134
+ title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-title'),
135
+ body: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-body'),
136
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-accept-button-text'),
137
+ acceptButtonIcon: 'check',
138
+ acceptButtonScheme: 'success',
139
+ confirm: (modal) => {
140
+ modal.startLoading();
141
+
142
+ return this.fetch.post('orders/ready', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
143
+ return this.fetchOrders().then((orders) => {
144
+ this.orders = orders;
145
+ modal.stopLoading();
146
+ });
147
+ });
148
+ },
149
+ });
150
+ }
151
+
152
+ @action markAsCompleted(order) {
153
+ this.modalsManager.confirm({
154
+ title: this.intl.t('storefront.component.widget.orders.mark-as-completed-modal-title'),
155
+ body: this.intl.t('storefront.component.widget.orders.mark-as-completed-modal-body'),
156
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-completed-accept-button-text'),
157
+ acceptButtonIcon: 'check',
158
+ acceptButtonScheme: 'success',
159
+ confirm: (modal) => {
160
+ modal.startLoading();
161
+
162
+ return this.fetch.post('orders/completed', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
163
+ return this.fetchOrders().then((orders) => {
164
+ this.orders = orders;
165
+ modal.stopLoading();
166
+ });
167
+ });
168
+ },
169
+ });
170
+ }
171
+
172
+ @action async assignDriver(order) {
173
+ await order.loadDriver();
174
+
175
+ this.modalsManager.show('modals/assign-driver', {
176
+ title: this.intl.t('storefront.component.widget.orders.assign-driver-modal-title'),
177
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.assign-driver-modal-accept-button-text'),
178
+ acceptButtonScheme: 'success',
179
+ acceptButtonIcon: 'check',
180
+ driver: order.driver_assigned,
181
+ order,
182
+ confirm: (modal) => {
183
+ modal.startLoading();
184
+
185
+ return order.save();
186
+ },
187
+ });
188
+ }
189
+ }
@@ -0,0 +1 @@
1
+ <OrderPanel::Details @order={{this.order}} @onPressCancel={{this.onPressCancel}} @onLoad={{this.setOverlayContext}} />
@@ -0,0 +1,38 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ import { action } from '@ember/object';
4
+ import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments';
5
+ import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
6
+ import { tracked } from '@glimmer/tracking';
7
+
8
+ export default class OrderPanelComponent extends Component {
9
+ @tracked context = null;
10
+
11
+ constructor() {
12
+ super(...arguments);
13
+
14
+ applyContextComponentArguments(this);
15
+ }
16
+
17
+ /**
18
+ * Sets the overlay context.
19
+ *
20
+ * @action
21
+ * @param {OverlayContextObject} overlayContext
22
+ */
23
+ @action setOverlayContext(overlayContext) {
24
+ this.context = overlayContext;
25
+ contextComponentCallback(this, 'onLoad', ...arguments);
26
+ }
27
+
28
+ /**
29
+ * Handles the cancel action.
30
+ *
31
+ * @method
32
+ * @action
33
+ * @returns {Boolean} Indicates whether the cancel action was overridden.
34
+ */
35
+ @action onPressCancel() {
36
+ return contextComponentCallback(this, 'onPressCancel', this.customer);
37
+ }
38
+ }
@@ -1,5 +1,12 @@
1
- {{#if (eq @model.type "storefront")}}
2
- <ContentPanel @title={{t "storefront.component.storefront-order-summary.order-summary-title"}} @prefixTitleRight={{if @order.payload.cod_amount "Cash" ""}} @prefixTitleRightClass="text-green-400" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
1
+ {{#if (eq @order.type "storefront")}}
2
+ <ContentPanel
3
+ @title={{t "storefront.component.storefront-order-summary.order-summary-title"}}
4
+ @prefixTitleRight={{if @order.payload.cod_amount "Cash" ""}}
5
+ @prefixTitleRightClass="text-green-400"
6
+ @open={{true}}
7
+ @pad={{true}}
8
+ @panelBodyClass="bg-white dark:bg-gray-800"
9
+ >
3
10
  <div class="flex flex-col space-y-4 p-2 overflow-hidden">
4
11
  {{#each @order.payload.entities as |entity|}}
5
12
  <div class="flex flex-1">
@@ -18,6 +18,7 @@
18
18
  <thead>
19
19
  <tr class="h-12 text-left py-1">
20
20
  <th>{{t "storefront.common.id"}}</th>
21
+ <th>{{t "storefront.common.name"}}</th>
21
22
  <th>{{t "storefront.common.phone"}}</th>
22
23
  <th>{{t "storefront.common.email"}}</th>
23
24
  <th>{{t "storefront.common.orders"}}</th>
@@ -27,7 +28,8 @@
27
28
  <tbody>
28
29
  {{#each this.customers as |customer|}}
29
30
  <tr class="h-12">
30
- <td>{{customer.customerId}}</td>
31
+ <td><a href="javascript:;" {{on "click" (fn this.viewCustomer customer)}}>{{customer.customerId}}</a></td>
32
+ <td>{{n-a customer.name}}</td>
31
33
  <td>{{n-a customer.phone}}</td>
32
34
  <td>{{n-a customer.email}}</td>
33
35
  <td></td>
@@ -8,6 +8,7 @@ export default class WidgetCustomersComponent extends Component {
8
8
  @service store;
9
9
  @service storefront;
10
10
  @service intl;
11
+ @service contextPanel;
11
12
  @tracked isLoading = true;
12
13
  @tracked customers = [];
13
14
  @tracked title = this.intl.t('storefront.component.widget.customers.widget-title');
@@ -54,4 +55,8 @@ export default class WidgetCustomersComponent extends Component {
54
55
  });
55
56
  });
56
57
  }
58
+
59
+ @action viewCustomer(customer) {
60
+ this.contextPanel.focus(customer, 'viewing');
61
+ }
57
62
  }
@@ -1,9 +1,9 @@
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 { inject as controller } from '@ember/controller';
4
5
  import { action, computed, get } from '@ember/object';
5
6
  import { later } from '@ember/runloop';
6
-
7
7
  export default class WidgetOrdersComponent extends Component {
8
8
  @service store;
9
9
  @service storefront;
@@ -11,8 +11,10 @@ export default class WidgetOrdersComponent extends Component {
11
11
  @service intl;
12
12
  @service appCache;
13
13
  @service modalsManager;
14
+ @service contextPanel;
14
15
  @tracked isLoading = true;
15
16
  @tracked orders = [];
17
+ @controller('orders.index.view') orderDetailsController;
16
18
 
17
19
  @computed('args.title') get title() {
18
20
  return this.args.title ?? this.intl.t('storefront.component.widget.orders.widget-title');
@@ -104,162 +106,22 @@ export default class WidgetOrdersComponent extends Component {
104
106
  }
105
107
 
106
108
  @action async viewOrder(order) {
107
- const store = this.storefront.activeStore;
108
-
109
- if (order.isFresh) {
110
- return this.acceptOrder(order);
111
- }
112
-
113
- if (order.isPreparing) {
114
- return this.markAsReady(order);
115
- }
116
-
117
- if (order.isPickupReady) {
118
- return this.markAsCompleted(order);
119
- }
120
-
121
- this.modalsManager.show('modals/incoming-order', {
122
- title: `${order.public_id}`,
123
- hideAcceptButton: true,
124
- declineButtonText: 'Done',
125
- declineButtonScheme: 'primary',
126
- declineButtonIcon: 'check',
127
- assignDriver: async () => {
128
- await this.modalsManager.done();
129
- this.assignDriver(order);
130
- },
131
- order,
132
- store,
133
- });
109
+ this.contextPanel.focus(order, 'viewing');
134
110
  }
135
111
 
136
112
  @action async acceptOrder(order) {
137
- const store = this.storefront.activeStore;
138
-
139
- await order.loadPayload();
140
- await order.loadCustomer();
141
-
142
- this.modalsManager.show('modals/incoming-order', {
143
- title: this.intl.t('storefront.component.widget.orders.accept-order'),
144
- acceptButtonText: this.intl.t('storefront.component.widget.orders.accept-order'),
145
- acceptButtonScheme: 'success',
146
- acceptButtonIcon: 'check',
147
- order,
148
- store,
149
- confirm: (modal) => {
150
- modal.startLoading();
151
-
152
- return this.fetch.post('orders/accept', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
153
- return this.fetchOrders().then((orders) => {
154
- this.orders = orders;
155
- modal.stopLoading();
156
- });
157
- });
158
- },
159
- });
113
+ await this.orderDetailsController.acceptOrder(order);
160
114
  }
161
115
 
162
116
  @action markAsReady(order) {
163
- // for pickup orders
164
- if (order.meta?.is_pickup === true) {
165
- this.modalsManager.confirm({
166
- title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-title'),
167
- body: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-body'),
168
- acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-pickup-accept-button-text'),
169
- acceptButtonIcon: 'check',
170
- acceptButtonScheme: 'success',
171
- confirm: (modal) => {
172
- modal.startLoading();
173
-
174
- return this.fetch.post('orders/ready', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
175
- return this.fetchOrders().then((orders) => {
176
- this.orders = orders;
177
- modal.stopLoading();
178
- });
179
- });
180
- },
181
- });
182
- }
183
-
184
- if (!order.adhoc) {
185
- // prompt to assign driver then dispatch
186
- return this.modalsManager.show('modals/order-ready-assign-driver', {
187
- title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-not-adhoc-title'),
188
- acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-not-adhoc-accept-button-text'),
189
- acceptButtonScheme: 'success',
190
- acceptButtonIcon: 'check',
191
- adhoc: false,
192
- driver: null,
193
- order,
194
- confirm: (modal) => {
195
- modal.startLoading();
196
-
197
- return this.fetch
198
- .post('orders/ready', { order: order.id, driver: modal.getOption('driver.id'), adhoc: modal.getOption('adhoc') }, { namespace: 'storefront/int/v1' })
199
- .then(() => {
200
- return this.fetchOrders().then((orders) => {
201
- this.orders = orders;
202
- modal.stopLoading();
203
- });
204
- });
205
- },
206
- });
207
- }
208
-
209
- this.modalsManager.confirm({
210
- title: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-title'),
211
- body: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-body'),
212
- acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-ready-modal-accept-button-text'),
213
- acceptButtonIcon: 'check',
214
- acceptButtonScheme: 'success',
215
- confirm: (modal) => {
216
- modal.startLoading();
217
-
218
- return this.fetch.post('orders/ready', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
219
- return this.fetchOrders().then((orders) => {
220
- this.orders = orders;
221
- modal.stopLoading();
222
- });
223
- });
224
- },
225
- });
117
+ this.orderDetailsController.markAsReady(order);
226
118
  }
227
119
 
228
120
  @action markAsCompleted(order) {
229
- this.modalsManager.confirm({
230
- title: this.intl.t('storefront.component.widget.orders.mark-as-completed-modal-title'),
231
- body: this.intl.t('storefront.component.widget.orders.mark-as-completed-modal-body'),
232
- acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-completed-accept-button-text'),
233
- acceptButtonIcon: 'check',
234
- acceptButtonScheme: 'success',
235
- confirm: (modal) => {
236
- modal.startLoading();
237
-
238
- return this.fetch.post('orders/completed', { order: order.id }, { namespace: 'storefront/int/v1' }).then(() => {
239
- return this.fetchOrders().then((orders) => {
240
- this.orders = orders;
241
- modal.stopLoading();
242
- });
243
- });
244
- },
245
- });
121
+ this.orderDetailsController.markAsCompleted(order);
246
122
  }
247
123
 
248
124
  @action async assignDriver(order) {
249
- await order.loadDriver();
250
-
251
- this.modalsManager.show('modals/assign-driver', {
252
- title: this.intl.t('storefront.component.widget.orders.assign-driver-modal-title'),
253
- acceptButtonText: this.intl.t('storefront.component.widget.orders.assign-driver-modal-accept-button-text'),
254
- acceptButtonScheme: 'success',
255
- acceptButtonIcon: 'check',
256
- driver: order.driver_assigned,
257
- order,
258
- confirm: (modal) => {
259
- modal.startLoading();
260
-
261
- return order.save();
262
- },
263
- });
125
+ await this.orderDetailsController.assignDriver(order);
264
126
  }
265
127
  }
@@ -0,0 +1,43 @@
1
+ import { action } from '@ember/object';
2
+ import BaseController from '@fleetbase/storefront-engine/controllers/base-controller';
3
+ import { tracked } from '@glimmer/tracking';
4
+
5
+ export default class CustomersIndexViewController extends BaseController {
6
+ /**
7
+ * The currently active view tab ('details' by default).
8
+ *
9
+ * @type {String}
10
+ * @tracked
11
+ */
12
+ @tracked view = 'details';
13
+
14
+ /**
15
+ * An array of query parameters to be serialized in the URL.
16
+ *
17
+ * @type {String[]}
18
+ * @tracked
19
+ */
20
+ @tracked queryParams = ['view'];
21
+
22
+ /**
23
+ * Transitions back to the "customers.index" route.
24
+ *
25
+ * @method
26
+ * @action
27
+ * @returns {Transition} The transition object representing the route change.
28
+ */
29
+ @action transitionBack() {
30
+ return this.transitionToRoute('customers.index');
31
+ }
32
+
33
+ /**
34
+ * Updates the active view tab.
35
+ *
36
+ * @method
37
+ * @param {String} tab - The name of the tab to activate.
38
+ * @action
39
+ */
40
+ @action onTabChanged(tab) {
41
+ this.view = tab;
42
+ }
43
+ }
@@ -1,11 +1,11 @@
1
- import Controller from '@ember/controller';
2
1
  import { inject as service } from '@ember/service';
3
- import { tracked } from '@glimmer/tracking';
4
2
  import { isBlank } from '@ember/utils';
3
+ import BaseController from '@fleetbase/storefront-engine/controllers/base-controller';
4
+ import { tracked } from '@glimmer/tracking';
5
5
  import { timeout } from 'ember-concurrency';
6
6
  import { task } from 'ember-concurrency-decorators';
7
-
8
- export default class CustomersIndexController extends Controller {
7
+ import { action } from '@ember/object';
8
+ export default class CustomersIndexController extends BaseController {
9
9
  /**
10
10
  * Inject the `notifications` service
11
11
  *
@@ -122,7 +122,7 @@ export default class CustomersIndexController extends Controller {
122
122
  valuePath: 'name',
123
123
  width: '15%',
124
124
  cellComponent: 'table/cell/media-name',
125
- // action: this.viewVendor,
125
+ action: this.viewCustomer,
126
126
  resizable: true,
127
127
  sortable: true,
128
128
  filterable: true,
@@ -226,7 +226,7 @@ export default class CustomersIndexController extends Controller {
226
226
  actions: [
227
227
  {
228
228
  label: this.intl.t('storefront.customers.index.view-customer-details'),
229
- // fn: this.viewVendor,
229
+ fn: this.viewCustomer,
230
230
  },
231
231
  {
232
232
  label: this.intl.t('storefront.customers.index.edit-customer'),
@@ -248,6 +248,10 @@ export default class CustomersIndexController extends Controller {
248
248
  },
249
249
  ];
250
250
 
251
+ @action viewCustomer(customer) {
252
+ return this.transitionToRoute('customers.index.view', customer);
253
+ }
254
+
251
255
  /**
252
256
  * The search task.
253
257
  *
@@ -1,3 +1,69 @@
1
- import Controller from '@ember/controller';
1
+ import { action } from '@ember/object';
2
+ import { inject as service } from '@ember/service';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import CustomersIndexController from '../../../customers';
2
5
 
3
- export default class NetworksIndexNetworkCustomersController extends Controller {}
6
+ /**
7
+ * This controller handles the logic for managing network customers.
8
+ */
9
+ export default class NetworksIndexNetworkCustomersController extends CustomersIndexController {
10
+ @service contextPanel;
11
+
12
+ @tracked columns = [
13
+ {
14
+ label: this.intl.t('storefront.common.name'),
15
+ valuePath: 'name',
16
+ width: '25%',
17
+ cellComponent: 'table/cell/media-name',
18
+ action: this.viewCustomer,
19
+ resizable: true,
20
+ sortable: true,
21
+ filterable: true,
22
+ filterComponent: 'filter/string',
23
+ },
24
+ {
25
+ label: this.intl.t('storefront.common.id'),
26
+ valuePath: 'public_id',
27
+ cellComponent: 'click-to-copy',
28
+ width: '15%',
29
+ resizable: true,
30
+ sortable: true,
31
+ filterable: true,
32
+ filterComponent: 'filter/string',
33
+ },
34
+ {
35
+ label: this.intl.t('storefront.common.email'),
36
+ valuePath: 'email',
37
+ cellComponent: 'table/cell/base',
38
+ width: '20%',
39
+ resizable: true,
40
+ sortable: true,
41
+ filterable: true,
42
+ filterComponent: 'filter/string',
43
+ },
44
+ {
45
+ label: this.intl.t('storefront.common.phone'),
46
+ valuePath: 'phone',
47
+ cellComponent: 'table/cell/base',
48
+ width: '16%',
49
+ resizable: true,
50
+ sortable: true,
51
+ filterable: true,
52
+ filterComponent: 'filter/string',
53
+ },
54
+ {
55
+ label: this.intl.t('storefront.customers.index.create-at'),
56
+ valuePath: 'createdAt',
57
+ sortParam: 'created_at',
58
+ width: '20%',
59
+ resizable: true,
60
+ sortable: true,
61
+ filterable: true,
62
+ filterComponent: 'filter/date',
63
+ },
64
+ ];
65
+
66
+ @action viewCustomer(customer) {
67
+ this.contextPanel.focus(customer, 'viewing');
68
+ }
69
+ }