@lookiero/checkout 0.4.0-beta.3 → 0.4.1

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 (52) hide show
  1. package/dist/domain/checkout/model/checkout.d.ts +3 -2
  2. package/dist/domain/checkout/model/checkout.js +1 -1
  3. package/dist/domain/checkoutBooking/command/blockCheckoutBooking.d.ts +13 -0
  4. package/dist/domain/checkoutBooking/command/blockCheckoutBooking.js +4 -0
  5. package/dist/domain/checkoutBooking/model/checkoutBooking.d.ts +5 -1
  6. package/dist/domain/checkoutBooking/model/checkoutBooking.js +17 -1
  7. package/dist/domain/checkoutBooking/model/checkoutBookingBlocked.d.ts +13 -0
  8. package/dist/domain/checkoutBooking/model/checkoutBookingBlocked.js +4 -0
  9. package/dist/domain/checkoutBooking/model/checkoutBookingExpired.d.ts +13 -0
  10. package/dist/domain/checkoutBooking/model/checkoutBookingExpired.js +4 -0
  11. package/dist/domain/checkoutItem/command/replaceCheckoutItem.d.ts +1 -1
  12. package/dist/domain/checkoutItem/model/checkoutItem.d.ts +1 -1
  13. package/dist/domain/checkoutItem/model/checkoutItem.js +2 -4
  14. package/dist/infrastructure/delivery/baseBootstrap.d.ts +2 -0
  15. package/dist/infrastructure/delivery/baseBootstrap.js +8 -2
  16. package/dist/infrastructure/delivery/bootstrap.js +2 -0
  17. package/dist/infrastructure/delivery/mock/dataSourceCheckoutBookings.js +5 -1
  18. package/dist/infrastructure/delivery/mock/dataSourceCheckoutItems.js +2 -0
  19. package/dist/infrastructure/delivery/mock/dataSourceCheckouts.js +2 -2
  20. package/dist/infrastructure/domain/checkout/model/httpCheckouts.js +1 -1
  21. package/dist/infrastructure/domain/checkout/react/useMarkCheckoutAsPaid.d.ts +1 -1
  22. package/dist/infrastructure/domain/checkout/react/useMarkCheckoutAsPaid.js +1 -1
  23. package/dist/infrastructure/domain/checkoutBooking/model/httpCheckoutBookings.js +9 -2
  24. package/dist/infrastructure/domain/checkoutBooking/model/httpCheckoutBookingsBlock.d.ts +5 -0
  25. package/dist/infrastructure/domain/checkoutBooking/model/httpCheckoutBookingsBlock.js +15 -0
  26. package/dist/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.d.ts +13 -0
  27. package/dist/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.js +12 -0
  28. package/dist/infrastructure/domain/checkoutBooking/react/useBookCheckoutBookingForCheckoutItem.d.ts +14 -0
  29. package/dist/infrastructure/domain/checkoutBooking/react/{useBookCheckouBookingForCheckoutItem.js → useBookCheckoutBookingForCheckoutItem.js} +4 -4
  30. package/dist/infrastructure/domain/checkoutItem/model/httpCheckoutItems.js +1 -1
  31. package/dist/infrastructure/domain/checkoutItem/model/httpCheckoutItemsReplace.js +2 -2
  32. package/dist/infrastructure/domain/checkoutItem/react/useReplaceCheckoutItem.d.ts +1 -1
  33. package/dist/infrastructure/domain/checkoutItem/react/useReplaceCheckoutItem.js +2 -2
  34. package/dist/infrastructure/projection/bookedSizeChangeProductsVariants/httpBookedSizeChangeProductsVariantsForCheckoutItemView.js +1 -1
  35. package/dist/infrastructure/projection/checkout/checkout.d.ts +1 -1
  36. package/dist/infrastructure/projection/checkout/react/useViewIsCheckoutAccessibleByCustomerId.js +3 -0
  37. package/dist/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.js +9 -1
  38. package/dist/infrastructure/ui/routing/CheckoutMiddleware.js +11 -11
  39. package/dist/infrastructure/ui/views/App.style.d.ts +1 -0
  40. package/dist/infrastructure/ui/views/App.style.js +1 -0
  41. package/dist/infrastructure/ui/views/checkout/Checkout.js +15 -7
  42. package/dist/infrastructure/ui/views/feedback/Feedback.js +6 -1
  43. package/dist/infrastructure/ui/views/item/Item.js +77 -33
  44. package/dist/infrastructure/ui/views/summary/components/checkoutItemsTabs/CheckoutItemsTabs.js +7 -4
  45. package/dist/infrastructure/ui/views/summary/components/pricing/Pricing.js +2 -2
  46. package/dist/projection/bookedSizeChangeProductsVariants/bookedSizeChangeProductsVariants.d.ts +0 -1
  47. package/dist/projection/checkout/checkout.d.ts +1 -1
  48. package/dist/projection/checkoutBooking/checkoutBooking.d.ts +2 -0
  49. package/dist/projection/checkoutItem/checkoutItem.d.ts +1 -1
  50. package/dist/projection/pricing/pricing.d.ts +3 -3
  51. package/package.json +1 -1
  52. package/dist/infrastructure/domain/checkoutBooking/react/useBookCheckouBookingForCheckoutItem.d.ts +0 -13
@@ -6,13 +6,14 @@ declare enum CheckoutStatus {
6
6
  NOTIFIED = "NOTIFIED",
7
7
  STARTED = "STARTED",
8
8
  COMPLETED = "COMPLETED",
9
- PAID = "PAID"
9
+ PAID = "PAID",
10
+ EXPIRED = "EXPIRED"
10
11
  }
11
12
  interface Checkout extends AggregateRoot {
12
13
  readonly status: CheckoutStatus;
13
14
  readonly customerId: string;
14
15
  readonly boxId: string;
15
- readonly bookingId: string;
16
+ readonly checkoutBookingId: string;
16
17
  readonly expiresOn: Date;
17
18
  }
18
19
  declare const startCheckoutHandler: CommandHandlerFunction<StartCheckout, Checkout>;
@@ -8,6 +8,7 @@ var CheckoutStatus;
8
8
  CheckoutStatus["STARTED"] = "STARTED";
9
9
  CheckoutStatus["COMPLETED"] = "COMPLETED";
10
10
  CheckoutStatus["PAID"] = "PAID";
11
+ CheckoutStatus["EXPIRED"] = "EXPIRED";
11
12
  })(CheckoutStatus || (CheckoutStatus = {}));
