@fleetbase/storefront-engine 0.3.18 → 0.3.21
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.
- package/addon/components/customer-panel/orders.hbs +107 -104
- package/addon/components/customer-panel/orders.js +52 -45
- package/addon/components/modals/incoming-order.hbs +208 -199
- package/addon/components/modals/order-ready-assign-driver.hbs +1 -1
- package/addon/components/order-panel/details.js +0 -2
- package/addon/components/order-panel.hbs +314 -1
- package/addon/components/order-panel.js +51 -3
- package/addon/components/widget/customers.hbs +75 -51
- package/addon/components/widget/customers.js +29 -41
- package/addon/components/widget/orders.hbs +278 -119
- package/addon/components/widget/orders.js +75 -80
- package/addon/components/widget/storefront-metrics.hbs +3 -6
- package/addon/components/widget/storefront-metrics.js +25 -41
- package/addon/controllers/orders/index.js +214 -105
- package/addon/controllers/settings/gateways.js +1 -1
- package/addon/helpers/get-tip-amount.js +13 -2
- package/addon/routes/application.js +2 -4
- package/addon/services/order-actions.js +248 -0
- package/addon/services/storefront.js +2 -0
- package/addon/styles/storefront-engine.css +48 -0
- package/addon/templates/home.hbs +2 -1
- package/addon/templates/orders/index/view.hbs +1 -1
- package/addon/templates/orders/index.hbs +26 -3
- package/addon/templates/products/index/index.hbs +28 -28
- package/addon/templates/settings.hbs +1 -1
- package/app/services/order-actions.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +1 -1
- package/server/config/storefront.php +20 -0
- package/server/migrations/2023_05_03_025307_create_carts_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_checkouts_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_gateways_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_network_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_networks_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_notification_channels_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_payment_methods_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_addon_categories_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_addons_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_variant_options_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_product_variants_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_products_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_reviews_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_store_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025307_create_votes_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_carts_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_checkouts_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_gateways_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_network_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_networks_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_notification_channels_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_payment_methods_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addon_categories_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_addons_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variant_options_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_product_variants_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_products_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_reviews_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_hours_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_store_locations_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_stores_table.php +1 -1
- package/server/migrations/2023_05_03_025310_add_foreign_keys_to_votes_table.php +1 -1
- package/server/src/Http/Controllers/ActionController.php +2 -1
- package/server/src/Http/Controllers/OrderController.php +15 -2
- package/server/src/Http/Controllers/v1/CheckoutController.php +12 -12
- package/server/src/Http/Controllers/v1/CustomerController.php +15 -7
- package/server/src/Http/Controllers/v1/ServiceQuoteController.php +5 -5
- package/server/src/Http/Requests/CreateCustomerRequest.php +4 -0
- package/server/src/Http/Requests/InitializeCheckoutRequest.php +2 -1
- package/server/src/Http/Resources/Cart.php +1 -1
- package/server/src/Models/Store.php +2 -2
- package/server/src/Observers/OrderObserver.php +7 -1
- package/server/src/Rules/IsValidLocation.php +2 -2
- package/server/src/Support/Storefront.php +34 -0
- package/translations/en-us.yaml +6 -1
|
@@ -2,36 +2,35 @@
|
|
|
2
2
|
<Layout::Section::Header @title={{t "storefront.common.orders"}} @onSearch={{this.search}} />
|
|
3
3
|
|
|
4
4
|
<Layout::Section::Body>
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
<td>
|
|
5
|
+
{{#if this.loadOrders.isRunning}}
|
|
6
|
+
<div class="px-3 py-2">
|
|
7
|
+
<Spinner class="text-sky-400" />
|
|
8
|
+
</div>
|
|
9
|
+
{{/if}}
|
|
10
|
+
<div class="hidden md:flex table-wrapper table-fluid">
|
|
11
|
+
<table>
|
|
12
|
+
<thead>
|
|
13
|
+
<tr class="h-12 text-left py-1">
|
|
14
|
+
<th>{{t "storefront.component.widget.orders.id-column"}}</th>
|
|
15
|
+
<th>{{t "storefront.common.amount"}}</th>
|
|
16
|
+
<th>{{t "storefront.common.driver"}}</th>
|
|
17
|
+
<th>{{t "storefront.common.created"}}</th>
|
|
18
|
+
<th>{{t "storefront.common.status"}}</th>
|
|
19
|
+
<th></th>
|
|
20
|
+
</tr>
|
|
21
|
+
</thead>
|
|
22
|
+
<tbody>
|
|
23
|
+
{{#each this.orders as |order|}}
|
|
24
|
+
<tr class="h-12">
|
|
25
|
+
<td><a href="javascript:;" {{on "click" (fn this.viewOrder order)}}>{{order.public_id}}</a></td>
|
|
26
|
+
<td>{{format-currency order.meta.total order.meta.currency}}</td>
|
|
27
|
+
<td>{{n-a order.driver_name}}</td>
|
|
28
|
+
<td>{{order.createdAgo}}</td>
|
|
29
|
+
<td>
|
|
30
|
+
<Badge @status={{order.status}} />
|
|
31
|
+
</td>
|
|
32
|
+
<td>
|
|
33
|
+
<div>
|
|
35
34
|
{{#if order.isFresh}}
|
|
36
35
|
<Button
|
|
37
36
|
@size="xs"
|
|
@@ -43,7 +42,7 @@
|
|
|
43
42
|
/>
|
|
44
43
|
{{/if}}
|
|
45
44
|
{{#if order.isPreparing}}
|
|
46
|
-
<Button @size="xs" @type="success" @icon="
|
|
45
|
+
<Button @size="xs" @type="success" @icon="bell-concierge" @text={{t "storefront.component.widget.orders.mark-as-ready"}} @onClick={{fn this.markAsReady order}} />
|
|
47
46
|
{{/if}}
|
|
48
47
|
{{#if order.isPickupReady}}
|
|
49
48
|
<Button
|
|
@@ -54,87 +53,91 @@
|
|
|
54
53
|
@onClick={{fn this.markAsCompleted order}}
|
|
55
54
|
/>
|
|
56
55
|
{{/if}}
|
|
57
|
-
</
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
</div>
|
|
57
|
+
<div>
|
|
58
|
+
<Button @size="xs" @type="danger" @icon="ban" @text="Cancel" @onClick={{fn this.cancelOrder order}} />
|
|
59
|
+
</div>
|
|
60
|
+
</td>
|
|
61
|
+
</tr>
|
|
62
|
+
{{/each}}
|
|
63
|
+
</tbody>
|
|
64
|
+
</table>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="flex flex-col md:hidden p-3 space-y-3">
|
|
67
|
+
{{#each this.orders as |order|}}
|
|
68
|
+
<div class="py-2 px-3 rounded-md border border-gray-400 dark:border-gray-700">
|
|
69
|
+
<div class="flex flex-row mb-3">
|
|
70
|
+
<div class="flex-1">
|
|
71
|
+
<a href="javascript:;" {{on "click" (fn this.viewOrder order)}} class="font-semibold">{{order.public_id}}</a>
|
|
72
|
+
<div>{{order.createdAt}}</div>
|
|
73
|
+
<div>{{order.createdAgo}}</div>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="flex-shrink-0 flex flex-col text-right">
|
|
76
|
+
<Badge class="mb-1" @status={{order.status}} />
|
|
77
|
+
<div>{{format-currency order.meta.total order.meta.currency}}</div>
|
|
76
78
|
</div>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
</div>
|
|
80
|
+
<div class="flex flex-row space-x-2 flex-wrap">
|
|
81
|
+
<Button @size="xs" @type="primary" @icon="eye" @text={{t "storefront.common.view"}} @onClick={{fn this.viewOrder order}} />
|
|
82
|
+
<Button
|
|
83
|
+
@size="xs"
|
|
84
|
+
@type="default"
|
|
85
|
+
@icon="id-card"
|
|
86
|
+
@text={{if order.has_driver_assigned (t "storefront.component.widget.order.change-driver") (t "storefront.component.widget.order.assign-driver")}}
|
|
87
|
+
@onClick={{fn this.assignDriver order}}
|
|
88
|
+
/>
|
|
89
|
+
{{#if order.isFresh}}
|
|
79
90
|
<Button
|
|
80
91
|
@size="xs"
|
|
81
|
-
@type="
|
|
82
|
-
@
|
|
83
|
-
@
|
|
84
|
-
@
|
|
92
|
+
@type="success"
|
|
93
|
+
@iconPrefix="fas"
|
|
94
|
+
@icon="check"
|
|
95
|
+
@text={{concat (t "storefront.component.widget.orders.accept-order") "!"}}
|
|
96
|
+
@onClick={{fn this.acceptOrder order}}
|
|
85
97
|
/>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{{
|
|
97
|
-
|
|
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}}
|
|
98
|
+
{{/if}}
|
|
99
|
+
{{#if order.isPreparing}}
|
|
100
|
+
<Button @size="xs" @type="success" @icon="bell-concierge" @text={{t "storefront.component.widget.orders.mark-as-mark"}} @onClick={{fn this.markAsReady order}} />
|
|
101
|
+
{{/if}}
|
|
102
|
+
{{#if order.isPickupReady}}
|
|
103
|
+
<Button @size="xs" @type="success" @icon="check" @text={{t "storefront.component.widget.orders.mark-as-completed"}} @onClick={{fn this.markAsCompleted order}} />
|
|
104
|
+
{{/if}}
|
|
105
|
+
</div>
|
|
106
|
+
<ContentPanel @title={{t "storefront.component.widget.orders.title"}} class="mt-2">
|
|
107
|
+
<div class="flex flex-col py-2 border-t dark:border-gray-800">
|
|
108
|
+
<div>{{t "storefront.component.widget.orders.customer"}}: {{n-a order.customer_name}}</div>
|
|
109
|
+
<div>{{t "storefront.component.widget.orders.driver"}}: {{n-a order.driver_name}}</div>
|
|
102
110
|
</div>
|
|
103
|
-
<
|
|
104
|
-
<div class="flex
|
|
105
|
-
<
|
|
106
|
-
<
|
|
111
|
+
<div class="py-2 space-y-2 border-t dark:border-gray-800">
|
|
112
|
+
<div class="flex items-center justify-between">
|
|
113
|
+
<span class="dark:text-gray-50">{{t "storefront.component.widget.orders.subtotal"}}</span>
|
|
114
|
+
<span class="dark:text-gray-50">{{format-currency order.meta.subtotal order.meta.currency}}</span>
|
|
107
115
|
</div>
|
|
108
|
-
|
|
116
|
+
{{#unless order.meta.is_pickup}}
|
|
117
|
+
<div class="flex items-center justify-between">
|
|
118
|
+
<span class="dark:text-gray-50">{{t "storefront.component.widget.orders.delivery-fee"}}</span>
|
|
119
|
+
<span class="dark:text-gray-50">{{format-currency order.meta.delivery_fee order.meta.currency}}</span>
|
|
120
|
+
</div>
|
|
121
|
+
{{/unless}}
|
|
122
|
+
{{#if order.meta.tip}}
|
|
109
123
|
<div class="flex items-center justify-between">
|
|
110
|
-
<span class="dark:text-gray-50">{{t "storefront.component.widget.
|
|
111
|
-
<span class="dark:text-gray-50">{{
|
|
124
|
+
<span class="dark:text-gray-50">{{t "storefront.component.widget.order.tip"}}</span>
|
|
125
|
+
<span class="dark:text-gray-50">{{get-tip-amount order.meta.tip order.meta.subtotal order.meta.currency}}</span>
|
|
112
126
|
</div>
|
|
113
|
-
|
|
114
|
-
|
|
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}}
|
|
127
|
+
{{/if}}
|
|
128
|
+
{{#if order.meta.delivery_tip}}
|
|
131
129
|
<div class="flex items-center justify-between">
|
|
132
|
-
<span class="dark:text-gray-50
|
|
133
|
-
<span class="dark:text-gray-50
|
|
130
|
+
<span class="dark:text-gray-50">{{t "storefront.component.widget.order.delivery-tip"}}</span>
|
|
131
|
+
<span class="dark:text-gray-50">{{get-tip-amount order.meta.delivery_tip order.meta.subtotal order.meta.currency}}</span>
|
|
134
132
|
</div>
|
|
133
|
+
{{/if}}
|
|
134
|
+
<div class="flex items-center justify-between">
|
|
135
|
+
<span class="dark:text-gray-50 font-bold">{{t "storefront.component.widget.order.tip"}}</span>
|
|
136
|
+
<span class="dark:text-gray-50 font-bold">{{format-currency order.meta.total order.meta.currency}}</span>
|
|
135
137
|
</div>
|
|
136
|
-
</
|
|
137
|
-
</
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
</div
|
|
138
|
+
</div>
|
|
139
|
+
</ContentPanel>
|
|
140
|
+
</div>
|
|
141
|
+
{{/each}}
|
|
142
|
+
</div>
|
|
143
|
+
</Layout::Section::Body>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
2
|
import { tracked } from '@glimmer/tracking';
|
|
3
3
|
import { inject as service } from '@ember/service';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { action, get } from '@ember/object';
|
|
5
|
+
import { debug } from '@ember/debug';
|
|
6
6
|
import { task } from 'ember-concurrency-decorators';
|
|
7
|
+
|
|
7
8
|
export default class CustomerPanelOrdersComponent extends Component {
|
|
8
9
|
@service store;
|
|
9
10
|
@service storefront;
|
|
@@ -12,67 +13,73 @@ export default class CustomerPanelOrdersComponent extends Component {
|
|
|
12
13
|
@service appCache;
|
|
13
14
|
@service modalsManager;
|
|
14
15
|
@service contextPanel;
|
|
15
|
-
@
|
|
16
|
+
@service orderActions;
|
|
17
|
+
@tracked loaded = false;
|
|
16
18
|
@tracked orders = [];
|
|
17
19
|
@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
20
|
|
|
24
|
-
constructor() {
|
|
21
|
+
constructor(owner, { customer }) {
|
|
25
22
|
super(...arguments);
|
|
26
|
-
this.customer =
|
|
27
|
-
this.
|
|
23
|
+
this.customer = customer;
|
|
24
|
+
this.loadOrders.perform();
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
@
|
|
31
|
-
this.
|
|
27
|
+
@action search(event) {
|
|
28
|
+
this.loadOrders.perform({ query: event.target.value ?? '' });
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
@
|
|
35
|
-
this.
|
|
31
|
+
@task *loadOrders(params = {}) {
|
|
32
|
+
const storefront = get(this.storefront, 'activeStore.public_id');
|
|
33
|
+
const queryParams = {
|
|
34
|
+
storefront,
|
|
35
|
+
limit: 14,
|
|
36
|
+
sort: '-created_at',
|
|
37
|
+
customer_uuid: this.customer?.id,
|
|
38
|
+
...params,
|
|
39
|
+
};
|
|
36
40
|
|
|
37
|
-
|
|
38
|
-
const
|
|
41
|
+
try {
|
|
42
|
+
const orders = yield this.fetch.get('orders', queryParams, { namespace: 'storefront/int/v1', normalizeToEmberData: true });
|
|
43
|
+
this.loaded = true;
|
|
44
|
+
this.orders = orders;
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
46
|
+
return orders;
|
|
47
|
+
} catch (err) {
|
|
48
|
+
debug('Error loading orders for widget:', err);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
sort: '-created_at',
|
|
49
|
-
customer_uuid: this.customer?.id,
|
|
50
|
-
...params,
|
|
51
|
-
};
|
|
52
|
+
@action async viewOrder(order) {
|
|
53
|
+
this.contextPanel.focus(order, 'viewing');
|
|
54
|
+
}
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
.then((orders) => {
|
|
59
|
-
this.isLoading = false;
|
|
56
|
+
@action async acceptOrder(order) {
|
|
57
|
+
await this.orderActions.acceptOrder(order, () => {
|
|
58
|
+
this.loadOrders.perform();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
@action markAsReady(order) {
|
|
63
|
+
this.orderActions.markAsReady(order, () => {
|
|
64
|
+
this.loadOrders.perform();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
@action markAsCompleted(order) {
|
|
69
|
+
this.orderActions.markAsCompleted(order, () => {
|
|
70
|
+
this.loadOrders.perform();
|
|
68
71
|
});
|
|
69
72
|
}
|
|
70
73
|
|
|
71
|
-
@action
|
|
72
|
-
this.
|
|
74
|
+
@action assignDriver(order) {
|
|
75
|
+
this.orderActions.assignDriver(order, () => {
|
|
76
|
+
this.loadOrders.perform();
|
|
77
|
+
});
|
|
73
78
|
}
|
|
74
79
|
|
|
75
|
-
@action
|
|
76
|
-
this.
|
|
80
|
+
@action cancelOrder(order) {
|
|
81
|
+
this.orderActions.cancelOrder(order, () => {
|
|
82
|
+
this.loadOrders.perform();
|
|
83
|
+
});
|
|
77
84
|
}
|
|
78
85
|
}
|