@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
@@ -1,20 +1,13 @@
1
- s<Modal::Default @onOpen={{fn this.fetchCategories @options.store}} @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
1
+ s<Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{perform this.saveChanges}} @decline={{@onDecline}}>
2
2
  <div class="modal-body-container">
3
3
  <div class="flex items-center justify-between mb-4">
4
4
  <div>
5
- {{#if this.isLoading}}
5
+ {{#unless (or this.getAddonCategories.isIdle this.saveAddonCategory.isIdle)}}
6
6
  <Spinner class="text-sky-400" />
7
- {{/if}}
7
+ {{/unless}}
8
8
  </div>
9
9
  <div>
10
- <Button
11
- @type="magic"
12
- @text={{t "storefront.component.modals.manage-addons.title"}}
13
- @icon="plus"
14
- @iconPrefix="fas"
15
- @onClick={{fn this.createCategory @options.store}}
16
- @disabled={{this.isLoading}}
17
- />
10
+ <Button @type="magic" @text={{t "storefront.component.modals.manage-addons.title"}} @icon="plus" @iconPrefix="fas" @onClick={{perform this.createAddonCategory}} @disabled={{not this.createAddonCategory.isIdle}} />
18
11
  </div>
19
12
  </div>
20
13
 
@@ -24,24 +17,13 @@ s<Modal::Default @onOpen={{fn this.fetchCategories @options.store}} @modalIsOpen
24
17
  <div class="flex items-center rounded-md shadow-sm px-3 py-2 font-semibold bg-gray-200 dark:bg-gray-800 dark:text-gray-100 mb-2">
25
18
  <div class="flex-1 flex items-center">
26
19
  <FaIcon @icon="pencil" class="mr-1 dark:text-gray-100" />
27
- <Input
28
- @type="text"
29
- @value={{category.name}}
30
- {{on "blur" (fn this.saveCategory category)}}
31
- class="w-full px-2 m-0 border-none bg-transparent dark:text-gray-100"
32
- />
20
+ <Input @type="text" @value={{category.name}} {{on "blur" (perform this.saveAddonCategory category)}} class="w-full px-2 m-0 border-none bg-transparent dark:text-gray-100" />
33
21
  </div>
34
22
  <div class="flex items-center">
35
- <Button
36
- @text={{t "storefront.component.modals.manage-addons.new-addon"}}
37
- @icon="plus"
38
- @iconPrefix="fas"
39
- @onClick={{fn this.insertNewAddon category}}
40
- class="mr-3"
41
- />
42
- <a href="javascript:;" {{on "click" (fn this.deleteCategory index)}} class="destroy-action opacity-50 hover:opacity-100 text-sm">{{t
43
- "storefront.component.modals.manage-addons.delete"
44
- }}</a>
23
+ <Button @text={{t "storefront.component.modals.manage-addons.new-addon"}} @icon="plus" @iconPrefix="fas" @onClick={{fn this.createNewAddon category}} class="mr-3" />
24
+ <a href="javascript:;" {{on "click" (perform this.deleteAddonCategory index)}} class="destroy-action opacity-50 hover:opacity-100 text-sm">
25
+ {{t "storefront.component.modals.manage-addons.delete"}}
26
+ </a>
45
27
  </div>
46
28
  </div>
47
29
  <div class="space-y-2 mb-2">
@@ -49,37 +31,18 @@ s<Modal::Default @onOpen={{fn this.fetchCategories @options.store}} @modalIsOpen
49
31
  <div class="grid grid-cols-10 gap-1 px-3 py-2 rounded-md dark:bg-gray-900 bg-gray-200">
50
32
  <div class="col-span-3 flex items-center">
51
33
  <FaIcon @icon="tag" class="text-sky-400 mr-2" />
52
- <Input
53
- @type="text"
54
- @value={{addon.name}}
55
- {{on "blur" (fn this.saveAddon addon)}}
56
- class="form-input flex-1 w-full"
57
- placeholder={{t "storefront.component.modals.manage-addons.addon-name"}}
58
- />
34
+ <Input @type="text" @value={{addon.name}} class="form-input flex-1 w-full" placeholder={{t "storefront.component.modals.manage-addons.addon-name"}} />
59
35
  </div>
60
36
  <div class="col-span-4">
61
- <Input
62
- @type="text"
63
- @value={{addon.description}}
64
- {{on "blur" (fn this.saveAddon addon)}}
65
- class="form-input w-full"
66
- placeholder={{t "storefront.component.modals.manage-addons.description"}}
67
- />
37
+ <Input @type="text" @value={{addon.description}} class="form-input w-full" placeholder={{t "storefront.component.modals.manage-addons.description"}} />
68
38
  </div>
69
39
  <div class="col-span-2">
70
- <MoneyInput
71
- class="w-full"
72
- @currency={{@options.store.currency}}
73
- @canSelectCurrency={{false}}
74
- @value={{addon.price}}
75
- @onFormatCompleted={{fn this.saveAddon addon}}
76
- @disabled={{this.isLoading}}
77
- />
40
+ <MoneyInput class="w-full" @currency={{this.activeStore.currency}} @canSelectCurrency={{false}} @value={{addon.price}} />
78
41
  </div>
79
42
  <div class="flex items-center justify-center text-center text-sm">
80
- <a href="javascript:;" class="destroy-action opacity-50 hover:opacity-100" {{on "click" (fn this.removeAddon category i)}}>{{t
81
- "storefront.common.remove"
82
- }}</a>
43
+ <a href="javascript:;" class="destroy-action opacity-50 hover:opacity-100" {{on "click" (perform this.removeAddon category i)}}>
44
+ {{t "storefront.common.remove"}}
45
+ </a>
83
46
  </div>
84
47
  </div>
85
48
  {{/each}}
@@ -2,85 +2,135 @@ 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 { isArray } from '@ember/array';
6
+ import { task } from 'ember-concurrency';
7
+ import { all } from 'rsvp';
5
8
 
9
+ /**
10
+ * Represents a component for managing addon categories and individual addons.
11
+ * Allows for the creation, deletion, and editing of addon categories, as well as adding and removing addons within those categories.
12
+ * This component uses various Ember services like store, internationalization, currentUser, modalsManager, and notifications for its operations.
13
+ */
6
14
  export default class ModalsManageAddonsComponent extends Component {
15
+ /** Service for data store operations. */
7
16
  @service store;
17
+
18
+ /** Service for internationalization. */
8
19
  @service intl;
20
+
21
+ /** Service for accessing current user information. */
9
22
  @service currentUser;
23
+
24
+ /** Service for managing modal dialogs. */
10
25
  @service modalsManager;
26
+
27
+ /** Service for displaying notifications. */
28
+ @service notifications;
29
+
30
+ /** Tracked array of addon categories. */
11
31
  @tracked categories = [];
12
- @tracked isLoading = true;
13
32
 
14
- @action saveAddon(addon) {
15
- this.isLoading = true;
33
+ /** Tracked options object for the component. */
34
+ @tracked options = {};
16
35
 
17
- return addon.save().then(() => {
18
- this.isLoading = false;
19
- });
36
+ /** The currently active store object. */
37
+ @tracked activeStore;
38
+
39
+ /**
40
+ * Constructs the ModalsManageAddonsComponent instance with the given options.
41
+ * @param {Object} owner - The owner of the instance.
42
+ * @param {Object} options - Configuration options for the component.
43
+ */
44
+ constructor(owner, { options }) {
45
+ super(...arguments);
46
+ this.options = options;
47
+ this.activeStore = options.store;
48
+ this.getAddonCategories.perform();
20
49
  }
21
50
 
22
- @action insertNewAddon(category) {
51
+ /**
52
+ * Creates a new addon associated with the provided category.
53
+ * @param {Object} category - The category to which the new addon will be added.
54
+ */
55
+ @action createNewAddon(category) {
23
56
  const productAddon = this.store.createRecord('product-addon', { category_uuid: category.id });
24
57
  category.addons.pushObject(productAddon);
25
58
  }
26
59
 
27
- @action removeAddon(category, index) {
28
- const addon = category.addons.objectAt(index);
60
+ /**
61
+ * Saves changes to all the categories.
62
+ * Displays loading modal during the operation and handles errors.
63
+ */
64
+ @task *saveChanges() {
65
+ this.modalsManager.startLoading();
66
+ try {
67
+ yield all(this.categories.map((_) => _.save()));
68
+ } catch (error) {
69
+ this.modalsManager.stopLoading();
70
+ return this.notifications.serverError(error);
71
+ }
72
+ yield this.modalsManager.done();
73
+ this.categories = [];
74
+ }
29
75
 
76
+ /**
77
+ * Removes an addon from the specified category.
78
+ * @param {Object} category - The category from which the addon will be removed.
79
+ * @param {number} index - The index of the addon to remove.
80
+ */
81
+ @task *removeAddon(category, index) {
82
+ const addon = category.addons.objectAt(index);
30
83
  category.addons.removeAt(index);
31
- return addon.destroyRecord();
84
+ yield addon.destroyRecord();
32
85
  }
33
86
 
34
- @action saveCategory(category) {
35
- this.isLoading = true;
36
- return category.save().then(() => {
37
- this.isLoading = false;
38
- });
87
+ /**
88
+ * Saves the provided addon category.
89
+ * @param {Object} category - The addon category to save.
90
+ */
91
+ @task *saveAddonCategory(category) {
92
+ yield category.save();
39
93
  }
40
94
 
41
- @action deleteCategory(index) {
95
+ /**
96
+ * Deletes an addon category at the specified index.
97
+ * @param {number} index - The index of the category to delete.
98
+ */
99
+ @task *deleteAddonCategory(index) {
42
100
  const category = this.categories.objectAt(index);
43
101
  const result = confirm(this.intl.t('storefront.component.modals.manage-addons.delete-this-addon-category-assosiated-will-lost'));
44
102
 
45
103
  if (result) {
46
- this.categories.removeAt(index);
47
- return category.destroyRecord();
104
+ this.categories = [...this.categories.filter((_, i) => i !== index)];
105
+ yield category.destroyRecord();
48
106
  }
49
107
  }
50
108
 
51
- @action pushCategory(category) {
52
- const { categories } = this;
53
- categories.pushObject(category);
54
- }
55
-
56
- @action createCategory(store) {
109
+ /**
110
+ * Creates a new addon category with default settings.
111
+ */
112
+ @task *createAddonCategory() {
57
113
  const category = this.store.createRecord('addon-category', {
58
114
  name: this.intl.t('storefront.component.modals.manage-addons.untitled-addon-category'),
59
115
  for: 'storefront_product_addon',
60
116
  owner_type: 'storefront:store',
61
- owner_uuid: store.id,
117
+ owner_uuid: this.activeStore.id,
62
118
  });
63
119
 
64
- this.isLoading = true;
65
-
66
- return category.save().then((category) => {
67
- this.pushCategory(category);
68
- this.isLoading = false;
69
- });
120
+ yield category.save();
121
+ this.categories.pushObject(category);
70
122
  }
71
123
 
72
- @action fetchCategories(store) {
73
- this.isLoading = true;
74
-
75
- return this.store
76
- .query('addon-category', {
77
- owner_uuid: store.id,
78
- })
79
- .then((categories) => {
80
- this.categories = categories.toArray();
81
- })
82
- .finally(() => {
83
- this.isLoading = false;
124
+ /**
125
+ * Retrieves and sets the addon categories associated with the active store.
126
+ */
127
+ @task *getAddonCategories() {
128
+ const categories = yield this.store.query('addon-category', { owner_uuid: this.activeStore.id });
129
+ if (isArray(categories)) {
130
+ this.categories = categories.map((category) => {
131
+ category.addons = isArray(category.addons) ? category.addons.filter((addon) => !addon.isNew) : [];
132
+ return category;
84
133
  });
134
+ }
85
135
  }
86
136
  }
@@ -2,7 +2,7 @@
2
2
  <div class="modal-body-container">
3
3
  <ComboBox
4
4
  @options={{@options.addonCategories}}
5
- @selected={{@options.product.addon_categories}}
5
+ @selected={{@options.selectedAddonCategories}}
6
6
  @optionLabel="name"
7
7
  @comparator="name"
8
8
  @selectionBoxLabel="Selected"
@@ -0,0 +1,245 @@
1
+ <Overlay @onLoad={{@onLoad}} position="right" @noBackdrop={{true}} @width="550px" @fullHeight={{true}} @isResizable={{true}} as |overlay|>
2
+ <Overlay::Header
3
+ @overlay={{overlay}}
4
+ @title={{@order.public_id}}
5
+ @status={{@order.status}}
6
+ @dispatched={{@order.dispatched}}
7
+ @createdAt={{@order.createdAt}}
8
+ @onPressCancel={{@onPressCancel}}
9
+ />
10
+
11
+ <Overlay::Body @wrapperClass="new-order-overlay-body">
12
+ <ContentPanel @title={{t "storefront.orders.index.view.activity"}} @open={{true}} @pad={{false}} @panelBodyWrapperClass="px-0 py-4" @panelBodyClass="bg-white dark:bg-gray-800">
13
+ {{#if @order.tracking_statuses}}
14
+ <Timeline @activity={{@order.tracking_statuses}} @arrowClass="bg-gray-600 border border-gray-900 shadow-md" as |TimelineItem|>
15
+ <TimelineItem @activeStatus={{@order.status}} as |trackingStatus|>
16
+ <div class="flex flex-col px-3 py-2 rounded text-sm leading-4 space-y-2 bg-gray-100 dark:bg-gray-900 dark:text-white">
17
+ <div class="flex flex-col space-y-1">
18
+ <div class="text-xs font-semibold truncate">{{trackingStatus.status}}</div>
19
+ <div class="text-xs truncate">{{n-a trackingStatus.details}}</div>
20
+ <div class="text-xs">{{trackingStatus.createdAtShortWithTime}}</div>
21
+ </div>
22
+ <Attach::Tooltip @class="clean" @animation="scale" @placement="top">
23
+ <InputInfo>
24
+ <div class="text-xs">{{or trackingStatus.details trackingStatus.status}}</div>
25
+ <div class="text-xs">{{trackingStatus.createdAtShortWithTime}}</div>
26
+ </InputInfo>
27
+ </Attach::Tooltip>
28
+ </div>
29
+ </TimelineItem>
30
+ </Timeline>
31
+ {{else}}
32
+ <div class="px-10 py-2 flex items-center justify-center">
33
+ <p class="text-red-600 dark:text-red-100">{{t "storefront.orders.index.view.unable-load-order-activity"}}</p>
34
+ </div>
35
+ {{/if}}
36
+ </ContentPanel>
37
+
38
+ <ContentPanel @title="Details" @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @actionButtons={{this.detailPanelButtons}}>
39
+ <div class="flex mb-4 space-x-2">
40
+ {{#if @order.dispatched}}
41
+ <Badge @hideStatusDot={{false}} @status="Dispatched" />
42
+ {{/if}}
43
+ {{#if @order.adhoc}}
44
+ <Badge @hideStatusDot={{false}} @disableHumanize={{true}} @status="success">{{t "storefront.orders.index.view.ad-hoc"}}</Badge>
45
+ {{/if}}
46
+ </div>
47
+ <div class="grid grid-cols-2 lg:grid-cols-3 field-info-containers-darker gap-4 lg:gap-2">
48
+ <div class="field-info-container space-y-2">
49
+ <div class="field-name">{{t "storefront.orders.index.view.customer"}}</div>
50
+ <div class="flex flex-row">
51
+ <div>
52
+ <Image
53
+ src={{avatar-url @order.customer.photo_url}}
54
+ @fallbackSrc={{config "defaultValues.contactImage"}}
55
+ class="w-8 h-8 rounded-md shadow-sm mr-2"
56
+ alt={{@order.customer.name}}
57
+ />
58
+ </div>
59
+ <div>
60
+ <div class="field-value">{{n-a @order.customer.name "No Customer"}}</div>
61
+ {{#if @order.customer}}
62
+ <div>{{@order.customer.phone}}</div>
63
+ {{/if}}
64
+ </div>
65
+ </div>
66
+ </div>
67
+ <div class="field-info-container space-y-2">
68
+ <div class="field-name">{{t "storefront.orders.index.view.facilitator"}}</div>
69
+ {{#if @order.facilitator.isIntegratedVendor}}
70
+ <div class="flex flex-row">
71
+ <div>
72
+ <Image
73
+ src={{avatar-url @order.facilitator.photo_url}}
74
+ @fallbackSrc={{config "defaultValues.contactImage"}}
75
+ class="w-8 h-8 rounded-md border border-gray-200 dark:border-gray-900 shadow-sm mr-2"
76
+ alt={{@order.facilitator.name}}
77
+ />
78
+ </div>
79
+ <div>
80
+ <div class="field-value">{{n-a @order.facilitator.name}}</div>
81
+ </div>
82
+ </div>
83
+ {{else}}
84
+ <div class="field-value">{{n-a @order.facilitator.name "No Facilitator"}}</div>
85
+ {{/if}}
86
+ </div>
87
+ <div class="field-info-container space-y-2">
88
+ <div class="field-name flex flex-row items-center justify-between">
89
+ <span>{{t "storefront.orders.index.view.driver-assigned"}}</span>
90
+ </div>
91
+ <div>
92
+ <a href="javascript:;" class="flex flex-row">
93
+ <div>
94
+ <Image
95
+ src={{avatar-url @order.driver_assigned.photo_url}}
96
+ @fallbackSrc={{config "defaultValues.driverImage"}}
97
+ width="32"
98
+ height="32"
99
+ class="w-8 h-8 rounded-md shadow-sm mr-3 lg:mr-2"
100
+ alt={{@order.driver_assigned.name}}
101
+ />
102
+ </div>
103
+ <div class="field-value">
104
+ <div>{{n-a @order.driver_assigned.name "No Driver"}}</div>
105
+ {{#if @order.driver_assigned}}
106
+ <div>{{@order.driver_assigned.phone}}</div>
107
+ {{/if}}
108
+ </div>
109
+ </a>
110
+ <div class="mt-1">
111
+ <Button
112
+ @size="xs"
113
+ @type="default"
114
+ @icon="edit"
115
+ @text={{if @order.has_driver_assigned (t "storefront.orders.index.view.change-driver") (t "storefront.orders.index.view.assign-driver")}}
116
+ @onClick={{fn this.assignDriver @order}}
117
+ />
118
+ </div>
119
+ </div>
120
+ </div>
121
+ <div class="field-info-container space-y-2">
122
+ <div class="field-name">{{t "storefront.common.internal-id"}}</div>
123
+ <div class="field-value">{{n-a @order.internal_id}}</div>
124
+ </div>
125
+ <div class="field-info-container space-y-2">
126
+ <div class="field-name">{{t "storefront.orders.index.view.tracking-number"}}</div>
127
+ <div class="field-value">{{n-a @order.tracking_number.tracking_number}}</div>
128
+ </div>
129
+ <div class="field-info-container space-y-2">
130
+ <div class="field-name">{{t "storefront.common.type"}}</div>
131
+ <div class="field-value">
132
+ <Badge @status="default">{{n-a (humanize @order.type)}}</Badge>
133
+ </div>
134
+ </div>
135
+ <div class="field-info-container space-y-2">
136
+ <div class="field-name">{{t "storefront.orders.index.view.date-scheduled"}}</div>
137
+ <div class="field-value">{{n-a @order.scheduledAt}}</div>
138
+ </div>
139
+ <div class="field-info-container space-y-2">
140
+ <div class="field-name">{{t "storefront.orders.index.view.date-dispatched"}}</div>
141
+ <div class="field-value">{{n-a @order.dispatchedAt}}</div>
142
+ </div>
143
+ <div class="field-info-container space-y-2">
144
+ <div class="field-name">{{t "storefront.orders.index.view.date-started"}}</div>
145
+ <div class="field-value">{{n-a @order.startedAt}}</div>
146
+ </div>
147
+ {{#if @order.pod_required}}
148
+ <div class="field-info-container space-y-2">
149
+ <div class="field-name">{{t "storefront.orders.index.view.proof-of-delivery"}}</div>
150
+ <div class="field-value">{{n-a (smart-humanize @order.pod_method)}}</div>
151
+ </div>
152
+ {{/if}}
153
+ </div>
154
+ </ContentPanel>
155
+ {{!--
156
+ {{#if @order.order_config}}
157
+ {{#each this.customFieldGroups as |group|}}
158
+ <ContentPanel @title={{group.name}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
159
+ <div class="grid grid-cols-{{or group.meta.grid_size 1}} gap-2">
160
+ {{#each group.customFields as |customField|}}
161
+ <div class="field-info-container space-y-2">
162
+ <div class="field-name">{{customField.label}}</div>
163
+ {{#if (and (eq customField.type "file-upload") customField.value.asFile)}}
164
+ <File @file={{customField.value.asFile}} @onDelete={{fn this.removeCustomFieldFile customField.value}} class="custom-field-file" />
165
+ {{else}}
166
+ <div class="field-value">{{n-a customField.value.value}}</div>
167
+ {{/if}}
168
+ </div>
169
+ {{/each}}
170
+ </div>
171
+ </ContentPanel>
172
+ {{/each}}
173
+ {{/if}} --}}
174
+
175
+ {{#if @order.tracking_number}}
176
+ <ContentPanel @title={{t "storefront.orders.index.view.tracking"}} @prefixTitleRight={{@order.tracking}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
177
+ <div class="flex flex-row items-center justify-center space-x-4">
178
+ <div class="p-2 rounded-md bg-white">
179
+ <img src={{concat "data:image/png;base64," @order.tracking_number.qr_code}} class="w-18 h-18" alt={{@order.public_id}} />
180
+ </div>
181
+ <div class="p-2 rounded-md bg-white">
182
+ <img src={{concat "data:image/png;base64," @order.tracking_number.barcode}} class="w-40 h-14" alt={{@order.public_id}} />
183
+ </div>
184
+ </div>
185
+ </ContentPanel>
186
+ {{/if}}
187
+
188
+ <ContentPanel @title={{t "storefront.orders.index.view.route-panel-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
189
+ <div class="py-2 px-6">
190
+ <div class="flex">
191
+ {{#if @order.meta.is_pickup}}
192
+ <div class="flex-1">
193
+ <div class="rounded-md bg-blue-50 mr-4">
194
+ <div class="rounded-t-md bg-blue-100 px-3 py-2 mb-3">
195
+ <span class="text-blue-500 font-semibold text-sm truncate">{{t "storefront.component.modals.incoming-order.pickup-order"}}</span>
196
+ </div>
197
+ <div class="flex flex-row items-center mb-4 pb-4 px-3">
198
+ <div class="flex items-center justify-center rounded-full bg-blue-500 w-8 h-8 mr-3">
199
+ <FaIcon @icon="store-alt" class="text-white" />
200
+ </div>
201
+ <div class="text-xs text-blue-900 truncate">
202
+ <DisplayPlace @place={{@options.order.payload.pickup}} @type="pickup" />
203
+ </div>
204
+ </div>
205
+ </div>
206
+ </div>
207
+ {{else if @order.payload.hasWaypoints}}
208
+ <RouteList @order={{@order}} />
209
+ {{else}}
210
+ <div class="order-route-list storefront flex-1">
211
+ <div class="order-route-stop">
212
+ <div class="order-route-stop-index">
213
+ <div class="index-count">
214
+ <FaIcon @prefix="fas" @icon="store-alt" />
215
+ </div>
216
+ </div>
217
+ <div class="order-route-location dark:text-gray-100">
218
+ <DisplayPlace @place={{@order.payload.pickup}} @type="pickup" @addressClass="text-sm dark:text-gray-100" @noAddressClass="text-sm" />
219
+ </div>
220
+ </div>
221
+ <div class="order-route-stop">
222
+ <div class="order-route-stop-index">
223
+ <div class="index-count">
224
+ <FaIcon @prefix="fas" @icon="map-marker-alt" />
225
+ </div>
226
+ </div>
227
+ <div class="order-route-location dark:text-gray-100">
228
+ <DisplayPlace @place={{@order.payload.dropoff}} @type="dropoff" @addressClass="text-sm dark:text-gray-100" @noAddressClass="text-sm" />
229
+ </div>
230
+ </div>
231
+ </div>
232
+ {{/if}}
233
+ </div>
234
+ </div>
235
+ </ContentPanel>
236
+
237
+ <StorefrontOrderSummary @order={{@order}} />
238
+
239
+ <ContentPanel @title={{t "storefront.orders.index.view.comments-title"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800" @wrapperClass="mb-20">
240
+ <CommentThread @subject={{@order}} @subjectType="storefront:order" />
241
+ </ContentPanel>
242
+
243
+ <Spacer @height="300px" />
244
+ </Overlay::Body>
245
+ </Overlay>