@fleetbase/storefront-engine 0.4.0 → 0.4.2

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 (77) hide show
  1. package/addon/components/customer-panel/orders.hbs +2 -2
  2. package/addon/components/modals/create-gateway.hbs +33 -12
  3. package/addon/components/network-category-picker.js +1 -1
  4. package/addon/components/order-panel.hbs +1 -1
  5. package/addon/components/widget/customers.hbs +5 -2
  6. package/addon/components/widget/customers.js +14 -6
  7. package/addon/components/widget/orders.hbs +31 -10
  8. package/addon/components/widget/orders.js +7 -1
  9. package/addon/components/widget/storefront-key-metrics.js +2 -2
  10. package/addon/components/widget/storefront-metrics.hbs +11 -1
  11. package/addon/components/widget/storefront-metrics.js +103 -1
  12. package/addon/controllers/networks/index/network/index.js +2 -0
  13. package/addon/controllers/networks/index/network/stores.js +0 -1
  14. package/addon/controllers/products/index/category/new.js +13 -2
  15. package/addon/controllers/settings/gateways.js +6 -1
  16. package/addon/controllers/settings/index.js +1 -0
  17. package/addon/controllers/settings/notifications.js +4 -5
  18. package/addon/models/network.js +1 -0
  19. package/addon/models/store.js +1 -0
  20. package/addon/routes/networks/index/network/index.js +5 -0
  21. package/addon/routes/settings/index.js +5 -0
  22. package/addon/services/order-actions.js +31 -0
  23. package/addon/styles/storefront-engine.css +22 -0
  24. package/addon/templates/home.hbs +2 -2
  25. package/addon/templates/networks/index/network/index.hbs +21 -8
  26. package/addon/templates/networks/index/network/stores.hbs +8 -1
  27. package/addon/templates/products/index/category/new.hbs +149 -134
  28. package/addon/templates/settings/gateways.hbs +15 -4
  29. package/addon/templates/settings/index.hbs +13 -0
  30. package/addon/templates/settings/notifications.hbs +2 -2
  31. package/addon/utils/commerce-date-ranges.js +263 -0
  32. package/app/utils/commerce-date-ranges.js +1 -0
  33. package/composer.json +1 -1
  34. package/extension.json +1 -1
  35. package/package.json +4 -4
  36. package/server/migrations/2025_09_01_041353_add_default_order_config_column.php +110 -0
  37. package/server/src/Console/Commands/MigrateStripeSandboxCustomers.php +165 -0
  38. package/server/src/Expansions/OrderExpansion.php +43 -0
  39. package/server/src/Http/Controllers/NetworkController.php +1 -1
  40. package/server/src/Http/Controllers/OrderController.php +62 -9
  41. package/server/src/Http/Controllers/v1/CheckoutController.php +57 -48
  42. package/server/src/Http/Controllers/v1/ServiceQuoteController.php +19 -3
  43. package/server/src/Http/Middleware/SetStorefrontSession.php +8 -6
  44. package/server/src/Http/Resources/Customer.php +41 -17
  45. package/server/src/Http/Resources/Gateway.php +16 -11
  46. package/server/src/Http/Resources/Network.php +35 -34
  47. package/server/src/Http/Resources/NotificationChannel.php +17 -10
  48. package/server/src/Http/Resources/Product.php +1 -0
  49. package/server/src/Http/Resources/Store.php +36 -35
  50. package/server/src/Models/Customer.php +18 -2
  51. package/server/src/Models/FoodTruck.php +29 -2
  52. package/server/src/Models/Network.php +63 -1
  53. package/server/src/Models/Store.php +71 -9
  54. package/server/src/Notifications/StorefrontOrderAccepted.php +164 -0
  55. package/server/src/Notifications/StorefrontOrderCanceled.php +11 -1
  56. package/server/src/Notifications/StorefrontOrderCompleted.php +11 -1
  57. package/server/src/Notifications/StorefrontOrderDriverAssigned.php +12 -4
  58. package/server/src/Notifications/StorefrontOrderEnroute.php +12 -4
  59. package/server/src/Notifications/StorefrontOrderNearby.php +12 -4
  60. package/server/src/Notifications/StorefrontOrderPreparing.php +12 -4
  61. package/server/src/Notifications/StorefrontOrderReadyForPickup.php +12 -4
  62. package/server/src/Observers/OrderObserver.php +6 -4
  63. package/server/src/Providers/StorefrontServiceProvider.php +1 -0
  64. package/server/src/Rules/IsValidLocation.php +12 -0
  65. package/server/src/Support/PushNotification.php +20 -4
  66. package/server/src/Support/Storefront.php +283 -37
  67. package/server/src/routes.php +1 -0
  68. package/translations/{ar-ae.yml → ar-ae.yaml} +313 -253
  69. package/translations/bg-bg.yaml +734 -0
  70. package/translations/en-us.yaml +5 -0
  71. package/translations/es-es.yaml +732 -0
  72. package/translations/fr-fr.yaml +748 -0
  73. package/translations/mn-mn.yaml +725 -0
  74. package/translations/pt-br.yaml +732 -0
  75. package/translations/ru-ru.yaml +726 -0
  76. package/translations/vi-vn.yaml +412 -338
  77. package/translations/zh-cn.yaml +659 -0