12
13
  const startCheckoutHandler = () => async ({ aggregateRoot, command }) => {
13
14
  const { aggregateId } = command;
@@ -21,7 +22,6 @@ const startCheckoutHandler = () => async ({ aggregateRoot, command }) => {
21
22
  };
22
23
  const markCheckoutAsPaidHandler = () => async ({ aggregateRoot, command }) => {
23
24
  const { aggregateId } = command;
24
- invariant(aggregateRoot.status !== CheckoutStatus.PAID, "Checkout is already paid");
25
25
  invariant(aggregateRoot.status !== CheckoutStatus.COMPLETED, "Checkout is already completed");
26
26
  return {
27
27
  ...aggregateRoot,
@@ -0,0 +1,13 @@
1
+ import { Command } from "@lookiero/messaging";
2
+ declare const BLOCK_CHECKOUT_BOOKING = "block_checkout_booking";
3
+ interface BlockCheckoutBookingPayload {
4
+ readonly aggregateId: string;
5
+ }
6
+ interface BlockCheckoutBooking extends Command<typeof BLOCK_CHECKOUT_BOOKING>, BlockCheckoutBookingPayload {
7
+ }
8
+ interface BlockCheckoutBookingFunction {
9
+ (payload: BlockCheckoutBookingPayload): BlockCheckoutBooking;
10
+ }
11
+ declare const blockCheckoutBooking: BlockCheckoutBookingFunction;
12
+ export type { BlockCheckoutBooking };
13
+ export { BLOCK_CHECKOUT_BOOKING, blockCheckoutBooking };
@@ -0,0 +1,4 @@
1
+ import { command } from "@lookiero/messaging";
2
+ const BLOCK_CHECKOUT_BOOKING = "block_checkout_booking";
3
+ const blockCheckoutBooking = ({ aggregateId }) => command({ aggregateId, name: BLOCK_CHECKOUT_BOOKING });
4
+ export { BLOCK_CHECKOUT_BOOKING, blockCheckoutBooking };
@@ -1,8 +1,12 @@
1
1
  import { AggregateRoot, CommandHandlerFunction } from "@lookiero/messaging";
2
+ import { CheckoutStatus } from "../../checkout/model/checkout";
3
+ import { BlockCheckoutBooking } from "../command/blockCheckoutBooking";
2
4
  import { BookCheckoutBookingForCheckoutItem } from "../command/bookCheckoutBookingForCheckoutItem";
3
5
  interface CheckoutBooking extends AggregateRoot {
4
6
  readonly checkoutItemIds: string[];
7
+ readonly checkoutStatus: CheckoutStatus;
5
8
  }
6
9
  declare const bookCheckoutBookingForCheckoutItemHandler: CommandHandlerFunction<BookCheckoutBookingForCheckoutItem, CheckoutBooking>;
10
+ declare const blockCheckoutBookingHandler: CommandHandlerFunction<BlockCheckoutBooking, CheckoutBooking>;
7
11
  export type { CheckoutBooking };
8
- export { bookCheckoutBookingForCheckoutItemHandler };
12
+ export { bookCheckoutBookingForCheckoutItemHandler, blockCheckoutBookingHandler };
@@ -1,4 +1,7 @@
1
+ import { CheckoutStatus } from "../../checkout/model/checkout";
2
+ import { checkoutBookingBlocked } from "./checkoutBookingBlocked";
1
3
  import { checkoutBookingBooked } from "./checkoutBookingBooked";
4
+ import { checkoutBookingExpired } from "./checkoutBookingExpired";
2
5
  const bookCheckoutBookingForCheckoutItemHandler = () => async ({ aggregateRoot, command }) => {
3
6
  const { aggregateId, checkoutItemId } = command;
4
7
  return {
@@ -6,4 +9,17 @@ const bookCheckoutBookingForCheckoutItemHandler = () => async ({ aggregateRoot,
6
9
  domainEvents: [checkoutBookingBooked({ aggregateId, checkoutItemId })],
7
10
  };
8
11
  };
9
- export { bookCheckoutBookingForCheckoutItemHandler };
12
+ const blockCheckoutBookingHandler = () => async ({ aggregateRoot, command }) => {
13
+ const { aggregateId } = command;
14
+ if (aggregateRoot.checkoutStatus === CheckoutStatus.EXPIRED) {
15
+ return {
16
+ ...aggregateRoot,
17
+ domainEvents: [checkoutBookingExpired({ aggregateId })],
18
+ };
19
+ }
20
+ return {
21
+ ...aggregateRoot,
22
+ domainEvents: [checkoutBookingBlocked({ aggregateId })],
23
+ };
24
+ };
25
+ export { bookCheckoutBookingForCheckoutItemHandler, blockCheckoutBookingHandler };
@@ -0,0 +1,13 @@
1
+ import { DomainEvent } from "@lookiero/messaging";
2
+ declare const CHECKOUT_BOOKING_BLOCKED = "checkout_booking_blocked";
3
+ interface CheckoutBookingBlokedPaylcoad {
4
+ readonly aggregateId: string;
5
+ }
6
+ interface CheckoutBookingBlocked extends DomainEvent<typeof CHECKOUT_BOOKING_BLOCKED>, CheckoutBookingBlokedPaylcoad {
7
+ }
8
+ interface CheckoutBookingBlokedFunctcion {
9
+ (payload: CheckoutBookingBlokedPaylcoad): CheckoutBookingBlocked;
10
+ }
11
+ declare const checkoutBookingBlocked: CheckoutBookingBlokedFunctcion;
12
+ export type { CheckoutBookingBlocked };
13
+ export { CHECKOUT_BOOKING_BLOCKED, checkoutBookingBlocked };
@@ -0,0 +1,4 @@
1
+ import { domainEvent } from "@lookiero/messaging";
2
+ const CHECKOUT_BOOKING_BLOCKED = "checkout_booking_blocked";
3
+ const checkoutBookingBlocked = ({ aggregateId }) => domainEvent({ aggregateId, name: CHECKOUT_BOOKING_BLOCKED });
4
+ export { CHECKOUT_BOOKING_BLOCKED, checkoutBookingBlocked };
@@ -0,0 +1,13 @@
1
+ import { DomainEvent } from "@lookiero/messaging";
2
+ declare const CHECKOUT_BOOKING_EXPIRED = "checkout_booking_expired";
3
+ interface CheckoutBookingExpiredPayload {
4
+ readonly aggregateId: string;
5
+ }
6
+ interface CheckoutBookingExpired extends DomainEvent<typeof CHECKOUT_BOOKING_EXPIRED>, CheckoutBookingExpiredPayload {
7
+ }
8
+ interface CheckoutBookingExpiredFunction {
9
+ (payload: CheckoutBookingExpiredPayload): CheckoutBookingExpired;
10
+ }
11
+ declare const checkoutBookingExpired: CheckoutBookingExpiredFunction;
12
+ export type { CheckoutBookingExpired };
13
+ export { CHECKOUT_BOOKING_EXPIRED, checkoutBookingExpired };
@@ -0,0 +1,4 @@
1
+ import { domainEvent } from "@lookiero/messaging";
2
+ const CHECKOUT_BOOKING_EXPIRED = "checkout_booking_expired";
3
+ const checkoutBookingExpired = ({ aggregateId }) => domainEvent({ aggregateId, name: CHECKOUT_BOOKING_EXPIRED });
4
+ export { CHECKOUT_BOOKING_EXPIRED, checkoutBookingExpired };
@@ -2,7 +2,7 @@ import { Command } from "@lookiero/messaging";
2
2
  declare const REPLACE_CHECKOUT_ITEM = "replace_checkout_item";
3
3
  interface ReplaceCheckoutItemPayload {
4
4
  readonly aggregateId: string;
5
- readonly replacedFor: string;
5
+ readonly replacedForId: string;
6
6
  }
7
7
  interface ReplaceCheckoutItem extends Command<typeof REPLACE_CHECKOUT_ITEM>, ReplaceCheckoutItemPayload {
8
8
  }
@@ -15,7 +15,7 @@ interface CheckoutItem extends AggregateRoot {
15
15
  readonly status: CheckoutItemStatus;
16
16
  readonly price: Price;
17
17
  readonly feedbacks: Feedbacks;
18
- readonly replacedFor?: string;
18
+ readonly replacedForId?: string;
19
19
  }
20
20
  declare const keepCheckoutItemHandler: CommandHandlerFunction<KeepCheckoutItem, CheckoutItem>;
21
21
  declare const returnCheckoutItemHandler: CommandHandlerFunction<ReturnCheckoutItem, CheckoutItem>;
@@ -1,4 +1,3 @@
1
- import invariant from "tiny-invariant";
2
1
  import { checkoutItemKept } from "./checkoutItemKept";
3
2
  import { checkoutItemReplaced } from "./checkoutItemReplaced";
4
3
  import { checkoutItemReturned } from "./checkoutItemReturned";
@@ -12,7 +11,6 @@ var CheckoutItemStatus;
12
11
  })(CheckoutItemStatus || (CheckoutItemStatus = {}));
13
12
  const keepCheckoutItemHandler = () => async ({ aggregateRoot, command }) => {
14
13
  const { aggregateId } = command;
15
- invariant(aggregateRoot.status !== CheckoutItemStatus.KEPT, "CheckoutItem is already kept");
16
14
  return {
17
15
  ...aggregateRoot,
18
16
  status: CheckoutItemStatus.KEPT,
@@ -29,10 +27,10 @@ const returnCheckoutItemHandler = () => async ({ aggregateRoot, command }) => {
29
27
  };
30
28
  };
31
29
  const replaceCheckoutItemHandler = () => async ({ aggregateRoot, command }) => {
32
- const { aggregateId, replacedFor } = command;
30
+ const { aggregateId, replacedForId } = command;
33
31
  return {
34
32
  ...aggregateRoot,
35
- replacedFor,
33
+ replacedForId,
36
34
  status: CheckoutItemStatus.REPLACED,
37
35
  domainEvents: [checkoutItemReplaced({ aggregateId })],
38
36
  };
@@ -15,6 +15,7 @@ import { CheckoutByIdView } from "../../projection/checkout/viewCheckoutById";
15
15
  import { FirstAvailableCheckoutByCustomerIdView } from "../../projection/checkout/viewFirstAvailableCheckoutByCustomerId";
16
16
  import { FiveItemsDiscountByCustomerIdView } from "../../projection/checkout/viewFiveItemsDiscountByCustomerId";
17
17
  import { IsCheckoutEnabledByCustomerIdView } from "../../projection/checkout/viewIsCheckoutEnabledByCustomerId";
18
+ import { CheckoutBookingByIdView } from "../../projection/checkoutBooking/viewCheckoutBookingById";
18
19
  import { CheckoutItemByIdView } from "../../projection/checkoutItem/viewCheckoutItemById";
19
20
  import { CheckoutQuestionsByCheckoutIdView } from "../../projection/checkoutQuestion/listCheckoutQuestionsByCheckoutId";
20
21
  import { PaymentFlowPayloadByCheckoutIdView } from "../../projection/payment/viewPaymentFlowPayloadByCheckoutId";
@@ -31,6 +32,7 @@ interface BaseBootstrapFunctionArgs<UiSettingGetFunctionArgs extends RepositoryG
31
32
  readonly fiveItemsDiscountByCustomerIdView: FiveItemsDiscountByCustomerIdView;
32
33
  readonly uiSettingByKeyView: UiSettingByKeyView;
33
34
  readonly checkoutItemByIdView: CheckoutItemByIdView;
35
+ readonly checkoutBookingByIdView: CheckoutBookingByIdView;
34
36
  readonly returnQuestionsByCheckoutItemIdView: ReturnQuestionsByCheckoutItemIdView;
35
37
  readonly bookedSizeChangeProductsVariantsForCheckoutItemView: BookedSizeChangeProductsVariantsForCheckoutItemView;
36
38
  readonly pricingByCheckoutIdView: PricingByCheckoutIdView;
@@ -2,8 +2,9 @@ import { bootstrap as messagingBootstrap } from "@lookiero/messaging-react";
2
2
  import { MARK_CHECKOUT_AS_PAID } from "../../domain/checkout/command/markCheckoutAsPaid";
3
3
  import { START_CHECKOUT } from "../../domain/checkout/command/startCheckout";
4
4
  import { markCheckoutAsPaidHandler, startCheckoutHandler } from "../../domain/checkout/model/checkout";
5
+ import { BLOCK_CHECKOUT_BOOKING } from "../../domain/checkoutBooking/command/blockCheckoutBooking";
5
6
  import { BOOK_CHECKOUT_BOOKING_FOR_CHECKOUT_ITEM } from "../../domain/checkoutBooking/command/bookCheckoutBookingForCheckoutItem";
6
- import { bookCheckoutBookingForCheckoutItemHandler, } from "../../domain/checkoutBooking/model/checkoutBooking";
7
+ import { blockCheckoutBookingHandler, bookCheckoutBookingForCheckoutItemHandler, } from "../../domain/checkoutBooking/model/checkoutBooking";
7
8
  import { GIVE_CHECKOUT_FEEDBACK } from "../../domain/checkoutFeedback/command/giveCheckoutFeedback";
8
9
  import { giveCheckoutFeedbackHandler } from "../../domain/checkoutFeedback/model/checkoutFeedback";
9
10
  import { KEEP_CHECKOUT_ITEM } from "../../domain/checkoutItem/command/keepCheckoutItem";
@@ -18,6 +19,7 @@ import { viewFirstAvailableCheckoutByCustomerIdHandler, VIEW_FIRST_AVAILABLE_CHE
18
19
  import { viewFiveItemsDiscountByCustomerIdHandler, VIEW_FIVE_ITEMS_DISCOUNT_BY_CUSTOMER_ID, } from "../../projection/checkout/viewFiveItemsDiscountByCustomerId";
19
20
  import { viewIsCheckoutAccessibleByCustomerIdHandler, VIEW_IS_CHECKOUT_ACCESSIBLE_BY_CUSTOMER_ID, } from "../../projection/checkout/viewIsCheckoutAccessibleByCustomerId";
20
21
  import { viewIsCheckoutEnabledByCustomerIdHandler, VIEW_IS_CHECKOUT_ENABLED_BY_CUSTOMER_ID, } from "../../projection/checkout/viewIsCheckoutEnabledByCustomerId";
22
+ import { viewCheckoutBookingByIdHandler, VIEW_CHECKOUT_BOOKING_BY_ID, } from "../../projection/checkoutBooking/viewCheckoutBookingById";
21
23
  import { viewCheckoutItemByIdHandler, VIEW_CHECKOUT_ITEM_BY_ID, } from "../../projection/checkoutItem/viewCheckoutItemById";
22
24
  import { listCheckoutQuestionsByCheckoutIdHandler, LIST_CHECKOUT_QUESTIONS_BY_CHECKOUT_ID, } from "../../projection/checkoutQuestion/listCheckoutQuestionsByCheckoutId";
23
25
  import { viewPaymentFlowPayloadByCheckoutIdHandler, VIEW_PAYMENT_FLOW_PAYLOAD_BY_CHECKOUT_ID, } from "../../projection/payment/viewPaymentFlowPayloadByCheckoutId";
@@ -25,7 +27,7 @@ import { viewPricingByCheckoutIdHandler, VIEW_PRICING_BY_CHECKOUT_ID, } from "..
25
27
  import { listReturnQuestionsByCheckoutItemIdHandler, LIST_RETURN_QUESTIONS_BY_CHECKOUT_ITEM_ID, } from "../../projection/returnQuestion/listReturnQuestionsByCheckoutItemId";
26
28
  import { viewUiSettingByKeyHandler, VIEW_UI_SETTING_BY_KEY, } from "../../projection/uiSetting/viewUiSettingByKey";
27
29
  const MESSAGING_CONTEXT_ID = "Checkout";
28
- const baseBootstrap = ({ checkoutByIdView, firstAvailableCheckoutByCustomerIdView, isCheckoutEnabledByCustomerIdView, fiveItemsDiscountByCustomerIdView, uiSettingByKeyView, checkoutItemByIdView, returnQuestionsByCheckoutItemIdView, bookedSizeChangeProductsVariantsForCheckoutItemView, pricingByCheckoutIdView, paymentFlowPayloadByCheckoutIdView, checkoutQuestionsByCheckoutIdView, getUiSetting, saveUiSetting, uiSettingsDependencies, getCheckout, saveCheckout, checkoutsDependencies, getCheckoutItem, saveCheckoutItem, checkoutItemsDependencies, getCheckoutBooking, saveCheckoutBooking, checkoutBookingsDependencies, getCheckoutFeedback, saveCheckoutFeedback, checkoutFeedbacksDependencies, }) => messagingBootstrap({ id: MESSAGING_CONTEXT_ID })
30
+ const baseBootstrap = ({ checkoutByIdView, firstAvailableCheckoutByCustomerIdView, isCheckoutEnabledByCustomerIdView, fiveItemsDiscountByCustomerIdView, uiSettingByKeyView, checkoutItemByIdView, returnQuestionsByCheckoutItemIdView, bookedSizeChangeProductsVariantsForCheckoutItemView, checkoutBookingByIdView, pricingByCheckoutIdView, paymentFlowPayloadByCheckoutIdView, checkoutQuestionsByCheckoutIdView, getUiSetting, saveUiSetting, uiSettingsDependencies, getCheckout, saveCheckout, checkoutsDependencies, getCheckoutItem, saveCheckoutItem, checkoutItemsDependencies, getCheckoutBooking, saveCheckoutBooking, checkoutBookingsDependencies, getCheckoutFeedback, saveCheckoutFeedback, checkoutFeedbacksDependencies, }) => messagingBootstrap({ id: MESSAGING_CONTEXT_ID })
29
31
  .query(VIEW_FIVE_ITEMS_DISCOUNT_BY_CUSTOMER_ID, viewFiveItemsDiscountByCustomerIdHandler, {
30
32
  view: fiveItemsDiscountByCustomerIdView,
31
33
  })
@@ -58,11 +60,15 @@ const baseBootstrap = ({ checkoutByIdView, firstAvailableCheckoutByCustomerIdVie
58
60
  })
59
61
  .query(LIST_CHECKOUT_QUESTIONS_BY_CHECKOUT_ID, listCheckoutQuestionsByCheckoutIdHandler, {
60
62
  view: checkoutQuestionsByCheckoutIdView,
63
+ })
64
+ .query(VIEW_CHECKOUT_BOOKING_BY_ID, viewCheckoutBookingByIdHandler, {
65
+ view: checkoutBookingByIdView,
61
66
  })
62
67
  .query(VIEW_BOOKED_SIZE_CHANGE_PRODUCT_VARIANTS_FOR_CHECKOUT_ITEM, viewBookedSizeChangeProductsVariantsForCheckoutItemHandler, {
63
68
  view: bookedSizeChangeProductsVariantsForCheckoutItemView,
64
69
  })
65
70
  .command(BOOK_CHECKOUT_BOOKING_FOR_CHECKOUT_ITEM, bookCheckoutBookingForCheckoutItemHandler)(getCheckoutBooking, saveCheckoutBooking, ...checkoutBookingsDependencies)
71
+ .command(BLOCK_CHECKOUT_BOOKING, blockCheckoutBookingHandler)(getCheckoutBooking, saveCheckoutBooking, ...checkoutBookingsDependencies)
66
72
  .command(GIVE_CHECKOUT_FEEDBACK, giveCheckoutFeedbackHandler)(getCheckoutFeedback, saveCheckoutFeedback, ...checkoutFeedbacksDependencies)
67
73
  .query(VIEW_UI_SETTING_BY_KEY, viewUiSettingByKeyHandler, {
68
74
  view: uiSettingByKeyView,
@@ -9,6 +9,7 @@ import { httpCheckoutByIdView } from "../projection/checkout/httpCheckoutByIdVie
9
9
  import { httpFirstAvailableCheckoutByCustomerIdView } from "../projection/checkout/httpFirstAvailableCheckoutByCustomerIdView";
10
10
  import { httpFiveItemsDiscountByCustomerIdView } from "../projection/checkout/httpFiveItemsDiscountByCustomerIdView";
11
11
  import { httpIsCheckoutEnabledByCustomerIdView } from "../projection/checkout/httpIsCheckoutEnabledByCustomerIdView";
12
+ import { httpCheckoutBookingByIdView } from "../projection/checkoutBooking/httpCheckoutBookingByIdView";
12
13
  import { httpCheckoutItemByIdView } from "../projection/checkoutItem/httpCheckoutItemByIdView";
13
14
  import { httpCheckoutQuestionsByCheckoutIdView } from "../projection/checkoutQuestion/httpCheckoutQuestionsByCheckoutIdView";
14
15
  import { httpPaymentFlowPayloadByCheckoutIdView } from "../projection/payment/httpPaymentFlowPayloadByCheckoutIdView";
@@ -28,6 +29,7 @@ const bootstrap = ({ apiUrl, getAuthToken }) => {
28
29
  uiSettingByKeyView: storageUiSettingByKeyView({ read }),
29
30
  checkoutItemByIdView: httpCheckoutItemByIdView({ httpPost }),
30
31
  returnQuestionsByCheckoutItemIdView: httpReturnQuestionsByCheckoutItemIdView({ httpPost }),
32
+ checkoutBookingByIdView: httpCheckoutBookingByIdView({ httpPost }),
31
33
  bookedSizeChangeProductsVariantsForCheckoutItemView: httpBookedSizeChangeProductsVariantsForCheckoutItemView({
32
34
  httpPost,
33
35
  }),
@@ -1,16 +1,20 @@
1
1
  import invariant from "tiny-invariant";
2
+ import { v4 as uuid } from "uuid";
3
+ import { CheckoutStatus } from "../../../domain/checkout/model/checkout";
2
4
  import { viewBookedSizeChangeProductsVariantsForCheckoutItem, } from "../../../projection/bookedSizeChangeProductsVariants/viewBookedSizeChangeProductVariantsForCheckoutItem";
3
5
  const toCheckoutBookingDomain = (checkoutBooking) => {
4
6
  invariant(checkoutBooking, "No checkoutBooking found!");
5
7
  return {
6
- aggregateId: checkoutBooking.bookingId,
8
+ aggregateId: uuid(),
7
9
  checkoutItemIds: checkoutBooking.productVariants.map((productVariant) => productVariant.id),
10
+ checkoutStatus: CheckoutStatus.AVAILABLE,
8
11
  domainEvents: [],
9
12
  };
10
13
  };
11
14
  const toCheckoutBookingProjection = (checkoutBooking) => ({
12
15
  id: checkoutBooking.aggregateId,
13
16
  checkoutItemIds: checkoutBooking.checkoutItemIds,
17
+ checkoutStatus: checkoutBooking.checkoutStatus,
14
18
  });
15
19
  const getCheckoutBooking = ({ queryBus }) => async (aggregateId) => toCheckoutBookingDomain(await queryBus(viewBookedSizeChangeProductsVariantsForCheckoutItem({ checkoutItemId: aggregateId })));
16
20
  const saveCheckoutBooking = ({ dataSource }) => async (aggregateRoot) => {
@@ -5,6 +5,7 @@ const toCheckoutItemProjection = (checkoutItem) => ({
5
5
  status: checkoutItem.status,
6
6
  productVariant: {},
7
7
  feedbacks: {},
8
+ replacedFor: null,
8
9
  price: checkoutItem.price,
9
10
  });
10
11
  const toCheckoutItemDomain = (checkoutItem) => {
@@ -15,6 +16,7 @@ const toCheckoutItemDomain = (checkoutItem) => {
15
16
  status: checkoutItem.status,
16
17
  price: checkoutItem.price,
17
18
  feedbacks: checkoutItem.feedbacks,
19
+ replacedForId: checkoutItem.replacedFor?.id,
18
20
  domainEvents: [],
19
21
  };
20
22
  };
@@ -7,7 +7,7 @@ const toCheckoutDomain = (checkout) => {
7
7
  status: checkout.status,
8
8
  customerId: checkout.customerId,
9
9
  boxId: checkout.boxId,
10
- bookingId: checkout.bookingId,
10
+ checkoutBookingId: checkout.checkoutBookingId,
11
11
  expiresOn: checkout.expiresOn,
12
12
  aggregateId: checkout.id,
13
13
  domainEvents: [],
@@ -18,7 +18,7 @@ const toCheckoutProjection = (checkout) => ({
18
18
  status: checkout.status,
19
19
  customerId: checkout.customerId,
20
20
  boxId: checkout.boxId,
21
- bookingId: checkout.bookingId,
21
+ checkoutBookingId: checkout.checkoutBookingId,
22
22
  expiresOn: checkout.expiresOn,
23
23
  items: [],
24
24
  });
@@ -9,7 +9,7 @@ const toDomain = (checkout) => {
9
9
  status: checkout.status,
10
10
  customerId: checkout.customerId,
11
11
  boxId: checkout.boxId,
12
- bookingId: checkout.bookingId,
12
+ checkoutBookingId: checkout.checkoutBookingId,
13
13
  expiresOn: checkout.expiresOn,
14
14
  aggregateId: checkout.id,
15
15
  domainEvents: [],
@@ -1,6 +1,6 @@
1
1
  import { CommandStatus } from "@lookiero/messaging-react";
2
2
  interface MarkAsPaidFunction {
3
- (): void;
3
+ (): Promise<void>;
4
4
  }
5
5
  type UseMarkCheckoutAsPaid = [markAsPaid: MarkAsPaidFunction, status: CommandStatus];
6
6
  interface UseMarkCheckoutAsPaidFunctionArgs {
@@ -7,7 +7,7 @@ const useMarkCheckoutAsPaid = ({ checkoutId }) => {
7
7
  const [commandBus, status] = useCommand({ contextId: MESSAGING_CONTEXT_ID });
8
8
  const markAsPaid = useCallback(() => {
9
9
  invariant(checkoutId, "CheckoutId must be defined in order to mark the checkout as paid");
10
- commandBus(markCheckoutAsPaid({
10
+ return commandBus(markCheckoutAsPaid({
11
11
  aggregateId: checkoutId,
12
12
  }));
13
13
  }, [checkoutId, commandBus]);
@@ -1,14 +1,21 @@
1
1
  import invariant from "tiny-invariant";
2
2
  import { viewCheckoutBookingById, } from "../../../../projection/checkoutBooking/viewCheckoutBookingById";
3
+ import { httpCheckoutBookingsBlock } from "./httpCheckoutBookingsBlock";
3
4
  import { httpCheckoutBookingsBook } from "./httpCheckoutBookingsBook";
4
5
  const toDomain = (checkoutBooking) => {
5
6
  invariant(checkoutBooking, "No checkout booking found!");
6
7
  return {
7
- checkoutItemIds: checkoutBooking.checkoutItemIds,
8
8
  aggregateId: checkoutBooking.id,
9
+ checkoutItemIds: checkoutBooking.checkoutItemIds,
10
+ checkoutStatus: checkoutBooking.checkoutStatus,
9
11
  domainEvents: [],
10
12
  };
11
13
  };
12
14
  const getCheckoutBooking = ({ queryBus }) => async (aggregateId) => toDomain(await queryBus(viewCheckoutBookingById({ checkoutBookingId: aggregateId })));
13
- const saveCheckoutBooking = ({ httpPost }) => async (aggregateRoot) => await httpCheckoutBookingsBook({ httpPost })(aggregateRoot);
15
+ const saveCheckoutBooking = ({ httpPost }) => async (aggregateRoot) => {
16
+ await Promise.all([
17
+ httpCheckoutBookingsBook({ httpPost })(aggregateRoot),
18
+ httpCheckoutBookingsBlock({ httpPost })(aggregateRoot),
19
+ ]);
20
+ };
14
21
  export { getCheckoutBooking, saveCheckoutBooking };
@@ -0,0 +1,5 @@
1
+ import { HttpCheckoutBookingsSaveFunction } from "./httpCheckoutBookings";
2
+ interface HttpCheckoutBookingsBlockFunction extends HttpCheckoutBookingsSaveFunction {
3
+ }
4
+ declare const httpCheckoutBookingsBlock: HttpCheckoutBookingsBlockFunction;
5
+ export { httpCheckoutBookingsBlock };
@@ -0,0 +1,15 @@
1
+ import { CHECKOUT_BOOKING_BLOCKED, } from "../../../../domain/checkoutBooking/model/checkoutBookingBlocked";
2
+ const isCheckoutBookingBlocked = (event) => event.name === CHECKOUT_BOOKING_BLOCKED;
3
+ const httpCheckoutBookingsBlock = ({ httpPost }) => async ({ aggregateId, domainEvents }) => {
4
+ const checkoutBookingBlocked = domainEvents.find(isCheckoutBookingBlocked);
5
+ if (!checkoutBookingBlocked) {
6
+ return;
7
+ }
8
+ await httpPost({
9
+ endpoint: "/block-checkout-booking",
10
+ body: {
11
+ checkoutBookingId: aggregateId,
12
+ },
13
+ });
14
+ };
15
+ export { httpCheckoutBookingsBlock };
@@ -0,0 +1,13 @@
1
+ import { CommandStatus } from "@lookiero/messaging-react";
2
+ interface BlockCheckoutBookingFunction {
3
+ (): Promise<void>;
4
+ }
5
+ type UseBlockCheckoutBooking = [blockCheckoutBooking: BlockCheckoutBookingFunction, status: CommandStatus];
6
+ interface UseBlockCheckoutBookingFunctionArgs {
7
+ readonly checkoutBookingId: string;
8
+ }
9
+ interface UseBlockCheckoutBookingFunction {
10
+ (args: UseBlockCheckoutBookingFunctionArgs): UseBlockCheckoutBooking;
11
+ }
12
+ declare const useBlockCheckoutBooking: UseBlockCheckoutBookingFunction;
13
+ export { useBlockCheckoutBooking };
@@ -0,0 +1,12 @@
1
+ import { useCommand } from "@lookiero/messaging-react";
2
+ import { useCallback } from "react";
3
+ import { blockCheckoutBooking as blockCheckoutBookingCommand } from "../../../../domain/checkoutBooking/command/blockCheckoutBooking";
4
+ import { MESSAGING_CONTEXT_ID } from "../../../delivery/baseBootstrap";
5
+ const useBlockCheckoutBooking = ({ checkoutBookingId }) => {
6
+ const [commandBus, status] = useCommand({ contextId: MESSAGING_CONTEXT_ID });
7
+ const blockCheckoutBooking = useCallback(() => commandBus(blockCheckoutBookingCommand({
8
+ aggregateId: checkoutBookingId,
9
+ })), [checkoutBookingId, commandBus]);
10
+ return [blockCheckoutBooking, status];
11
+ };
12
+ export { useBlockCheckoutBooking };
@@ -0,0 +1,14 @@
1
+ import { CommandStatus } from "@lookiero/messaging-react";
2
+ interface BookFunction {
3
+ (): Promise<void>;
4
+ }
5
+ type UseBookCheckoutBookingForCheckoutItem = [book: BookFunction, status: CommandStatus];
6
+ interface UseBookCheckoutBookingForCheckoutItemFunctionArgs {
7
+ readonly checkoutItemId: string;
8
+ readonly checkoutBookingId: string | undefined;
9
+ }
10
+ interface UseBookCheckoutBookingForCheckoutItemFunction {
11
+ (args: UseBookCheckoutBookingForCheckoutItemFunctionArgs): UseBookCheckoutBookingForCheckoutItem;
12
+ }
13
+ declare const useBookCheckoutBookingForCheckoutItem: UseBookCheckoutBookingForCheckoutItemFunction;
14
+ export { useBookCheckoutBookingForCheckoutItem };
@@ -3,12 +3,12 @@ import { useCallback } from "react";
3
3
  import { v4 as uuid } from "uuid";
4
4
  import { bookCheckoutBookingForCheckoutItem } from "../../../../domain/checkoutBooking/command/bookCheckoutBookingForCheckoutItem";
5
5
  import { MESSAGING_CONTEXT_ID } from "../../../delivery/baseBootstrap";
6
- const useBookCheckouBookingForCheckoutItem = ({ checkoutItemId }) => {
6
+ const useBookCheckoutBookingForCheckoutItem = ({ checkoutItemId, checkoutBookingId, }) => {
7
7
  const [commandBus, status] = useCommand({ contextId: MESSAGING_CONTEXT_ID });
8
8
  const book = useCallback(() => commandBus(bookCheckoutBookingForCheckoutItem({
9
- aggregateId: uuid(),
9
+ aggregateId: checkoutBookingId || uuid(),
10
10
  checkoutItemId,
11
- })), [checkoutItemId, commandBus]);
11
+ })), [checkoutBookingId, checkoutItemId, commandBus]);
12
12
  return [book, status];
13
13
  };
14
- export { useBookCheckouBookingForCheckoutItem };
14
+ export { useBookCheckoutBookingForCheckoutItem };
@@ -10,7 +10,7 @@ const toDomain = (checkoutItem) => {
10
10
  status: checkoutItem.status,
11
11
  price: checkoutItem.price,
12
12
  feedbacks: checkoutItem.feedbacks,
13
- replacedFor: checkoutItem.replacedFor,
13
+ replacedForId: checkoutItem.replacedFor?.id,
14
14
  aggregateId: checkoutItem.id,
15
15
  domainEvents: [],
16
16
  };
@@ -1,13 +1,13 @@
1
1
  import { CHECKOUT_ITEM_REPLACED, } from "../../../../domain/checkoutItem/model/checkoutItemReplaced";
2
2
  const isCheckoutItemReplaced = (event) => event.name === CHECKOUT_ITEM_REPLACED;
3
- const httpCheckoutItemsReplace = ({ httpPost }) => async ({ aggregateId, replacedFor, domainEvents }) => {
3
+ const httpCheckoutItemsReplace = ({ httpPost }) => async ({ aggregateId, replacedForId, domainEvents }) => {
4
4
  const checkoutItemReplaced = domainEvents.find(isCheckoutItemReplaced);
5
5
  if (!checkoutItemReplaced) {
6
6
  return;
7
7
  }
8
8
  await httpPost({
9
9
  endpoint: "/replace-checkout-item",
10
- body: { checkoutItemId: aggregateId, replacedFor },
10
+ body: { checkoutItemId: aggregateId, replacedFor: replacedForId },
11
11
  });
12
12
  };
13
13
  export { httpCheckoutItemsReplace };
@@ -1,6 +1,6 @@
1
1
  import { CommandStatus } from "@lookiero/messaging-react";
2
2
  interface ReplaceCheckoutItemFunctionArgs {
3
- readonly replacedFor: string;
3
+ readonly replacedForId: string;
4
4
  }
5
5
  interface ReplaceCheckoutItemFunction {
6
6
  (args: ReplaceCheckoutItemFunctionArgs): Promise<void>;
@@ -4,9 +4,9 @@ import { replaceCheckoutItem } from "../../../../domain/checkoutItem/command/rep
4
4
  import { MESSAGING_CONTEXT_ID } from "../../../delivery/baseBootstrap";
5
5
  const useReplaceCheckoutItem = ({ checkoutItemId }) => {
6
6
  const [commandBus, status] = useCommand({ contextId: MESSAGING_CONTEXT_ID });
7
- const replace = useCallback(({ replacedFor }) => commandBus(replaceCheckoutItem({
7
+ const replace = useCallback(({ replacedForId }) => commandBus(replaceCheckoutItem({
8
8
  aggregateId: checkoutItemId,
9
- replacedFor,
9
+ replacedForId,
10
10
  })), [checkoutItemId, commandBus]);
11
11
  return [replace, status];
12
12
  };
@@ -1,6 +1,6 @@
1
1
  const httpBookedSizeChangeProductsVariantsForCheckoutItemView = ({ httpPost }) => async ({ checkoutItemId, signal }) => {
2
2
  const response = await httpPost({
3
- endpoint: "/view-booked-size-change-product-variants-for-checkout-item",
3
+ endpoint: "/view-booked-product-variants-for-checkout-item",
4
4
  body: { checkoutItemId },
5
5
  signal,
6
6
  });
@@ -5,7 +5,7 @@ interface CheckoutDto {
5
5
  readonly id: string;
6
6
  readonly customerId: string;
7
7
  readonly boxId: string;
8
- readonly bookingId: string;
8
+ readonly checkoutBookingId: string;
9
9
  readonly status: CheckoutStatus;
10
10
  readonly expiresOn: string;
11
11
  readonly items: CheckoutItemProjection[];
@@ -1,9 +1,12 @@
1
1
  import { useQuery } from "@lookiero/messaging-react";
2
+ import { CHECKOUT_FEEDBACK_GIVEN, } from "../../../../domain/checkoutFeedback/model/checkoutFeedbackGiven";
2
3
  import { viewIsCheckoutAccessibleByCustomerId, } from "../../../../projection/checkout/viewIsCheckoutAccessibleByCustomerId";
3
4
  import { MESSAGING_CONTEXT_ID } from "../../../delivery/baseBootstrap";
5
+ const isCheckoutFeedbackGiven = (event) => event.name === CHECKOUT_FEEDBACK_GIVEN;
4
6
  const useViewIsCheckoutAccessibleByCustomerId = ({ customerId }) => useQuery({
5
7
  query: viewIsCheckoutAccessibleByCustomerId({ customerId }),
6
8
  contextId: MESSAGING_CONTEXT_ID,
9
+ invalidation: isCheckoutFeedbackGiven,
7
10
  options: { staleTime: Infinity, retry: false, refetchOnWindowFocus: false },
8
11
  });
9
12
  export { useViewIsCheckoutAccessibleByCustomerId };
@@ -1,9 +1,17 @@
1
1
  import { useQuery } from "@lookiero/messaging-react";
2
+ import { CHECKOUT_ITEM_KEPT } from "../../../../domain/checkoutItem/model/checkoutItemKept";
3
+ import { CHECKOUT_ITEM_REPLACED, } from "../../../../domain/checkoutItem/model/checkoutItemReplaced";
4
+ import { CHECKOUT_ITEM_RETURNED, } from "../../../../domain/checkoutItem/model/checkoutItemReturned";
2
5
  import { viewPricingByCheckoutId } from "../../../../projection/pricing/viewPricingByCheckoutId";
3
6
  import { MESSAGING_CONTEXT_ID } from "../../../delivery/baseBootstrap";
7
+ const isCheckoutItemKept = (event) => event.name === CHECKOUT_ITEM_KEPT;
8
+ const isCheckoutItemReturned = (event) => event.name === CHECKOUT_ITEM_RETURNED;
9
+ const isCheckoutItemReplaced = (event) => event.name === CHECKOUT_ITEM_REPLACED;
10
+ const shouldInvalidate = (event) => isCheckoutItemKept(event) || isCheckoutItemReplaced(event) || isCheckoutItemReturned(event);
4
11
  const useViewPricingByCheckoutId = ({ checkoutId }) => useQuery({
5
12
  query: viewPricingByCheckoutId({ checkoutId }),
6
13
  contextId: MESSAGING_CONTEXT_ID,
7
- options: { staleTime: Infinity, retry: false, refetchOnWindowFocus: false },
14
+ invalidation: shouldInvalidate,
15
+ options: { staleTime: Infinity, retry: false, refetchOnWindowFocus: false, refetchOnMount: "always" },
8
16
  });
9
17
  export { useViewPricingByCheckoutId };
@@ -12,6 +12,7 @@ const CheckoutMiddleware = ({ customerId, loader = React.createElement(Spinner,
12
12
  const basePath = useBasePath();
13
13
  const introShown = useRef(false);
14
14
  const [shouldIntroBeShown, shouldIntroBeShownStatus] = useShouldIntroBeShown();
15
+ const navigatedToFirstItemWithoutCustomerDecision = useRef(false);
15
16
  const [checkout, checkoutStatus] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
16
17
  const firstItemWithoutCustomerDecision = checkout?.items.find((item) => [CheckoutItemStatus.EXPIRED, CheckoutItemStatus.INITIAL].includes(item.status));
17
18
  const introRouteMatch = useMatch(`${basePath}/${Routes.INTRO}`);
@@ -20,24 +21,20 @@ const CheckoutMiddleware = ({ customerId, loader = React.createElement(Spinner,
20
21
  const summaryRouteMatch = useMatch(`${basePath}/${Routes.SUMMARY}`);
21
22
  const checkoutRouteMatch = useMatch(`${basePath}/${Routes.CHECKOUT}`);
22
23
  const feedbackRouteMatch = useMatch(`${basePath}/${Routes.FEEDBACK}`);
23
- const notFoundRouteMatch = useMatch(`${basePath}/${Routes.NOT_FOUND}`);
24
24
  const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
25
25
  const dependenciesLoaded = dependenciesLoadedStatuses.includes(shouldIntroBeShownStatus) &&
26
- dependenciesLoadedStatuses.includes(checkoutStatus);
26
+ (dependenciesLoadedStatuses.includes(checkoutStatus) || checkout);
27
27
  if (!dependenciesLoaded) {
28
28
  return loader;
29
29
  }
30
- /* Navigate to NotFound if checkout is completed */
31
- if (checkout?.status === CheckoutStatus.COMPLETED && !notFoundRouteMatch) {
32
- return React.createElement(Navigate, { to: `${basePath}/${Routes.NOT_FOUND}`, replace: true });
33
- }
34
30
  /* Navigate to the feedback if checkout is paid */
35
- if (checkout?.status === CheckoutStatus.PAID && !feedbackRouteMatch) {
31
+ if (checkout?.status === CheckoutStatus.PAID && !(feedbackRouteMatch || checkoutRouteMatch)) {
36
32
  return React.createElement(Navigate, { to: `${basePath}/${Routes.FEEDBACK}`, replace: true });
37
33
  }
38
34
  /* Navigate to the summary if required */
39
- if (checkout?.status !== CheckoutStatus.PAID &&
40
- checkout?.status !== CheckoutStatus.COMPLETED &&
35
+ if ((checkout?.status === CheckoutStatus.AVAILABLE ||
36
+ checkout?.status === CheckoutStatus.STARTED ||
37
+ checkout?.status === CheckoutStatus.NOTIFIED) &&
41
38
  firstItemWithoutCustomerDecision === undefined &&
42
39
  !(summaryRouteMatch || itemDetailRouteMatch || checkoutRouteMatch)) {
43
40
  return React.createElement(Navigate, { to: `${basePath}/${Routes.SUMMARY}`, replace: true });
@@ -60,8 +57,11 @@ const CheckoutMiddleware = ({ customerId, loader = React.createElement(Spinner,
60
57
  }
61
58
  }
62
59
  /* Navigate to the first item without customer's decission */
63
- if (firstItemWithoutCustomerDecision && !itemRouteMatch) {
64
- console.log("navigate to first item...", firstItemWithoutCustomerDecision.id);
60
+ navigatedToFirstItemWithoutCustomerDecision.current =
61
+ navigatedToFirstItemWithoutCustomerDecision.current ||
62
+ Boolean(itemRouteMatch && itemRouteMatch.params.id === firstItemWithoutCustomerDecision?.id);
63
+ if (firstItemWithoutCustomerDecision && !navigatedToFirstItemWithoutCustomerDecision.current) {
64
+ navigatedToFirstItemWithoutCustomerDecision.current = true;
65
65
  return (React.createElement(Navigate, { to: generatePath(`${basePath}/${Routes.ITEM}`, { id: firstItemWithoutCustomerDecision.id }), replace: true }));
66
66
  }
67
67
  }
@@ -1,5 +1,6 @@
1
1
  declare const style: {
2
2
  body: {
3
+ minHeight: string;
3
4
  paddingTop: number;
4
5
  zIndex: number;
5
6
  };
@@ -3,6 +3,7 @@ import { theme } from "../theme/theme";
3
3
  const { spaceXXXL } = theme();
4
4
  const style = StyleSheet.create({
5
5
  body: {
6
+ minHeight: "100%",
6
7
  paddingTop: spaceXXXL,
7
8
  zIndex: 0,
8
9
  },
@@ -40,21 +40,21 @@ const Checkout = ({ customerId, getAuthToken, useRedirect }) => {
40
40
  });
41
41
  const [markAsPaid, markAsPaidStatus] = useMarkCheckoutAsPaid({ checkoutId: checkout?.id });
42
42
  const [createNotification] = useCreateNotification();
43
+ const [success, setSuccess] = useState(false);
43
44
  const [processingCheckout, setProcessingCheckout] = useState(false);
44
45
  const navigate = useNavigate();
45
46
  const basePath = useBasePath();
46
47
  const { returnUrl } = useRedirect();
47
48
  const handleOnSubmitCheckout = useCallback(() => {
48
- console.log("onSubmit checkout");
49
49
  if (!paymentFlowRef.current) {
50
50
  return;
51
51
  }
52
52
  setProcessingCheckout(true);
53
+ setSuccess(false);
53
54
  paymentFlowRef.current.startLegacyBoxCheckout(
54
55
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
55
56
  // @ts-ignore
56
- paymentFlowPayload, async ({ status, final, ...rest }) => {
57
- console.log("Checkout flow event", status, final, rest);
57
+ paymentFlowPayload, async ({ status, final }) => {
58
58
  if (status === ChargeStatus.REJECTED) {
59
59
  createNotification({ level: NotificationLevel.ERROR, bodyI18nKey: I18nMessages.CHECKOUT_TOAST_REJECTED });
60
60
  }
@@ -62,22 +62,30 @@ const Checkout = ({ customerId, getAuthToken, useRedirect }) => {
62
62
  createNotification({ level: NotificationLevel.ERROR, bodyI18nKey: I18nMessages.CHECKOUT_TOAST_ERROR });
63
63
  }
64
64
  else if (status === ChargeStatus.EXECUTED) {
65
- markAsPaid();
65
+ try {
66
+ await markAsPaid();
67
+ setSuccess(true);
68
+ }
69
+ catch (e) { }
66
70
  }
67
71
  if (final) {
68
72
  setProcessingCheckout(false);
69
73
  }
70
74
  });
71
75
  }, [createNotification, markAsPaid, paymentFlowPayload]);
72
- const handleOnSuccessModalDismiss = useCallback(() => navigate(`${basePath}/${Routes.FEEDBACK}`), [basePath, navigate]);
76
+ const handleOnSuccessModalDismiss = useCallback(() => {
77
+ setSuccess(false);
78
+ navigate(`${basePath}/${Routes.FEEDBACK}`);
79
+ }, [basePath, navigate]);
73
80
  const checkoutItemsKept = useMemo(() => checkout?.items.filter((checkoutItem) => checkoutItem.status === CheckoutItemStatus.KEPT || checkoutItem.status === CheckoutItemStatus.REPLACED), [checkout?.items]);
74
81
  const hasReplacedCheckoutItem = useMemo(() => checkout?.items.some((checkoutItem) => checkoutItem.status === CheckoutItemStatus.REPLACED), [checkout?.items]);
75
82
  const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
76
- const dependenciesLoaded = dependenciesLoadedStatuses.includes(checkoutStatus) && dependenciesLoadedStatuses.includes(pricingStatus);
83
+ const dependenciesLoaded = (dependenciesLoadedStatuses.includes(checkoutStatus) || checkout) &&
84
+ dependenciesLoadedStatuses.includes(pricingStatus);
77
85
  if (!dependenciesLoaded)
78
86
  return React.createElement(Spinner, null);
79
87
  return (React.createElement(React.Fragment, null,
80
- React.createElement(CheckoutSuccessModal, { visible: markAsPaidStatus === CommandStatus.SUCCESS, onDismiss: handleOnSuccessModalDismiss }),
88
+ React.createElement(CheckoutSuccessModal, { visible: success, onDismiss: handleOnSuccessModalDismiss }),
81
89
  React.createElement(SafeAreaScrollView, null,
82
90
  React.createElement(Body, { style: { column: style.bodyColumn } },
83
91
  hasReplacedCheckoutItem && (React.createElement(View, { style: style.deliveryBannerContainer },
@@ -17,7 +17,12 @@ const Feedback = ({ customerId }) => {
17
17
  const [giveCheckoutFeedback, giveCheckoutFeedbackStatus] = useGiveCheckoutFeedback({
18
18
  checkoutId: checkout?.id,
19
19
  });
20
- const handleOnSubmit = useCallback((feedbacks) => giveCheckoutFeedback({ feedbacks }), [giveCheckoutFeedback]);
20
+ const handleOnSubmit = useCallback(async (feedbacks) => {
21
+ try {
22
+ await giveCheckoutFeedback({ feedbacks });
23
+ }
24
+ catch (e) { }
25
+ }, [giveCheckoutFeedback]);
21
26
  const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
22
27
  const dependenciesLoaded = dependenciesLoadedStatuses.includes(checkoutStatus) && dependenciesLoadedStatuses.includes(checkoutQuestionsStatus);
23
28
  if (!dependenciesLoaded)
@@ -1,11 +1,11 @@
1
1
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
2
2
  import React, { useCallback, useEffect, useMemo, useState } from "react";
3
3
  import { View } from "react-native";
4
- import { useParams } from "react-router-native";
4
+ import { generatePath, useMatch, useNavigate, useParams } from "react-router-native";
5
5
  import { CheckoutItemStatus } from "../../../../domain/checkoutItem/model/checkoutItem";
6
6
  import "../../../../projection/checkout/viewFirstAvailableCheckoutByCustomerId";
7
7
  import { Spinner } from "../../../../shared/ui/components/atoms/spinner/Spinner";
8
- import { useBookCheckouBookingForCheckoutItem } from "../../../domain/checkoutBooking/react/useBookCheckouBookingForCheckoutItem";
8
+ import { useBookCheckoutBookingForCheckoutItem } from "../../../domain/checkoutBooking/react/useBookCheckoutBookingForCheckoutItem";
9
9
  import { useKeepCheckoutItem } from "../../../domain/checkoutItem/react/useKeepCheckoutItem";
10
10
  import { useReplaceCheckoutItem } from "../../../domain/checkoutItem/react/useReplaceCheckoutItem";
11
11
  import { useReturnCheckoutItem } from "../../../domain/checkoutItem/react/useReturnCheckoutItem";
@@ -15,6 +15,8 @@ import { useListReturnQuestionsByCheckoutItemId } from "../../../projection/retu
15
15
  import { Body } from "../../components/layouts/body/Body";
16
16
  import { ReturnQuestionFeedbackProvider } from "../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
17
17
  import { SafeAreaScrollView } from "../../components/templates/SafeAreaScrollView";
18
+ import { Routes } from "../../routing/routes";
19
+ import { useBasePath } from "../../routing/useBasePath";
18
20
  import { style } from "./Item.style";
19
21
  import { CustomerDecissionBanner } from "./components/banner/CustomerDecissionBanner";
20
22
  import { ItemActions } from "./components/itemActions/ItemActions";
@@ -28,60 +30,102 @@ const Item = ({ customerId }) => {
28
30
  const { id } = useParams();
29
31
  const [checkout, checkoutStatus] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
30
32
  const checkoutItem = checkout?.items.find((checkoutItem) => checkoutItem.id === id);
31
- const [customerDecissionMade, setCustomerDecissionMade] = useState(() => checkoutItem.status === CheckoutItemStatus.INITIAL || checkoutItem.status === CheckoutItemStatus.EXPIRED);
32
- const handleOnBannerPress = useCallback(() => setCustomerDecissionMade(!customerDecissionMade), [customerDecissionMade]);
33
+ const basePath = useBasePath();
34
+ const itemRouteMatch = useMatch(`${basePath}/${Routes.ITEM}`);
35
+ const itemDetailRouteMatch = useMatch(`${basePath}/${Routes.ITEM_DETAIL}`);
36
+ const navigate = useNavigate();
37
+ const navigateToNextView = useCallback(() => {
38
+ if (itemRouteMatch) {
39
+ const nextItemWithoutCustomerDecision = checkout?.items
40
+ .filter((item) => item.id !== id)
41
+ .find((item) => [CheckoutItemStatus.EXPIRED, CheckoutItemStatus.INITIAL].includes(item.status));
42
+ if (nextItemWithoutCustomerDecision) {
43
+ navigate(generatePath(`${basePath}/${Routes.ITEM}`, { id: nextItemWithoutCustomerDecision.id }));
44
+ }
45
+ }
46
+ else if (itemDetailRouteMatch) {
47
+ navigate(`${basePath}/${Routes.SUMMARY}`);
48
+ }
49
+ }, [itemRouteMatch, itemDetailRouteMatch, checkout?.items, id, navigate, basePath]);
50
+ const [customerDecissionMade, setCustomerDecissionMade] = useState();
51
+ useEffect(() => {
52
+ setCustomerDecissionMade(checkoutItem.status !== CheckoutItemStatus.INITIAL && checkoutItem.status !== CheckoutItemStatus.EXPIRED);
53
+ }, [checkoutItem.status, id]);
54
+ const handleOnBannerPress = useCallback(() => setCustomerDecissionMade(false), []);
55
+ const [keepCheckoutItem, keepCheckoutItemStatus] = useKeepCheckoutItem({ checkoutItemId: checkoutItem.id });
56
+ const [returnCheckoutItem, returnCheckoutItemStatus] = useReturnCheckoutItem({
57
+ checkoutItemId: checkoutItem.id,
58
+ });
59
+ const [replaceCheckoutItem, replaceCheckoutItemStatus] = useReplaceCheckoutItem({
60
+ checkoutItemId: checkoutItem.id,
61
+ });
33
62
  const [sizeWithoutStockModalVisible, setSizeWithoutStockModalVisible] = useState(false);
34
63
  const handleOnShowSizeWithoutStockModal = useCallback(() => setSizeWithoutStockModalVisible(true), []);
35
64
  const handleOnHideSizeWithoutStockModal = useCallback(() => setSizeWithoutStockModalVisible(false), []);
36
65
  const [sizeChangeModalVisible, setSizeChangeModalVisible] = useState(false);
37
66
  const handleOnShowSizeChangeModal = useCallback(() => setSizeChangeModalVisible(true), []);
38
- const handleOnHideSizeChangeModal = useCallback(() => setSizeChangeModalVisible(false), []);
67
+ const handleOnHideSizeChangeModal = useCallback(() => {
68
+ setSizeChangeModalVisible(false);
69
+ if (replaceCheckoutItemStatus === CommandStatus.SUCCESS) {
70
+ navigateToNextView();
71
+ }
72
+ }, [navigateToNextView, replaceCheckoutItemStatus]);
39
73
  const [bookedSizeChangeProductsVariants, bookedSizeChangeProductsVariantsStatus] = useViewBookedSizeChangeProductsVariantsForCheckoutItem({
40
74
  checkoutItemId: checkoutItem.id,
41
75
  });
42
- const [bookCheckouBooking] = useBookCheckouBookingForCheckoutItem({
76
+ const [bookCheckoutBooking] = useBookCheckoutBookingForCheckoutItem({
43
77
  checkoutItemId: checkoutItem.id,
78
+ checkoutBookingId: checkout?.checkoutBookingId,
44
79
  });
45
80
  useEffect(() => {
46
- bookedSizeChangeProductsVariants === null && bookCheckouBooking();
47
- }, [bookCheckouBooking, bookedSizeChangeProductsVariants, bookedSizeChangeProductsVariants?.bookingId]);
81
+ checkout && bookedSizeChangeProductsVariants === null && bookCheckoutBooking();
82
+ }, [bookCheckoutBooking, bookedSizeChangeProductsVariants, checkout]);
48
83
  const [returnQuestions, returnQuestionsStatus] = useListReturnQuestionsByCheckoutItemId({
49
84
  checkoutItemId: checkoutItem.id,
50
85
  });
51
- const [keepCheckoutItem, keepCheckoutItemStatus] = useKeepCheckoutItem({ checkoutItemId: checkoutItem.id });
52
- const [returnCheckoutItem, returnCheckoutItemStatus] = useReturnCheckoutItem({
53
- checkoutItemId: checkoutItem.id,
54
- });
55
- const [replaceCheckoutItem, replaceCheckoutItemStatus] = useReplaceCheckoutItem({
56
- checkoutItemId: checkoutItem.id,
57
- });
58
86
  const [stickyHeight, setStickyHeight] = useState(0);
59
87
  const handleOnStickyLayout = useCallback(({ height }) => setStickyHeight(height), []);
60
88
  const [returnQuestionsVisible, setReturnQuestionsVisible] = useState(false);
61
89
  const handleOnShowReturnQuestions = useCallback(() => setReturnQuestionsVisible(true), []);
62
90
  const handleOnHideReturnQuestions = useCallback(() => setReturnQuestionsVisible(false), []);
63
91
  const handleOnEditFeedback = useCallback(() => handleOnShowReturnQuestions(), [handleOnShowReturnQuestions]);
64
- const handleOnSubmit = useCallback((feedbacks) => {
92
+ const handleOnSubmit = useCallback(async (feedbacks) => {
65
93
  handleOnHideReturnQuestions();
66
- returnCheckoutItem({ feedbacks });
67
- }, [handleOnHideReturnQuestions, returnCheckoutItem]);
68
- const handleOnReplace = useCallback((replacedFor) => {
69
- handleOnShowSizeChangeModal();
70
- replaceCheckoutItem({ replacedFor });
94
+ try {
95
+ await returnCheckoutItem({ feedbacks });
96
+ navigateToNextView();
97
+ }
98
+ catch (e) {
99
+ // TODO show an error Notification?
100
+ }
101
+ }, [handleOnHideReturnQuestions, navigateToNextView, returnCheckoutItem]);
102
+ const handleOnKeep = useCallback(async () => {
103
+ try {
104
+ await keepCheckoutItem();
105
+ navigateToNextView();
106
+ }
107
+ catch (e) {
108
+ // TODO show an error Notification?
109
+ }
110
+ }, [keepCheckoutItem, navigateToNextView]);
111
+ const handleOnReplace = useCallback(async (replacedForId) => {
112
+ try {
113
+ await replaceCheckoutItem({ replacedForId });
114
+ handleOnShowSizeChangeModal();
115
+ }
116
+ catch (e) {
117
+ // TODO show an error Notification?
118
+ }
71
119
  }, [handleOnShowSizeChangeModal, replaceCheckoutItem]);
72
120
  const handleOnReturn = useCallback(() => handleOnShowReturnQuestions(), [handleOnShowReturnQuestions]);
73
- const productVariantSelected = useMemo(() => checkoutItem.replacedFor
74
- ? bookedSizeChangeProductsVariants?.productVariants.find((productVariant) => productVariant.id === checkoutItem.replacedFor)
75
- : { id: checkoutItem.productVariant.id, size: checkoutItem.productVariant.size }, [
76
- bookedSizeChangeProductsVariants?.productVariants,
77
- checkoutItem.productVariant.id,
78
- checkoutItem.productVariant.size,
79
- checkoutItem.replacedFor,
80
- ]);
121
+ const productVariantSelected = useMemo(() => checkoutItem.status === CheckoutItemStatus.REPLACED && checkoutItem.replacedFor
122
+ ? { id: checkoutItem.replacedFor.id, size: checkoutItem.replacedFor.size }
123
+ : { id: checkoutItem.productVariant.id, size: checkoutItem.productVariant.size }, [checkoutItem.productVariant.id, checkoutItem.productVariant.size, checkoutItem.replacedFor, checkoutItem.status]);
81
124
  const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
82
125
  const dependenciesLoaded = dependenciesLoadedStatuses.includes(returnQuestionsStatus) &&
83
- dependenciesLoadedStatuses.includes(checkoutStatus) &&
84
- dependenciesLoadedStatuses.includes(bookedSizeChangeProductsVariantsStatus);
126
+ (dependenciesLoadedStatuses.includes(checkoutStatus) || checkout) &&
127
+ dependenciesLoadedStatuses.includes(bookedSizeChangeProductsVariantsStatus) &&
128
+ bookedSizeChangeProductsVariants;
85
129
  if (!dependenciesLoaded)
86
130
  return React.createElement(Spinner, null);
87
131
  const { price } = checkoutItem;
@@ -91,14 +135,14 @@ const Item = ({ customerId }) => {
91
135
  React.createElement(SizeChangeModal, { visible: sizeChangeModalVisible, onDismiss: handleOnHideSizeChangeModal }),
92
136
  React.createElement(SafeAreaScrollView, null,
93
137
  React.createElement(Body, null,
94
- !customerDecissionMade && (React.createElement(CustomerDecissionBanner, { checkoutItemStatus: checkoutItem.status, onPress: handleOnBannerPress })),
138
+ customerDecissionMade && (React.createElement(CustomerDecissionBanner, { checkoutItemStatus: checkoutItem.status, onPress: handleOnBannerPress })),
95
139
  React.createElement(View, { style: [style.container, { paddingBottom: stickyHeight }] },
96
140
  React.createElement(View, { style: style.sliderContainer },
97
141
  React.createElement(ProductVariantSlider, { producVariantMedia: media })),
98
142
  React.createElement(ProductVariantDescription, { brand: brand, color: color, name: name, price: price, size: productVariantSelected.size }),
99
143
  checkoutItem.status === CheckoutItemStatus.RETURNED && (React.createElement(View, { style: style.feedbackContainer },
100
144
  React.createElement(ReturnQuestionsFeedback, { returnQuestions: returnQuestions || [], onEditFeedback: handleOnEditFeedback })))))),
101
- customerDecissionMade && (React.createElement(ItemActions, { keepButtonLoading: keepCheckoutItemStatus === CommandStatus.LOADING, productVariantSelected: productVariantSelected, productVariants: bookedSizeChangeProductsVariants?.productVariants || [], returnButtonLoading: returnCheckoutItemStatus === CommandStatus.LOADING, sizeSelectorDisabled: replaceCheckoutItemStatus === CommandStatus.LOADING, onKeep: keepCheckoutItem, onLayout: handleOnStickyLayout, onReplace: handleOnReplace, onReturn: handleOnReturn, onSizeSelectorPress: handleOnShowSizeWithoutStockModal })),
145
+ !customerDecissionMade && (React.createElement(ItemActions, { keepButtonLoading: keepCheckoutItemStatus === CommandStatus.LOADING, productVariantSelected: productVariantSelected, productVariants: bookedSizeChangeProductsVariants?.productVariants || [], returnButtonLoading: returnCheckoutItemStatus === CommandStatus.LOADING, sizeSelectorDisabled: replaceCheckoutItemStatus === CommandStatus.LOADING, onKeep: handleOnKeep, onLayout: handleOnStickyLayout, onReplace: handleOnReplace, onReturn: handleOnReturn, onSizeSelectorPress: handleOnShowSizeWithoutStockModal })),
102
146
  React.createElement(ReturnQuestionsForm, { checkoutItemPrice: checkoutItem.price, productVariant: checkoutItem.productVariant, returnQuestions: returnQuestions || [], visible: returnQuestionsVisible, onClose: handleOnHideReturnQuestions, onSubmit: handleOnSubmit })));
103
147
  };
104
148
  export { Item };
@@ -2,12 +2,13 @@ import { Text } from "@lookiero/aurora-next/build/components/primitives/Text/Tex
2
2
  import { useI18nMessage } from "@lookiero/i18n-react";
3
3
  import React, { useCallback } from "react";
4
4
  import { View } from "react-native";
5
+ import { CheckoutItemStatus } from "../../../../../../domain/checkoutItem/model/checkoutItem";
5
6
  import { Tabs } from "../../../../components/layouts/tabs/Tabs";
6
7
  import { I18nMessages } from "../../../../i18n/i18n";
7
8
  import { ProductVariant } from "../../../item/components/productVariant/ProductVariant";
8
9
  import { style } from "./CheckoutItemsTabs.style";
9
- const CheckoutItem = ({ checkoutItem, discarded = false, testID, style: customStyle, onPress, }) => (React.createElement(View, { style: style.checkoutItem, testID: testID },
10
- React.createElement(ProductVariant, { brand: checkoutItem.productVariant.brand, color: checkoutItem.productVariant.color, discarded: discarded, media: checkoutItem.productVariant.media, name: checkoutItem.productVariant.name, price: checkoutItem.price, size: checkoutItem.productVariant.size, status: checkoutItem.status, style: customStyle, onPress: onPress })));
10
+ const CheckoutItem = ({ checkoutItemStatus, checkoutItemProductVariant, checkoutItemPrice, discarded = false, testID, style: customStyle, onPress, }) => (React.createElement(View, { style: style.checkoutItem, testID: testID },
11
+ React.createElement(ProductVariant, { brand: checkoutItemProductVariant.brand, color: checkoutItemProductVariant.color, discarded: discarded, media: checkoutItemProductVariant.media, name: checkoutItemProductVariant.name, price: checkoutItemPrice, size: checkoutItemProductVariant.size, status: checkoutItemStatus, style: customStyle, onPress: onPress })));
11
12
  const CheckoutItemsTabs = ({ checkoutItemsKept, checkoutItemsReturned, onPressItem }) => {
12
13
  const keepTabText = useI18nMessage({ id: I18nMessages.SUMMARY_KEEP_TAB });
13
14
  const returnTabText = useI18nMessage({ id: I18nMessages.SUMMARY_RETURN_TAB });
@@ -15,7 +16,9 @@ const CheckoutItemsTabs = ({ checkoutItemsKept, checkoutItemsReturned, onPressIt
15
16
  const returnEmptyText = useI18nMessage({ id: I18nMessages.SUMMARY_RETURN_EMPTY });
16
17
  const handleOnPressItem = useCallback((checkoutItemId) => onPressItem(checkoutItemId), [onPressItem]);
17
18
  return (React.createElement(Tabs, { style: { sliderContainer: style.sliderContainer }, tabLabels: [`${keepTabText} (${checkoutItemsKept.length})`, `${returnTabText} (${checkoutItemsReturned.length})`] },
18
- React.createElement(React.Fragment, null, checkoutItemsKept.length === 0 ? (React.createElement(Text, null, keepEmptyText)) : (checkoutItemsKept.map((checkoutItem) => (React.createElement(CheckoutItem, { key: checkoutItem.id, checkoutItem: checkoutItem, testID: "keep-checkout-item", onPress: () => handleOnPressItem(checkoutItem.id) }))))),
19
- React.createElement(React.Fragment, null, checkoutItemsReturned.length === 0 ? (React.createElement(Text, null, returnEmptyText)) : (checkoutItemsReturned.map((checkoutItem) => (React.createElement(CheckoutItem, { key: checkoutItem.id, checkoutItem: checkoutItem, style: { image: style.returnCheckoutItem }, testID: "return-checkout-item", discarded: true, onPress: () => handleOnPressItem(checkoutItem.id) })))))));
19
+ React.createElement(React.Fragment, null, checkoutItemsKept.length === 0 ? (React.createElement(Text, null, keepEmptyText)) : (checkoutItemsKept.map((checkoutItem) => (React.createElement(CheckoutItem, { key: checkoutItem.id, checkoutItemPrice: checkoutItem.price, checkoutItemStatus: checkoutItem.status, testID: "keep-checkout-item", checkoutItemProductVariant: checkoutItem.status === CheckoutItemStatus.REPLACED && checkoutItem.replacedFor
20
+ ? checkoutItem.replacedFor
21
+ : checkoutItem.productVariant, onPress: () => handleOnPressItem(checkoutItem.id) }))))),
22
+ React.createElement(React.Fragment, null, checkoutItemsReturned.length === 0 ? (React.createElement(Text, null, returnEmptyText)) : (checkoutItemsReturned.map((checkoutItem) => (React.createElement(CheckoutItem, { key: checkoutItem.id, checkoutItemPrice: checkoutItem.price, checkoutItemProductVariant: checkoutItem.productVariant, checkoutItemStatus: checkoutItem.status, style: { image: style.returnCheckoutItem }, testID: "return-checkout-item", discarded: true, onPress: () => handleOnPressItem(checkoutItem.id) })))))));
20
23
  };
21
24
  export { CheckoutItemsTabs };
@@ -44,9 +44,9 @@ const Pricing = ({ orderTotal, subtotal, balanceDiscount, discount, discountPerc
44
44
  React.createElement(Button, { busy: busy, small: true, onPress: onSubmit }, submitButtonText)))) : (React.createElement(animated.View, { style: { opacity: notCollapsedStyle.opacitiy } },
45
45
  React.createElement(Row, { text: `${subtotalText} ${totalCheckoutItemsKeptText}` },
46
46
  React.createElement(Price, { price: subtotal, variant: "subtotal" })),
47
- discount && (React.createElement(Row, { text: discountText },
47
+ discount && discount.amount !== 0 && (React.createElement(Row, { text: discountText },
48
48
  React.createElement(Price, { price: discount, variant: "subtotal" }))),
49
- balanceDiscount && (React.createElement(Row, { text: creditText },
49
+ balanceDiscount && balanceDiscount.amount !== 0 && (React.createElement(Row, { text: creditText },
50
50
  React.createElement(Price, { price: balanceDiscount, variant: "subtotal" }))),
51
51
  React.createElement(Row, { text: feeText }, isPSServiceFree ? (React.createElement(Text, { level: 3, style: style.uppercase, action: true }, freeText)) : (React.createElement(Price, { price: service.finalPrice, variant: "subtotal" }))),
52
52
  React.createElement(View, { style: style.divider }),
@@ -4,7 +4,6 @@ interface ProductVariantProjection {
4
4
  readonly size: SizeProjection;
5
5
  }
6
6
  interface BookedSizeChangeProductsVariantsProjection {
7
- readonly bookingId: string;
8
7
  readonly productVariants: ProductVariantProjection[];
9
8
  }
10
9
  export type { BookedSizeChangeProductsVariantsProjection, ProductVariantProjection };
@@ -4,7 +4,7 @@ interface CheckoutProjection {
4
4
  readonly id: string;
5
5
  readonly customerId: string;
6
6
  readonly boxId: string;
7
- readonly bookingId: string;
7
+ readonly checkoutBookingId: string;
8
8
  readonly status: CheckoutStatus;
9
9
  readonly expiresOn: Date;
10
10
  readonly items: CheckoutItemProjection[];
@@ -1,5 +1,7 @@
1
+ import { CheckoutStatus } from "../../domain/checkout/model/checkout";
1
2
  interface CheckoutBookingProjection {
2
3
  readonly id: string;
3
4
  readonly checkoutItemIds: string[];
5
+ readonly checkoutStatus: CheckoutStatus;
4
6
  }
5
7
  export type { CheckoutBookingProjection };
@@ -37,7 +37,7 @@ interface CheckoutItemProjection {
37
37
  readonly id: string;
38
38
  readonly status: CheckoutItemStatus;
39
39
  readonly price: PriceProjection;
40
- readonly replacedFor?: string;
40
+ readonly replacedFor: CheckoutItemProductVariantProjection | null;
41
41
  readonly productVariant: CheckoutItemProductVariantProjection;
42
42
  readonly feedbacks: FeedbackProjection;
43
43
  }
@@ -9,9 +9,9 @@ interface ServiceProjection {
9
9
  interface PricingProjection {
10
10
  readonly orderTotal: PriceProjection;
11
11
  readonly subtotal: PriceProjection;
12
- readonly balanceDiscount?: PriceProjection;
13
- readonly discount?: PriceProjection;
14
- readonly discountPercentage?: number;
12
+ readonly balanceDiscount: PriceProjection;
13
+ readonly discount: PriceProjection;
14
+ readonly discountPercentage: number;
15
15
  readonly service: ServiceProjection;
16
16
  }
17
17
  export type { PricingProjection, ServiceProjection };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookiero/checkout",
3
- "version": "0.4.0-beta.3",
3
+ "version": "0.4.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -1,13 +0,0 @@
1
- import { CommandStatus } from "@lookiero/messaging-react";
2
- interface BookFunction {
3
- (): Promise<void>;
4
- }
5
- type UseBookCheckouBookingForCheckoutItem = [book: BookFunction, status: CommandStatus];
6
- interface UseBookCheckouBookingForCheckoutItemFunctionArgs {
7
- readonly checkoutItemId: string;
8
- }
9
- interface UseBookCheckouBookingForCheckoutItemFunction {
10
- (args: UseBookCheckouBookingForCheckoutItemFunctionArgs): UseBookCheckouBookingForCheckoutItem;
11
- }
12
- declare const useBookCheckouBookingForCheckoutItem: UseBookCheckouBookingForCheckoutItemFunction;
13
- export { useBookCheckouBookingForCheckoutItem };