@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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -0
  3. package/esm2022/almatar-smart-booking-dashboard.mjs +5 -0
  4. package/esm2022/lib/components/action-card/action-card.component.mjs +19 -0
  5. package/esm2022/lib/components/action-dialog/action-dialog.component.mjs +177 -0
  6. package/esm2022/lib/components/action-grid/action-grid.component.mjs +18 -0
  7. package/esm2022/lib/components/add-note-dialog/add-note-dialog.component.mjs +62 -0
  8. package/esm2022/lib/components/booking-input/booking-input.component.mjs +43 -0
  9. package/esm2022/lib/components/cancel-dialog/cancel-dialog.component.mjs +1441 -0
  10. package/esm2022/lib/components/data-search/data-search.component.mjs +84 -0
  11. package/esm2022/lib/components/flight-itinerary-card/flight-itinerary-card.component.mjs +73 -0
  12. package/esm2022/lib/components/result-panel/result-panel.component.mjs +46 -0
  13. package/esm2022/lib/components/workflow-actions/workflow-actions.component.mjs +19 -0
  14. package/esm2022/lib/config/dashboard.config.mjs +16 -0
  15. package/esm2022/lib/config/flight-actions.config.mjs +906 -0
  16. package/esm2022/lib/config/hotel-actions.config.mjs +53 -0
  17. package/esm2022/lib/config/labels.ar.mjs +116 -0
  18. package/esm2022/lib/models/action.types.mjs +2 -0
  19. package/esm2022/lib/models/booking.types.mjs +2 -0
  20. package/esm2022/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.mjs +145 -0
  21. package/esm2022/lib/services/booking.service.mjs +65 -0
  22. package/esm2022/lib/services/toast.service.mjs +19 -0
  23. package/esm2022/lib/smart-booking-dashboard.module.mjs +17 -0
  24. package/esm2022/lib/smart-booking-dashboard.routes.mjs +7 -0
  25. package/esm2022/public-api.mjs +9 -0
  26. package/fesm2022/almatar-smart-booking-dashboard.mjs +3259 -0
  27. package/fesm2022/almatar-smart-booking-dashboard.mjs.map +1 -0
  28. package/index.d.ts +5 -0
  29. package/lib/components/action-card/action-card.component.d.ts +10 -0
  30. package/lib/components/action-dialog/action-dialog.component.d.ts +26 -0
  31. package/lib/components/action-grid/action-grid.component.d.ts +10 -0
  32. package/lib/components/add-note-dialog/add-note-dialog.component.d.ts +25 -0
  33. package/lib/components/booking-input/booking-input.component.d.ts +23 -0
  34. package/lib/components/cancel-dialog/cancel-dialog.component.d.ts +395 -0
  35. package/lib/components/data-search/data-search.component.d.ts +21 -0
  36. package/lib/components/flight-itinerary-card/flight-itinerary-card.component.d.ts +17 -0
  37. package/lib/components/result-panel/result-panel.component.d.ts +14 -0
  38. package/lib/components/workflow-actions/workflow-actions.component.d.ts +7 -0
  39. package/lib/config/dashboard.config.d.ts +15 -0
  40. package/lib/config/flight-actions.config.d.ts +2 -0
  41. package/lib/config/hotel-actions.config.d.ts +2 -0
  42. package/lib/config/labels.ar.d.ts +2 -0
  43. package/lib/models/action.types.d.ts +34 -0
  44. package/lib/models/booking.types.d.ts +6 -0
  45. package/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.d.ts +43 -0
  46. package/lib/services/booking.service.d.ts +22 -0
  47. package/lib/services/toast.service.d.ts +10 -0
  48. package/lib/smart-booking-dashboard.module.d.ts +7 -0
  49. package/lib/smart-booking-dashboard.routes.d.ts +2 -0
  50. package/package.json +50 -0
  51. package/public-api.d.ts +5 -0
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="@almatar/smart-booking-dashboard" />
5
+ export * from './public-api';
@@ -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,2 @@
1
+ import { ActionConfig } from '../models/action.types';
2
+ export declare const FLIGHT_ACTIONS: ActionConfig[];
@@ -0,0 +1,2 @@
1
+ import { ActionConfig } from '../models/action.types';
2
+ export declare const HOTEL_ACTIONS: ActionConfig[];
@@ -0,0 +1,2 @@
1
+ export declare const AR_LABELS: Record<string, string>;
2
+ export declare const AR_SECTION_TITLES: Record<string, string>;
@@ -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
+ }
@@ -0,0 +1,6 @@
1
+ export type ProductType = 'flight' | 'hotel';
2
+ export type BookingStatus = 'idle' | 'loading' | 'success' | 'error';
3
+ export interface BookingResponse {
4
+ data: any;
5
+ elapsedMs: number;
6
+ }