@almatar/smart-booking-dashboard 0.0.2-alpha.2 → 0.0.2-alpha.3

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 (50) hide show
  1. package/esm2022/lib/components/almatar-aside/aside.component.mjs +6 -7
  2. package/esm2022/lib/components/hotel-cancel/almatar-hotel-auto-cancellation.component.mjs +2 -2
  3. package/esm2022/lib/components/hotel-cancel/components/almatar-hotel-auto-cancellation-select-rooms/components/almatar-hotel-auto-cancellation-non-refundable-room/almatar-hotel-auto-cancellation-non-refundable-room.component.mjs +2 -2
  4. package/esm2022/lib/components/hotel-cancel/services/almatar-hotel-auto-cancellation-endpoints.service.mjs +13 -4
  5. package/esm2022/lib/components/reissue-dialog/reissue-dialog.component.mjs +135 -0
  6. package/esm2022/lib/components/reissue-dialog/reissue-upgrade.store.mjs +305 -0
  7. package/esm2022/lib/components/reissue-dialog/reissue.store.mjs +349 -0
  8. package/esm2022/lib/components/reissue-dialog/steps/reissue-date-step/reissue-date-step.component.mjs +45 -0
  9. package/esm2022/lib/components/reissue-dialog/steps/reissue-legs-step/reissue-legs-step.component.mjs +140 -0
  10. package/esm2022/lib/components/reissue-dialog/steps/reissue-notice/reissue-notice.component.mjs +16 -0
  11. package/esm2022/lib/components/reissue-dialog/steps/reissue-route-step/reissue-route-step.component.mjs +104 -0
  12. package/esm2022/lib/components/reissue-dialog/steps/reissue-service-step/reissue-service-step.component.mjs +44 -0
  13. package/esm2022/lib/components/reissue-dialog/steps/reissue-upgrade-confirm-step/reissue-upgrade-confirm-step.component.mjs +193 -0
  14. package/esm2022/lib/components/reissue-dialog/steps/reissue-upgrade-step/reissue-upgrade-step.component.mjs +88 -0
  15. package/esm2022/lib/components/workflow-actions/workflow-actions.component.mjs +5 -3
  16. package/esm2022/lib/config/dashboard.config.mjs +3 -1
  17. package/esm2022/lib/models/reissue.types.mjs +2 -0
  18. package/esm2022/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.mjs +9 -3
  19. package/esm2022/lib/services/reissue.service.mjs +142 -0
  20. package/esm2022/lib/services/toast.service.mjs +15 -7
  21. package/esm2022/lib/utils/reissue-format.mjs +64 -0
  22. package/esm2022/lib/utils/reissue-url.builder.mjs +314 -0
  23. package/esm2022/public-api.mjs +3 -1
  24. package/fesm2022/almatar-smart-booking-dashboard.mjs +1919 -25
  25. package/fesm2022/almatar-smart-booking-dashboard.mjs.map +1 -1
  26. package/lib/components/action-dialog/action-dialog.component.d.ts +1 -1
  27. package/lib/components/almatar-aside/aside.component.d.ts +1 -2
  28. package/lib/components/hotel-cancel/components/hotel-content/hotel-content.component.d.ts +1 -1
  29. package/lib/components/hotel-cancel/services/almatar-hotel-auto-cancellation-endpoints.service.d.ts +6 -0
  30. package/lib/components/reissue-dialog/reissue-dialog.component.d.ts +34 -0
  31. package/lib/components/reissue-dialog/reissue-upgrade.store.d.ts +96 -0
  32. package/lib/components/reissue-dialog/reissue.store.d.ts +124 -0
  33. package/lib/components/reissue-dialog/steps/reissue-date-step/reissue-date-step.component.d.ts +11 -0
  34. package/lib/components/reissue-dialog/steps/reissue-legs-step/reissue-legs-step.component.d.ts +16 -0
  35. package/lib/components/reissue-dialog/steps/reissue-notice/reissue-notice.component.d.ts +8 -0
  36. package/lib/components/reissue-dialog/steps/reissue-route-step/reissue-route-step.component.d.ts +21 -0
  37. package/lib/components/reissue-dialog/steps/reissue-service-step/reissue-service-step.component.d.ts +17 -0
  38. package/lib/components/reissue-dialog/steps/reissue-upgrade-confirm-step/reissue-upgrade-confirm-step.component.d.ts +28 -0
  39. package/lib/components/reissue-dialog/steps/reissue-upgrade-step/reissue-upgrade-step.component.d.ts +13 -0
  40. package/lib/components/result-panel/result-panel.component.d.ts +1 -1
  41. package/lib/components/workflow-actions/workflow-actions.component.d.ts +3 -1
  42. package/lib/config/dashboard.config.d.ts +29 -0
  43. package/lib/models/reissue.types.d.ts +147 -0
  44. package/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.d.ts +4 -1
  45. package/lib/services/reissue.service.d.ts +45 -0
  46. package/lib/services/toast.service.d.ts +14 -1
  47. package/lib/utils/reissue-format.d.ts +28 -0
  48. package/lib/utils/reissue-url.builder.d.ts +24 -0
  49. package/package.json +9 -7
  50. package/public-api.d.ts +5 -1
