orionplace-nuxt 0.7.7 → 0.7.8
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/package.json +1 -1
- package/templates/app/components/orionplace/orders/OrderDetails.vue +2 -2
- package/templates/app/components/orionplace/products/StorefrontProduct.vue +3 -1
- package/templates/app/layouts/default.vue +2 -3
- package/templates/app/utils/orionplace/orderPresentation.ts +45 -2
- package/templates/app/utils/orionplace/productActionLabels.ts +21 -0
- package/templates/app/utils/orionplace/productActions.ts +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orionplace-nuxt",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "Nuxt 4 storefront for your Orionplace marketplace: setup CLI, server API gateway, typed store and ready-made catalog, cart, checkout and account components in English, Russian and Spanish, plus an Android app build.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -372,10 +372,10 @@
|
|
|
372
372
|
{{ labels.stepStates.current }}
|
|
373
373
|
</span>
|
|
374
374
|
<span
|
|
375
|
-
v-if="step.
|
|
375
|
+
v-if="step.date"
|
|
376
376
|
class="op-orders-step-note"
|
|
377
377
|
>
|
|
378
|
-
{{
|
|
378
|
+
{{ step.date }}
|
|
379
379
|
</span>
|
|
380
380
|
<span
|
|
381
381
|
v-else-if="stepCount(step.count, step.total)"
|
|
@@ -192,7 +192,9 @@
|
|
|
192
192
|
actionLabels.value.failed
|
|
193
193
|
);
|
|
194
194
|
}
|
|
195
|
-
return actions.success.value
|
|
195
|
+
return actions.success.value
|
|
196
|
+
? actionLabels.value[actions.done.value ?? 'saved']
|
|
197
|
+
: '';
|
|
196
198
|
});
|
|
197
199
|
const previewStatus = computed(() => {
|
|
198
200
|
if (!props.previewKey || !product.value) {
|
|
@@ -137,9 +137,8 @@
|
|
|
137
137
|
if (!actions.success.value) {
|
|
138
138
|
return '';
|
|
139
139
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
: actionCopy.value.saved;
|
|
140
|
+
// The notice names what the action did («Added to the cart.»).
|
|
141
|
+
return actionCopy.value[actions.done.value ?? 'saved'];
|
|
143
142
|
});
|
|
144
143
|
// Header selection messages stay neutral.
|
|
145
144
|
const actionTone = computed(() => {
|
|
@@ -63,6 +63,8 @@ export interface OrderStep {
|
|
|
63
63
|
current: boolean;
|
|
64
64
|
count: number;
|
|
65
65
|
total: number;
|
|
66
|
+
/** The date the step was reached ('' until then); see orderStepDate. */
|
|
67
|
+
date?: string;
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export type OrderShipmentStateKey =
|
|
@@ -237,7 +239,39 @@ export function orderCanCancel(
|
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
// Canceled and returned orders have no delivery progress to show.
|
|
240
|
-
|
|
242
|
+
// The date a step was reached: the order's own date for Placed; for Shipped
|
|
243
|
+
// and Delivered, once every shipment got there, the latest of their sent
|
|
244
|
+
// (or delivery) dates; '' while a shipment has not reached the step.
|
|
245
|
+
export function orderStepDate(
|
|
246
|
+
order: OrderShipmentCounters & Partial<Pick<IOrder, 'time_submited'>>,
|
|
247
|
+
key: OrderStepKey,
|
|
248
|
+
): string {
|
|
249
|
+
if (key === 'placed') {
|
|
250
|
+
return order.time_submited?.date ?? '';
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const shipments = order.delivery_froms ?? [];
|
|
254
|
+
const reached = shipments.map((shipment) =>
|
|
255
|
+
key === 'shipped'
|
|
256
|
+
? shipment.dates?.sent || shipment.dates?.delivery_date_real
|
|
257
|
+
: shipment.dates?.delivery_date_real,
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
if (!reached.length || reached.some((date) => !date?.date)) {
|
|
261
|
+
return '';
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// The latest is the one the fewest minutes ago (any date format).
|
|
265
|
+
const latest = reached.reduce((best, date) =>
|
|
266
|
+
Number(date?.minutes_ago ?? 0) < Number(best?.minutes_ago ?? 0) ? date : best,
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
return latest?.date ?? '';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export function orderSteps(
|
|
273
|
+
order: OrderShipmentCounters & Partial<Pick<IOrder, 'time_submited'>>,
|
|
274
|
+
): OrderStep[] {
|
|
241
275
|
const { total, sent, delivered } = orderShipmentProgress(order);
|
|
242
276
|
|
|
243
277
|
if (
|
|
@@ -248,13 +282,21 @@ export function orderSteps(order: OrderShipmentCounters): OrderStep[] {
|
|
|
248
282
|
}
|
|
249
283
|
|
|
250
284
|
const steps = [
|
|
251
|
-
{
|
|
285
|
+
{
|
|
286
|
+
key: 'placed',
|
|
287
|
+
state: 'done',
|
|
288
|
+
current: false,
|
|
289
|
+
count: 1,
|
|
290
|
+
total: 1,
|
|
291
|
+
date: orderStepDate(order, 'placed'),
|
|
292
|
+
},
|
|
252
293
|
{
|
|
253
294
|
key: 'shipped',
|
|
254
295
|
state: stepState(sent, total),
|
|
255
296
|
current: false,
|
|
256
297
|
count: sent,
|
|
257
298
|
total,
|
|
299
|
+
date: orderStepDate(order, 'shipped'),
|
|
258
300
|
},
|
|
259
301
|
{
|
|
260
302
|
key: 'delivered',
|
|
@@ -262,6 +304,7 @@ export function orderSteps(order: OrderShipmentCounters): OrderStep[] {
|
|
|
262
304
|
current: false,
|
|
263
305
|
count: delivered,
|
|
264
306
|
total,
|
|
307
|
+
date: orderStepDate(order, 'delivered'),
|
|
265
308
|
},
|
|
266
309
|
] satisfies OrderStep[];
|
|
267
310
|
|
|
@@ -4,6 +4,13 @@ const labels = {
|
|
|
4
4
|
en: {
|
|
5
5
|
pending: 'Updating product…',
|
|
6
6
|
saved: 'Product updated.',
|
|
7
|
+
cartAdded: 'Added to the cart.',
|
|
8
|
+
cartUpdated: 'Cart quantity updated.',
|
|
9
|
+
cartRemoved: 'Removed from the cart.',
|
|
10
|
+
favoriteAdded: 'Saved to favorites.',
|
|
11
|
+
favoriteRemoved: 'Removed from favorites.',
|
|
12
|
+
subscribed: 'We will let you know when it is back in stock.',
|
|
13
|
+
unsubscribed: 'Availability notification turned off.',
|
|
7
14
|
failed: 'The request failed. Your confirmed product data is unchanged.',
|
|
8
15
|
unavailable: 'This action is unavailable.',
|
|
9
16
|
login: 'Sign in to save favorites or availability notifications.',
|
|
@@ -31,6 +38,13 @@ const labels = {
|
|
|
31
38
|
ru: {
|
|
32
39
|
pending: 'Обновляем товар…',
|
|
33
40
|
saved: 'Товар обновлён.',
|
|
41
|
+
cartAdded: 'Товар добавлен в корзину.',
|
|
42
|
+
cartUpdated: 'Количество в корзине изменено.',
|
|
43
|
+
cartRemoved: 'Товар удалён из корзины.',
|
|
44
|
+
favoriteAdded: 'Товар добавлен в избранное.',
|
|
45
|
+
favoriteRemoved: 'Товар удалён из избранного.',
|
|
46
|
+
subscribed: 'Сообщим, когда товар появится в наличии.',
|
|
47
|
+
unsubscribed: 'Уведомление о наличии отключено.',
|
|
34
48
|
failed: 'Запрос не выполнен. Подтверждённые данные товара сохранены.',
|
|
35
49
|
unavailable: 'Это действие недоступно.',
|
|
36
50
|
login: 'Войдите, чтобы сохранять избранное и уведомления о наличии.',
|
|
@@ -56,6 +70,13 @@ const labels = {
|
|
|
56
70
|
es: {
|
|
57
71
|
pending: 'Actualizando el producto…',
|
|
58
72
|
saved: 'Producto actualizado.',
|
|
73
|
+
cartAdded: 'Añadido al carrito.',
|
|
74
|
+
cartUpdated: 'Cantidad del carrito actualizada.',
|
|
75
|
+
cartRemoved: 'Eliminado del carrito.',
|
|
76
|
+
favoriteAdded: 'Guardado en favoritos.',
|
|
77
|
+
favoriteRemoved: 'Eliminado de favoritos.',
|
|
78
|
+
subscribed: 'Te avisaremos cuando vuelva a estar disponible.',
|
|
79
|
+
unsubscribed: 'Aviso de disponibilidad desactivado.',
|
|
59
80
|
failed: 'La solicitud ha fallado. Los datos confirmados del producto no han cambiado.',
|
|
60
81
|
unavailable: 'Esta acción no está disponible.',
|
|
61
82
|
login: 'Inicia sesión para guardar favoritos o avisos de disponibilidad.',
|
|
@@ -140,6 +140,18 @@ export function applyProductActionPatch(
|
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
+
// What a finished action did, so the notice can say it («Added to the
|
|
144
|
+
// cart.» rather than «Product updated.»); a key of productActionLabels.
|
|
145
|
+
export type ProductActionDone =
|
|
146
|
+
| 'cartAdded'
|
|
147
|
+
| 'cartUpdated'
|
|
148
|
+
| 'cartRemoved'
|
|
149
|
+
| 'favoriteAdded'
|
|
150
|
+
| 'favoriteRemoved'
|
|
151
|
+
| 'subscribed'
|
|
152
|
+
| 'unsubscribed'
|
|
153
|
+
| 'preorderSaved';
|
|
154
|
+
|
|
143
155
|
export function createProductActions(options: {
|
|
144
156
|
request: ProductActionRequest;
|
|
145
157
|
authenticated: () => boolean;
|
|
@@ -164,6 +176,7 @@ export function createProductActions(options: {
|
|
|
164
176
|
}>();
|
|
165
177
|
const success = ref(false);
|
|
166
178
|
const preorderId = ref<number>();
|
|
179
|
+
const done = ref<ProductActionDone>();
|
|
167
180
|
const needsRefresh = ref(false);
|
|
168
181
|
let refreshTarget: { store: ProductActionStore; id: number } | undefined;
|
|
169
182
|
|
|
@@ -482,6 +495,7 @@ export function createProductActions(options: {
|
|
|
482
495
|
|
|
483
496
|
error.value = undefined;
|
|
484
497
|
success.value = false;
|
|
498
|
+
done.value = undefined;
|
|
485
499
|
preorderId.value = undefined;
|
|
486
500
|
|
|
487
501
|
try {
|
|
@@ -511,16 +525,28 @@ export function createProductActions(options: {
|
|
|
511
525
|
|
|
512
526
|
pending.value = true;
|
|
513
527
|
|
|
528
|
+
let finished: ProductActionDone | undefined;
|
|
529
|
+
|
|
514
530
|
if (action === 'toggleFavorite') {
|
|
515
531
|
await changeFavorite(store, selection);
|
|
532
|
+
finished = selection.selected ? 'favoriteAdded' : 'favoriteRemoved';
|
|
516
533
|
} else if (action === 'add' || action === 'remove') {
|
|
534
|
+
// Adding a product already in the cart sets its new quantity.
|
|
535
|
+
const inCart = Boolean(product.cart_counts?.cart_id);
|
|
536
|
+
|
|
517
537
|
await changeCart(store, action, selection, product);
|
|
538
|
+
finished = action === 'remove'
|
|
539
|
+
? 'cartRemoved'
|
|
540
|
+
: inCart ? 'cartUpdated' : 'cartAdded';
|
|
518
541
|
} else if (action === 'subscribe' || action === 'unsubscribe') {
|
|
519
542
|
await changeSubscription(store, action, id);
|
|
543
|
+
finished = action === 'subscribe' ? 'subscribed' : 'unsubscribed';
|
|
520
544
|
} else if (action === 'preorder') {
|
|
521
545
|
await createPreorder(selection, availability.canPreorder);
|
|
546
|
+
finished = 'preorderSaved';
|
|
522
547
|
}
|
|
523
548
|
|
|
549
|
+
done.value = finished;
|
|
524
550
|
success.value = true;
|
|
525
551
|
return true;
|
|
526
552
|
} catch (reason) {
|
|
@@ -540,6 +566,7 @@ export function createProductActions(options: {
|
|
|
540
566
|
pending,
|
|
541
567
|
error,
|
|
542
568
|
success,
|
|
569
|
+
done,
|
|
543
570
|
preorderId,
|
|
544
571
|
needsRefresh,
|
|
545
572
|
retryRefresh,
|