@almatar/smart-booking-dashboard 0.0.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.
- package/LICENSE +21 -0
- package/README.md +132 -0
- package/esm2022/almatar-smart-booking-dashboard.mjs +5 -0
- package/esm2022/lib/components/action-card/action-card.component.mjs +19 -0
- package/esm2022/lib/components/action-dialog/action-dialog.component.mjs +177 -0
- package/esm2022/lib/components/action-grid/action-grid.component.mjs +18 -0
- package/esm2022/lib/components/add-note-dialog/add-note-dialog.component.mjs +62 -0
- package/esm2022/lib/components/booking-input/booking-input.component.mjs +43 -0
- package/esm2022/lib/components/cancel-dialog/cancel-dialog.component.mjs +1441 -0
- package/esm2022/lib/components/data-search/data-search.component.mjs +84 -0
- package/esm2022/lib/components/flight-itinerary-card/flight-itinerary-card.component.mjs +73 -0
- package/esm2022/lib/components/result-panel/result-panel.component.mjs +46 -0
- package/esm2022/lib/components/workflow-actions/workflow-actions.component.mjs +19 -0
- package/esm2022/lib/config/dashboard.config.mjs +16 -0
- package/esm2022/lib/config/flight-actions.config.mjs +906 -0
- package/esm2022/lib/config/hotel-actions.config.mjs +53 -0
- package/esm2022/lib/config/labels.ar.mjs +116 -0
- package/esm2022/lib/models/action.types.mjs +2 -0
- package/esm2022/lib/models/booking.types.mjs +2 -0
- package/esm2022/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.mjs +145 -0
- package/esm2022/lib/services/booking.service.mjs +65 -0
- package/esm2022/lib/services/toast.service.mjs +19 -0
- package/esm2022/lib/smart-booking-dashboard.module.mjs +17 -0
- package/esm2022/lib/smart-booking-dashboard.routes.mjs +7 -0
- package/esm2022/public-api.mjs +9 -0
- package/fesm2022/almatar-smart-booking-dashboard.mjs +3259 -0
- package/fesm2022/almatar-smart-booking-dashboard.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/action-card/action-card.component.d.ts +10 -0
- package/lib/components/action-dialog/action-dialog.component.d.ts +26 -0
- package/lib/components/action-grid/action-grid.component.d.ts +10 -0
- package/lib/components/add-note-dialog/add-note-dialog.component.d.ts +25 -0
- package/lib/components/booking-input/booking-input.component.d.ts +23 -0
- package/lib/components/cancel-dialog/cancel-dialog.component.d.ts +395 -0
- package/lib/components/data-search/data-search.component.d.ts +21 -0
- package/lib/components/flight-itinerary-card/flight-itinerary-card.component.d.ts +17 -0
- package/lib/components/result-panel/result-panel.component.d.ts +14 -0
- package/lib/components/workflow-actions/workflow-actions.component.d.ts +7 -0
- package/lib/config/dashboard.config.d.ts +15 -0
- package/lib/config/flight-actions.config.d.ts +2 -0
- package/lib/config/hotel-actions.config.d.ts +2 -0
- package/lib/config/labels.ar.d.ts +2 -0
- package/lib/models/action.types.d.ts +34 -0
- package/lib/models/booking.types.d.ts +6 -0
- package/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.d.ts +43 -0
- package/lib/services/booking.service.d.ts +22 -0
- package/lib/services/toast.service.d.ts +10 -0
- package/lib/smart-booking-dashboard.module.d.ts +7 -0
- package/lib/smart-booking-dashboard.routes.d.ts +2 -0
- package/package.json +50 -0
- package/public-api.d.ts +5 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ActionConfig } from '../../models/action.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class SbdActionCardComponent {
|
|
4
|
+
action: import("@angular/core").InputSignal<ActionConfig>;
|
|
5
|
+
active: import("@angular/core").InputSignal<boolean>;
|
|
6
|
+
loading: import("@angular/core").InputSignal<boolean>;
|
|
7
|
+
selected: import("@angular/core").OutputEmitterRef<string>;
|
|
8
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdActionCardComponent, never>;
|
|
9
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdActionCardComponent, "app-sbd-action-card", never, { "action": { "alias": "action"; "required": true; "isSignal": true; }; "active": { "alias": "active"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; }, { "selected": "selected"; }, never, never, true, never>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ActionConfig, ResultContent } from '../../models/action.types';
|
|
2
|
+
import { ProductType } from '../../models/booking.types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class SbdActionDialogComponent {
|
|
5
|
+
private bookingService;
|
|
6
|
+
private toast;
|
|
7
|
+
visible: import("@angular/core").InputSignal<boolean>;
|
|
8
|
+
bookingId: import("@angular/core").InputSignal<string>;
|
|
9
|
+
product: import("@angular/core").InputSignal<ProductType>;
|
|
10
|
+
actions: import("@angular/core").InputSignal<ActionConfig[]>;
|
|
11
|
+
initialKey: import("@angular/core").InputSignal<string>;
|
|
12
|
+
preloadedData: import("@angular/core").InputSignal<any>;
|
|
13
|
+
closed: import("@angular/core").OutputEmitterRef<void>;
|
|
14
|
+
selectedAction: import("@angular/core").WritableSignal<ActionConfig>;
|
|
15
|
+
actionStatus: import("@angular/core").WritableSignal<"error" | "idle" | "loading" | "success">;
|
|
16
|
+
actionData: import("@angular/core").WritableSignal<unknown>;
|
|
17
|
+
elapsedMs: import("@angular/core").WritableSignal<number>;
|
|
18
|
+
copying: import("@angular/core").WritableSignal<boolean>;
|
|
19
|
+
resultContent: import("@angular/core").Signal<ResultContent>;
|
|
20
|
+
constructor();
|
|
21
|
+
copyResult(mode: 'en' | 'ar' | 'both'): void;
|
|
22
|
+
private buildBilingualText;
|
|
23
|
+
onActionSelect(action: ActionConfig | null): void;
|
|
24
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdActionDialogComponent, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdActionDialogComponent, "app-sbd-action-dialog", never, { "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "bookingId": { "alias": "bookingId"; "required": false; "isSignal": true; }; "product": { "alias": "product"; "required": false; "isSignal": true; }; "actions": { "alias": "actions"; "required": false; "isSignal": true; }; "initialKey": { "alias": "initialKey"; "required": false; "isSignal": true; }; "preloadedData": { "alias": "preloadedData"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, never, true, never>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ActionConfig } from '../../models/action.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class SbdActionGridComponent {
|
|
4
|
+
actions: import("@angular/core").InputSignal<ActionConfig[]>;
|
|
5
|
+
activeKey: import("@angular/core").InputSignal<string>;
|
|
6
|
+
loadingKey: import("@angular/core").InputSignal<string>;
|
|
7
|
+
actionSelected: import("@angular/core").OutputEmitterRef<string>;
|
|
8
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdActionGridComponent, never>;
|
|
9
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdActionGridComponent, "app-sbd-action-grid", never, { "actions": { "alias": "actions"; "required": true; "isSignal": true; }; "activeKey": { "alias": "activeKey"; "required": false; "isSignal": true; }; "loadingKey": { "alias": "loadingKey"; "required": false; "isSignal": true; }; }, { "actionSelected": "actionSelected"; }, never, never, true, never>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ProductType } from '../../models/booking.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
type NoteAction = 'GENERAL' | 'FEEDBACK' | 'REMARK';
|
|
4
|
+
export declare class SbdAddNoteDialogComponent {
|
|
5
|
+
private bookingService;
|
|
6
|
+
private toast;
|
|
7
|
+
visible: import("@angular/core").InputSignal<boolean>;
|
|
8
|
+
bookingId: import("@angular/core").InputSignal<string>;
|
|
9
|
+
product: import("@angular/core").InputSignal<ProductType>;
|
|
10
|
+
closed: import("@angular/core").OutputEmitterRef<void>;
|
|
11
|
+
message: import("@angular/core").WritableSignal<string>;
|
|
12
|
+
action: import("@angular/core").WritableSignal<NoteAction>;
|
|
13
|
+
submitting: import("@angular/core").WritableSignal<boolean>;
|
|
14
|
+
readonly actionOptions: {
|
|
15
|
+
label: string;
|
|
16
|
+
value: NoteAction;
|
|
17
|
+
icon: string;
|
|
18
|
+
}[];
|
|
19
|
+
constructor();
|
|
20
|
+
submit(): void;
|
|
21
|
+
private reset;
|
|
22
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdAddNoteDialogComponent, never>;
|
|
23
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdAddNoteDialogComponent, "app-sbd-add-note-dialog", never, { "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "bookingId": { "alias": "bookingId"; "required": false; "isSignal": true; }; "product": { "alias": "product"; "required": false; "isSignal": true; }; }, { "closed": "closed"; }, never, never, true, never>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ProductType } from '../../models/booking.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
interface ProductOption {
|
|
4
|
+
label: string;
|
|
5
|
+
value: ProductType;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class SbdBookingInputComponent {
|
|
9
|
+
loading: import("@angular/core").InputSignal<boolean>;
|
|
10
|
+
product: import("@angular/core").ModelSignal<ProductType>;
|
|
11
|
+
bookingId: import("@angular/core").ModelSignal<string>;
|
|
12
|
+
lookup: import("@angular/core").OutputEmitterRef<void>;
|
|
13
|
+
readonly productOptions: ProductOption[];
|
|
14
|
+
readonly demoIds: {
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}[];
|
|
18
|
+
fillDemo(id: string): void;
|
|
19
|
+
onKeydown(event: KeyboardEvent): void;
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdBookingInputComponent, never>;
|
|
21
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdBookingInputComponent, "app-sbd-booking-input", never, { "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "product": { "alias": "product"; "required": false; "isSignal": true; }; "bookingId": { "alias": "bookingId"; "required": false; "isSignal": true; }; }, { "product": "productChange"; "bookingId": "bookingIdChange"; "lookup": "lookup"; }, never, never, true, never>;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
type LegSelection = 'onward' | 'return' | 'both';
|
|
3
|
+
type RefundData = any;
|
|
4
|
+
export declare class SbdCancelDialogComponent {
|
|
5
|
+
private bookingService;
|
|
6
|
+
private toast;
|
|
7
|
+
visible: import("@angular/core").InputSignal<boolean>;
|
|
8
|
+
bookingId: import("@angular/core").InputSignal<string>;
|
|
9
|
+
product: import("@angular/core").InputSignal<"flight" | "hotel">;
|
|
10
|
+
pnrInfo: import("@angular/core").InputSignal<{
|
|
11
|
+
pnr?: string;
|
|
12
|
+
LegDirectionality?: string;
|
|
13
|
+
}[]>;
|
|
14
|
+
/** Same `booking_info` payload the dashboard already fetches (getBooking(..., 'booking_info')) — reused here to render real route/time details on the select-leg cards, instead of a second API call. */
|
|
15
|
+
bookingInfo: import("@angular/core").InputSignal<any>;
|
|
16
|
+
closed: import("@angular/core").OutputEmitterRef<void>;
|
|
17
|
+
confirmed: import("@angular/core").OutputEmitterRef<LegSelection>;
|
|
18
|
+
/** Per-leg route/time details, mirroring app-sbd-flight-itinerary-card's mapping of booking_info.leg_info. */
|
|
19
|
+
itineraryLegs: import("@angular/core").Signal<any>;
|
|
20
|
+
/**
|
|
21
|
+
* The return leg is matched by an explicit 'Return' direction; the onward
|
|
22
|
+
* leg is whatever's left (some bookings don't tag the outbound leg with an
|
|
23
|
+
* explicit 'Departure' value), falling back to the first entry.
|
|
24
|
+
*/
|
|
25
|
+
itineraryLeg(kind: 'onward' | 'return'): any;
|
|
26
|
+
fmtTime(dt: string): string;
|
|
27
|
+
fmtShortDate(dt: string): string;
|
|
28
|
+
fmtMins(mins: number | null): string;
|
|
29
|
+
refundData: import("@angular/core").WritableSignal<any>;
|
|
30
|
+
cancelResult: import("@angular/core").WritableSignal<any>;
|
|
31
|
+
loading: import("@angular/core").WritableSignal<boolean>;
|
|
32
|
+
cancelling: import("@angular/core").WritableSignal<boolean>;
|
|
33
|
+
confirming: import("@angular/core").WritableSignal<boolean>;
|
|
34
|
+
/**
|
|
35
|
+
* 'select-leg' shown once the refund preview resolves, for round-trip
|
|
36
|
+
* bookings the backend hasn't already restricted to a single leg — mirrors
|
|
37
|
+
* almatar-b2c's select-leg screen. Skipped straight to 'details' otherwise.
|
|
38
|
+
*/
|
|
39
|
+
step: import("@angular/core").WritableSignal<"loading" | "select-leg" | "details">;
|
|
40
|
+
/** Per-leg inclusion (checkbox) and expand/collapse state — round-trip only. */
|
|
41
|
+
onwardChecked: import("@angular/core").WritableSignal<boolean>;
|
|
42
|
+
returnChecked: import("@angular/core").WritableSignal<boolean>;
|
|
43
|
+
onwardExpanded: import("@angular/core").WritableSignal<boolean>;
|
|
44
|
+
returnExpanded: import("@angular/core").WritableSignal<boolean>;
|
|
45
|
+
selectedSource: import("@angular/core").WritableSignal<string>;
|
|
46
|
+
cancelHint: import("@angular/core").WritableSignal<string>;
|
|
47
|
+
paidSummaryExpanded: import("@angular/core").WritableSignal<boolean>;
|
|
48
|
+
preferredRefundMethod: import("@angular/core").WritableSignal<"wallet" | "originalPaymentMethod" | "split">;
|
|
49
|
+
private readonly CANCEL_HINTS;
|
|
50
|
+
private hintTimer;
|
|
51
|
+
hasOnward: import("@angular/core").Signal<boolean>;
|
|
52
|
+
hasReturn: import("@angular/core").Signal<boolean>;
|
|
53
|
+
isRoundTrip: import("@angular/core").Signal<boolean>;
|
|
54
|
+
/** Which leg(s) the backend allows cancelling, from the refund preview response. */
|
|
55
|
+
legDirectionality: import("@angular/core").Signal<"ONWARD" | "RETURN" | "BOTH">;
|
|
56
|
+
/**
|
|
57
|
+
* Whether to render the round-trip "two leg cards" UI. Only when the
|
|
58
|
+
* backend explicitly allows cancelling both legs — otherwise (ONWARD-only /
|
|
59
|
+
* RETURN-only) show a single card for that leg, same as a one-way booking.
|
|
60
|
+
*/
|
|
61
|
+
showRoundTripLegCards: import("@angular/core").Signal<boolean>;
|
|
62
|
+
/** Derived from the per-leg checkboxes — 'both' unless exactly one is unchecked. */
|
|
63
|
+
selectedLeg: import("@angular/core").Signal<LegSelection>;
|
|
64
|
+
activeSourceBreakdown: import("@angular/core").Signal<Record<string, any>>;
|
|
65
|
+
availableSources: import("@angular/core").Signal<string[]>;
|
|
66
|
+
currentData: import("@angular/core").Signal<any>;
|
|
67
|
+
adjustedData: import("@angular/core").Signal<any>;
|
|
68
|
+
private applySourceOverride;
|
|
69
|
+
/**
|
|
70
|
+
* When exactly one of the four refund-destination fields (wallet / card /
|
|
71
|
+
* credit / loyalty) is non-zero, the backend has occasionally sent that
|
|
72
|
+
* field as a pre-deduction value that disagrees with the declared total
|
|
73
|
+
* (e.g. wallet = total + cancellation fee) — there's no ambiguity about
|
|
74
|
+
* *where* the money goes, only a stale number in that one field, so trust
|
|
75
|
+
* the declared total and correct the sole destination to match rather
|
|
76
|
+
* than surfacing a false discrepancy.
|
|
77
|
+
*/
|
|
78
|
+
private reconcileSoleDestination;
|
|
79
|
+
/**
|
|
80
|
+
* Per-leg refund view (independent of the checkbox inclusion state) — used
|
|
81
|
+
* to render both legs' own breakdown cards simultaneously.
|
|
82
|
+
*/
|
|
83
|
+
legAdjustedData(legType: 'onward' | 'return'): RefundData | null;
|
|
84
|
+
/** Deduction rows for a single leg's card. */
|
|
85
|
+
legDeductions(legType: 'onward' | 'return'): {
|
|
86
|
+
label: string;
|
|
87
|
+
value: number;
|
|
88
|
+
badge: string;
|
|
89
|
+
}[];
|
|
90
|
+
/**
|
|
91
|
+
* Refundable pool ("Fare") for a leg — that leg's own paid amount
|
|
92
|
+
* (`totalSupplierBookingAmount`). `totalRefundAmount + totalCancellationFee`
|
|
93
|
+
* isn't reliable: `totalCancellationFee` doesn't include every deduction
|
|
94
|
+
* (e.g. `handlingFee`), which produced a Fare that didn't reconcile with
|
|
95
|
+
* Total Refund + the shown deductions.
|
|
96
|
+
*/
|
|
97
|
+
legRefundPool(legType: 'onward' | 'return'): number;
|
|
98
|
+
/** True once a leg's own departure time has passed. */
|
|
99
|
+
legAlreadyFlown(legType: 'onward' | 'return'): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Non-CrossSeller airlines require the whole round-trip/multicity
|
|
102
|
+
* itinerary to be cancelled together — a leg can't be excluded on its own
|
|
103
|
+
* unless it has already flown (which naturally degrades to a one-way
|
|
104
|
+
* cancellation of just the remaining leg). Set when an uncheck attempt was
|
|
105
|
+
* blocked for this reason, so the leg's checkbox can be frozen (locked)
|
|
106
|
+
* and the note shown.
|
|
107
|
+
*/
|
|
108
|
+
forcedLegType: import("@angular/core").WritableSignal<"return" | "onward">;
|
|
109
|
+
/**
|
|
110
|
+
* Toggle a leg's inclusion. A non-refundable leg can't be checked, and the
|
|
111
|
+
* last checked leg can't be unchecked. Used on both the select-leg screen
|
|
112
|
+
* and the round-trip leg cards.
|
|
113
|
+
*/
|
|
114
|
+
toggleLeg(legType: 'onward' | 'return'): void;
|
|
115
|
+
/** Toggle a leg card's expanded/collapsed state. */
|
|
116
|
+
toggleLegExpanded(legType: 'onward' | 'return'): void;
|
|
117
|
+
sourceNonRefundableHint: import("@angular/core").Signal<string>;
|
|
118
|
+
deductions: import("@angular/core").Signal<{
|
|
119
|
+
label: string;
|
|
120
|
+
value: number;
|
|
121
|
+
badge: string;
|
|
122
|
+
}[]>;
|
|
123
|
+
/**
|
|
124
|
+
* Itemized refundable rows ("Fare" + named refundable add-ons/ancillaries)
|
|
125
|
+
* from `refundBreakdown.refundable`. Empty when the backend hasn't sent a
|
|
126
|
+
* breakdown yet — callers fall back to the single aggregate Fare row.
|
|
127
|
+
*/
|
|
128
|
+
refundableBreakdownRows(d: any): {
|
|
129
|
+
label: string;
|
|
130
|
+
value: number;
|
|
131
|
+
}[];
|
|
132
|
+
/** Named refundable add-ons/ancillaries only (excludes Fare) — drives the "processed separately" note. */
|
|
133
|
+
private refundableAddonItems;
|
|
134
|
+
/** Whether to show the "add-on refund processed separately by Customer Service" note. */
|
|
135
|
+
hasRefundableAddonNote(d: any): boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Deduction rows for the "Not Refunded" section. When an itemized
|
|
138
|
+
* breakdown is present, its named add-ons/ancillaries replace the
|
|
139
|
+
* aggregate `totalAncillaryRefundAmount`/`totalGiftAmount` rows (same
|
|
140
|
+
* money, named instead of lumped); the other generic rows (cancellation
|
|
141
|
+
* fee, handling fee, service charge) are unaffected.
|
|
142
|
+
*/
|
|
143
|
+
private deductionRows;
|
|
144
|
+
refunds: import("@angular/core").Signal<{
|
|
145
|
+
label: string;
|
|
146
|
+
value: number;
|
|
147
|
+
}[]>;
|
|
148
|
+
creditShellNote: import("@angular/core").Signal<string>;
|
|
149
|
+
private resolvePnr;
|
|
150
|
+
/**
|
|
151
|
+
* Booking includes a Golden Guarantee gift ("Cancel for any reason") —
|
|
152
|
+
* overrides all credit-shell handling below, since a Golden Guarantee
|
|
153
|
+
* cancellation always refunds 100% through the standard payment method
|
|
154
|
+
* rather than the airline credit shell. May be carried on either the
|
|
155
|
+
* preview (`refundData`) or the confirm (`cancelResult`) response — both
|
|
156
|
+
* share the same shape, and either one may set it independently of the
|
|
157
|
+
* other.
|
|
158
|
+
*/
|
|
159
|
+
hasGoldenGuaranteeGift: import("@angular/core").Signal<boolean>;
|
|
160
|
+
isCreditShell: import("@angular/core").Signal<boolean>;
|
|
161
|
+
/**
|
|
162
|
+
* Refundable ancillaries (baggage, seats, …) that carry their own
|
|
163
|
+
* `isCreditShell` flag, independent of the booking-level flag — rendered
|
|
164
|
+
* as individual cards on the credit-shell refund-method screen so each
|
|
165
|
+
* one can show either the credit-shell card style or the normal wallet
|
|
166
|
+
* card style (both include the same nested credit-shell note when true).
|
|
167
|
+
*/
|
|
168
|
+
creditShellAncillaryItems: import("@angular/core").Signal<any[]>;
|
|
169
|
+
creditShellSupplierName: import("@angular/core").Signal<string>;
|
|
170
|
+
refundTypeLabel: import("@angular/core").Signal<string>;
|
|
171
|
+
currency: import("@angular/core").Signal<string>;
|
|
172
|
+
discrepancyNote: import("@angular/core").Signal<string>;
|
|
173
|
+
/** Real per-booking CrossSeller flag from the refund preview — CrossSeller suppliers allow cancelling either leg independently. */
|
|
174
|
+
isCrossSeller: import("@angular/core").Signal<boolean>;
|
|
175
|
+
onwardRefundable: import("@angular/core").Signal<boolean>;
|
|
176
|
+
returnRefundable: import("@angular/core").Signal<boolean>;
|
|
177
|
+
isMixed: import("@angular/core").Signal<boolean>;
|
|
178
|
+
/** Both legs present and BOTH non-refundable — nothing can be refunded for this booking. */
|
|
179
|
+
allLegsNonRefundable: import("@angular/core").Signal<boolean>;
|
|
180
|
+
mixedHint: import("@angular/core").Signal<string>;
|
|
181
|
+
giftHint: import("@angular/core").Signal<string>;
|
|
182
|
+
selectionHint: import("@angular/core").Signal<string>;
|
|
183
|
+
confirmDeductions: import("@angular/core").Signal<{
|
|
184
|
+
label: string;
|
|
185
|
+
value: number;
|
|
186
|
+
}[]>;
|
|
187
|
+
confirmRefunds: import("@angular/core").Signal<{
|
|
188
|
+
key: string;
|
|
189
|
+
label: string;
|
|
190
|
+
value: number;
|
|
191
|
+
subRows?: {
|
|
192
|
+
label: string;
|
|
193
|
+
value: number;
|
|
194
|
+
}[];
|
|
195
|
+
hasLoyaltyNote?: boolean;
|
|
196
|
+
}[]>;
|
|
197
|
+
/** Rows that land in the wallet — plain wallet, wallet+loyalty combined, or loyalty-only — share the wallet icon/layout on the result screen. */
|
|
198
|
+
isWalletDestinationRow(r: {
|
|
199
|
+
key: string;
|
|
200
|
+
}): boolean;
|
|
201
|
+
/**
|
|
202
|
+
* The result screen's "issued as an Airline Credit Shell" note. Golden
|
|
203
|
+
* Guarantee overrides this to '' — the confirmation renders like a
|
|
204
|
+
* standard Sabre/Amadeus refund instead (see `confirmRefunds`' folding
|
|
205
|
+
* of any credit-shell amount into the normal payment-method row).
|
|
206
|
+
*/
|
|
207
|
+
confirmCreditShellNote: import("@angular/core").Signal<string>;
|
|
208
|
+
fmtResult(value: number): string;
|
|
209
|
+
/**
|
|
210
|
+
* The customer-facing total (ceiled) must match the pre-rounding total the
|
|
211
|
+
* refund is actually computed from — i.e. `totalRefundAmount` must be
|
|
212
|
+
* `totalRefundAmountBeforeCeil` rounded up to a whole currency unit (e.g.
|
|
213
|
+
* 1454.5 → 1455). A mismatch here means the supplier response itself is
|
|
214
|
+
* internally inconsistent and must block confirmation.
|
|
215
|
+
*/
|
|
216
|
+
refundReconciles: import("@angular/core").Signal<boolean>;
|
|
217
|
+
canConfirm: import("@angular/core").Signal<boolean>;
|
|
218
|
+
/**
|
|
219
|
+
* `totalLoyaltyPoints` is normally the forfeited-at-booking points count
|
|
220
|
+
* (no refund destination of its own). But when the backend never
|
|
221
|
+
* populates `totalLoyaltyPointsRefundAmount` for a `loyaltyPaymentType`
|
|
222
|
+
* booking, this is the only signal that a loyalty program was involved,
|
|
223
|
+
* so it doubles as a split-refund row (alongside Card/Wallet) rather than
|
|
224
|
+
* disappearing from the refund breakdown entirely. Always shown as its
|
|
225
|
+
* own row under the program name (e.g. "Wala") — never merged into the
|
|
226
|
+
* generic Wallet row, even when `walletRefundAmount` is also non-zero.
|
|
227
|
+
*/
|
|
228
|
+
private forfeitedLoyaltyPointsFallback;
|
|
229
|
+
/**
|
|
230
|
+
* Some `/confirm` responses for a single-leg (non-cross-seller) booking
|
|
231
|
+
* put `walletRefundAmount`/`totalLoyaltyPoints` on the wrong side at the
|
|
232
|
+
* root — e.g. root reads `walletRefundAmount: 40, totalLoyaltyPoints: 0`
|
|
233
|
+
* while the single leg (which should mirror root exactly here) reads
|
|
234
|
+
* `walletRefundAmount: 0, totalLoyaltyPoints: 40`. Detected narrowly: root
|
|
235
|
+
* shows no forfeited loyalty despite `loyaltyPaymentType` being set, the
|
|
236
|
+
* root wallet amount exactly equals the leg's loyalty points, and the
|
|
237
|
+
* leg's own wallet amount disagrees — in that specific case the leg's
|
|
238
|
+
* values are trusted instead, since with only one leg they're unambiguous.
|
|
239
|
+
*
|
|
240
|
+
* A second, more common shape: root doesn't swap at all, it folds the
|
|
241
|
+
* points straight into `walletRefundAmount` as one opaque lump sum (e.g.
|
|
242
|
+
* root wallet 340 = the leg's own cash wallet 300 + the leg's forfeited
|
|
243
|
+
* loyalty points 40). Split that back into the two parts the leg already
|
|
244
|
+
* tells us about too, so the result screen can show a combined wallet card
|
|
245
|
+
* with the program named instead of one unexplained total.
|
|
246
|
+
*/
|
|
247
|
+
private correctedConfirmWalletAndLoyalty;
|
|
248
|
+
/** How many of {wallet, card, loyalty} the refund is actually split across. */
|
|
249
|
+
private splitPartsCount;
|
|
250
|
+
/**
|
|
251
|
+
* A portion of the refund is forced to the wallet (e.g. loyalty points used)
|
|
252
|
+
* — in that case offer a "Split Refund" option instead of a pure
|
|
253
|
+
* original-payment-method option, since the whole amount can't go to card.
|
|
254
|
+
*/
|
|
255
|
+
hasSplitRefund: import("@angular/core").Signal<boolean>;
|
|
256
|
+
/**
|
|
257
|
+
* Wallet covers the whole refund (no card or loyalty portion at all) — show
|
|
258
|
+
* the wallet option alone rather than a "split" with empty other sides.
|
|
259
|
+
*/
|
|
260
|
+
isWalletOnlyRefund: import("@angular/core").Signal<boolean>;
|
|
261
|
+
/**
|
|
262
|
+
* The entire refund is forfeited loyalty points (e.g. Wala) landing back as
|
|
263
|
+
* wallet balance — no cash-wallet, card, credit or real
|
|
264
|
+
* loyalty-points-refund portion at all. Without this the picker falls
|
|
265
|
+
* through to the "Original Payment Method" card and mislabels the
|
|
266
|
+
* destination as the original gateway (e.g. "Tabby"), even though
|
|
267
|
+
* `totalCardRefundAmount` is 0 and nothing goes back to that card.
|
|
268
|
+
*/
|
|
269
|
+
isLoyaltyOnlyRefund: import("@angular/core").Signal<boolean>;
|
|
270
|
+
/** A real cash-wallet portion is part of the refund (distinct from forfeited loyalty points landing in the wallet). */
|
|
271
|
+
hasCashWalletRefund: import("@angular/core").Signal<boolean>;
|
|
272
|
+
/**
|
|
273
|
+
* Wallet card's title — normally "Almatar Wallet", but the loyalty program
|
|
274
|
+
* name (Wala, Qitaf, …) when the whole refund is that program's forfeited
|
|
275
|
+
* balance landing back in the wallet.
|
|
276
|
+
*/
|
|
277
|
+
walletCardLabel: import("@angular/core").Signal<string>;
|
|
278
|
+
/**
|
|
279
|
+
* Part of the refund came from converting external loyalty points into
|
|
280
|
+
* wallet funds — surfaced as a note under the wallet destination so the
|
|
281
|
+
* agent knows those points land as permanent wallet balance, not cash.
|
|
282
|
+
*/
|
|
283
|
+
hasLoyaltyPointsRefund: import("@angular/core").Signal<boolean>;
|
|
284
|
+
/**
|
|
285
|
+
* The booking is refundable but nets to 0.00 after deductions — a
|
|
286
|
+
* dedicated NIL Refund state, distinct from "not refundable": no refund
|
|
287
|
+
* method to choose between, just confirmation that nothing is owed back.
|
|
288
|
+
*/
|
|
289
|
+
isNilRefund: import("@angular/core").Signal<boolean>;
|
|
290
|
+
/** Same as `isNilRefund`, scoped to the confirmed cancellation result — drives the result screen's title. */
|
|
291
|
+
confirmIsNilRefund: import("@angular/core").Signal<boolean>;
|
|
292
|
+
/** Whether the customer may send the whole refund to their Almatar Wallet. */
|
|
293
|
+
isFullWalletRefundAllowed: import("@angular/core").Signal<boolean>;
|
|
294
|
+
/** Whether the customer paid via an installment gateway (Tamara, Tabby, …). */
|
|
295
|
+
isInstallmentMethod: import("@angular/core").Signal<boolean>;
|
|
296
|
+
/** Whether the customer paid via a loyalty-program gateway (Al Rajhi Mokafaa, …). */
|
|
297
|
+
isLoyaltyMethod: import("@angular/core").Signal<boolean>;
|
|
298
|
+
/** Any gateway that refunds somewhere other than a plain card — used for the wallet-style icon. */
|
|
299
|
+
isSpecialGatewayMethod: import("@angular/core").Signal<boolean>;
|
|
300
|
+
/**
|
|
301
|
+
* Card-refund settlement-timeline badge — Tabby and Tamara each have their
|
|
302
|
+
* own processing window, distinct from a plain card's generic bank policy.
|
|
303
|
+
*/
|
|
304
|
+
cardBadgeText: import("@angular/core").Signal<"From 5-7 business days" | "Up to 10 business days" | "Loyalty Program Policy" | "Up to 15 business days, bank policy">;
|
|
305
|
+
/** Same as `cardBadgeText`, scoped to the confirmed cancellation result. */
|
|
306
|
+
confirmCardBadgeText: import("@angular/core").Signal<"From 5-7 business days" | "Up to 10 business days" | "Loyalty Program Policy" | "Up to 15 business days, bank policy">;
|
|
307
|
+
/**
|
|
308
|
+
* Per-method breakdown of the "Total paid" amount. The backend doesn't
|
|
309
|
+
* (yet) expose a dedicated original-payment breakdown, so the known
|
|
310
|
+
* refund-destination fields (card / wallet / loyalty) are used as a proxy
|
|
311
|
+
* for how the booking was originally paid, and whatever's left over after
|
|
312
|
+
* those (e.g. a non-refundable leg/fee that never shows up in any refund
|
|
313
|
+
* field) is folded into the primary payment method — so the rows always
|
|
314
|
+
* add up to the full `originalAmount` shown above them, instead of only
|
|
315
|
+
* covering the refundable portion.
|
|
316
|
+
*/
|
|
317
|
+
paidBreakdownRows: import("@angular/core").Signal<{
|
|
318
|
+
label: string;
|
|
319
|
+
value: number;
|
|
320
|
+
}[]>;
|
|
321
|
+
/** The "Total paid" row always expands — there's always at least one method to show. */
|
|
322
|
+
hasPaidBreakdown: import("@angular/core").Signal<boolean>;
|
|
323
|
+
togglePaidSummary(): void;
|
|
324
|
+
/**
|
|
325
|
+
* The backend has sent `paymentMethodCustomerUsed` as both a short code
|
|
326
|
+
* (`"CH"`) and a full gateway name (`"Card"`) at different times — match
|
|
327
|
+
* either, case-insensitively, against the known codes/labels rather than
|
|
328
|
+
* assuming one format.
|
|
329
|
+
*/
|
|
330
|
+
private normalizeGatewayCode;
|
|
331
|
+
/**
|
|
332
|
+
* Display label for `paymentMethodCustomerUsed`, or '' if unknown/internal.
|
|
333
|
+
* Never surfaces an internal processor name (e.g. Hyperpay) to the agent —
|
|
334
|
+
* callers fall back to a generic "Original Payment Method" label whenever
|
|
335
|
+
* this returns ''.
|
|
336
|
+
*/
|
|
337
|
+
customerPaymentLabel: import("@angular/core").Signal<string>;
|
|
338
|
+
/** Whether the confirmed cancellation's card refund settles via Mada. */
|
|
339
|
+
isMadaMethod: import("@angular/core").Signal<boolean>;
|
|
340
|
+
/**
|
|
341
|
+
* Label for the standalone "Original Payment Method" option card (shown
|
|
342
|
+
* when the whole refund goes to one destination). Mada wins over
|
|
343
|
+
* everything else, reading "Mada Card" instead of the generic gateway
|
|
344
|
+
* name or the "Original Payment Method" fallback.
|
|
345
|
+
*/
|
|
346
|
+
originalPaymentLabel: import("@angular/core").Signal<string>;
|
|
347
|
+
/** Same as `isMadaMethod`, scoped to the confirmed cancellation result. */
|
|
348
|
+
confirmIsMadaMethod: import("@angular/core").Signal<boolean>;
|
|
349
|
+
/**
|
|
350
|
+
* Split-refund destination rows — up to four: Almatar Wallet (generic
|
|
351
|
+
* label), the original payment method (card/installment gateway), a
|
|
352
|
+
* separate loyalty-points-refund row when the backend sends one, and a
|
|
353
|
+
* dedicated loyalty-program row (Wala, Qitaf, …) for forfeited points
|
|
354
|
+
* (`forfeitedLoyaltyPointsFallback`) — kept distinct from the Wallet row
|
|
355
|
+
* even when both are non-zero.
|
|
356
|
+
*/
|
|
357
|
+
splitRefundRows: import("@angular/core").Signal<{
|
|
358
|
+
label: string;
|
|
359
|
+
value: number;
|
|
360
|
+
instant: boolean;
|
|
361
|
+
isLoyalty: boolean;
|
|
362
|
+
badgeText: string;
|
|
363
|
+
isMada?: boolean;
|
|
364
|
+
}[]>;
|
|
365
|
+
/**
|
|
366
|
+
* Wallet-row label for a loyalty-program redemption — `loyaltyPaymentType`
|
|
367
|
+
* (e.g. Wala, Qitaf) names the program that redeemed into the wallet
|
|
368
|
+
* balance and applies regardless of `paymentMethodCustomerUsed`; the
|
|
369
|
+
* backend can report an unrelated original payment gateway (e.g. Tabby)
|
|
370
|
+
* alongside a wallet portion that's actually a loyalty redemption.
|
|
371
|
+
*/
|
|
372
|
+
walletOrLoyaltyLabel(d: any): string;
|
|
373
|
+
constructor();
|
|
374
|
+
private loadRefund;
|
|
375
|
+
/**
|
|
376
|
+
* Both legs in play — sum each leg's own figures instead of trusting root
|
|
377
|
+
* (root isn't reliably scoped to the picked alternatives, e.g. rounding
|
|
378
|
+
* can drift between leg totals and the combined root total).
|
|
379
|
+
*/
|
|
380
|
+
private buildCombinedLegData;
|
|
381
|
+
/** Combine two legs' itemized breakdowns for the "both legs" combined view. */
|
|
382
|
+
private mergeBreakdowns;
|
|
383
|
+
private buildLegData;
|
|
384
|
+
startHints(): void;
|
|
385
|
+
stopHints(): void;
|
|
386
|
+
fmt(value: number, currency?: string): string;
|
|
387
|
+
fmtNum(value: number): string;
|
|
388
|
+
fmtNeg(value: number, currency?: string): string;
|
|
389
|
+
fmtNegResult(value: number): string;
|
|
390
|
+
requestCancel(): void;
|
|
391
|
+
confirm(): void;
|
|
392
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdCancelDialogComponent, never>;
|
|
393
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdCancelDialogComponent, "app-sbd-cancel-dialog", never, { "visible": { "alias": "visible"; "required": false; "isSignal": true; }; "bookingId": { "alias": "bookingId"; "required": false; "isSignal": true; }; "product": { "alias": "product"; "required": false; "isSignal": true; }; "pnrInfo": { "alias": "pnrInfo"; "required": false; "isSignal": true; }; "bookingInfo": { "alias": "bookingInfo"; "required": false; "isSignal": true; }; }, { "closed": "closed"; "confirmed": "confirmed"; }, never, never, true, never>;
|
|
394
|
+
}
|
|
395
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
type EntryType = 'date' | 'duration' | 'bool' | 'number' | 'text';
|
|
3
|
+
interface FlatEntry {
|
|
4
|
+
path: string;
|
|
5
|
+
key: string;
|
|
6
|
+
rawValue: string;
|
|
7
|
+
displayValue: string;
|
|
8
|
+
type: EntryType;
|
|
9
|
+
}
|
|
10
|
+
export declare class SbdDataSearchComponent {
|
|
11
|
+
data: import("@angular/core").InputSignal<any>;
|
|
12
|
+
query: import("@angular/core").WritableSignal<string>;
|
|
13
|
+
private allEntries;
|
|
14
|
+
results: import("@angular/core").Signal<FlatEntry[]>;
|
|
15
|
+
totalCount: import("@angular/core").Signal<number>;
|
|
16
|
+
private flatten;
|
|
17
|
+
private formatEntry;
|
|
18
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdDataSearchComponent, never>;
|
|
19
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdDataSearchComponent, "app-sbd-data-search", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ProductType } from '../../models/booking.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class SbdFlightItineraryCardComponent {
|
|
4
|
+
data: import("@angular/core").InputSignal<any>;
|
|
5
|
+
product: import("@angular/core").InputSignal<ProductType>;
|
|
6
|
+
verified: import("@angular/core").InputSignal<boolean>;
|
|
7
|
+
private bi;
|
|
8
|
+
legs: import("@angular/core").Signal<any>;
|
|
9
|
+
passengers: import("@angular/core").Signal<any[]>;
|
|
10
|
+
payment: import("@angular/core").Signal<any>;
|
|
11
|
+
readonly typeLabel: Record<string, string>;
|
|
12
|
+
fmtTime(dt: string): string;
|
|
13
|
+
fmtShortDate(dt: string): string;
|
|
14
|
+
fmtMins(mins: number): string;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdFlightItineraryCardComponent, never>;
|
|
16
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdFlightItineraryCardComponent, "app-sbd-flight-itinerary-card", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "product": { "alias": "product"; "required": true; "isSignal": true; }; "verified": { "alias": "verified"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ResultContent } from '../../models/action.types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class SbdResultPanelComponent {
|
|
4
|
+
private toast;
|
|
5
|
+
actionLabel: import("@angular/core").InputSignal<string>;
|
|
6
|
+
elapsedMs: import("@angular/core").InputSignal<number>;
|
|
7
|
+
status: import("@angular/core").InputSignal<"error" | "idle" | "loading" | "success">;
|
|
8
|
+
result: import("@angular/core").InputSignal<ResultContent>;
|
|
9
|
+
feedbackGiven: import("@angular/core").OutputEmitterRef<"up" | "down">;
|
|
10
|
+
get elapsedSeconds(): string;
|
|
11
|
+
copy(): void;
|
|
12
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdResultPanelComponent, never>;
|
|
13
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdResultPanelComponent, "app-sbd-result-panel", never, { "actionLabel": { "alias": "actionLabel"; "required": false; "isSignal": true; }; "elapsedMs": { "alias": "elapsedMs"; "required": false; "isSignal": true; }; "status": { "alias": "status"; "required": false; "isSignal": true; }; "result": { "alias": "result"; "required": false; "isSignal": true; }; }, { "feedbackGiven": "feedbackGiven"; }, never, never, true, never>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export declare class SbdWorkflowActionsComponent {
|
|
3
|
+
bookingId: import("@angular/core").InputSignal<string>;
|
|
4
|
+
cancelBooking: import("@angular/core").OutputEmitterRef<void>;
|
|
5
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SbdWorkflowActionsComponent, never>;
|
|
6
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SbdWorkflowActionsComponent, "app-sbd-workflow-actions", never, { "bookingId": { "alias": "bookingId"; "required": true; "isSignal": true; }; }, { "cancelBooking": "cancelBooking"; }, never, never, true, never>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { EnvironmentProviders, InjectionToken } from '@angular/core';
|
|
2
|
+
/**
|
|
3
|
+
* Host-app configuration for the Smart Booking Dashboard.
|
|
4
|
+
* Every field is optional; the defaults match the Almatar backoffice.
|
|
5
|
+
*/
|
|
6
|
+
export interface SbdConfig {
|
|
7
|
+
/** Base URL of the backend API. Default: '/api' */
|
|
8
|
+
apiBase: string;
|
|
9
|
+
/** Value of the `platform` header sent with FCR requests. Default: 'BO' */
|
|
10
|
+
platform: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const SBD_DEFAULT_CONFIG: SbdConfig;
|
|
13
|
+
export declare const SBD_CONFIG: InjectionToken<SbdConfig>;
|
|
14
|
+
/** Optional: call in the host app's providers to override the defaults. */
|
|
15
|
+
export declare function provideSmartBookingDashboard(config?: Partial<SbdConfig>): EnvironmentProviders;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface ResultPoint {
|
|
2
|
+
label: string;
|
|
3
|
+
value: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ResultCallout {
|
|
6
|
+
type: 'info' | 'warning' | 'tip';
|
|
7
|
+
message: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ResultRow {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string;
|
|
12
|
+
valueClass?: 'positive' | 'negative' | 'neutral';
|
|
13
|
+
}
|
|
14
|
+
export interface ResultSection {
|
|
15
|
+
title: string;
|
|
16
|
+
rows: ResultRow[];
|
|
17
|
+
}
|
|
18
|
+
export interface ResultContent {
|
|
19
|
+
title: string;
|
|
20
|
+
subtitle?: string;
|
|
21
|
+
points?: ResultPoint[];
|
|
22
|
+
sections?: ResultSection[];
|
|
23
|
+
callout?: ResultCallout;
|
|
24
|
+
}
|
|
25
|
+
export interface ActionConfig {
|
|
26
|
+
key: string;
|
|
27
|
+
type: 'flight' | 'hotel';
|
|
28
|
+
label: string;
|
|
29
|
+
subtitle: string;
|
|
30
|
+
icon: string;
|
|
31
|
+
apiField: string | string[];
|
|
32
|
+
hidden?: boolean;
|
|
33
|
+
formatter: (data: any) => ResultContent;
|
|
34
|
+
}
|