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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orionplace-nuxt",
3
- "version": "0.7.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.key === 'placed' && order.time_submited?.date"
375
+ v-if="step.date"
376
376
  class="op-orders-step-note"
377
377
  >
378
- {{ order.time_submited.date }}
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 ? actionLabels.value.saved : '';
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
- return actions.preorderId.value
141
- ? actionCopy.value.preorderSaved
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
- export function orderSteps(order: OrderShipmentCounters): OrderStep[] {
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
- { key: 'placed', state: 'done', current: false, count: 1, total: 1 },
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,