@fleetbase/storefront-engine 0.3.5 → 0.3.7

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 +10 -4
  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,5 @@
1
+ {{#if this.contextPanel.currentContextRegistry}}
2
+ {{#let this.contextPanel.currentContext this.contextPanel.currentContextRegistry this.contextPanel.currentContextComponentArguments as |model registry dynamicArgs|}}
3
+ {{component registry.component context=model dynamicArgs=dynamicArgs onPressCancel=this.contextPanel.clear options=this.contextPanel.contextOptions}}
4
+ {{/let}}
5
+ {{/if}}
@@ -0,0 +1,6 @@
1
+ import Component from '@glimmer/component';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ContextPanelComponent extends Component {
5
+ @service contextPanel;
6
+ }
@@ -0,0 +1,34 @@
1
+ <div class="p-4">
2
+ <div class="grid grid-cols-1 gap-2 lg:grid-cols-2 lg:gap-4 text-xs dark:text-gray-100">
3
+
4
+ <div class="field-info-container">
5
+ <div class="field-name">{{t "storefront.customers.customer-panel.details.web-url"}}</div>
6
+ <div class="field-value">{{n-a @customer.name}}</div>
7
+ </div>
8
+
9
+ <div class="field-info-container">
10
+ <div class="field-name">{{t "storefront.common.title"}}</div>
11
+ <div class="field-value">{{n-a @customer.title}}</div>
12
+ </div>
13
+
14
+ <div class="field-info-container">
15
+ <div class="field-name">{{t "storefront.common.internal-id"}}</div>
16
+ <div class="field-value">{{n-a @customer.internal_id}}</div>
17
+ </div>
18
+
19
+ <div class="field-info-container">
20
+ <div class="field-name">{{t "storefront.common.email"}}</div>
21
+ <div class="field-value">{{n-a @customer.email}}</div>
22
+ </div>
23
+
24
+ <div class="field-info-container">
25
+ <div class="field-name">{{t "storefront.common.phone"}}</div>
26
+ <div class="field-value">{{n-a @customer.phone}}</div>
27
+ </div>
28
+
29
+ <div class="field-info-container">
30
+ <div class="field-name">{{t "storefront.common.type"}}</div>
31
+ <div class="field-value"><Badge @status={{@customer.type}} /></div>
32
+ </div>
33
+ </div>
34
+ </div>
@@ -0,0 +1,3 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class CustomerPanelDetailsComponent extends Component {}
@@ -0,0 +1,140 @@
1
+ {{! template-lint-disable no-unbound }}
2
+ <Layout::Section::Header @title={{t "storefront.common.orders"}} @onSearch={{this.search}} />
3
+
4
+ <Layout::Section::Body>
5
+ <div class="p-4">
6
+
7
+ {{#if this.isLoading}}
8
+ <div class="px-3 py-2">
9
+ <Spinner class="text-sky-400" />
10
+ </div>
11
+ {{/if}}
12
+ <div class="hidden md:flex table-wrapper table-fluid">
13
+ <table>
14
+ <thead>
15
+ <tr class="h-12 text-left py-1">
16
+ <th>{{t "storefront.component.widget.orders.id-column"}}</th>
17
+ <th>{{t "storefront.common.amount"}}</th>
18
+ <th>{{t "storefront.common.driver"}}</th>
19
+ <th>{{t "storefront.common.created"}}</th>
20
+ <th>{{t "storefront.common.status"}}</th>
21
+ <th></th>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ {{#each this.orders as |order|}}
26
+ <tr class="h-12">
27
+ <td><a href="javascript:;" {{on "click" (fn this.viewOrder order)}}>{{order.public_id}}</a></td>
28
+ <td>{{format-currency order.meta.total order.meta.currency}}</td>
29
+ <td>{{n-a order.driver_name}}</td>
30
+ <td>{{order.createdAgo}}</td>
31
+ <td>
32
+ <Badge @status={{order.status}} />
33
+ </td>
34
+ <td>
35
+ {{#if order.isFresh}}
36
+ <Button
37
+ @size="xs"
38
+ @type="success"
39
+ @iconPrefix="fas"
40
+ @icon="check"
41
+ @text={{concat (t "storefront.component.widget.orders.accept-order") "!"}}
42
+ @onClick={{fn this.acceptOrder order}}
43
+ />
44
+ {{/if}}
45
+ {{#if order.isPreparing}}
46
+ <Button @size="xs" @type="success" @icon="bells" @text={{t "storefront.component.widget.orders.mark-as-ready"}} @onClick={{fn this.markAsReady order}} />
47
+ {{/if}}
48
+ {{#if order.isPickupReady}}
49
+ <Button
50
+ @size="xs"
51
+ @type="success"
52
+ @icon="check"
53
+ @text={{t "storefront.component.widget.orders.mark-as-completed"}}
54
+ @onClick={{fn this.markAsCompleted order}}
55
+ />
56
+ {{/if}}
57
+ </td>
58
+ </tr>
59
+ {{/each}}
60
+ </tbody>
61
+ </table>
62
+ </div>
63
+ <div class="flex flex-col md:hidden p-3 space-y-3">
64
+ {{#each this.orders as |order|}}
65
+ <div class="py-2 px-3 rounded-md border border-gray-400 dark:border-gray-700">
66
+ <div class="flex flex-row mb-3">
67
+ <div class="flex-1">
68
+ <a href="javascript:;" {{on "click" (fn this.viewOrder order)}} class="font-semibold">{{order.public_id}}</a>
69
+ <div>{{order.createdAt}}</div>
70
+ <div>{{order.createdAgo}}</div>
71
+ </div>
72
+ <div class="flex-shrink-0 flex flex-col text-right">
73
+ <Badge class="mb-1" @status={{order.status}} />
74
+ <div>{{format-currency order.meta.total order.meta.currency}}</div>
75
+ </div>
76
+ </div>
77
+ <div class="flex flex-row space-x-2 flex-wrap">
78
+ <Button @size="xs" @type="primary" @icon="eye" @text={{t "storefront.common.view"}} @onClick={{fn this.viewOrder order}} />
79
+ <Button
80
+ @size="xs"
81
+ @type="default"
82
+ @icon="steering-wheel"
83
+ @text={{if order.has_driver_assigned (t "storefront.component.widget.order.change-driver") (t "storefront.component.widget.order.assign-driver")}}
84
+ @onClick={{fn this.assignDriver order}}
85
+ />
86
+ {{#if order.isFresh}}
87
+ <Button
88
+ @size="xs"
89
+ @type="success"
90
+ @iconPrefix="fas"
91
+ @icon="check"
92
+ @text={{concat (t "storefront.component.widget.orders.accept-order") "!"}}
93
+ @onClick={{fn this.acceptOrder order}}
94
+ />
95
+ {{/if}}
96
+ {{#if order.isPreparing}}
97
+ <Button @size="xs" @type="success" @icon="bells" @text={{t "storefront.component.widget.orders.mark-as-mark"}} @onClick={{fn this.markAsReady order}} />
98
+ {{/if}}
99
+ {{#if order.isPickupReady}}
100
+ <Button @size="xs" @type="success" @icon="check" @text={{t "storefront.component.widget.orders.mark-as-completed"}} @onClick={{fn this.markAsCompleted order}} />
101
+ {{/if}}
102
+ </div>
103
+ <ContentPanel @title={{t "storefront.component.widget.orders.title"}} class="mt-2">
104
+ <div class="flex flex-col py-2 border-t dark:border-gray-800">
105
+ <div>{{t "storefront.component.widget.orders.customer"}}: {{n-a order.customer_name}}</div>
106
+ <div>{{t "storefront.component.widget.orders.driver"}}: {{n-a order.driver_name}}</div>
107
+ </div>
108
+ <div class="py-2 space-y-2 border-t dark:border-gray-800">
109
+ <div class="flex items-center justify-between">
110
+ <span class="dark:text-gray-50">{{t "storefront.component.widget.orders.subtotal"}}</span>
111
+ <span class="dark:text-gray-50">{{format-currency order.meta.subtotal order.meta.currency}}</span>
112
+ </div>
113
+ {{#unless order.meta.is_pickup}}
114
+ <div class="flex items-center justify-between">
115
+ <span class="dark:text-gray-50">{{t "storefront.component.widget.orders.delivery-fee"}}</span>
116
+ <span class="dark:text-gray-50">{{format-currency order.meta.delivery_fee order.meta.currency}}</span>
117
+ </div>
118
+ {{/unless}}
119
+ {{#if order.meta.tip}}
120
+ <div class="flex items-center justify-between">
121
+ <span class="dark:text-gray-50">{{t "storefront.component.widget.order.tip"}}</span>
122
+ <span class="dark:text-gray-50">{{get-tip-amount order.meta.tip order.meta.subtotal order.meta.currency}}</span>
123
+ </div>
124
+ {{/if}}
125
+ {{#if order.meta.delivery_tip}}
126
+ <div class="flex items-center justify-between">
127
+ <span class="dark:text-gray-50">{{t "storefront.component.widget.order.delivery-tip"}}</span>
128
+ <span class="dark:text-gray-50">{{get-tip-amount order.meta.delivery_tip order.meta.subtotal order.meta.currency}}</span>
129
+ </div>
130
+ {{/if}}
131
+ <div class="flex items-center justify-between">
132
+ <span class="dark:text-gray-50 font-bold">{{t "storefront.component.widget.order.tip"}}</span>
133
+ <span class="dark:text-gray-50 font-bold">{{format-currency order.meta.total order.meta.currency}}</span>
134
+ </div>
135
+ </div>
136
+ </ContentPanel>
137
+ </div>
138
+ {{/each}}
139
+ </div>
140
+ </div></Layout::Section::Body>
@@ -0,0 +1,78 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { inject as controller } from '@ember/controller';
5
+ import { action, computed, get } from '@ember/object';
6
+ import { task } from 'ember-concurrency-decorators';
7
+ export default class CustomerPanelOrdersComponent extends Component {
8
+ @service store;
9
+ @service storefront;
10
+ @service fetch;
11
+ @service intl;
12
+ @service appCache;
13
+ @service modalsManager;
14
+ @service contextPanel;
15
+ @tracked isLoading = true;
16
+ @tracked orders = [];
17
+ @tracked customer;
18
+ @controller('orders.index.view') orderDetailsController;
19
+
20
+ @computed('args.title') get title() {
21
+ return this.args.title ?? this.intl.t('storefront.component.widget.orders.widget-title');
22
+ }
23
+
24
+ constructor() {
25
+ super(...arguments);
26
+ this.customer = this.args.customer;
27
+ this.reloadOrders.perform();
28
+ }
29
+
30
+ @task *reloadOrders(params = {}) {
31
+ this.orders = yield this.fetchOrders(params);
32
+ }
33
+
34
+ @action fetchOrders(params = {}) {
35
+ this.isLoading = true;
36
+
37
+ return new Promise((resolve) => {
38
+ const storefront = get(this.storefront, 'activeStore.public_id');
39
+
40
+ if (!storefront || !this.customer?.id) {
41
+ this.isLoading = false;
42
+ return resolve([]);
43
+ }
44
+
45
+ const queryParams = {
46
+ storefront,
47
+ limit: 25,
48
+ sort: '-created_at',
49
+ customer_uuid: this.customer?.id,
50
+ ...params,
51
+ };
52
+
53
+ this.fetch
54
+ .get('orders', queryParams, {
55
+ namespace: 'storefront/int/v1',
56
+ normalizeToEmberData: true,
57
+ })
58
+ .then((orders) => {
59
+ this.isLoading = false;
60
+
61
+ resolve(orders);
62
+ })
63
+ .catch(() => {
64
+ this.isLoading = false;
65
+
66
+ resolve(this.orders);
67
+ });
68
+ });
69
+ }
70
+
71
+ @action search(event) {
72
+ this.reloadOrders.perform({ query: event.target.value ?? '' });
73
+ }
74
+
75
+ @action async viewOrder(order) {
76
+ this.contextPanel.focus(order, 'viewing');
77
+ }
78
+ }
@@ -0,0 +1,70 @@
1
+ <Overlay
2
+ @onLoad={{this.setOverlayContext}}
3
+ @position="right"
4
+ @noBackdrop={{true}}
5
+ @fullHeight={{true}}
6
+ @isResizable={{or this.isResizable @isResizable}}
7
+ @width={{or this.width @width "570px"}}
8
+ >
9
+ <Overlay::Header @hideLeftSection={{true}} @actionsWrapperClass="flex-1 flex-col py-3" class="h-auto-i min-h-[127px]">
10
+ <div class="flex flex-row items-center justify-between w-full mb-4">
11
+
12
+ <div class="flex flex-1 justify-end">
13
+ <Button
14
+ @type="default"
15
+ @icon="times"
16
+ @helpText={{if this.customer.id (t "storefront.customers.customer-panel.cancel-edit-button") (t "fleet-ops.component.customer-panel.cancel-new-button")}}
17
+ @onClick={{this.onPressCancel}}
18
+ />
19
+ </div>
20
+ </div>
21
+ <div class="flex flex-row justify-between w-full">
22
+ <div class="flex flex-col flex-1 w-3/4">
23
+ <div class="flex flex-row">
24
+ <div class="w-14 flex items-center justify-start">
25
+ <Image
26
+ src={{this.customer.photo_url}}
27
+ @fallbackSrc={{config "defaultValues.customerImage"}}
28
+ alt={{this.customer.name}}
29
+ height="48"
30
+ width="48"
31
+ class="h-12 w-12 rounded-lg shadow-sm"
32
+ />
33
+ <Attach::Tooltip @class="clean" @animation="scale" @placement="top">
34
+ <InputInfo @text={{this.customer.public_id}} />
35
+ </Attach::Tooltip>
36
+ </div>
37
+ <div class="flex flex-col">
38
+ <h1 class="text-gray-900 dark:text-white text-2xl">{{this.customer.name}}</h1>
39
+ <div class="-mt-1">
40
+ <div class="flex flex-row items-center">
41
+ <span class="text-sm dark:text-blue-400 text-blue-600">{{smart-humanize this.customer.type}}</span>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ <div class="flex justify-end w-1/4">
48
+ <Badge @status={{this.customer.public_id}} @type="info" @hideStatusDot={{true}} />
49
+ </div>
50
+
51
+ </div>
52
+ </Overlay::Header>
53
+ <Overlay::Body class="no-padding">
54
+ <div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto">
55
+ <div class="ui-tabs mt-4">
56
+ <nav>
57
+ {{#each this.tabs as |tab|}}
58
+ <a href="javascript:;" class="ui-tab {{if (eq this.tab.slug tab.slug) 'active'}}" {{on "click" (fn this.onTabChanged tab.slug)}}>
59
+ <FaIcon @icon={{tab.icon}} class="mr-1" />
60
+ <span>{{tab.title}}</span>
61
+ </a>
62
+ {{/each}}
63
+ </nav>
64
+ </div>
65
+ </div>
66
+ <div class="tab-content tab-{{this.tab.slug}}">
67
+ {{component this.tab.component customer=this.customer tabOptions=this.tab options=this.tab.componentParams}}
68
+ </div>
69
+ </Overlay::Body>
70
+ </Overlay>
@@ -0,0 +1,171 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+ import { inject as service } from '@ember/service';
5
+ import { isArray } from '@ember/array';
6
+ import CustomerPanelDetailsComponent from './customer-panel/details';
7
+ import CustomerPanelOrdersComponent from './customer-panel/orders';
8
+ import contextComponentCallback from '@fleetbase/ember-core/utils/context-component-callback';
9
+ import applyContextComponentArguments from '@fleetbase/ember-core/utils/apply-context-component-arguments';
10
+ export default class CustomerPanelComponent extends Component {
11
+ /**
12
+ * Service for fetching data.
13
+ *
14
+ * @type {Service}
15
+ */
16
+ @service fetch;
17
+
18
+ /**
19
+ * Service for managing modals.
20
+ *
21
+ * @type {Service}
22
+ */
23
+ @service modalsManager;
24
+
25
+ /**
26
+ * Universe service for managing global data and settings.
27
+ *
28
+ * @type {Service}
29
+ */
30
+ @service universe;
31
+
32
+ /**
33
+ * Ember data store service.
34
+ *
35
+ * @type {Service}
36
+ */
37
+ @service store;
38
+
39
+ /**
40
+ * Service for managing routing within the host app.
41
+ *
42
+ * @type {Service}
43
+ */
44
+ @service hostRouter;
45
+
46
+ /**
47
+ * Service for managing the context panel.
48
+ *
49
+ * @type {Service}
50
+ */
51
+ @service contextPanel;
52
+
53
+ /**
54
+ * The current active tab.
55
+ *
56
+ * @type {Object}
57
+ * @tracked
58
+ */
59
+ @tracked tab;
60
+
61
+ /**
62
+ * The customer being displayed or edited.
63
+ *
64
+ * @type {customerModel}
65
+ * @tracked
66
+ */
67
+ @tracked customer;
68
+
69
+ /**
70
+ * Overlay context.
71
+ * @type {any}
72
+ */
73
+ @tracked context;
74
+
75
+ /**
76
+ * Initializes the customer panel component.
77
+ */
78
+ constructor() {
79
+ super(...arguments);
80
+ this.customer = this.args.customer;
81
+
82
+ this.tab = this.getTabUsingSlug(this.args.tab);
83
+ applyContextComponentArguments(this);
84
+ }
85
+
86
+ /**
87
+ /**
88
+ * Returns the array of tabs available for the panel.
89
+ *
90
+ * @type {Array}
91
+ */
92
+ get tabs() {
93
+ const registeredTabs = this.universe.getMenuItemsFromRegistry('component:customer-panel');
94
+
95
+ const defaultTabs = [
96
+ this.universe._createMenuItem('Details', null, { icon: 'circle-info', component: CustomerPanelDetailsComponent }),
97
+ this.universe._createMenuItem('Orders', null, { icon: 'circle-info', component: CustomerPanelOrdersComponent }),
98
+ ];
99
+
100
+ if (isArray(registeredTabs)) {
101
+ return [...defaultTabs, ...registeredTabs];
102
+ }
103
+
104
+ return defaultTabs;
105
+ }
106
+ /**
107
+ * Sets the overlay context.
108
+ *
109
+ * @action
110
+ * @param {OverlayContextObject} overlayContext
111
+ */
112
+ @action setOverlayContext(overlayContext) {
113
+ this.context = overlayContext;
114
+ contextComponentCallback(this, 'onLoad', ...arguments);
115
+ }
116
+
117
+ /**
118
+ * Handles changing the active tab.
119
+ *
120
+ * @method
121
+ * @param {String} tab - The new tab to switch to.
122
+ * @action
123
+ */
124
+ @action onTabChanged(tab) {
125
+ this.tab = this.getTabUsingSlug(tab);
126
+ contextComponentCallback(this, 'onTabChanged', tab);
127
+ }
128
+
129
+ /**
130
+ * Handles edit action for the customer.
131
+ *
132
+ * @method
133
+ * @action
134
+ */
135
+ @action onEdit() {
136
+ const isActionOverrided = contextComponentCallback(this, 'onEdit', this.customer);
137
+
138
+ if (!isActionOverrided) {
139
+ this.contextPanel.focus(this.customer, 'editing', {
140
+ onAfterSave: () => {
141
+ this.contextPanel.clear();
142
+ },
143
+ });
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Handles the cancel action.
149
+ *
150
+ * @method
151
+ * @action
152
+ * @returns {Boolean} Indicates whether the cancel action was overridden.
153
+ */
154
+ @action onPressCancel() {
155
+ return contextComponentCallback(this, 'onPressCancel', this.customer);
156
+ }
157
+
158
+ /**
159
+ * Finds and returns a tab based on its slug.
160
+ *
161
+ * @param {String} tabSlug - The slug of the tab.
162
+ * @returns {Object|null} The found tab or null.
163
+ */
164
+ getTabUsingSlug(tabSlug) {
165
+ if (tabSlug) {
166
+ return this.tabs.find(({ slug }) => slug === tabSlug);
167
+ }
168
+
169
+ return this.tabs[0];
170
+ }
171
+ }
@@ -0,0 +1,52 @@
1
+ <div {{did-insert this.setupComponent}} ...attributes>
2
+ {{#let (or @place.place @place) as |place|}}
3
+ {{#if (is-empty place)}}
4
+ <div class={{@noAddressClass}}>
5
+ <span class="text-red-500">
6
+ {{#if @type}}
7
+ {{t "fleet-ops.component.display-panel.no-address" htmlSafe=true type=@type}}
8
+ {{else}}
9
+ {{t "fleet-ops.component.display-panel.no-address-message"}}
10
+ {{/if}}
11
+ </span>
12
+ </div>
13
+ {{else}}
14
+ <address class={{@addressClass}}>
15
+ {{#if place.name}}
16
+ {{place.name}}<br />
17
+ {{/if}}
18
+ {{#if place.street1}}
19
+ {{place.street1}}<br />
20
+ {{/if}}
21
+ {{#if place.street2}}
22
+ {{place.street2}}<br />
23
+ {{/if}}
24
+ <div class="comma-spans">
25
+ {{#if place.city}}
26
+ <span>{{place.city}}</span>
27
+ {{/if}}
28
+ {{#if place.province}}
29
+ <span>{{place.province}}</span>
30
+ {{/if}}
31
+ {{#if place.postal_code}}
32
+ <span>{{place.postal_code}}</span>
33
+ {{/if}}
34
+ </div>
35
+ <div class="comma-spans">
36
+ {{#if place.neighborhood}}
37
+ <span>{{place.neighborhood}}</span>
38
+ {{/if}}
39
+ {{#if place.district}}
40
+ <span>{{place.district}}</span>
41
+ {{/if}}
42
+ {{#if (and place.building (not place.street1))}}
43
+ <span>{{place.building}}</span>
44
+ {{/if}}
45
+ </div>
46
+ {{#if place.phone}}
47
+ <a href="tel:{{place.phone}}" class="text-blue-500 hover:text-blue-400">{{place.phone}}</a><br />
48
+ {{/if}}
49
+ </address>
50
+ {{/if}}
51
+ {{/let}}
52
+ </div>
@@ -0,0 +1,11 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+
5
+ export default class DisplayPlaceComponent extends Component {
6
+ @tracked ref;
7
+
8
+ @action setupComponent(element) {
9
+ this.ref = element;
10
+ }
11
+ }