@@ -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
  }
@@ -84,3 +90,19 @@ td.network-store-name-column > div > svg {
84
90
  height: 0.5rem;
85
91
  width: 0.5rem;
86
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
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  <Layout::Section::Body class="space-y-4 h-full overflow-y-scroll" @padded={{true}}>
4
4
  <Widget::StorefrontMetrics />
5
- <Widget::Orders />
6
- <Widget::Customers />
5
+ <Widget::Orders @wrapperClass="bordered-classic" />
6
+ <Widget::Customers @wrapperClass="bordered-classic" />
7
7
  <Spacer @height="300px" />
8
8
  </Layout::Section::Body>
@@ -1,5 +1,5 @@
1
- <div class="space-y-4 px-6 py-4">
2
- <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-title"}} @open={{true}} @pad={{true}}>
1
+ <div class="space-y-2">
2
+ <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-title"}} @open={{true}} @pad={{false}} @wrapperClass="bordered-top">
3
3
  <div class="space-y-4">
4
4
  <div>
5
5
  <h1 class="text-lg leading-6 font-bold text-gray-900 dark:text-gray-100">
@@ -22,11 +22,24 @@
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
 
29
- <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-form.contact-social-panel.panel-title"}} @open={{false}} @pad={{true}}>
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
+
42
+ <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-form.contact-social-panel.panel-title"}} @open={{false}} @pad={{false}} @wrapperClass="bordered-top">
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" />
32
45
  </InputGroup>
@@ -62,7 +75,7 @@
62
75
  />
63
76
  </ContentPanel>
64
77
 
65
- <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-form.logo-backdrop-panel.panel-title"}} @open={{false}} @pad={{true}}>
78
+ <ContentPanel @title={{t "storefront.networks.index.network.index.general-network-settings-form.logo-backdrop-panel.panel-title"}} @open={{false}} @pad={{false}} @wrapperClass="bordered-top">
66
79
  <InputGroup
67
80
  @name={{t "storefront.networks.index.network.index.general-network-settings-form.logo-backdrop-panel.logo-label"}}
68
81
  @helpText={{t "storefront.networks.index.network.index.general-network-settings-form.logo-backdrop-panel.logo-help-text"}}
@@ -255,7 +268,7 @@
255
268
  </div>
256
269
  </ContentPanel>
257
270
 
258
- <ContentPanel @title={{t "storefront.networks.index.network.index.api-panel.panel-title"}} @open={{false}} @pad={{true}}>
271
+ <ContentPanel @title={{t "storefront.networks.index.network.index.api-panel.panel-title"}} @open={{false}} @pad={{false}} @wrapperClass="bordered-top">
259
272
  <div class="space-y-6">
260
273
  <div>
261
274
  <h1 class="text-lg leading-6 font-bold text-gray-900 dark:text-gray-100">
@@ -275,7 +288,7 @@
275
288
  </div>
276
289
  </ContentPanel>
277
290
 
278
- <ContentPanel @title={{t "storefront.networks.index.network.index.payment-gateways-panel.panel-title"}} @open={{false}} @pad={{true}}>
291
+ <ContentPanel @title={{t "storefront.networks.index.network.index.payment-gateways-panel.panel-title"}} @open={{false}} @pad={{false}} @wrapperClass="bordered-top">
279
292
  <div class="space-y-6">
280
293
  <div class="flex justify-between">
281
294
  <div>
@@ -298,7 +311,7 @@
298
311
  </div>
299
312
 
300
313
  {{#each this.gateways as |gateway|}}
301
- <ContentPanel @title={{gateway.name}} @open={{true}} @pad={{true}}>
314
+ <ContentPanel @title={{gateway.name}} @open={{true}} @pad={{false}} @wrapperClass="bordered-top">
302
315
  <InputGroup
303
316
  @name={{t "storefront.networks.index.network.index.payment-gateways-panel.gateway-form.name"}}
304
317
  @value={{gateway.name}}
@@ -355,7 +368,7 @@
355
368
  </div>
356
369
  </ContentPanel>
357
370
 
358
- <ContentPanel @title={{t "storefront.networks.index.network.index.notification-channels-panel.panel-title"}} @open={{false}} @pad={{true}}>
371
+ <ContentPanel @title={{t "storefront.networks.index.network.index.notification-channels-panel.panel-title"}} @open={{false}} @pad={{false}} @wrapperClass="bordered-top">
359
372
  <div class="space-y-6">
360
373
  <div class="flex justify-between">
361
374
  <div class="w-3/4">
@@ -20,7 +20,14 @@
20
20
 
21
21
  <Layout::Section::Body>
22
22
  <div class="flex flex-row items-center space-x-2">
23
- <NetworkCategoryPicker @network={{this.network}} @category={{this.category}} @onCreateNewCategory={{this.createNewCategory}} @onSelect={{this.selectCategory}} @onReady={{this.setCategoryPickerContext}} @wrapperClass="w-64 my-4 ml-9" />
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
+ />
24
31
  {{#if this.categoryModel}}
25
32
  <Button @icon="arrow-left" @size="xs" @onClick={{this.categoryPicker.loadParentCategories}} />
26
33
  <Button @icon="cog" @text="Edit Category" @size="xs" @onClick={{fn this.editCategory this.categoryModel}} />
@@ -7,79 +7,100 @@
7
7
  @headerLeftInnerClass="w-full flex-1"
8
8
  @onPressCancel={{this.transitionBack}}
9
9
  >
10
- <Button
11
- @icon={{this.overlayActionButtonIcon}}
12
- @type="primary"
13
- @text={{this.overlayActionButtonTitle}}
14
- @onClick={{perform this.saveProduct}}
15
- @isLoading={{not this.saveProduct.isIdle}}
16
- @permission={{this.abilityPermission}}
17
- />
10
+ <:actions>
11
+ <Button
12
+ @icon={{this.overlayActionButtonIcon}}
13
+ @type="primary"
14
+ @text={{this.overlayActionButtonTitle}}
15
+ @onClick={{perform this.saveProduct}}
16
+ @isLoading={{not this.saveProduct.isIdle}}
17
+ @permission={{this.abilityPermission}}
18
+ />
19
+ </:actions>
18
20
  </Overlay::Header>
19
21
 
20
- <Overlay::Body @increaseInnerBodyHeightBy="0" @wrapperClass="new-order-overlay-body px-4 space-y-4 pt-4">
22
+ <Overlay::Body>
21
23
  {{#let (cannot this.abilityPermission) as |unauthorized|}}
22
- <InputGroup @name="Product Name" @value={{this.product.name}} @helpText="Enter your product's name" @disabled={{unauthorized}} />
23
- <InputGroup @name="Product Description" @helpText="Enter a description of your product">
24
- <Textarea @value={{this.product.description}} class="form-input w-full" placeholder="Enter a description of your product...." disabled={{unauthorized}} rows={{4}} />
25
- </InputGroup>
26
- <InputGroup @name="Product Status">
27
- <Select
28
- class="w-full"
29
- @value={{this.product.status}}
30
- @placeholder="Select product status"
31
- @options={{this.statusOptions}}
32
- @onSelect={{fn (mut this.product.status)}}
33
- @humanize={{true}}
34
- />
35
- </InputGroup>
36
- <InputGroup @name="Product Tags">
37
- <TagInput
38
- class="form-input"
39
- @placeholder="Add tags"
40
- @allowSpacesInTags={{true}}
41
- @tags={{this.product.tags}}
42
- @addTag={{this.addTag}}
43
- @removeTagAtIndex={{this.removeTag}}
44
- @disabled={{unauthorized}}
45
- as |tag|
46
- >
47
- {{tag}}
48
- </TagInput>
49
- </InputGroup>
50
- <InputGroup @name="Product SKU" @value={{this.product.sku}} @helpText="Enter product SKU if applicable" @disabled={{unauthorized}} />
51
- <div class="grid grid-cols-2 gap-2">
52
- <InputGroup @name="Price" @helpText="Enter a price users will pay to purchase this product">
53
- <MoneyInput
24
+ <ContentPanel @title={{t "common.details"}} @open={{true}} @wrapperClass="bordered-top">
25
+ <InputGroup @name="Product Name" @value={{this.product.name}} @helpText="Enter your product's name" @disabled={{unauthorized}} />
26
+ <InputGroup @name="Product Description" @helpText="Enter a description of your product">
27
+ <Textarea @value={{this.product.description}} class="form-input w-full" placeholder="Enter a description of your product...." disabled={{unauthorized}} rows={{4}} />
28
+ </InputGroup>
29
+ <InputGroup @name="Product Category">
30
+ <ModelSelect
31
+ @modelName="category"
32
+ @selectedModel={{this.product.category}}
33
+ @query={{hash for="storefront_product" owner_uuid=this.activeStore.id}}
34
+ @placeholder="Select Product Category"
35
+ @triggerClass="form-select form-input"
36
+ @infiniteScroll={{false}}
37
+ @renderInPlace={{true}}
38
+ @allowClear={{true}}
39
+ @onChange={{fn (mut this.product.category)}}
40
+ @onChangeId={{fn (mut this.product.category_uuid)}}
41
+ as |model|
42
+ >
43
+ <div class="flex items-center">
44
+ <span class="uppercase">
45
+ {{model.name}}
46
+ </span>
47
+ </div>
48
+ </ModelSelect>
49
+ </InputGroup>
50
+ <InputGroup @name="Product Status">
51
+ <Select
54
52
  class="w-full"
55
- @currency={{if this.product.currency this.product.currency this.activeStore.currency}}
56
- @value={{this.product.price}}
57
- @canSelectCurrency={{false}}
58
- @onCurrencyChange={{fn (mut this.product.currency)}}
59
- @disabled={{unauthorized}}
53
+ @value={{this.product.status}}
54
+ @placeholder="Select product status"
55
+ @options={{this.statusOptions}}
56
+ @onSelect={{fn (mut this.product.status)}}
57
+ @humanize={{true}}
60
58
  />
61
59
  </InputGroup>
62
- <InputGroup @name="Sale Price" @helpText="Optionally add a sale price for the product if the product is put on sale">
63
- <MoneyInput
64
- class="w-full"
65
- @currency={{if this.product.currency this.product.currency this.activeStore.currency}}
66
- @value={{this.product.sale_price}}
67
- @canSelectCurrency={{false}}
68
- @onCurrencyChange={{fn (mut this.product.currency)}}
60
+ <InputGroup @name="Product Tags">
61
+ <TagInput
62
+ class="form-input"
63
+ @placeholder="Add tags"
64
+ @allowSpacesInTags={{true}}
65
+ @tags={{this.product.tags}}
66
+ @addTag={{this.addTag}}
67
+ @removeTagAtIndex={{this.removeTag}}
69
68
  @disabled={{unauthorized}}
70
- />
69
+ as |tag|
70
+ >
71
+ {{tag}}
72
+ </TagInput>
71
73
  </InputGroup>
72
- </div>
74
+ <InputGroup @name="Product SKU" @value={{this.product.sku}} @helpText="Enter product SKU if applicable" @disabled={{unauthorized}} />
75
+ <div class="grid grid-cols-2 gap-2">
76
+ <InputGroup @name="Price" @helpText="Enter a price users will pay to purchase this product">
77
+ <MoneyInput
78
+ class="w-full"
79
+ @currency={{if this.product.currency this.product.currency this.activeStore.currency}}
80
+ @value={{this.product.price}}
81
+ @canSelectCurrency={{false}}
82
+ @onCurrencyChange={{fn (mut this.product.currency)}}
83
+ @disabled={{unauthorized}}
84
+ />
85
+ </InputGroup>
86
+ <InputGroup @name="Sale Price" @helpText="Optionally add a sale price for the product if the product is put on sale">
87
+ <MoneyInput
88
+ class="w-full"
89
+ @currency={{if this.product.currency this.product.currency this.activeStore.currency}}
90
+ @value={{this.product.sale_price}}
91
+ @canSelectCurrency={{false}}
92
+ @onCurrencyChange={{fn (mut this.product.currency)}}
93
+ @disabled={{unauthorized}}
94
+ />
95
+ </InputGroup>
96
+ </div>
97
+ </ContentPanel>
73
98
 
74
- <ContentPanel
75
- @title="Metadata"
76
- @open={{this.product.meta_array.length}}
77
- @actionButtons={{this.metadataButtons}}
78
- @pad={{true}}
79
- @panelBodyWrapperClass="px-0 py-4"
80
- @panelBodyClass="bg-white dark:bg-gray-800"
81
- >
82
- {{#each this.product.meta_array as |metaField index|}}
99
+ <ContentPanel @title={{t "common.metadata"}} @open={{true}} @wrapperClass="bordered-top">
100
+ <div>
101
+ <MetadataEditor @value={{this.product.meta}} @onChange={{fn (mut this.product.meta)}} />
102
+ </div>
103
+ {{!-- {{#each this.product.meta_array as |metaField index|}}
83
104
  <div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700">
84
105
  <div class="input-group">
85
106
  <div class="flex justify-between items-center mb-1">
@@ -97,7 +118,7 @@
97
118
  <Input class="w-full form-input" @value={{metaField.value}} placeholder={{metaField.label}} disabled={{unauthorized}} />
98
119
  </div>
99
120
  </div>
100
- {{/each}}
121
+ {{/each}} --}}
101
122
  </ContentPanel>
102
123
 
103
124
  <InputGroup>
@@ -143,11 +164,9 @@
143
164
  </div>
144
165
  </div>
145
166
 
146
- <ContentPanel @title="Variants" @open={{true}} @pad={{false}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
147
- <div class="content-panel-body p-4">
148
- <div class="flex items-center justify-end">
149
- <Button @text="New Variant" @icon="plus" @iconPrefix="fas" @onClick={{this.createProductVariant}} @permission="storefront create product-variant" />
150
- </div>
167
+ <ContentPanel @title="Variants" @open={{true}} @wrapperClass="bordered-top">
168
+ <div class="flex items-center justify-end">
169
+ <Button @text="New Variant" @icon="plus" @iconPrefix="fas" @onClick={{this.createProductVariant}} @permission="storefront create product-variant" />
151
170
  </div>
152
171
  <Tabs class="overlay-content-panel" as |Tab|>
153
172
  {{#each this.product.variants as |variant|}}
@@ -224,78 +243,74 @@
224
243
  </Tabs>
225
244
  </ContentPanel>
226
245
 
227
- <ContentPanel @title="Add-Ons" @open={{true}} @pad={{false}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
228
- <div class="px-4">
229
- <div class="flex items-center justify-end mb-3">
230
- <Button
231
- @text="Select Addon Categories"
232
- @icon="plus"
233
- @iconPrefix="fas"
234
- @onClick={{perform this.promptSelectAddonCategories}}
235
- @permission="storefront list product-addon"
236
- />
237
- </div>
238
- <div class="space-y-2">
239
- {{#each this.product.addon_categories as |addonCategory index|}}
240
- <div>
241
- <div class="flex items-center rounded-md shadow-sm px-3 py-2 font-semibold bg-gray-200 dark:bg-gray-900 dark:text-gray-100 mb-2">
242
- <div class="flex-1 flex items-center">
243
- <FaIcon @icon="pencil" class="mr-1 dark:text-gray-100" />
244
- <div class="w-full px-2 m-0 border-none bg-transparent dark:text-gray-100">
245
- {{addonCategory.name}}
246
- </div>
247
- </div>
248
- <div class="flex items-center">
249
- <a
250
- href="javascript:;"
251
- class="destroy-action opacity-50 hover:opacity-100 text-sm"
252
- {{on "click" (fn this.removeAddonCategory index)}}
253
- disabled={{cannot "storefront delete product-addon"}}
254
- >Remove</a>
246
+ <ContentPanel @title="Add-Ons" @open={{true}} @wrapperClass="bordered-top">
247
+ <div class="flex items-center justify-end mb-2">
248
+ <Button
249
+ @text="Select Addon Categories"
250
+ @icon="plus"
251
+ @iconPrefix="fas"
252
+ @onClick={{perform this.promptSelectAddonCategories}}
253
+ @permission="storefront list product-addon"
254
+ />
255
+ </div>
256
+ <div class="space-y-2">
257
+ {{#each this.product.addon_categories as |addonCategory index|}}
258
+ <div>
259
+ <div class="flex items-center rounded-md shadow-sm px-3 py-2 font-semibold bg-gray-200 dark:bg-gray-900 dark:text-gray-100 mb-2">
260
+ <div class="flex-1 flex items-center">
261
+ <FaIcon @icon="pencil" class="mr-1 dark:text-gray-100" />
262
+ <div class="w-full px-2 m-0 border-none bg-transparent dark:text-gray-100">
263
+ {{addonCategory.name}}
255
264
  </div>
256
265
  </div>
257
- <div class="space-y-2 mb-2">
258
- {{#each addonCategory.category.addons as |addon|}}
259
- <div class="grid grid-cols-10 gap-1 px-3 py-2 rounded-md border border-gray-200 dark:border-gray-900 dark:text-gray-100 dark:bg-gray-800 bg-gray-200">
260
- <div class="flex items-center">
261
- <Checkbox
262
- @value={{not (in-array addon.id addonCategory.excluded_addons)}}
263
- @onToggle={{fn this.excludeAddon index addon}}
264
- disabled={{cannot "storefront update product-addon"}}
265
- />
266
- </div>
267
- <div class="col-span-3 flex items-center">
268
- {{addon.name}}
269
- </div>
270
- <div class="col-span-4">
271
- {{addon.description}}
272
- </div>
273
- <div class="col-span-2">
274
- {{format-currency addon.price this.product.currency}}
275
- </div>
276
- </div>
277
- {{/each}}
266
+ <div class="flex items-center">
267
+ <a
268
+ href="javascript:;"
269
+ class="destroy-action opacity-50 hover:opacity-100 text-sm"
270
+ {{on "click" (fn this.removeAddonCategory index)}}
271
+ disabled={{cannot "storefront delete product-addon"}}
272
+ >Remove</a>
278
273
  </div>
279
274
  </div>
280
- {{/each}}
281
- </div>
275
+ <div class="space-y-2 mb-2">
276
+ {{#each addonCategory.category.addons as |addon|}}
277
+ <div class="grid grid-cols-10 gap-1 px-3 py-2 rounded-md border border-gray-200 dark:border-gray-900 dark:text-gray-100 dark:bg-gray-800 bg-gray-200">
278
+ <div class="flex items-center">
279
+ <Checkbox
280
+ @value={{not (in-array addon.id addonCategory.excluded_addons)}}
281
+ @onToggle={{fn this.excludeAddon index addon}}
282
+ disabled={{cannot "storefront update product-addon"}}
283
+ />
284
+ </div>
285
+ <div class="col-span-3 flex items-center">
286
+ {{addon.name}}
287
+ </div>
288
+ <div class="col-span-4">
289
+ {{addon.description}}
290
+ </div>
291
+ <div class="col-span-2">
292
+ {{format-currency addon.price this.product.currency}}
293
+ </div>
294
+ </div>
295
+ {{/each}}
296
+ </div>
297
+ </div>
298
+ {{/each}}
282
299
  </div>
283
300
  </ContentPanel>
284
301
 
285
- <ContentPanel @title="Availability" @open={{this.product.hours.length}} @pad={{false}} @panelBodyClass="bg-white dark:bg-gray-800">
286
- <div class="p-2">
287
- <ScheduleManager
288
- @subject={{this.product}}
289
- @subjectKey="product_uuid"
290
- @hourModelType="product-hour"
291
- @disabled={{unauthorized}}
292
- class="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-2"
293
- />
294
- </div>
302
+ <ContentPanel @title="Availability" @open={{true}} @wrapperClass="bordered-top">
303
+ <ScheduleManager
304
+ @subject={{this.product}}
305
+ @subjectKey="product_uuid"
306
+ @hourModelType="product-hour"
307
+ @disabled={{unauthorized}}
308
+ class="grid grid-cols-1 gap-4 lg:grid-cols-2 lg:gap-2"
309
+ />
295
310
  </ContentPanel>
296
311
 
297
- <ContentPanel @title="Images & Videos" @open={{this.product.files.length}} @pad={{false}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
298
- <div class="px-6 space-y-4">
312
+ <ContentPanel @title="Images & Videos" @open={{true}} @wrapperClass="bordered-top">
313
+ <div class="space-y-2">
299
314
  {{#if this.isUploading}}
300
315
  <div
301
316
  class="min-h-56 dropzone w-full rounded-lg px-4 py-8 min-h bg-gray-50 dark:bg-gray-900 bg-opacity-25 text-gray-900 dark:text-white text-center flex flex-col items-center justify-center border-2 border-dashed border-gray-200 dark:border-indigo-500"
@@ -382,7 +397,7 @@
382
397
  </div>
383
398
  </ContentPanel>
384
399
 
385
- <ContentPanel @title="Youtube Videos" @open={{this.product.youtube_urls.length}} @wrapperClass="mb-12" @panelBodyWrapperClass="p-4" @panelBodyClass="bg-white dark:bg-gray-800">
400
+ <ContentPanel @title="Youtube Videos" @open={{true}} @wrapperClass="bordered-top">
386
401
  <p class="text-sm">Add YouTube video urls to assosciate with this product or service.</p>
387
402
  <div class="input-group">
388
403
  <ArrayInput @data={{this.product.youtube_urls}} @placeholder="Enter youtube video url" @onDataChanged={{fn (mut this.product.youtube_urls)}} @disabled={{unauthorized}}>
@@ -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>