@@ -0,0 +1,147 @@
1
+ /** Services that end in a web search redirect. */
2
+ export type ReissueSearchService = 'change_date' | 'change_route';
3
+ export type ReissueServiceKey = ReissueSearchService | 'upgrade_class';
4
+ export type ReissueTripType = 'OneWay' | 'RoundTrip' | 'MultiCity';
5
+ export interface ReissueAirport {
6
+ id: string;
7
+ name: string;
8
+ city_name: string;
9
+ country_name: string;
10
+ type: 'airport' | 'city';
11
+ }
12
+ /** One leg of the original booking, normalized from `booking_info.leg_info`. */
13
+ export interface ReissueLeg {
14
+ legId: string;
15
+ direction: string;
16
+ originCode: string;
17
+ originName: string;
18
+ originCityName: string;
19
+ originCountryName: string;
20
+ destinationCode: string;
21
+ destinationName: string;
22
+ destinationCityName: string;
23
+ destinationCountryName: string;
24
+ /** Original departure, ISO-like string as the backend returns it. */
25
+ departure: string;
26
+ arrival: string;
27
+ airline: string;
28
+ /** Number of stops (layovers) on the leg. */
29
+ stops: number;
30
+ flightNo: string;
31
+ }
32
+ /** Everything the web search URL needs from the original booking. */
33
+ export interface ReissueBookingContext {
34
+ bookingId: string;
35
+ tripType: ReissueTripType;
36
+ legs: ReissueLeg[];
37
+ adults: number;
38
+ children: number;
39
+ infants: number;
40
+ cabinName: string;
41
+ cabinCode: string;
42
+ currency: string;
43
+ airlineCode: string;
44
+ flightNumber: string;
45
+ airlineName: string;
46
+ totalStops: number;
47
+ }
48
+ export interface ReissueLegAvailability {
49
+ legId: string;
50
+ available: boolean;
51
+ isWhatsapp?: boolean;
52
+ }
53
+ export interface ReissueAvailabilityResponse {
54
+ data?: {
55
+ legs?: ReissueLegAvailability[];
56
+ /** `false` = a round trip must be upgraded as a whole (the web's `allowCustomerToSelectSingleLeg`). Missing = allowed. */
57
+ allowCustomerToSelectSingleLeg?: boolean;
58
+ };
59
+ }
60
+ /** What the agent picked on the edit step. */
61
+ export interface ReissueSelection {
62
+ service: ReissueSearchService;
63
+ legs: ReissueLegChange[];
64
+ }
65
+ export interface ReissueLegChange {
66
+ legId: string;
67
+ /** change_date: new departure date, `YYYY-MM-DD`. */
68
+ departDate?: string;
69
+ /** change_route: new airports. */
70
+ origin?: ReissueAirport;
71
+ destination?: ReissueAirport;
72
+ }
73
+ export interface ReissueUpgradeOption {
74
+ /** Sent back to choose-flight (`ItineraryId` for booking scope, `legId` for leg scope). */
75
+ referenceKey: string;
76
+ code: string;
77
+ name: string;
78
+ providerType: string;
79
+ type?: string;
80
+ fareDetails?: {
81
+ totalAdditionalFare?: number;
82
+ };
83
+ priceDifference?: number;
84
+ }
85
+ export interface ReissueUpgradeExistingLeg {
86
+ legIndex?: number;
87
+ origin: string;
88
+ destination: string;
89
+ departureDateTime?: string;
90
+ airlineCode?: string;
91
+ flightNumber?: string;
92
+ class?: string;
93
+ bookingClass?: string;
94
+ fareBrand?: {
95
+ code?: string;
96
+ name?: string;
97
+ };
98
+ }
99
+ export interface ReissueUpgradeLeg {
100
+ legIndex: number;
101
+ origin?: string;
102
+ destination?: string;
103
+ options?: ReissueUpgradeOption[];
104
+ existingLeg: ReissueUpgradeExistingLeg;
105
+ }
106
+ export interface ReissueUpgradeOptionsResponse {
107
+ fareOptionScope?: 'leg' | 'booking';
108
+ /** scope `leg`: options per leg. */
109
+ legs?: ReissueUpgradeLeg[];
110
+ /** scope `booking`: options for the whole booking. */
111
+ options?: ReissueUpgradeOption[];
112
+ existingLegs?: ReissueUpgradeExistingLeg[];
113
+ originalLegs?: ReissueUpgradeExistingLeg[];
114
+ }
115
+ /** Body of `POST .../reissue/choose-flight/{bookingId}/{postBookingId}` (same shape the web sends for Upgrade Class). */
116
+ export interface ReissueChooseFlightRequest {
117
+ fareOptionScope: 'leg' | 'booking';
118
+ /** scope `booking`: the chosen itinerary. */
119
+ ItineraryId?: string;
120
+ /** scope `leg`: the chosen option per leg. */
121
+ onwardLeg?: {
122
+ legId: string;
123
+ providerType: string;
124
+ };
125
+ returnLeg?: {
126
+ legId: string;
127
+ providerType: string;
128
+ };
129
+ }
130
+ /** `data` of the choose-flight response (fields the web reads). */
131
+ export interface ReissueChooseFlightResponse {
132
+ itineraryAvailable?: boolean;
133
+ priceChanged?: boolean;
134
+ price?: number;
135
+ currency?: string;
136
+ }
137
+ /**
138
+ * Payment link of a reissue. There is no separate API: it comes from the cart of the post-booking
139
+ * (`GET /v2/manage-booking/flight/cart/{postBookingId}`), see `ReissueService.getPaymentLink`. The agent copies it and
140
+ * sends it to the customer; the dialog does not follow the payment afterwards.
141
+ */
142
+ export interface ReissuePaymentLink {
143
+ url: string;
144
+ amount: number;
145
+ currency: string;
146
+ expiresAt?: string;
147
+ }
@@ -3,14 +3,17 @@ import * as i0 from "@angular/core";
3
3
  export declare class SmartBookingDashboardComponent {
4
4
  private bookingService;
5
5
  private toast;
6
+ /** The Reissue button is shown for flights only, and only when the host enabled the feature. */
7
+ protected readonly reissueEnabled: boolean;
6
8
  product: import("@angular/core").WritableSignal<ProductType>;
7
9
  bookingId: import("@angular/core").WritableSignal<string>;
8
- bookingStatus: import("@angular/core").WritableSignal<"error" | "idle" | "loading" | "success">;
10
+ bookingStatus: import("@angular/core").WritableSignal<"error" | "success" | "idle" | "loading">;
9
11
  bookingData: import("@angular/core").WritableSignal<any>;
10
12
  cancelDialogOpen: import("@angular/core").WritableSignal<boolean>;
11
13
  hotelAutoCancelDialogOpen: import("@angular/core").WritableSignal<boolean>;
12
14
  actionDialogOpen: import("@angular/core").WritableSignal<boolean>;
13
15
  addNoteDialogOpen: import("@angular/core").WritableSignal<boolean>;
16
+ reissueDialogOpen: import("@angular/core").WritableSignal<boolean>;
14
17
  selectedActionKey: import("@angular/core").WritableSignal<string>;
15
18
  activeContextTab: import("@angular/core").WritableSignal<"notes" | "changes">;
16
19
  availableActions: import("@angular/core").Signal<import("../../models/action.types").ActionConfig[]>;
@@ -0,0 +1,45 @@
1
+ import { Observable } from 'rxjs';
2
+ import { ReissueAirport, ReissueAvailabilityResponse, ReissueBookingContext, ReissueChooseFlightRequest, ReissueChooseFlightResponse, ReissuePaymentLink, ReissueUpgradeOptionsResponse } from '../models/reissue.types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * Reissue APIs — the same endpoints the consumer web uses (the backend opens them for BO).
6
+ */
7
+ export declare class SbdReissueService {
8
+ private http;
9
+ private config;
10
+ private base;
11
+ private get headers();
12
+ /** `POST /v2/manage-booking/flight/create-post-booking/{bookingId}` -> `postBookingId`. */
13
+ createPostBooking(bookingId: string): Observable<string>;
14
+ /** `GET /v3/manage-booking/flight/reissue/availability/{bookingId}/{postBookingId}` -> `data.legs[]`. */
15
+ getAvailability(bookingId: string, postBookingId: string, ctx?: ReissueBookingContext): Observable<ReissueAvailabilityResponse>;
16
+ /**
17
+ * `POST /v3/manage-booking/flight/reissue/upgrade-class/{bookingId}/{postBookingId}` — same call (and body) the
18
+ * web makes to decide whether the "Upgrade Class" option is shown. Returns the unwrapped `data`.
19
+ */
20
+ getUpgradeClassOptions(bookingId: string, postBookingId: string, ctx: ReissueBookingContext): Observable<ReissueUpgradeOptionsResponse | null>;
21
+ /** Same rule as the web's `hasUpgradeOptions()`: at least one option in any section. */
22
+ hasUpgradeOptions(data: ReissueUpgradeOptionsResponse | null): boolean;
23
+ /**
24
+ * Airport picker for Change Route. Same typeahead endpoint the web and the backoffice already use
25
+ * (`StaticDataService.getAirports`) — no extra backend work needed. Response: `data[].items[].items[]`.
26
+ * An empty term makes no request (the dialog lists the booking's own airports meanwhile).
27
+ */
28
+ searchAirports(term: string): Observable<ReissueAirport[]>;
29
+ /**
30
+ * `POST /v3/manage-booking/flight/reissue/choose-flight/{bookingId}/{postBookingId}` — prices the chosen upgrade
31
+ * option. Same endpoint/body the web uses; response `data` carries `itineraryAvailable`, `priceChanged`, `price`, `currency`.
32
+ */
33
+ chooseFlight(bookingId: string, postBookingId: string, body: ReissueChooseFlightRequest): Observable<ReissueChooseFlightResponse>;
34
+ /** `POST /v2/manage-booking/flight/book-now` — places a zero-total reissue (no payment needed). */
35
+ bookNow(postBookingId: string): Observable<unknown>;
36
+ /**
37
+ * Payment link of a reissue with an amount to pay. There is no separate API: the backend puts the link in the
38
+ * cart of the post-booking (`GET /v2/manage-booking/flight/cart/{postBookingId}`, the call the web checkout reads).
39
+ * The name of the field is not final yet: the first of the names below that exists is used, and the call fails
40
+ * with a clear message when the cart has none.
41
+ */
42
+ getPaymentLink(postBookingId: string, amount?: number, currency?: string): Observable<ReissuePaymentLink>;
43
+ static ɵfac: i0.ɵɵFactoryDeclaration<SbdReissueService, never>;
44
+ static ɵprov: i0.ɵɵInjectableDeclaration<SbdReissueService>;
45
+ }
@@ -1,10 +1,23 @@
1
+ import { InjectionToken } from '@angular/core';
1
2
  import * as i0 from "@angular/core";
3
+ /**
4
+ * How the dashboard shows messages. The backoffice uses ngx-toastr (the default); a host that has its own toast
5
+ * system (e.g. Helix with PrimeNG's `MessageService`) provides this token and the dashboard uses it instead.
6
+ */
7
+ export interface SbdToastHandler {
8
+ success(message: string): void;
9
+ error(message: string): void;
10
+ info(message: string): void;
11
+ warning(message: string): void;
12
+ }
13
+ export declare const SBD_TOAST_HANDLER: InjectionToken<SbdToastHandler>;
2
14
  export declare class SbdToastService {
3
- private toastr;
15
+ private handler;
4
16
  success(msg: string): void;
5
17
  error(msg: string): void;
6
18
  info(msg: string): void;
7
19
  warning(msg: string): void;
20
+ private show;
8
21
  static ɵfac: i0.ɵɵFactoryDeclaration<SbdToastService, never>;
9
22
  static ɵprov: i0.ɵɵInjectableDeclaration<SbdToastService>;
10
23
  }
@@ -0,0 +1,28 @@
1
+ import { ReissueAirport, ReissueLeg } from '../models/reissue.types';
2
+ /** Today as `YYYY-MM-DD` in the agent's timezone (what `<input type="date">` compares against). */
3
+ export declare function todayIso(): string;
4
+ export declare function formatReissueDate(value: string): string;
5
+ /**
6
+ * Expiry of the payment link as epoch ms. The backend sends `YYYY-MM-DD HH:mm:ss` with no timezone, read as UTC (to
7
+ * be confirmed with the backend); a value that carries `Z` or an offset is read as it is. `null` when missing/invalid.
8
+ */
9
+ export declare function parseLinkExpiry(value?: string | null): number | null;
10
+ /** `mm:ss` (or `h:mm:ss` from one hour up) for a countdown. */
11
+ export declare function formatCountdown(ms: number): string;
12
+ export declare function legTitle(leg: ReissueLeg): string;
13
+ export declare function airportOf(id: string, name: string, city: string, country: string): ReissueAirport;
14
+ export declare const originAirport: (l: ReissueLeg) => ReissueAirport;
15
+ export declare const destinationAirport: (l: ReissueLeg) => ReissueAirport;
16
+ export declare const compareAirports: (a: ReissueAirport, b: ReissueAirport) => boolean;
17
+ export declare function formatMoney(amount: number, currency: string): string;
18
+ /** `21 Oct` — same short date the cancel dialog shows on a leg card. */
19
+ export declare function formatShortDate(value: string): string;
20
+ /** `01:55` straight from the `YYYY-MM-DDTHH:mm:ss` string (no timezone conversion). */
21
+ export declare function formatTime(value: string): string;
22
+ /**
23
+ * The leg already departed. The booking gives no timezone for `LegDepartureDateTime` (airport local time), so this
24
+ * compares with the agent's clock: it can be off by a few hours on the day of the flight, never by a day.
25
+ */
26
+ export declare function isLegFlown(leg: {
27
+ departure: string;
28
+ }): boolean;
@@ -0,0 +1,24 @@
1
+ import { ReissueBookingContext, ReissueSelection } from '../models/reissue.types';
2
+ /**
3
+ * Port of the web's `FlightManageBookingService.navigateToOnlineBooking()`
4
+ * (almatar-consumer-apps) — builds the query params of
5
+ * `/flights/manage-booking/list`, where the web continues the reissue
6
+ * (search -> view-price -> choose-flight -> payment).
7
+ * Keep the param names/values identical to the web.
8
+ */
9
+ export declare const REISSUE_WEB_PATH = "/flights/manage-booking/list/";
10
+ type Raw = any;
11
+ /**
12
+ * Normalizes the dashboard's `booking_info` (from `/v1/fcr/booking/information`)
13
+ * into what the URL builder needs. Reads defensively: any field missing in the
14
+ * BO response falls back to an empty value.
15
+ */
16
+ export declare function buildReissueBookingContext(bookingData: Raw, bookingId: string): ReissueBookingContext | null;
17
+ export declare function buildReissueSearchParams(rawCtx: ReissueBookingContext, selection: ReissueSelection, postBookingId: string): Record<string, string>;
18
+ export declare function buildReissueSearchUrl(webBaseUrl: string, ctx: ReissueBookingContext, selection: ReissueSelection, postBookingId: string): string;
19
+ /**
20
+ * Adds the host's auth parameters (for example its token) to the web link: in the query string, or in the `#fragment`
21
+ * (which browsers do not send to servers or in the Referer). Empty values are skipped.
22
+ */
23
+ export declare function appendAuthParams(url: string, params: Record<string, string>, where?: 'query' | 'hash'): string;
24
+ export {};
package/package.json CHANGED
@@ -1,16 +1,18 @@
1
1
  {
2
2
  "name": "@almatar/smart-booking-dashboard",
3
- "version": "0.0.2-alpha.2",
3
+ "version": "0.0.2-alpha.3",
4
4
  "description": "Almatar Smart Booking Dashboard (Angular library)",
5
5
  "peerDependencies": {
6
- "@angular/animations": "^18.0.0",
7
- "@angular/common": "^18.0.0",
8
- "@angular/core": "^18.0.0",
9
- "@angular/forms": "^18.0.0",
10
- "@angular/router": "^18.0.0",
6
+ "@angular/animations": "^18.0.0 || ^21.0.0",
7
+ "@angular/common": "^18.0.0 || ^21.0.0",
8
+ "@angular/core": "^18.0.0 || ^21.0.0",
9
+ "@angular/forms": "^18.0.0 || ^21.0.0",
10
+ "@angular/router": "^18.0.0 || ^21.0.0",
11
11
  "@ng-select/ng-select": "^13.7.0",
12
+ "@ngrx/store": "^18.0.0 || ^21.0.0",
13
+ "moment": "^2.29.0",
12
14
  "ngx-toastr": "^17.0.2",
13
- "primeng": "^14.1.2",
15
+ "primeng": "^14.1.2 || ^21.0.0",
14
16
  "rxjs": "^7.8.0"
15
17
  },
16
18
  "dependencies": {
package/public-api.d.ts CHANGED
@@ -2,4 +2,8 @@ export { SmartBookingDashboardComponent } from './lib/pages/smart-booking-dashbo
2
2
  export { smartBookingDashboardRoutes } from './lib/smart-booking-dashboard.routes';
3
3
  export { SmartBookingDashboardModule } from './lib/smart-booking-dashboard.module';
4
4
  export { SBD_CONFIG, SBD_DEFAULT_CONFIG, provideSmartBookingDashboard } from './lib/config/dashboard.config';
5
- export type { SbdConfig } from './lib/config/dashboard.config';
5
+ export type { SbdConfig, SbdRedirectAuthParams } from './lib/config/dashboard.config';
6
+ export { buildReissueSearchUrl, buildReissueSearchParams, buildReissueBookingContext, appendAuthParams } from './lib/utils/reissue-url.builder';
7
+ export type * from './lib/models/reissue.types';
8
+ export { SBD_TOAST_HANDLER } from './lib/services/toast.service';
9
+ export type { SbdToastHandler } from './lib/services/toast.service';