@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
@@ -3,67 +3,18 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
4
  import { action, set } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
  import createShareableLink from '../../../../utils/create-shareable-link';
9
8
  import isEmail from '@fleetbase/ember-core/utils/is-email';
10
9
  import isModel from '@fleetbase/ember-core/utils/is-model';
11
10
 
12
11
  export default class NetworksIndexNetworkStoresController extends Controller {
13
- /**
14
- * Inject the `notifications` service
15
- *
16
- * @var {Service}
17
- * @memberof NetworksIndexNetworkStoresController
18
- */
19
12
  @service notifications;
20
-
21
- /**
22
- * Inject the `intl` service
23
- *
24
- * @var {Service}
25
- * @memberof NetworksIndexNetworkStoresController
26
- */
27
13
  @service intl;
28
-
29
- /**
30
- * Inject the `modals-manager` service
31
- *
32
- * @var {Service}
33
- * @memberof NetworksIndexNetworkStoresController
34
- */
35
14
  @service modalsManager;
36
-
37
- /**
38
- * Inject the `crud` service
39
- *
40
- * @var {Service}
41
- * @memberof NetworksIndexNetworkStoresController
42
- */
43
15
  @service crud;
44
-
45
- /**
46
- * Inject the `fetch` service
47
- *
48
- * @var {Service}
49
- * @memberof NetworksIndexNetworkStoresController
50
- */
51
16
  @service fetch;
52
-
53
- /**
54
- * Inject the `store` service
55
- *
56
- * @var {Service}
57
- * @memberof NetworksIndexNetworkStoresController
58
- */
59
17
  @service store;
60
-
61
- /**
62
- * Inject the `hostRouter` service
63
- *
64
- * @var {Service}
65
- * @memberof NetworksIndexNetworkStoresController
66
- */
67
18
  @service hostRouter;
68
19
 
69
20
  /**
@@ -122,12 +73,25 @@ export default class NetworksIndexNetworkStoresController extends Controller {
122
73
  @tracked network;
123
74
 
124
75
  /**
125
- * The loading state.
76
+ * The stores loaded.
77
+ *
78
+ * @memberof NetworksIndexNetworkStoresController
79
+ */
80
+ @tracked stores = [];
81
+
82
+ /**
83
+ * The category picker component context.
84
+ *
85
+ * @memberof NetworksIndexNetworkStoresController
86
+ */
87
+ @tracked categoryPicker;
88
+
89
+ /**
90
+ * The current category model instance.
126
91
  *
127
- * @var {Boolean}
128
92
  * @memberof NetworksIndexNetworkStoresController
129
93
  */
130
- @tracked isLoading = false;
94
+ @tracked categoryModel;
131
95
 
132
96
  /**
133
97
  * All columns applicable for network stores
@@ -144,6 +108,7 @@ export default class NetworksIndexNetworkStoresController extends Controller {
144
108
  filterable: true,
145
109
  filterComponent: 'filter/string',
146
110
  showOnlineIndicator: true,
111
+ cellClassNames: 'network-store-name-column',
147
112
  },
148
113
  {
149
114
  label: this.intl.t('storefront.common.id'),
@@ -208,6 +173,11 @@ export default class NetworksIndexNetworkStoresController extends Controller {
208
173
  label: this.intl.t('storefront.networks.index.network.stores.assign-category'),
209
174
  fn: this.assignStoreToCategory,
210
175
  },
176
+ {
177
+ label: this.intl.t('storefront.networks.index.network.stores.remove-category'),
178
+ fn: this.removeStoreCategory,
179
+ isVisible: (store) => store.category,
180
+ },
211
181
  {
212
182
  separator: true,
213
183
  },
@@ -247,6 +217,10 @@ export default class NetworksIndexNetworkStoresController extends Controller {
247
217
  this.storeQuery = value;
248
218
  }
249
219
 
220
+ @action setCategoryPickerContext(context) {
221
+ this.categoryPicker = context;
222
+ }
223
+
250
224
  /**
251
225
  * Selects a category and assigns its ID to the current category property.
252
226
  * If the selected category is null, the category property is set to null.
@@ -255,6 +229,8 @@ export default class NetworksIndexNetworkStoresController extends Controller {
255
229
  * @param {CategoryModel|null} selectedCategory - The selected category object containing the ID.
256
230
  */
257
231
  @action selectCategory(selectedCategory) {
232
+ this.categoryModel = selectedCategory;
233
+
258
234
  if (selectedCategory) {
259
235
  this.category = selectedCategory.id;
260
236
  } else {
@@ -285,6 +261,36 @@ export default class NetworksIndexNetworkStoresController extends Controller {
285
261
  });
286
262
  }
287
263
 
264
+ /**
265
+ * Displays a confirmation modal to remove a specified store from the network.
266
+ * Allows the user to confirm the removal.
267
+ *
268
+ * @action
269
+ * @param {StoreModel} store - The store object to be removed.
270
+ */
271
+ @action async removeStoreCategory(store) {
272
+ this.modalsManager.confirm({
273
+ title: this.intl.t('storefront.networks.index.network.stores.remove-store-category'),
274
+ body: this.intl.t('storefront.networks.index.network.stores.remove-store-category-body', { storeName: store.name, categoryName: store.category?.get('name') }),
275
+ acceptButtonIcon: 'check',
276
+ acceptButtonIconPrefix: 'fas',
277
+ declineButtonIcon: 'times',
278
+ declineButtonIconPrefix: 'fas',
279
+ confirm: async (modal) => {
280
+ modal.startLoading();
281
+
282
+ try {
283
+ await this.fetch.post(`networks/${this.network.id}/remove-store-category`, { store: store.id }, { namespace: 'storefront/int/v1' });
284
+ await this.hostRouter.refresh();
285
+ modal.done();
286
+ } catch (error) {
287
+ modal.stopLoading();
288
+ this.notifications.serverError(error);
289
+ }
290
+ },
291
+ });
292
+ }
293
+
288
294
  /**
289
295
  * Displays a modal to assign a store to a category or create a new category.
290
296
  * Allows the user to select a category, create a new one, or confirm the assignment.
@@ -516,19 +522,17 @@ export default class NetworksIndexNetworkStoresController extends Controller {
516
522
  acceptButtonIconPrefix: 'fas',
517
523
  declineButtonIcon: 'times',
518
524
  declineButtonIconPrefix: 'fas',
519
- confirm: (modal) => {
525
+ confirm: async (modal) => {
520
526
  modal.startLoading();
521
527
 
522
- this.fetch
523
- .post(`networks/${this.network.id}/remove-stores`, { stores: [store.id] }, { namespace: 'storefront/int/v1' })
524
- .then(() => {
525
- this.stores.removeObject(store);
526
- modal.done();
527
- })
528
- .catch((error) => {
529
- modal.stopLoading();
530
- this.notifications.serverError(error);
531
- });
528
+ try {
529
+ await this.fetch.post(`networks/${this.network.id}/remove-stores`, { stores: [store.id] }, { namespace: 'storefront/int/v1' });
530
+ await this.hostRouter.refresh();
531
+ modal.done();
532
+ } catch (error) {
533
+ modal.stopLoading();
534
+ this.notifications.serverError(error);
535
+ }
532
536
  },
533
537
  });
534
538
  }
@@ -4,8 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { tracked } from '@glimmer/tracking';
5
5
  import { action } from '@ember/object';
6
6
  import { isBlank } from '@ember/utils';
7
- import { timeout } from 'ember-concurrency';
8
- import { task } from 'ember-concurrency-decorators';
7
+ import { timeout, task } from 'ember-concurrency';
9
8
 
10
9
  export default class NetworksIndexController extends BaseController {
11
10
  /**
@@ -4,8 +4,7 @@ import { inject as service } from '@ember/service';
4
4
  import { action } from '@ember/object';
5
5
  import { dasherize } from '@ember/string';
6
6
  import { isBlank } from '@ember/utils';
7
- import { timeout } from 'ember-concurrency';
8
- import { task } from 'ember-concurrency-decorators';
7
+ import { timeout, task } from 'ember-concurrency';
9
8
 
10
9
  export default class ProductsIndexCategoryController extends BaseController {
11
10
  @service intl;
@@ -3,8 +3,7 @@ import { inject as service } from '@ember/service';
3
3
  import { tracked } from '@glimmer/tracking';
4
4
  import { action } from '@ember/object';
5
5
  import { isBlank } from '@ember/utils';
6
- import { timeout } from 'ember-concurrency';
7
- import { task } from 'ember-concurrency-decorators';
6
+ import { timeout, task } from 'ember-concurrency';
8
7
 
9
8
  export default class ProductsIndexIndexController extends BaseController {
10
9
  @service filters;
@@ -43,10 +43,15 @@ export default class SettingsGatewaysController extends Controller {
43
43
  const schemas = getGatewaySchemas();
44
44
  const schemaOptions = Object.keys(schemas);
45
45
 
46
+ let schema = null;
47
+ if (!gateway.get('isNew')) {
48
+ schema = schemas[gateway.code];
49
+ }
50
+
46
51
  this.modalsManager.show('modals/create-gateway', {
47
52
  title: this.intl.t('storefront.settings.gateways.edit-payment-gateway'),
48
53
  acceptButtonText: this.intl.t('storefront.settings.gateways.save-changes'),
49
- schema: null,
54
+ schema,
50
55
  schemas,
51
56
  schemaOptions,
52
57
  gateway,
@@ -17,6 +17,7 @@ export default class SettingsIndexController extends Controller {
17
17
  @tracked isLoading = false;
18
18
  @tracked uploadQueue = [];
19
19
  @tracked uploadedFiles = [];
20
+ @tracked orderConfigs = [];
20
21
 
21
22
  @action addTag(tag) {
22
23
  if (!isArray(this.model.tags)) {
@@ -1,5 +1,4 @@
1
1
  import Controller from '@ember/controller';
2
- import { tracked } from '@glimmer/tracking';
3
2
  import { inject as service } from '@ember/service';
4
3
  import { alias } from '@ember/object/computed';
5
4
  import { action, set } from '@ember/object';
@@ -14,7 +13,6 @@ export default class SettingsNotificationsController extends Controller {
14
13
  @service crud;
15
14
  @service storefront;
16
15
  @alias('storefront.activeStore') activeStore;
17
- @tracked channels = [];
18
16
 
19
17
  @action createChannel() {
20
18
  const channel = this.store.createRecord('notification-channel', {
@@ -71,9 +69,9 @@ export default class SettingsNotificationsController extends Controller {
71
69
 
72
70
  return channel
73
71
  .save()
74
- .then((channel) => {
72
+ .then(() => {
75
73
  this.notifications.success(this.intl.t('storefront.settings.notification.new-notification-channel-added'));
76
- this.channels.pushObject(channel);
74
+ this.hostRouter.refresh();
77
75
  })
78
76
  .catch((error) => {
79
77
  // gateway.rollbackAttributes();
@@ -94,7 +92,7 @@ export default class SettingsNotificationsController extends Controller {
94
92
 
95
93
  return channel.destroyRecord().then(() => {
96
94
  // justincase
97
- this.channels.removeObject(channel);
95
+ this.hostRouter.refresh();
98
96
  modal.stopLoading();
99
97
  });
100
98
  },
@@ -10,6 +10,7 @@ export default class NetworkModel extends Model {
10
10
  @attr('string') company_uuid;
11
11
  @attr('string') logo_uuid;
12
12
  @attr('string') backdrop_uuid;
13
+ @attr('string') order_config_uuid;
13
14
 
14
15
  /** @relationships */
15
16
  @hasMany('store') stores;
@@ -11,6 +11,7 @@ export default class StoreModel extends Model {
11
11
  @attr('string') company_uuid;
12
12
  @attr('string') logo_uuid;
13
13
  @attr('string') backdrop_uuid;
14
+ @attr('string') order_config_uuid;
14
15
 
15
16
  /** @relationships */
16
17
  @hasMany('notification-channel') notification_channels;
@@ -7,4 +7,9 @@ export default class NetworksIndexNetworkIndexRoute extends Route {
7
7
  model() {
8
8
  return this.modelFor('networks.index.network');
9
9
  }
10
+
11
+ async setupController(controller) {
12
+ super.setupController(...arguments);
13
+ controller.orderConfigs = await this.store.findAll('order-config');
14
+ }
10
15
  }
@@ -3,6 +3,7 @@ import { inject as service } from '@ember/service';
3
3
 
4
4
  export default class NetworksIndexNetworkStoresRoute extends Route {
5
5
  @service store;
6
+ @service hostRouter;
6
7
 
7
8
  queryParams = {
8
9
  category: { refreshModel: true },
@@ -23,10 +24,10 @@ export default class NetworksIndexNetworkStoresRoute extends Route {
23
24
  // set the network to controller
24
25
  controller.network = this.network;
25
26
 
26
- // // load the network categories
27
- // const categories = await this.store.query('category', { owner_uuid: network.id, parents_only: true, for: 'storefront_network' });
28
-
29
- // // set the categories loaded
30
- // controller.categories = categories.toArray();
27
+ // set the cateogry if set
28
+ const { category: categoryId } = this.paramsFor(this.routeName);
29
+ if (categoryId) {
30
+ controller.category = categoryId;
31
+ }
31
32
  }
32
33
  }
@@ -24,4 +24,9 @@ export default class SettingsIndexRoute extends Route {
24
24
  afterModel(model) {
25
25
  model?.loadFiles();
26
26
  }
27
+
28
+ async setupController(controller) {
29
+ super.setupController(...arguments);
30
+ controller.orderConfigs = await this.store.findAll('order-config');
31
+ }
27
32
  }
@@ -215,6 +215,37 @@ export default class OrderActionsService extends Service {
215
215
  });
216
216
  }
217
217
 
218
+ markAsPreparing(order, callback) {
219
+ this.modalsManager.confirm({
220
+ title: this.intl.t('storefront.component.widget.orders.mark-as-preparing-modal-title'),
221
+ body: this.intl.t('storefront.component.widget.orders.mark-as-preparing-modal-body'),
222
+ acceptButtonText: this.intl.t('storefront.component.widget.orders.mark-as-preparing-accept-button-text'),
223
+ acceptButtonIcon: 'check',
224
+ acceptButtonScheme: 'success',
225
+ confirm: async (modal) => {
226
+ modal.startLoading();
227
+
228
+ try {
229
+ await this.fetch.post('orders/preparing', { order: order.id }, { namespace: 'storefront/int/v1' });
230
+ modal.done();
231
+ if (typeof callback === 'function') {
232
+ callback(order);
233
+ }
234
+ } catch (err) {
235
+ this.notifications.serverError(err);
236
+ } finally {
237
+ modal.stopLoading();
238
+ }
239
+ },
240
+ decline: async (modal) => {
241
+ if (typeof callback === 'function') {
242
+ callback(order);
243
+ }
244
+ modal.done();
245
+ },
246
+ });
247
+ }
248
+
218
249
  markAsCompleted(order, callback) {
219
250
  this.modalsManager.confirm({
220
251
  title: this.intl.t('storefront.component.widget.orders.mark-as-completed-modal-title'),
@@ -40,12 +40,14 @@
40
40
  max-width: 100%;
41
41
  }
42
42
 
43
+ .status-badge.accepted-status-badge > span,
43
44
  .status-badge.pickup-ready-status-badge > span {
44
45
  background-color: #166534;
45
46
  border: 1px solid #15803d;
46
47
  color: #dcfce7;
47
48
  }
48
49
 
50
+ .status-badge.accepted-status-badge > span svg,
49
51
  .status-badge.pickup-ready-status-badge > span svg {
50
52
  color: #86efac;
51
53
  }
@@ -60,12 +62,16 @@
60
62
  color: #fca5a5;
61
63
  }
62
64
 
65
+ .status-badge.driver-picked-up-status-badge > span,
66
+ .status-badge.driver-enroute-to-store-status-badge > span,
63
67
  .status-badge.draft-status-badge > span {
64
68
  background-color: #a16207;
65
69
  border: 1px solid #a16207;
66
70
  color: #fef9c3;
67
71
  }
68
72
 
73
+ .status-badge.driver-picked-up-status-badge > span svg,
74
+ .status-badge.driver-enroute-to-store-status-badge > span svg,
69
75
  .status-badge.draft-status-badge > span svg {
70
76
  color: #fef9c3;
71
77
  }
@@ -77,3 +83,26 @@ body[data-theme='dark'] .ui-tabs.overlay-content-panel > ul .ui-tab.active,
77
83
  body[data-theme='dark'] .ui-tabs.overlay-content-panel > nav .ui-tab.active {
78
84
  background-color: #202a37;
79
85
  }
86
+
87
+ /** hotfix online indicator overflowing store name */
88
+ td.network-store-name-column > div > svg {
89
+ margin-left: -0.7rem;
90
+ height: 0.5rem;
91
+ width: 0.5rem;
92
+ }
93
+
94
+ .storefront-datepicker .air-datepicker-buttons {
95
+ animation: slideIn 0.3s ease-out;
96
+ display: flex;
97
+ flex-wrap: wrap;
98
+ gap: 8px;
99
+ padding: 0.5rem;
100
+ max-height: 235px;
101
+ overflow-y: auto;
102
+ }
103
+
104
+ .storefront-datepicker .air-datepicker-buttons .quick-select-btn {
105
+ display: flex;
106
+ align-items: center;
107
+ width: 48%;
108
+ }
@@ -22,10 +22,23 @@
22
22
  @placeholder={{t "storefront.networks.index.network.index.general-network-settings-form.description-placeholder"}}
23
23
  @helpText={{t "storefront.networks.index.network.index.general-network-settings-form.description-help-text"}}
24
24
  />
25
+
25
26
  <InputGroup @name={{t "storefront.networks.index.network.index.general-network-settings-form.currency"}}>
26
27
  <CurrencySelect @currency={{@model.currency}} @onCurrencyChange={{fn (mut @model.currency)}} @triggerClass="w-full form-select" />
27
28
  </InputGroup>
28
29
 
30
+ <InputGroup @name="Default Order Config" @helpText="Select the order config which will apply to all orders created for this network.">
31
+ <Select
32
+ @value={{@model.order_config_uuid}}
33
+ @options={{this.orderConfigs}}
34
+ @optionValue="id"
35
+ @optionLabel="name"
36
+ @onSelect={{fn (mut @model.order_config_uuid)}}
37
+ @placeholder="Select default order config"
38
+ class="w-full"
39
+ />
40
+ </InputGroup>
41
+
29
42
  <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-form.contact-social-panel.panel-title"}} @open={{false}} @pad={{true}}>
30
43
  <InputGroup @name={{t "storefront.networks.index.network.index.general-network-settings-form.contact-social-panel.phone"}}>
31
44
  <PhoneInput @value={{@model.phone}} @onInput={{fn (mut @model.phone)}} class="form-input w-full" />
@@ -19,6 +19,20 @@
19
19
  </Layout::Section::Header>
20
20
 
21
21
  <Layout::Section::Body>
22
- <NetworkCategoryPicker @network={{this.network}} @onCreateNewCategory={{this.createNewCategory}} @onSelect={{this.selectCategory}} @wrapperClass="my-4 ml-9" />
22
+ <div class="flex flex-row items-center space-x-2">
23
+ <NetworkCategoryPicker
24
+ @network={{this.network}}
25
+ @category={{this.category}}
26
+ @onCreateNewCategory={{this.createNewCategory}}
27
+ @onSelect={{this.selectCategory}}
28
+ @onReady={{this.setCategoryPickerContext}}
29
+ @wrapperClass="w-64 my-4 ml-9"
30
+ />
31
+ {{#if this.categoryModel}}
32
+ <Button @icon="arrow-left" @size="xs" @onClick={{this.categoryPicker.loadParentCategories}} />
33
+ <Button @icon="cog" @text="Edit Category" @size="xs" @onClick={{fn this.editCategory this.categoryModel}} />
34
+ <Button @icon="trash" @text="Delete Category" @size="xs" @type="danger" @onClick={{fn this.deleteCategory this.categoryModel}} />
35
+ {{/if}}
36
+ </div>
23
37
  <Table @rows={{@model}} @columns={{this.columns}} @selectable={{true}} @canSelectAll={{true}} @onSetup={{fn (mut this.table)}} @tfoot={{false}} @selectAllColumnWidth={{20}} />
24
38
  </Layout::Section::Body>
@@ -12,7 +12,7 @@
12
12
  <Image src={{network.logo_url}} class="w-32" alt={{network.name}} @fallbackSrc="https://flb-assets.s3.ap-southeast-1.amazonaws.com/static/image-file-icon.png" />
13
13
  </div>
14
14
  <div class="border-t dark:border-gray-700 px-4 py-2">
15
- <div class="flex items-center justify-between">
15
+ <div class="flex items-start justify-between">
16
16
  <div>
17
17
  <LinkTo @route="networks.index.network" @model={{network}} class="font-bold text-lg text-gray-700 dark:text-gray-100">{{network.name}}</LinkTo>
18
18
  </div>
@@ -38,17 +38,28 @@
38
38
  {{#each-in gateway.config as |key value|}}
39
39
  {{#if (is-bool-value value)}}
40
40
  <div class="input-group">
41
- <Checkbox @value={{value}} @label={{humanize key}} />
41
+ <Checkbox @value={{value}} @label={{humanize key}} @disabled={{true}} />
42
42
  </div>
43
43
  {{else}}
44
44
  <InputGroup @name={{humanize key}}>
45
- <Input class="form-input w-full" placeholder={{humanize key}} @value={{value}} />
45
+ <Input
46
+ @type={{if (can "storefront update gateway") "text" "password"}}
47
+ class="form-input w-full"
48
+ placeholder={{humanize key}}
49
+ @value={{value}}
50
+ disabled
51
+ />
46
52
  </InputGroup>
47
53
  {{/if}}
48
54
  {{/each-in}}
49
55
  </div>
50
- <div>
51
- <Button @size="sm" @type="danger" @icon="trash" @text={{t "storefront.settings.gateways.delete-payment-gateway"}} @onClick={{fn this.deleteGateway gateway}} />
56
+ <div class="flex flex-row items-center space-x-2">
57
+ {{#if (can "storefront update gateway")}}
58
+ <Button @size="sm" @type="primary" @icon="pencil" @text="Edit Gateway" @onClick={{fn this.editGateway gateway}} />
59
+ {{/if}}
60
+ {{#if (can "storefront delete gateway")}}
61
+ <Button @size="sm" @type="danger" @icon="trash" @text={{t "storefront.settings.gateways.delete-payment-gateway"}} @onClick={{fn this.deleteGateway gateway}} />
62
+ {{/if}}
52
63
  </div>
53
64
  </ContentPanel>
54
65
  {{/each}}
@@ -36,10 +36,23 @@
36
36
  {{tag}}
37
37
  </TagInput>
38
38
  </InputGroup>
39
+
39
40
  <InputGroup @name={{t "storefront.common.currency"}}>
40
41
  <CurrencySelect @currency={{@model.currency}} @onCurrencyChange={{fn (mut @model.currency)}} @triggerClass="w-full form-select" />
41
42
  </InputGroup>
42
43
 
44
+ <InputGroup @name="Default Order Config" @helpText="Select the order config which will apply to all orders created for this store">
45
+ <Select
46
+ @value={{@model.order_config_uuid}}
47
+ @options={{this.orderConfigs}}
48
+ @optionValue="id"
49
+ @optionLabel="name"
50
+ @onSelect={{fn (mut @model.order_config_uuid)}}
51
+ @placeholder="Select default order config"
52
+ class="w-full"
53
+ />
54
+ </InputGroup>
55
+
43
56
  <ContentPanel @title={{t "storefront.settings.index.contact-social"}} @open={{false}} @pad={{true}}>
44
57
  <InputGroup @name={{t "storefront.common.phone"}}>
45
58
  <PhoneInput @value={{@model.phone}} @onInput={{fn (mut @model.phone)}} class="form-input w-full" />
@@ -16,8 +16,8 @@
16
16
  </div>
17
17
 
18
18
  <div class="space-y-3">
19
- {{#each this.channels as |notificationChannel|}}
20
- <div class="flex px-4 py-2 items-center justify-between shadow-sm rounded-md dark:bg-gray-900 bg-gray-200">
19
+ {{#each @model as |notificationChannel|}}
20
+ <div class="flex px-4 py-2 items-center justify-between shadow-sm rounded-md dark:bg-gray-900 bg-gray-200 border border-gray-200 dark:border-gray-700">
21
21
  <div>
22
22
  <span class="dark:text-gray-50">{{notificationChannel.name}}</span>
23
23
  </div>