kaafil-react-uikit 0.1.0-beta.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/CHANGELOG.md +70 -0
- package/LICENSE +21 -0
- package/README.md +187 -0
- package/dist/OfflineFallbackScreen-B5dfaJBN.d.ts +37 -0
- package/dist/OfflineFallbackScreen-Ctm7nBa-.d.cts +37 -0
- package/dist/SessionExpiredScreen-CytQNuak.d.cts +50 -0
- package/dist/SessionExpiredScreen-D8GHyZc3.d.ts +50 -0
- package/dist/admin/index.cjs +23779 -0
- package/dist/admin/index.cjs.map +1 -0
- package/dist/admin/index.d.cts +1157 -0
- package/dist/admin/index.d.ts +1157 -0
- package/dist/admin/index.js +23724 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/chunk-6FPAGGFL.js +6028 -0
- package/dist/chunk-6FPAGGFL.js.map +1 -0
- package/dist/chunk-ACVU55PZ.cjs +294 -0
- package/dist/chunk-ACVU55PZ.cjs.map +1 -0
- package/dist/chunk-EM7JV3D7.cjs +6051 -0
- package/dist/chunk-EM7JV3D7.cjs.map +1 -0
- package/dist/chunk-IIPQ4JNC.js +287 -0
- package/dist/chunk-IIPQ4JNC.js.map +1 -0
- package/dist/chunk-LL243STJ.cjs +2195 -0
- package/dist/chunk-LL243STJ.cjs.map +1 -0
- package/dist/chunk-PJRZCOFF.cjs +958 -0
- package/dist/chunk-PJRZCOFF.cjs.map +1 -0
- package/dist/chunk-PTQ2CJKE.cjs +40 -0
- package/dist/chunk-PTQ2CJKE.cjs.map +1 -0
- package/dist/chunk-PZKXLQSU.js +10 -0
- package/dist/chunk-PZKXLQSU.js.map +1 -0
- package/dist/chunk-QHUDOVKW.cjs +111 -0
- package/dist/chunk-QHUDOVKW.cjs.map +1 -0
- package/dist/chunk-TOBZFADB.cjs +12 -0
- package/dist/chunk-TOBZFADB.cjs.map +1 -0
- package/dist/chunk-UUGMNP27.js +936 -0
- package/dist/chunk-UUGMNP27.js.map +1 -0
- package/dist/chunk-UYJ6LIWP.js +2154 -0
- package/dist/chunk-UYJ6LIWP.js.map +1 -0
- package/dist/chunk-VHTSTUCJ.cjs +346 -0
- package/dist/chunk-VHTSTUCJ.cjs.map +1 -0
- package/dist/chunk-WUAFL77X.js +340 -0
- package/dist/chunk-WUAFL77X.js.map +1 -0
- package/dist/chunk-XI7MK4Y7.js +38 -0
- package/dist/chunk-XI7MK4Y7.js.map +1 -0
- package/dist/chunk-YDGR7JSY.js +107 -0
- package/dist/chunk-YDGR7JSY.js.map +1 -0
- package/dist/core/index.cjs +1254 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +1267 -0
- package/dist/core/index.d.ts +1267 -0
- package/dist/core/index.js +995 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.css +1 -0
- package/dist/manager/index.cjs +13562 -0
- package/dist/manager/index.cjs.map +1 -0
- package/dist/manager/index.d.cts +1054 -0
- package/dist/manager/index.d.ts +1054 -0
- package/dist/manager/index.js +13518 -0
- package/dist/manager/index.js.map +1 -0
- package/dist/testing/index.cjs +221 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +269 -0
- package/dist/testing/index.d.ts +269 -0
- package/dist/testing/index.js +208 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tokenStyle-CToG5oOS.d.cts +3 -0
- package/dist/tokenStyle-CToG5oOS.d.ts +3 -0
- package/dist/traveller/index.cjs +1799 -0
- package/dist/traveller/index.cjs.map +1 -0
- package/dist/traveller/index.d.cts +58 -0
- package/dist/traveller/index.d.ts +58 -0
- package/dist/traveller/index.js +1789 -0
- package/dist/traveller/index.js.map +1 -0
- package/dist/useAgencyTrip-BUYSIaC2.d.cts +454 -0
- package/dist/useAgencyTrip-BzyJB1D9.d.ts +454 -0
- package/dist/useNotifications-BZW1Z_ur.d.cts +356 -0
- package/dist/useNotifications-D262i5BQ.d.ts +356 -0
- package/dist/useVendors-DXOuZWhZ.d.cts +784 -0
- package/dist/useVendors-DXOuZWhZ.d.ts +784 -0
- package/package.json +95 -0
|
@@ -0,0 +1,1054 @@
|
|
|
1
|
+
export { B as BootErrorScreen, a as BootErrorScreenProps, b as BootFailureMode, O as OfflineFallbackScreen, c as OfflineFallbackScreenProps } from '../OfflineFallbackScreen-B5dfaJBN.js';
|
|
2
|
+
export { L as LockedTripScreen, a as LockedTripScreenProps, N as NotFoundScreen, b as NotFoundScreenProps, S as SessionExpiredScreen, c as SessionExpiredScreenProps } from '../SessionExpiredScreen-D8GHyZc3.js';
|
|
3
|
+
import { ComponentType, ReactNode } from 'react';
|
|
4
|
+
import { C as ChecklistSectionRow, a as ChecklistsReady, T as TripFormRow, L as FormDefinitionDetail, M as FormResponseDetail, N as TravellerFormResponseRow, I as ItineraryDayRow, d as ItineraryItemRow, r as ItineraryReady, O as ExpenseLiveRow, s as RoomingReady, e as TripVendorRow } from '../useVendors-DXOuZWhZ.js';
|
|
5
|
+
export { Q as ChecklistAvailableTemplateRow, F as FileListItem, S as FilePurpose, b as FloatLedgerMovementRow, f as FloatLedgerSummaryRow, U as ManagerFileView } from '../useVendors-DXOuZWhZ.js';
|
|
6
|
+
import { K as KaafilTokenOverrides } from '../tokenStyle-CToG5oOS.js';
|
|
7
|
+
import { p as CloseoutBlockerRow, d as ManagerTodayReady, q as PickupManifestResult, M as ManagerMeReady, h as SeatingReady } from '../useNotifications-D262i5BQ.js';
|
|
8
|
+
export { r as CloseoutAggregate, C as ConflictRecord, c as ManagerNotification, s as PartiesTripRosterRow } from '../useNotifications-D262i5BQ.js';
|
|
9
|
+
import { PickupStopDeltaRow, ManagerOwnTrip } from 'kaafil-js/client';
|
|
10
|
+
export { ManagerOwnTrip, OutboxOp, PickupStopDeltaRow } from 'kaafil-js/client';
|
|
11
|
+
|
|
12
|
+
interface ItemRowProps {
|
|
13
|
+
readonly item: ChecklistItemLiveRow;
|
|
14
|
+
/** Resolved via `useManagers(tripRef)`, joined on `managerId` — real name,
|
|
15
|
+
* never a raw id, never fabricated when the join can't resolve. */
|
|
16
|
+
readonly completedByName: string | undefined;
|
|
17
|
+
readonly pending: boolean;
|
|
18
|
+
readonly onToggle: () => void;
|
|
19
|
+
readonly onEdit: () => void;
|
|
20
|
+
readonly onDelete: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface ProgressCardProps {
|
|
24
|
+
readonly title: string | undefined;
|
|
25
|
+
readonly subtitle: string | undefined;
|
|
26
|
+
readonly progress: {
|
|
27
|
+
readonly total: number;
|
|
28
|
+
readonly complete: number;
|
|
29
|
+
} | undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface SectionCardProps {
|
|
33
|
+
readonly section: ChecklistSectionRow;
|
|
34
|
+
readonly items: readonly ChecklistItemLiveRow[];
|
|
35
|
+
readonly completedByNameFor: (managerId: string) => string | undefined;
|
|
36
|
+
readonly pendingItemIds: ReadonlySet<string>;
|
|
37
|
+
readonly onToggleItem: (item: ChecklistItemLiveRow) => void;
|
|
38
|
+
readonly onEditItem: (item: ChecklistItemLiveRow) => void;
|
|
39
|
+
readonly onDeleteItem: (item: ChecklistItemLiveRow) => void;
|
|
40
|
+
readonly ItemRowComponent: ComponentType<ItemRowProps>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** One row of `useChecklists()`'s `items[]` — a live item or a tombstone,
|
|
44
|
+
* `useChecklists.ts`'s own documented split. */
|
|
45
|
+
type ChecklistItemDeltaRow = ChecklistsReady['items'][number];
|
|
46
|
+
/** `ChecklistItemDeltaRow`, narrowed to the live shape — a
|
|
47
|
+
* deleted-since-last-cursor row carries no `title`/`status`/etc. at all. */
|
|
48
|
+
type ChecklistItemLiveRow = Exclude<ChecklistItemDeltaRow, {
|
|
49
|
+
readonly _tombstone: true;
|
|
50
|
+
}>;
|
|
51
|
+
type ChecklistItemPhase = ChecklistSectionRow['phase'];
|
|
52
|
+
type ChecklistItemGate = ChecklistItemLiveRow['gate'];
|
|
53
|
+
interface ManagerChecklistSectionProps {
|
|
54
|
+
/** The trip this section reads `useChecklists(tripRef)` for. */
|
|
55
|
+
readonly tripRef: string;
|
|
56
|
+
/** Tier-4 named-component overrides — the three genuinely reskinnable
|
|
57
|
+
* regions. Each receives EXACTLY the same props this composite's own
|
|
58
|
+
* default renders it with. */
|
|
59
|
+
readonly components?: {
|
|
60
|
+
readonly ProgressCard?: ComponentType<ProgressCardProps>;
|
|
61
|
+
readonly SectionCard?: ComponentType<SectionCardProps>;
|
|
62
|
+
readonly ItemRow?: ComponentType<ItemRowProps>;
|
|
63
|
+
};
|
|
64
|
+
readonly style?: KaafilTokenOverrides;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare function ManagerChecklistSection({ tripRef, components, style, }: ManagerChecklistSectionProps): ReactNode;
|
|
68
|
+
|
|
69
|
+
interface BlockerRowProps {
|
|
70
|
+
readonly blocker: CloseoutBlockerRow;
|
|
71
|
+
readonly onAction?: (blocker: CloseoutBlockerRow) => void;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface ManagerCloseoutSectionProps {
|
|
75
|
+
readonly tripRef: string;
|
|
76
|
+
/** Real dispatch, never a fabricated route: `ManagerTripSection` wires
|
|
77
|
+
* this to its own `actionKey → ManagerTripTabKey` map and switches its
|
|
78
|
+
* own tab state — see this composite's own header. Omit to render every
|
|
79
|
+
* blocker action button disabled/absent-of-navigation (still shows the
|
|
80
|
+
* blocker itself, just no dispatch). */
|
|
81
|
+
readonly onBlockerAction?: (blocker: CloseoutBlockerRow) => void;
|
|
82
|
+
/** `UnlockForm`'s own real contract (`04-closing-day.md`, verbatim): "this
|
|
83
|
+
* screen makes no `kaafil-js` call of its own" for unlock — `unlockCloseout`
|
|
84
|
+
* is `apiKeyAuth`-only. Submitting the reason form calls this instead, the
|
|
85
|
+
* host's own out-of-band route to ops. Omitted → a static "contact ops to
|
|
86
|
+
* reopen" message renders in place of the form. */
|
|
87
|
+
readonly onSubmitUnlockRequest?: (payload: {
|
|
88
|
+
readonly tripRef: string;
|
|
89
|
+
readonly reason: string;
|
|
90
|
+
}) => Promise<void>;
|
|
91
|
+
readonly components?: {
|
|
92
|
+
readonly BlockerRow?: ComponentType<BlockerRowProps>;
|
|
93
|
+
};
|
|
94
|
+
readonly style?: KaafilTokenOverrides;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
declare function ManagerCloseoutSection({ tripRef, onBlockerAction, onSubmitUnlockRequest, components, style, }: ManagerCloseoutSectionProps): ReactNode;
|
|
98
|
+
|
|
99
|
+
interface ManagerDocumentsSectionProps {
|
|
100
|
+
readonly tripRef: string;
|
|
101
|
+
readonly style?: KaafilTokenOverrides;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
declare function ManagerDocumentsSection({ tripRef, style, }: ManagerDocumentsSectionProps): ReactNode;
|
|
105
|
+
|
|
106
|
+
interface ManagerFloatLedgerSectionProps {
|
|
107
|
+
readonly tripRef: string;
|
|
108
|
+
readonly style?: KaafilTokenOverrides;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
declare function ManagerFloatLedgerSection({ tripRef, style, }: ManagerFloatLedgerSectionProps): ReactNode;
|
|
112
|
+
|
|
113
|
+
/** One answer this composite is about to write back — mirrors
|
|
114
|
+
* `SubmitFormResponseInput['answers'][number]` so nothing here hand-shapes
|
|
115
|
+
* the array passed to `submitResponse`. */
|
|
116
|
+
interface FieldAnswer {
|
|
117
|
+
readonly fieldKey: string;
|
|
118
|
+
readonly value: unknown;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
interface FormFillRendererProps {
|
|
122
|
+
readonly form: TripFormRow;
|
|
123
|
+
readonly definition: FormDefinitionDetail;
|
|
124
|
+
/** The subject's (self, or the on-behalf traveller's) existing response,
|
|
125
|
+
* when one is known — `undefined` starts a fresh fill. */
|
|
126
|
+
readonly existingResponse: FormResponseDetail | undefined;
|
|
127
|
+
/** `existingResponse?.status === 'SUBMITTED'`, OR the parent's own
|
|
128
|
+
* optimistic "we just submitted this" flag — kept as an explicit prop
|
|
129
|
+
* rather than derived only from `existingResponse` so a just-submitted
|
|
130
|
+
* fill locks immediately using the answers already held in THIS
|
|
131
|
+
* component's own local state, without the parent fabricating a
|
|
132
|
+
* `FormResponseDetail` it doesn't really have back from the write. */
|
|
133
|
+
readonly locked: boolean;
|
|
134
|
+
/** Set only for on-behalf capture — gates the `SELF_ONLY` sensitivity
|
|
135
|
+
* filter (05-forms.md's own privacy rule). */
|
|
136
|
+
readonly travellerRef: string | undefined;
|
|
137
|
+
readonly pending: boolean;
|
|
138
|
+
readonly hasConflict: boolean;
|
|
139
|
+
readonly onSave: (answers: readonly FieldAnswer[]) => void;
|
|
140
|
+
readonly onSubmit: (answers: readonly FieldAnswer[]) => void;
|
|
141
|
+
readonly onRefreshAfterConflict: () => void;
|
|
142
|
+
readonly onBack: () => void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
interface TripFormsPanelProps {
|
|
146
|
+
readonly rows: readonly FormsListRow[];
|
|
147
|
+
readonly now: string | undefined;
|
|
148
|
+
readonly travellerScoped: boolean;
|
|
149
|
+
readonly onSelectForm: (row: FormsListRow) => void;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** One row of `TripFormsPanel`'s list. `response` is the SUBJECT's own
|
|
153
|
+
* response for this form when known — always `undefined` in self-fill mode
|
|
154
|
+
* (`useForms.ts` exposes no "list my own manager responses" read; this
|
|
155
|
+
* composite's own header documents the gap), populated in traveller-scoped
|
|
156
|
+
* mode (`travellerRef` set) from `travellerResponses(travellerRef)`. */
|
|
157
|
+
interface FormsListRow {
|
|
158
|
+
readonly form: TripFormRow;
|
|
159
|
+
readonly response: TravellerFormResponseRow | undefined;
|
|
160
|
+
}
|
|
161
|
+
interface ManagerFormsSectionProps {
|
|
162
|
+
/** The trip this section reads `useForms(tripRef)` for. */
|
|
163
|
+
readonly tripRef: string;
|
|
164
|
+
/** Deep-link straight into one form's fill UI, skipping the list. */
|
|
165
|
+
readonly initialFormRef?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Scopes this composite to a SINGLE traveller instead of the manager's
|
|
168
|
+
* own self-fill list — the only honest way to serve "view what a
|
|
169
|
+
* traveller submitted," using the two real reads this SDK exposes
|
|
170
|
+
* (`travellerResponses`/`getResponse`). A caller who already knows which
|
|
171
|
+
* traveller (e.g. a row-tap in `ManagerManifestSection`/
|
|
172
|
+
* `ManagerTravellerProfileSection`) mounts this composite with
|
|
173
|
+
* `travellerRef` set; the list switches to that traveller's response rows
|
|
174
|
+
* joined against `forms[]`, and an unanswered row's tap becomes on-behalf
|
|
175
|
+
* capture (`submitResponse({ travellerRef, ... })`).
|
|
176
|
+
*/
|
|
177
|
+
readonly travellerRef?: string;
|
|
178
|
+
readonly onSubmitted?: (formRef: string, responseId: string) => void;
|
|
179
|
+
/** Tier-4 named-component overrides — the two genuinely reskinnable
|
|
180
|
+
* regions, matching `05-forms.md`'s own `FormFillFlow.components` slot. */
|
|
181
|
+
readonly components?: {
|
|
182
|
+
readonly TripFormsPanel?: ComponentType<TripFormsPanelProps>;
|
|
183
|
+
readonly FormFillRenderer?: ComponentType<FormFillRendererProps>;
|
|
184
|
+
};
|
|
185
|
+
readonly style?: KaafilTokenOverrides;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
declare function ManagerFormsSection({ tripRef, initialFormRef, travellerRef, onSubmitted, components, style, }: ManagerFormsSectionProps): ReactNode;
|
|
189
|
+
|
|
190
|
+
interface DayStripProps {
|
|
191
|
+
readonly days: readonly ItineraryDayRow[];
|
|
192
|
+
readonly selectedDayIndex: number;
|
|
193
|
+
readonly onSelect: (dayIndex: number) => void;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
interface ItemCardProps {
|
|
197
|
+
readonly item: ItineraryItemRow;
|
|
198
|
+
readonly canMoveUp: boolean;
|
|
199
|
+
readonly canMoveDown: boolean;
|
|
200
|
+
readonly onMoveUp: (item: ItineraryItemRow) => void;
|
|
201
|
+
readonly onMoveDown: (item: ItineraryItemRow) => void;
|
|
202
|
+
readonly onEdit: (item: ItineraryItemRow) => void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
type ItineraryChangeLogRow = ItineraryReady['changeLog'][number];
|
|
206
|
+
interface ManagerItinerarySectionProps {
|
|
207
|
+
/** The trip this section reads `useItinerary()`'s own reads for. */
|
|
208
|
+
readonly tripRef: string;
|
|
209
|
+
/** Overrides the "no days yet" empty state — same render-prop shape
|
|
210
|
+
* `ManagerRoomingSection.emptyView`/`ManagerVehiclesSection.emptyView`
|
|
211
|
+
* already establish. Omit for the built-in message. Days materialize
|
|
212
|
+
* lazily server-side on first read, so this should never actually fire
|
|
213
|
+
* in practice, but the composite still handles it honestly rather than
|
|
214
|
+
* crashing on an empty `days[]`. */
|
|
215
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
216
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
|
|
217
|
+
* "the only way to replace a named component"). Each receives EXACTLY
|
|
218
|
+
* the same props this composite's own default renders it with. */
|
|
219
|
+
readonly components?: {
|
|
220
|
+
readonly DayStrip?: ComponentType<DayStripProps>;
|
|
221
|
+
readonly ItemCard?: ComponentType<ItemCardProps>;
|
|
222
|
+
};
|
|
223
|
+
readonly style?: KaafilTokenOverrides;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
declare function ManagerItinerarySection({ tripRef, emptyView, components, style, }: ManagerItinerarySectionProps): ReactNode;
|
|
227
|
+
|
|
228
|
+
interface TripBookingGroupCardProps {
|
|
229
|
+
readonly group: ManifestBookingGroup;
|
|
230
|
+
readonly onCollect: (groupId: string) => void;
|
|
231
|
+
/** Fired when a member chip is tapped — the same real destination
|
|
232
|
+
* `TripTravellerRow.onOpen` already opens, so a traveller reachable from
|
|
233
|
+
* either the group card or the all-travellers list below lands on the
|
|
234
|
+
* identical `ManagerTravellerProfileSection`. */
|
|
235
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
interface ManifestStats {
|
|
239
|
+
readonly confirmedCount: number;
|
|
240
|
+
readonly vegCount: number;
|
|
241
|
+
readonly totalCount: number;
|
|
242
|
+
readonly balanceDueMinor: number;
|
|
243
|
+
readonly currency: string;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
interface TripManifestStatsProps {
|
|
247
|
+
readonly stats: ManifestStats;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
interface TripTravellerRowProps {
|
|
251
|
+
readonly traveller: ManifestTraveller;
|
|
252
|
+
/** `fullName` is passed alongside the id — already in scope here, so a
|
|
253
|
+
* host wiring `onOpenTraveller` to a header/nav can show a real name
|
|
254
|
+
* immediately, before `ManagerTravellerProfileSection` finishes its own
|
|
255
|
+
* fetch, without a second lookup. */
|
|
256
|
+
readonly onOpen: (travellerId: string, fullName: string) => void;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
interface ManagerManifestSectionProps {
|
|
260
|
+
/** The trip this section reads `useParties()`'s two real reads for. */
|
|
261
|
+
readonly tripRef: string;
|
|
262
|
+
/** Fired when a booking group's "Collect" CTA is tapped — nav-only
|
|
263
|
+
* (hard rule #9): no group-level collect endpoint exists (`collections`'s
|
|
264
|
+
* DTOs key strictly on `travellerId`), so the host resolves this into
|
|
265
|
+
* whatever real per-traveller flow it wants. */
|
|
266
|
+
readonly onCollectFromGroup: (groupId: string) => void;
|
|
267
|
+
/** Fired when a traveller row is tapped — the destination is
|
|
268
|
+
* `ManagerTravellerProfileSection` (a standalone composite, also
|
|
269
|
+
* exported), still fired via a callback rather than a router (hard rule
|
|
270
|
+
* #9). `fullName` is passed alongside the id so a host can show a real
|
|
271
|
+
* header title immediately, before the profile composite's own fetch
|
|
272
|
+
* resolves. */
|
|
273
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
274
|
+
/** Overrides the "no travellers match your search or filters" empty
|
|
275
|
+
* state — same render-prop shape `ManagerNowSection.idleView` already
|
|
276
|
+
* establishes for a state override. Omit for the built-in message. */
|
|
277
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
278
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
|
|
279
|
+
* "the only way to replace a named component") — the three leaf pieces a
|
|
280
|
+
* partner CRM is most likely to reskin: its own traveller-row layout,
|
|
281
|
+
* its own booking-group card, its own stat cells. Each receives EXACTLY
|
|
282
|
+
* the same props this composite's own default renders it with; a host
|
|
283
|
+
* overriding `TravellerRow` still gets real `onOpen`/real traveller data,
|
|
284
|
+
* never a stripped-down shape. */
|
|
285
|
+
readonly components?: {
|
|
286
|
+
readonly TravellerRow?: ComponentType<TripTravellerRowProps>;
|
|
287
|
+
readonly BookingGroupCard?: ComponentType<TripBookingGroupCardProps>;
|
|
288
|
+
readonly Stats?: ComponentType<TripManifestStatsProps>;
|
|
289
|
+
};
|
|
290
|
+
readonly style?: KaafilTokenOverrides;
|
|
291
|
+
}
|
|
292
|
+
type ManifestDiet = 'V' | 'NV' | 'J';
|
|
293
|
+
/** `BookingStatus` (`kaafil-engine`'s real Prisma enum) — never a free
|
|
294
|
+
* string; the DTO widens it to `z.string()` on the wire, but this composite
|
|
295
|
+
* only ever recognizes these three real values. */
|
|
296
|
+
type ManifestBookingStatus = 'CONFIRMED' | 'TENTATIVE' | 'CANCELLED';
|
|
297
|
+
interface ManifestTraveller {
|
|
298
|
+
readonly travellerId: string;
|
|
299
|
+
readonly fullName: string;
|
|
300
|
+
readonly bookingStatus: ManifestBookingStatus;
|
|
301
|
+
readonly diet: ManifestDiet | null;
|
|
302
|
+
readonly groupId: string | null;
|
|
303
|
+
readonly dueMinor: number;
|
|
304
|
+
readonly currency: string;
|
|
305
|
+
}
|
|
306
|
+
interface ManifestBookingGroup {
|
|
307
|
+
readonly groupId: string;
|
|
308
|
+
/** `Party.kind` (real) — used only for the i18n fallback name when
|
|
309
|
+
* `label` is null, never rendered as its own badge (the reference
|
|
310
|
+
* screenshot shows no kind badge on the group card itself). */
|
|
311
|
+
readonly kind: 'FAMILY' | 'COUPLE' | 'FRIENDS' | 'CORPORATE' | 'OTHER';
|
|
312
|
+
readonly label: string | null;
|
|
313
|
+
readonly members: readonly {
|
|
314
|
+
readonly travellerId: string;
|
|
315
|
+
readonly fullName: string;
|
|
316
|
+
}[];
|
|
317
|
+
readonly dueMinor: number;
|
|
318
|
+
readonly currency: string;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
declare function ManagerManifestSection({ tripRef, onCollectFromGroup, onOpenTraveller, emptyView, components, style, }: ManagerManifestSectionProps): ReactNode;
|
|
322
|
+
|
|
323
|
+
interface ManagerMeSectionProps {
|
|
324
|
+
/** Fired when a recent-trip row is tapped — the host's own real
|
|
325
|
+
* navigation into `ManagerTripSection` for that trip (hard rule #9, ships
|
|
326
|
+
* no router). Omit to render rows as plain, non-interactive text. */
|
|
327
|
+
readonly onOpenTrip?: (tripRef: string) => void;
|
|
328
|
+
/** Renders a "Sign out" button only when supplied — `useSession()` itself
|
|
329
|
+
* exposes no sign-out method (credential storage is host-owned), same
|
|
330
|
+
* "prop presence gates the affordance" convention `ManagerCloseoutSection`
|
|
331
|
+
* `UnlockRequestForm` already establishes. */
|
|
332
|
+
readonly onSignOut?: () => void;
|
|
333
|
+
readonly style?: KaafilTokenOverrides;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
declare function ManagerMeSection({ onOpenTrip, onSignOut, style, }: ManagerMeSectionProps): ReactNode;
|
|
337
|
+
|
|
338
|
+
interface BalanceDueDisplayRow {
|
|
339
|
+
readonly travellerId: string;
|
|
340
|
+
readonly fullName: string;
|
|
341
|
+
readonly initials: string;
|
|
342
|
+
readonly outstandingMinor: number;
|
|
343
|
+
readonly currency: string;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
interface BalancesDueSectionProps {
|
|
347
|
+
readonly rows: readonly BalanceDueDisplayRow[];
|
|
348
|
+
readonly showingAll: boolean;
|
|
349
|
+
readonly onSelect: (row: BalanceDueDisplayRow) => void;
|
|
350
|
+
readonly onSeeAll: () => void;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
interface MoneyStatsProps {
|
|
354
|
+
readonly float?: {
|
|
355
|
+
readonly balanceMinor: number;
|
|
356
|
+
readonly issuedMinor: number;
|
|
357
|
+
readonly currency: string;
|
|
358
|
+
};
|
|
359
|
+
readonly spend?: {
|
|
360
|
+
readonly amountMinor: number;
|
|
361
|
+
readonly currency: string;
|
|
362
|
+
};
|
|
363
|
+
readonly collect?: {
|
|
364
|
+
readonly amountMinor: number;
|
|
365
|
+
readonly travellerCount: number;
|
|
366
|
+
readonly currency: string;
|
|
367
|
+
};
|
|
368
|
+
readonly reimbursable?: {
|
|
369
|
+
readonly amountMinor: number;
|
|
370
|
+
readonly count: number;
|
|
371
|
+
readonly currency: string;
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
interface RecentExpensesSectionProps {
|
|
376
|
+
readonly expenses: readonly ExpenseLiveRow[];
|
|
377
|
+
readonly onSelect: (expense: ExpenseLiveRow) => void;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
interface ManagerMoneySectionProps {
|
|
381
|
+
/** The trip this section reads every real hook's own data for. */
|
|
382
|
+
readonly tripRef: string;
|
|
383
|
+
/** Fired when a balances-due row's traveller name is tapped — the same
|
|
384
|
+
* real destination `ManagerManifestSection`/`ManagerRoomingSection`'s
|
|
385
|
+
* `onOpenTraveller` already open. Still fired via a callback rather than
|
|
386
|
+
* a router (hard rule #9). */
|
|
387
|
+
readonly onOpenTraveller?: (travellerId: string, fullName: string) => void;
|
|
388
|
+
/** Fired when the float balance card's "View full ledger" affordance is
|
|
389
|
+
* tapped — the host pushes `ManagerFloatLedgerSection` (a full-screen
|
|
390
|
+
* deep-dive, never a tab, matching the `openTraveller`/`openTraveller`-
|
|
391
|
+
* style push convention). Omit to hide the affordance entirely — "prop
|
|
392
|
+
* presence gates the affordance," the same convention
|
|
393
|
+
* `ManagerCloseoutSection`'s own `UnlockRequestForm` establishes. */
|
|
394
|
+
readonly onViewFloatLedger?: () => void;
|
|
395
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
|
|
396
|
+
* "the only way to replace a named component") — the three genuinely
|
|
397
|
+
* reskinnable regions. Each receives EXACTLY the same props this
|
|
398
|
+
* composite's own default renders it with. */
|
|
399
|
+
readonly components?: {
|
|
400
|
+
readonly Stats?: ComponentType<MoneyStatsProps>;
|
|
401
|
+
readonly RecentExpenses?: ComponentType<RecentExpensesSectionProps>;
|
|
402
|
+
readonly BalancesDue?: ComponentType<BalancesDueSectionProps>;
|
|
403
|
+
};
|
|
404
|
+
readonly style?: KaafilTokenOverrides;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
declare function ManagerMoneySection({ tripRef, onViewFloatLedger, components, style, }: ManagerMoneySectionProps): ReactNode;
|
|
408
|
+
|
|
409
|
+
interface ManagerNotificationsSectionProps {
|
|
410
|
+
/** Fired after a row marks itself read — the host decides what a non-null
|
|
411
|
+
* `tripId` means (navigate there); a `null` tripId row has nowhere to go,
|
|
412
|
+
* so a host may simply no-op. Required, matching the spec's own
|
|
413
|
+
* `NotificationsFeed` contract (never optional — a row with no navigation
|
|
414
|
+
* destination at all would be a dead tap target). */
|
|
415
|
+
readonly onSelectNotification: (notification: {
|
|
416
|
+
readonly notificationId: string;
|
|
417
|
+
readonly tripId: string | null;
|
|
418
|
+
}) => void;
|
|
419
|
+
readonly style?: KaafilTokenOverrides;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
declare function ManagerNotificationsSection({ onSelectNotification, style, }: ManagerNotificationsSectionProps): ReactNode;
|
|
423
|
+
|
|
424
|
+
type WireOnly<T> = T extends unknown ? Omit<T, 'status' | 'syncedAt'> : never;
|
|
425
|
+
type ManagerTodayEngaged = Extract<WireOnly<ManagerTodayReady>, {
|
|
426
|
+
kind: 'trip';
|
|
427
|
+
}>;
|
|
428
|
+
type ManagerTodayIdle = Extract<WireOnly<ManagerTodayReady>, {
|
|
429
|
+
kind: 'idle';
|
|
430
|
+
}>;
|
|
431
|
+
interface ManagerNowSectionProps {
|
|
432
|
+
/** The trip this section reads `useManagerToday(tripRef)` for — resolved
|
|
433
|
+
* by the caller, typically off `useManagerMe()`'s own `defaultTripId`. */
|
|
434
|
+
readonly tripRef: string;
|
|
435
|
+
/** Fired when a hero quick-link chip (Manifest/Rooming/Checklist/Docs) OR
|
|
436
|
+
* the post-trip closeout card's "N item(s) still need closing" row is
|
|
437
|
+
* tapped — pure navigation, no router (hard rule #9). The host decides
|
|
438
|
+
* where each key routes to; a module whose composite doesn't exist yet
|
|
439
|
+
* (`'closing-day'` included — `ClosingDayFlow` is a later wave) still
|
|
440
|
+
* fires this callback, so the host can no-op it until it does. */
|
|
441
|
+
readonly onNavigateModule: (moduleKey: 'manifest' | 'rooming' | 'checklist' | 'docs' | 'closing-day') => void;
|
|
442
|
+
/** Fired once a Quick Actions "Log an expense" submit REALLY succeeds
|
|
443
|
+
* (the FAB opens a real `LogExpenseSheet` internally, backed by
|
|
444
|
+
* `useExpenses(tripRef).log()` — the same sheet `ManagerMoneySection`'s
|
|
445
|
+
* own "+" menu uses) — a completion hook for host-side toasts/analytics,
|
|
446
|
+
* not the trigger that opens anything. */
|
|
447
|
+
readonly onLogExpense: () => void;
|
|
448
|
+
/** Fired once a Quick Actions "Collect payment" submit REALLY succeeds
|
|
449
|
+
* (backed by `useCollections(tripRef).record()`), same shape as
|
|
450
|
+
* `onLogExpense` above. */
|
|
451
|
+
readonly onCollectPayment: () => void;
|
|
452
|
+
readonly components?: {
|
|
453
|
+
readonly ManagerNowSectionUI?: ComponentType<ManagerNowSectionUIProps>;
|
|
454
|
+
};
|
|
455
|
+
/** Overrides the default `kind: 'idle'` empty/upcoming-trip card. */
|
|
456
|
+
readonly idleView?: ReactNode | ((reading: ManagerTodayIdle) => ReactNode);
|
|
457
|
+
readonly style?: KaafilTokenOverrides;
|
|
458
|
+
}
|
|
459
|
+
interface ManagerNowSectionUIProps {
|
|
460
|
+
readonly data: ManagerTodayEngaged;
|
|
461
|
+
readonly syncedAt: string;
|
|
462
|
+
readonly onNavigateModule: ManagerNowSectionProps['onNavigateModule'];
|
|
463
|
+
readonly onLogExpense: () => void;
|
|
464
|
+
readonly onCollectPayment: () => void;
|
|
465
|
+
readonly style?: KaafilTokenOverrides;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
declare function ManagerNowSection(props: ManagerNowSectionProps): ReactNode;
|
|
469
|
+
|
|
470
|
+
interface ManagerOverviewSectionProps {
|
|
471
|
+
readonly tripRef: string;
|
|
472
|
+
readonly style?: KaafilTokenOverrides;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
declare function ManagerOverviewSection({ tripRef, style }: ManagerOverviewSectionProps): ReactNode;
|
|
476
|
+
|
|
477
|
+
interface CloseStopResolution {
|
|
478
|
+
readonly travellerId: string;
|
|
479
|
+
readonly status: 'BOARDED' | 'NO_SHOW';
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
interface BoardingViewProps {
|
|
483
|
+
readonly manifest: PickupManifestResult;
|
|
484
|
+
readonly activeStopId: string;
|
|
485
|
+
readonly eventType: 'TRIP' | 'TREK';
|
|
486
|
+
readonly pendingWriteIds: ReadonlySet<string>;
|
|
487
|
+
readonly closePending: boolean;
|
|
488
|
+
readonly onSelectStop: (stopId: string) => void;
|
|
489
|
+
readonly onBoard: (travellerId: string, status: 'BOARDED' | 'NO_SHOW') => void;
|
|
490
|
+
readonly onCorrect: (travellerId: string, status: 'BOARDED' | 'NO_SHOW') => void;
|
|
491
|
+
readonly onCloseStop: (input: {
|
|
492
|
+
readonly resolutions?: readonly CloseStopResolution[];
|
|
493
|
+
readonly confirm?: boolean;
|
|
494
|
+
readonly confirmedHeadCount?: number;
|
|
495
|
+
}) => void;
|
|
496
|
+
readonly onBack: () => void;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
interface StopListProps {
|
|
500
|
+
readonly stops: readonly PickupStopLiveRow[];
|
|
501
|
+
readonly kind: PickupStopKind;
|
|
502
|
+
readonly hasDropStops: boolean;
|
|
503
|
+
readonly onKindChange: (kind: PickupStopKind) => void;
|
|
504
|
+
readonly onSelectStop: (stop: PickupStopLiveRow) => void;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/** `PickupStopDeltaRow`, narrowed to the live shape — a deleted-since-last-
|
|
508
|
+
* cursor row carries no `name`/`rollup`/etc at all. */
|
|
509
|
+
type PickupStopLiveRow = Exclude<PickupStopDeltaRow, {
|
|
510
|
+
readonly _tombstone: true;
|
|
511
|
+
}>;
|
|
512
|
+
type PickupStopKind = PickupStopLiveRow['kind'];
|
|
513
|
+
interface ManagerPickupsSectionProps {
|
|
514
|
+
/** The trip this section reads `usePickups(tripRef)` for. */
|
|
515
|
+
readonly tripRef: string;
|
|
516
|
+
/** Real, resolved upstream (`useManagerMe()`'s own trip row) — the close-
|
|
517
|
+
* stop flow's two real policies (TRIP hard-resolve vs TREK short-close
|
|
518
|
+
* confirm) are selected by this, never re-derived inside this composite. */
|
|
519
|
+
readonly eventType: 'TRIP' | 'TREK';
|
|
520
|
+
/** Tier-4 named-component overrides — the two genuinely reskinnable
|
|
521
|
+
* regions. */
|
|
522
|
+
readonly components?: {
|
|
523
|
+
readonly StopList?: ComponentType<StopListProps>;
|
|
524
|
+
readonly BoardingView?: ComponentType<BoardingViewProps>;
|
|
525
|
+
};
|
|
526
|
+
readonly style?: KaafilTokenOverrides;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
declare function ManagerPickupsSection({ tripRef, eventType, components, style, }: ManagerPickupsSectionProps): ReactNode;
|
|
530
|
+
|
|
531
|
+
interface RoomCardProps {
|
|
532
|
+
readonly room: RoomingRoom;
|
|
533
|
+
readonly onSelectBed: (room: RoomingRoom, bed: RoomingBed) => void;
|
|
534
|
+
readonly onEditRoom: (room: RoomingRoom) => void;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
interface RoomingBedStats {
|
|
538
|
+
readonly occupied: number;
|
|
539
|
+
readonly total: number;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
interface RoomingStatsProps {
|
|
543
|
+
readonly roomCount: number;
|
|
544
|
+
readonly beds: RoomingBedStats;
|
|
545
|
+
readonly unassignedCount: number;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
interface UnassignedPoolSectionProps$1 {
|
|
549
|
+
readonly travellers: readonly RoomingOccupantRow[];
|
|
550
|
+
readonly loaded: boolean;
|
|
551
|
+
readonly onSelectTraveller: (traveller: RoomingOccupantRow) => void;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
type RoomingRoomDeltaRow = RoomingReady['rooms'][number];
|
|
555
|
+
type RoomingRoom = Exclude<RoomingRoomDeltaRow, {
|
|
556
|
+
readonly _tombstone: true;
|
|
557
|
+
}>;
|
|
558
|
+
type RoomingStayWindowDeltaRow = RoomingReady['stayWindows'][number];
|
|
559
|
+
type RoomingStayWindow = Exclude<RoomingStayWindowDeltaRow, {
|
|
560
|
+
readonly _tombstone: true;
|
|
561
|
+
}>;
|
|
562
|
+
type RoomingOccupantRow = RoomingReady['unassignedPool']['travellers'][number];
|
|
563
|
+
type RoomingBed = RoomingRoom['beds'][number];
|
|
564
|
+
type RoomingAutoAssignResult = Awaited<ReturnType<RoomingReady['autoAssign']>>;
|
|
565
|
+
interface ManagerRoomingSectionProps {
|
|
566
|
+
/** The trip this section reads `useRooming()`'s own reads for. */
|
|
567
|
+
readonly tripRef: string;
|
|
568
|
+
/** Fired when an occupied bed's "View profile" row is tapped — the same
|
|
569
|
+
* real destination `ManagerManifestSection.onOpenTraveller` already opens,
|
|
570
|
+
* so a traveller reachable from the rooming board lands on the identical
|
|
571
|
+
* `ManagerTravellerProfileSection`. Still fired via a callback rather than
|
|
572
|
+
* a router (hard rule #9). */
|
|
573
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
574
|
+
/** Overrides the "no rooms in this stay window yet" empty state — same
|
|
575
|
+
* render-prop shape `ManagerManifestSection.emptyView`/
|
|
576
|
+
* `ManagerNowSection.idleView` already establish. Omit for the built-in
|
|
577
|
+
* message. */
|
|
578
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
579
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
|
|
580
|
+
* "the only way to replace a named component") — the three leaf pieces a
|
|
581
|
+
* partner CRM is most likely to reskin. Each receives EXACTLY the same
|
|
582
|
+
* props this composite's own default renders it with. */
|
|
583
|
+
readonly components?: {
|
|
584
|
+
readonly Stats?: ComponentType<RoomingStatsProps>;
|
|
585
|
+
readonly RoomCard?: ComponentType<RoomCardProps>;
|
|
586
|
+
readonly UnassignedPool?: ComponentType<UnassignedPoolSectionProps$1>;
|
|
587
|
+
};
|
|
588
|
+
readonly style?: KaafilTokenOverrides;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
declare function ManagerRoomingSection({ tripRef, onOpenTraveller, emptyView, components, style, }: ManagerRoomingSectionProps): ReactNode;
|
|
592
|
+
|
|
593
|
+
interface ManagerRosterSectionProps {
|
|
594
|
+
readonly tripRef: string;
|
|
595
|
+
/** Same prop shape `ManagerManifestSection` already exposes and
|
|
596
|
+
* `ManagerTripSection` already threads through — reused verbatim, not a
|
|
597
|
+
* new contract. */
|
|
598
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
599
|
+
readonly style?: KaafilTokenOverrides;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
declare function ManagerRosterSection({ tripRef, onOpenTraveller, style, }: ManagerRosterSectionProps): ReactNode;
|
|
603
|
+
|
|
604
|
+
interface ManagerSyncCenterSectionProps {
|
|
605
|
+
/** Scopes the itemized outbox view to one trip's own lane — the real
|
|
606
|
+
* `OutboxOp.tripRef` field. Per spec, `SyncCenterScreen`'s own `tripRef`
|
|
607
|
+
* is optional (aggregating across every open lane when omitted); this
|
|
608
|
+
* composite requires it because every other manager composite in this
|
|
609
|
+
* package is already single-trip-scoped (no cross-trip aggregation
|
|
610
|
+
* exists anywhere else to be consistent with). */
|
|
611
|
+
readonly tripRef: string;
|
|
612
|
+
/** The host supplies this since only it knows every module's own label
|
|
613
|
+
* conventions for a `listName` — omit to fall back to the real
|
|
614
|
+
* `entity.listName` (or the op's own `path` when no `entity` is set)
|
|
615
|
+
* verbatim, never a fabricated generic label. `entityId` is the real
|
|
616
|
+
* `OutboxEntityRef.id`, renamed at this boundary only to keep the bare
|
|
617
|
+
* word "id" out of every exported prop table (U-019/dx-17). */
|
|
618
|
+
readonly getEntityLabel?: (entity: {
|
|
619
|
+
readonly listName: string;
|
|
620
|
+
readonly entityId?: string;
|
|
621
|
+
}) => string;
|
|
622
|
+
/** Fired after a conflict resolves, for host-side telemetry only — per
|
|
623
|
+
* spec, T2. */
|
|
624
|
+
readonly onResolved?: (opId: string, choice: 'keep-queued' | 'keep-current') => void;
|
|
625
|
+
readonly style?: KaafilTokenOverrides;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
declare function ManagerSyncCenterSection({ tripRef, getEntityLabel, onResolved, style, }: ManagerSyncCenterSectionProps): ReactNode;
|
|
629
|
+
|
|
630
|
+
type TravellerDiet = 'V' | 'NV' | 'J';
|
|
631
|
+
interface DietaryRow {
|
|
632
|
+
readonly key: string;
|
|
633
|
+
readonly labelKey: string;
|
|
634
|
+
readonly value: string;
|
|
635
|
+
readonly diet: TravellerDiet | null;
|
|
636
|
+
readonly isAlert: boolean;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
interface TravellerDietaryCardProps {
|
|
640
|
+
readonly rows: readonly DietaryRow[];
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
interface TravellerEmergencyCardProps {
|
|
644
|
+
readonly name: string;
|
|
645
|
+
readonly relation: string | null;
|
|
646
|
+
readonly phone: string | null;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
interface TravellerNote {
|
|
650
|
+
readonly id: string;
|
|
651
|
+
readonly body: string;
|
|
652
|
+
readonly performedByKind: string | null;
|
|
653
|
+
readonly createdAt: string;
|
|
654
|
+
}
|
|
655
|
+
interface TravellerNotesSectionProps {
|
|
656
|
+
readonly notes: readonly TravellerNote[];
|
|
657
|
+
readonly onAddNote: (body: string) => Promise<void>;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
interface TravellerPaymentCardProps {
|
|
661
|
+
readonly currency: string;
|
|
662
|
+
readonly totalMinor: number;
|
|
663
|
+
readonly collectedMinor: number;
|
|
664
|
+
readonly dueMinor: number;
|
|
665
|
+
readonly canLogPayment: boolean;
|
|
666
|
+
readonly onLogPayment: () => void;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
interface ManagerTravellerProfileSectionProps {
|
|
670
|
+
/** The trip this section reads `useTravellerProfile`/`useParties`/
|
|
671
|
+
* `useCollections` for. */
|
|
672
|
+
readonly tripRef: string;
|
|
673
|
+
readonly travellerRef: string;
|
|
674
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`) — the
|
|
675
|
+
* leaf pieces a partner CRM is most likely to reskin. Each receives
|
|
676
|
+
* exactly the same real props this composite's own default renders it
|
|
677
|
+
* with. */
|
|
678
|
+
readonly components?: {
|
|
679
|
+
readonly DietaryCard?: ComponentType<TravellerDietaryCardProps>;
|
|
680
|
+
readonly EmergencyCard?: ComponentType<TravellerEmergencyCardProps>;
|
|
681
|
+
readonly PaymentCard?: ComponentType<TravellerPaymentCardProps>;
|
|
682
|
+
readonly NotesSection?: ComponentType<TravellerNotesSectionProps>;
|
|
683
|
+
};
|
|
684
|
+
readonly style?: KaafilTokenOverrides;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
declare function ManagerTravellerProfileSection({ tripRef, travellerRef, components, style, }: ManagerTravellerProfileSectionProps): ReactNode;
|
|
688
|
+
|
|
689
|
+
/** The one real trip-vs-trek field (`Trip.eventType`, no third value) —
|
|
690
|
+
* derived structurally off `useManagerMe()`'s own trip row so this file
|
|
691
|
+
* never imports `kaafil-js` directly. */
|
|
692
|
+
type ManagerTripEventType = ManagerMeReady['trips'][number]['eventType'];
|
|
693
|
+
/**
|
|
694
|
+
* Every real tab key this composite knows about — the merge this build's
|
|
695
|
+
* own plan locks in: ONE tab set computed from `eventType`, never two
|
|
696
|
+
* independent screens (the boilerplate's own posture, deliberately not
|
|
697
|
+
* followed here). `docs`/`info` are excluded entirely: no real endpoint
|
|
698
|
+
* backs either (this build's own audit), so no tab key is minted for a
|
|
699
|
+
* screen that would always render nothing.
|
|
700
|
+
*/
|
|
701
|
+
type ManagerTripTabKey = 'manifest' | 'rooming' | 'vehicles' | 'itinerary' | 'money' | 'vendors' | 'checklist' | 'forms' | 'pickups' | 'overview' | 'roster' | 'closing' | 'documents';
|
|
702
|
+
interface ManagerTripSectionProps {
|
|
703
|
+
/** The trip this section reads `useManagerMe()`'s own trip list for,
|
|
704
|
+
* resolved by the caller — same convention `ManagerNowSection.tripRef`
|
|
705
|
+
* already establishes. */
|
|
706
|
+
readonly tripRef: string;
|
|
707
|
+
/** Uncontrolled by default (the section owns its own active-tab state,
|
|
708
|
+
* same as `ManagerShell`'s bottom bar being host-controlled while this
|
|
709
|
+
* screen's OWN chip row is nested one level below it) — pass both to
|
|
710
|
+
* control it from outside. */
|
|
711
|
+
readonly activeTabKey?: ManagerTripTabKey;
|
|
712
|
+
readonly onTabChange?: (key: ManagerTripTabKey) => void;
|
|
713
|
+
/** Fired when a booking group's "Collect" CTA is tapped — nav-only
|
|
714
|
+
* (hard rule #9): no group-level collect endpoint exists (`collections`'s
|
|
715
|
+
* DTOs key strictly on `travellerId`), so the host resolves this into
|
|
716
|
+
* whatever real per-traveller flow it wants. Required once the manifest
|
|
717
|
+
* panel is live; a caller with no groups yet may still pass a no-op. */
|
|
718
|
+
readonly onCollectFromGroup: (groupId: string) => void;
|
|
719
|
+
/** Fired when a traveller row is tapped — see
|
|
720
|
+
* `ManagerManifestSectionProps.onOpenTraveller`'s own doc comment (this
|
|
721
|
+
* composite just forwards it to its built-in manifest panel). */
|
|
722
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
723
|
+
/** Fired when a vendor row is tapped in the built-in vendors panel — see
|
|
724
|
+
* `ManagerVendorsSectionProps.onVendorSelect`'s own doc comment (this
|
|
725
|
+
* composite just forwards it). */
|
|
726
|
+
readonly onVendorSelect: (tripVendorId: string) => void;
|
|
727
|
+
/** Forwarded straight through to the built-in `'money'` panel's own
|
|
728
|
+
* `onViewFloatLedger` — see `ManagerMoneySectionProps`'s own doc comment.
|
|
729
|
+
* Omit to hide the "View full ledger" affordance entirely. */
|
|
730
|
+
readonly onViewFloatLedger?: () => void;
|
|
731
|
+
/** Forwarded straight through to the built-in `'closing'` panel's own
|
|
732
|
+
* `onSubmitUnlockRequest` — see `ManagerCloseoutSectionProps`'s own doc
|
|
733
|
+
* comment for why this composite never calls `closeout.unlock()` itself
|
|
734
|
+
* (`apiKeyAuth`-only). Omit to render the built-in closing panel's static
|
|
735
|
+
* "contact ops to reopen" message once locked. */
|
|
736
|
+
readonly onSubmitUnlockRequest?: (payload: {
|
|
737
|
+
readonly tripRef: string;
|
|
738
|
+
readonly reason: string;
|
|
739
|
+
}) => Promise<void>;
|
|
740
|
+
/** Registry of real panel content, keyed by tab (hard rule #8 — never a
|
|
741
|
+
* switch/if-else here). Overrides this composite's OWN built-in panel for
|
|
742
|
+
* a key (`'manifest'`, this wave) when supplied; every other key still
|
|
743
|
+
* renders the built-in "not built yet" placeholder until a later wave
|
|
744
|
+
* fills it — no restructuring required when that happens. */
|
|
745
|
+
readonly panels?: Partial<Record<ManagerTripTabKey, ReactNode>>;
|
|
746
|
+
readonly style?: KaafilTokenOverrides;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
declare function ManagerTripSection(props: ManagerTripSectionProps): ReactNode;
|
|
750
|
+
|
|
751
|
+
interface UnassignedPoolSectionProps {
|
|
752
|
+
readonly travellers: readonly SeatingOccupantRow[];
|
|
753
|
+
readonly loaded: boolean;
|
|
754
|
+
readonly onSelectTraveller: (traveller: SeatingOccupantRow) => void;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
interface VehicleCardProps {
|
|
758
|
+
readonly vehicle: SeatingVehicle;
|
|
759
|
+
readonly ownerName: string | undefined;
|
|
760
|
+
readonly onSelectSeat: (vehicle: SeatingVehicle, seat: SeatingSeatSlot) => void;
|
|
761
|
+
readonly onSelectOccupant: (vehicle: SeatingVehicle, travellerId: string) => void;
|
|
762
|
+
readonly onAddOccupant: (vehicle: SeatingVehicle) => void;
|
|
763
|
+
/** Opens the sheet's `customSeat` flow — a manager types the traveller's
|
|
764
|
+
* REAL boarding-pass/ticket seat number (business rows, exit rows, gaps
|
|
765
|
+
* this vehicle's synthesised grid doesn't model), rather than being
|
|
766
|
+
* limited to the grid's own auto-generated labels. Only offered on a
|
|
767
|
+
* seat-mapped vehicle. */
|
|
768
|
+
readonly onEnterCustomSeat: (vehicle: SeatingVehicle) => void;
|
|
769
|
+
readonly onEditVehicle: (vehicle: SeatingVehicle) => void;
|
|
770
|
+
readonly onEditOwner: (vehicle: SeatingVehicle) => void;
|
|
771
|
+
/** Opens `VehicleRosterSheet` — a full scrollable list of every real
|
|
772
|
+
* occupant on this vehicle, for a capacity too large to scan comfortably
|
|
773
|
+
* as wrapped chips (e.g. a 12-seat tempo traveller). */
|
|
774
|
+
readonly onViewRoster: (vehicle: SeatingVehicle) => void;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
interface VehicleStatsProps {
|
|
778
|
+
readonly vehicleCount: number;
|
|
779
|
+
readonly seated: number;
|
|
780
|
+
readonly capacity: number;
|
|
781
|
+
readonly unassignedCount: number;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
type SeatingVehicleRowRaw = SeatingReady['vehicles'][number];
|
|
785
|
+
type SeatingVehicle = Exclude<SeatingVehicleRowRaw, {
|
|
786
|
+
readonly _tombstone: true;
|
|
787
|
+
}>;
|
|
788
|
+
type SeatingOccupantRow = SeatingReady['unassignedPool']['travellers'][number];
|
|
789
|
+
type SeatingSeatSlot = SeatingVehicle['seats'][number];
|
|
790
|
+
interface ManagerVehiclesSectionProps {
|
|
791
|
+
/** The trip this section reads `useSeating()`'s own reads for. */
|
|
792
|
+
readonly tripRef: string;
|
|
793
|
+
/** Fired when an occupied seat/occupant slot's "View profile" row is
|
|
794
|
+
* tapped — the same real destination `ManagerManifestSection`/
|
|
795
|
+
* `ManagerRoomingSection.onOpenTraveller` already open, so a traveller
|
|
796
|
+
* reachable from the vehicles board lands on the identical
|
|
797
|
+
* `ManagerTravellerProfileSection`. Still fired via a callback rather
|
|
798
|
+
* than a router (hard rule #9). */
|
|
799
|
+
readonly onOpenTraveller: (travellerId: string, fullName: string) => void;
|
|
800
|
+
/** Overrides the "no vehicles yet" empty state — same render-prop shape
|
|
801
|
+
* `ManagerRoomingSection.emptyView`/`ManagerManifestSection.emptyView`
|
|
802
|
+
* already establish. Omit for the built-in message. */
|
|
803
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
804
|
+
/** Tier-4 named-component overrides (`04-customization-ladder.md`'s own
|
|
805
|
+
* "the only way to replace a named component") — the three leaf pieces a
|
|
806
|
+
* partner CRM is most likely to reskin. Each receives EXACTLY the same
|
|
807
|
+
* props this composite's own default renders it with. */
|
|
808
|
+
readonly components?: {
|
|
809
|
+
readonly Stats?: ComponentType<VehicleStatsProps>;
|
|
810
|
+
readonly VehicleCard?: ComponentType<VehicleCardProps>;
|
|
811
|
+
readonly UnassignedPool?: ComponentType<UnassignedPoolSectionProps>;
|
|
812
|
+
};
|
|
813
|
+
readonly style?: KaafilTokenOverrides;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
declare function ManagerVehiclesSection({ tripRef, onOpenTraveller, emptyView, components, style, }: ManagerVehiclesSectionProps): ReactNode;
|
|
817
|
+
|
|
818
|
+
interface VendorListSectionProps {
|
|
819
|
+
readonly vendors: readonly TripVendorRow[];
|
|
820
|
+
readonly onVendorSelect: (tripVendorId: string) => void;
|
|
821
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
type VendorCategory = TripVendorRow['category'];
|
|
825
|
+
interface ManagerVendorsSectionProps {
|
|
826
|
+
/** The trip this section reads `useVendors(tripRef, '')` for. */
|
|
827
|
+
readonly tripRef: string;
|
|
828
|
+
/** Narrows the already-fetched list to one category, client-side — the
|
|
829
|
+
* spec's own claim that this is "the SDK's own `?category=` filter,
|
|
830
|
+
* passed straight through" does not match the real
|
|
831
|
+
* `client.vendors.list()` signature (verified: no such query param
|
|
832
|
+
* exists), so this never round-trips to the server. */
|
|
833
|
+
readonly category?: VendorCategory;
|
|
834
|
+
/** Fired when a vendor row is tapped — a pure passthrough (`10-vendors.md`
|
|
835
|
+
* §VendorList's own "Does NOT": "`onVendorSelect` only reports which row
|
|
836
|
+
* was activated"). No detail sheet exists in this build; the host decides
|
|
837
|
+
* what happens next, the same convention `onOpenTraveller` already
|
|
838
|
+
* establishes elsewhere in this UIKit. */
|
|
839
|
+
readonly onVendorSelect: (tripVendorId: string) => void;
|
|
840
|
+
/** Overrides the default empty state shown when the real list is
|
|
841
|
+
* genuinely empty (zero vendors is a legitimate state, never confused
|
|
842
|
+
* with a dark capability) — same `ReactNode | (() => ReactNode)` shape
|
|
843
|
+
* `ManagerVehiclesSection.emptyView`/`ManagerManifestSection.emptyView`
|
|
844
|
+
* already use. */
|
|
845
|
+
readonly emptyView?: ReactNode | (() => ReactNode);
|
|
846
|
+
/** Tier-4 named-component override — the one genuinely reskinnable
|
|
847
|
+
* region, named after the spec's own `VendorList` component. */
|
|
848
|
+
readonly components?: {
|
|
849
|
+
readonly VendorListUI?: ComponentType<VendorListSectionProps>;
|
|
850
|
+
};
|
|
851
|
+
readonly style?: KaafilTokenOverrides;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
declare function ManagerVendorsSection({ tripRef, category, onVendorSelect, emptyView, components, style, }: ManagerVendorsSectionProps): ReactNode;
|
|
855
|
+
|
|
856
|
+
/** The 3 bottom-nav destinations this Surface owns — Trip/Trek merge into
|
|
857
|
+
* one tab (icon/label switch off the selected trip's real `eventType`),
|
|
858
|
+
* matching `apps/sample-manager/src/App.tsx`'s own real `BottomTabKey`. */
|
|
859
|
+
type KaafilManagerAppTabKey = 'now' | 'trip' | 'me';
|
|
860
|
+
interface TripListRowProps {
|
|
861
|
+
readonly trip: ManagerOwnTrip;
|
|
862
|
+
readonly onSelect: (tripRef: string) => void;
|
|
863
|
+
readonly style?: KaafilTokenOverrides;
|
|
864
|
+
}
|
|
865
|
+
interface KaafilManagerAppProps {
|
|
866
|
+
/** Seeds which trip is selected on first mount — skips the trip-list
|
|
867
|
+
* picker even with 2+ live trips (the deep-link case). Ignored once
|
|
868
|
+
* `selectedTripRef` (below) is supplied, since that makes selection fully
|
|
869
|
+
* host-controlled. */
|
|
870
|
+
readonly initialTripRef?: string;
|
|
871
|
+
/** Fully controls which trip is selected — omit to let this component own
|
|
872
|
+
* its own selection state (seeded by `initialTripRef`, then updated by the
|
|
873
|
+
* trip-list picker / "Me" tab's own trip list / a trip-linked
|
|
874
|
+
* notification, exactly as `apps/sample-manager/src/App.tsx` already
|
|
875
|
+
* does). Supplying this makes the Surface a controlled component for trip
|
|
876
|
+
* selection — `onSelectTrip` still fires so the host can react. */
|
|
877
|
+
readonly selectedTripRef?: string;
|
|
878
|
+
/** Fully controls the bottom-tab selection — omit to let this component
|
|
879
|
+
* own it (defaulting to `'now'`). */
|
|
880
|
+
readonly activeTab?: KaafilManagerAppTabKey;
|
|
881
|
+
/** Seeds `ManagerTripSection`'s own internal chip-tab (Manifest/Rooming/
|
|
882
|
+
* Money/etc.) on first entry into the Trip tab — a second, real
|
|
883
|
+
* deep-linking level below `initialTripRef`/`activeTab` (e.g. landing
|
|
884
|
+
* directly on the Money tab from a push notification). */
|
|
885
|
+
readonly initialTripTabKey?: ManagerTripTabKey;
|
|
886
|
+
/** → `ManagerNowSection.onNavigateModule` (required there). */
|
|
887
|
+
readonly onNavigateModule: (moduleKey: 'manifest' | 'rooming' | 'checklist' | 'docs' | 'closing-day') => void;
|
|
888
|
+
/** → `ManagerNowSection.onLogExpense` (required there). */
|
|
889
|
+
readonly onLogExpense: () => void;
|
|
890
|
+
/** → `ManagerNowSection.onCollectPayment` (required there). */
|
|
891
|
+
readonly onCollectPayment: () => void;
|
|
892
|
+
/** → `ManagerTripSection.onCollectFromGroup` (required there). */
|
|
893
|
+
readonly onCollectFromGroup: (groupId: string) => void;
|
|
894
|
+
/** → `ManagerTripSection.onVendorSelect` (required there). */
|
|
895
|
+
readonly onVendorSelect: (tripVendorId: string) => void;
|
|
896
|
+
/** → `ManagerTripSection.onSubmitUnlockRequest` (optional there — omit to
|
|
897
|
+
* render its own static "contact ops to reopen" message once locked). */
|
|
898
|
+
readonly onSubmitUnlockRequest?: (payload: {
|
|
899
|
+
readonly tripRef: string;
|
|
900
|
+
readonly reason: string;
|
|
901
|
+
}) => Promise<void>;
|
|
902
|
+
/** Renders "Sign out" on the Me tab only when supplied (prop-presence
|
|
903
|
+
* gates the affordance, same convention `ManagerMeSection` itself already
|
|
904
|
+
* establishes) — this Surface has no credential/session-teardown method
|
|
905
|
+
* of its own to call first. */
|
|
906
|
+
readonly onSignOut?: () => void;
|
|
907
|
+
/** Fires whenever the selected trip changes (picker row tap, the Me tab's
|
|
908
|
+
* own trip list, or a trip-linked notification) — per spec, T2. */
|
|
909
|
+
readonly onSelectTrip?: (tripRef: string) => void;
|
|
910
|
+
/** Fires whenever the bottom tab changes — per spec, T2. */
|
|
911
|
+
readonly onTabChange?: (tabKey: KaafilManagerAppTabKey) => void;
|
|
912
|
+
/** Fires whenever `ManagerTripSection`'s own internal chip-tab changes —
|
|
913
|
+
* the second deep-linking level `initialTripTabKey` seeds. */
|
|
914
|
+
readonly onTripTabChange?: (tabKey: ManagerTripTabKey) => void;
|
|
915
|
+
/** Fired alongside the internal traveller-profile push opening/closing —
|
|
916
|
+
* an analytics/URL-sync hook, never the only way this navigation happens
|
|
917
|
+
* (the real trigger is always a row tap inside a mounted composite). */
|
|
918
|
+
readonly onOpenTraveller?: (travellerId: string, fullName: string) => void;
|
|
919
|
+
readonly onCloseTraveller?: () => void;
|
|
920
|
+
/** Fired alongside the internal notifications push opening/closing. */
|
|
921
|
+
readonly onOpenNotifications?: () => void;
|
|
922
|
+
readonly onCloseNotifications?: () => void;
|
|
923
|
+
/** Fired alongside the internal float-ledger push opening/closing. */
|
|
924
|
+
readonly onOpenFloatLedger?: () => void;
|
|
925
|
+
readonly onCloseFloatLedger?: () => void;
|
|
926
|
+
/** Fired alongside the internal sync-center push opening/closing — the
|
|
927
|
+
* real destination the connectivity badge's own "N need attention" text
|
|
928
|
+
* opens (`ManagerSyncCenterSection`); a caught bug this wave: that text
|
|
929
|
+
* rendered with nowhere to go before this push existed. */
|
|
930
|
+
readonly onOpenSyncCenter?: () => void;
|
|
931
|
+
readonly onCloseSyncCenter?: () => void;
|
|
932
|
+
/** → `ManagerSyncCenterSection.getEntityLabel` (optional there; `entityId`
|
|
933
|
+
* is that composite's own renamed `OutboxEntityRef.id`, kept consistent
|
|
934
|
+
* at this boundary too so this prop table stays free of the bare word
|
|
935
|
+
* "id", U-019/dx-17). */
|
|
936
|
+
readonly getSyncEntityLabel?: (entity: {
|
|
937
|
+
readonly listName: string;
|
|
938
|
+
readonly entityId?: string;
|
|
939
|
+
}) => string;
|
|
940
|
+
/** → `ManagerSyncCenterSection.onResolved` (optional there). */
|
|
941
|
+
readonly onConflictResolved?: (opId: string, choice: 'keep-queued' | 'keep-current') => void;
|
|
942
|
+
readonly components?: {
|
|
943
|
+
/** The trip-list picker's own row renderer (spec-named). */
|
|
944
|
+
readonly TripListItem?: ComponentType<TripListRowProps>;
|
|
945
|
+
/** Maps onto `ManagerShell`'s own existing `components.TabIcon` slot —
|
|
946
|
+
* the only real tab-bar customization point that exists today.
|
|
947
|
+
* Deliberately narrower than the spec's "TabBar" name implies:
|
|
948
|
+
* `ManagerShell` has no slot to replace the whole tab-bar chrome with,
|
|
949
|
+
* so this Surface does not invent a second, parallel tab-bar renderer
|
|
950
|
+
* just to satisfy the literal name (one mechanism per slot, U-004). */
|
|
951
|
+
readonly TabBar?: ComponentType<{
|
|
952
|
+
readonly icon: string;
|
|
953
|
+
}>;
|
|
954
|
+
/** Overrides the honest "no active trip assignment" empty state — real
|
|
955
|
+
* integrators reskin/rebrand this message, they don't fabricate a fake
|
|
956
|
+
* trip to avoid it. */
|
|
957
|
+
readonly EmptyState?: ComponentType<Record<string, never>>;
|
|
958
|
+
/** Overrides the initial loading skeleton. */
|
|
959
|
+
readonly LoadingView?: ComponentType<Record<string, never>>;
|
|
960
|
+
/** Overrides the unconditional connectivity indicator (spec: "not a
|
|
961
|
+
* prop an integrator can turn off" — replacing its PRESENTATION is
|
|
962
|
+
* still allowed; only removing it entirely is not, so this slot has no
|
|
963
|
+
* `false`/hide variant). */
|
|
964
|
+
readonly SyncStatusBadge?: ComponentType<{
|
|
965
|
+
readonly isOnline: boolean;
|
|
966
|
+
readonly pending: number;
|
|
967
|
+
readonly parked: number;
|
|
968
|
+
readonly onOpenSyncCenter?: () => void;
|
|
969
|
+
}>;
|
|
970
|
+
};
|
|
971
|
+
readonly style?: KaafilTokenOverrides;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
declare function KaafilManagerApp(props: KaafilManagerAppProps): ReactNode;
|
|
975
|
+
|
|
976
|
+
interface ManagerFabProps {
|
|
977
|
+
readonly onClick: () => void;
|
|
978
|
+
/** Accessible name — there is no visible label on the button itself
|
|
979
|
+
* (boilerplate's own `MFab`: an icon-only circle), so this is required,
|
|
980
|
+
* never optional. */
|
|
981
|
+
readonly label: string;
|
|
982
|
+
/** Defaults to a plus glyph — the one icon every family composite that
|
|
983
|
+
* has reached for a FAB so far has needed (`ManagerNowSection`'s own
|
|
984
|
+
* quick-actions trigger); pass a different icon for a family composite
|
|
985
|
+
* that needs a different primary action. */
|
|
986
|
+
readonly icon?: ReactNode;
|
|
987
|
+
readonly tone?: 'accent' | 'ink';
|
|
988
|
+
readonly style?: KaafilTokenOverrides;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
declare function ManagerFab({ onClick, label, icon, tone, style, }: ManagerFabProps): ReactNode;
|
|
992
|
+
|
|
993
|
+
interface ManagerShellTab {
|
|
994
|
+
readonly key: string;
|
|
995
|
+
readonly label: string;
|
|
996
|
+
/** One glyph, `icon="clock"` etc. — a registry key (hard rule #8), never
|
|
997
|
+
* an inline SVG passed per-tab (`ManagerShell` owns its own icon set,
|
|
998
|
+
* matching the boilerplate's own fixed 4-icon tab bar; a host wanting a
|
|
999
|
+
* fifth tab's own glyph uses `components.TabIcon`). */
|
|
1000
|
+
readonly icon: 'now' | 'trek' | 'trip' | 'me';
|
|
1001
|
+
}
|
|
1002
|
+
interface ManagerShellHeaderPage {
|
|
1003
|
+
readonly variant?: 'page';
|
|
1004
|
+
readonly eyebrow?: string;
|
|
1005
|
+
readonly title: string;
|
|
1006
|
+
/** Real unread count (`useNotifications()`'s own `unreadCount`) — never a
|
|
1007
|
+
* boolean or a guessed number; omit entirely to hide the bell. */
|
|
1008
|
+
readonly unread?: number;
|
|
1009
|
+
readonly onBellPress?: () => void;
|
|
1010
|
+
/** 2-letter avatar initials — omit renders a person glyph, never a "?"
|
|
1011
|
+
* (boilerplate's own `m-header.tsx` documents exactly this reasoning:
|
|
1012
|
+
* a question mark on your own avatar reads as "we don't know who you
|
|
1013
|
+
* are," which is never true once a session is open). */
|
|
1014
|
+
readonly avatarInitials?: string;
|
|
1015
|
+
readonly onAvatarPress?: () => void;
|
|
1016
|
+
/** Replaces the whole right-hand slot (bell + avatar) at once. */
|
|
1017
|
+
readonly right?: ReactNode;
|
|
1018
|
+
readonly style?: KaafilTokenOverrides;
|
|
1019
|
+
}
|
|
1020
|
+
interface ManagerShellHeaderBack {
|
|
1021
|
+
readonly variant: 'back';
|
|
1022
|
+
readonly eyebrow?: string;
|
|
1023
|
+
readonly title: string;
|
|
1024
|
+
readonly onBack: () => void;
|
|
1025
|
+
readonly right?: ReactNode;
|
|
1026
|
+
readonly style?: KaafilTokenOverrides;
|
|
1027
|
+
}
|
|
1028
|
+
type ManagerShellHeaderConfig = ManagerShellHeaderPage | ManagerShellHeaderBack;
|
|
1029
|
+
interface ManagerShellProps {
|
|
1030
|
+
readonly children?: ReactNode;
|
|
1031
|
+
/** Omit to render no header at all — a screen that wants a "back" header
|
|
1032
|
+
* passes `{ variant: 'back', ... }` here instead of mounting its own. */
|
|
1033
|
+
readonly header?: ManagerShellHeaderConfig;
|
|
1034
|
+
/** Omit to render no tab bar (e.g. a screen pushed on top of the tab
|
|
1035
|
+
* stack) — the tab bar is never assumed present. */
|
|
1036
|
+
readonly tabs?: readonly ManagerShellTab[];
|
|
1037
|
+
readonly activeTabKey?: string;
|
|
1038
|
+
readonly onTabChange?: (key: string) => void;
|
|
1039
|
+
/** The floating action button slot — a fully caller-owned node (usually
|
|
1040
|
+
* an `MFab`-equivalent button this family will ship once the FAB pattern
|
|
1041
|
+
* is needed by more than one composite); `ManagerShell` only positions
|
|
1042
|
+
* it, never renders a default. */
|
|
1043
|
+
readonly fab?: ReactNode;
|
|
1044
|
+
readonly components?: {
|
|
1045
|
+
readonly TabIcon?: ComponentType<{
|
|
1046
|
+
readonly icon: string;
|
|
1047
|
+
}>;
|
|
1048
|
+
};
|
|
1049
|
+
readonly style?: KaafilTokenOverrides;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
declare function ManagerShell({ children, header, tabs, activeTabKey, onTabChange, fab, style, }: ManagerShellProps): ReactNode;
|
|
1053
|
+
|
|
1054
|
+
export { type ChecklistItemDeltaRow, type ChecklistItemGate, type ChecklistItemLiveRow, type ChecklistItemPhase, ChecklistSectionRow, CloseoutBlockerRow, FormDefinitionDetail, FormResponseDetail, type ItineraryChangeLogRow, ItineraryDayRow, ItineraryItemRow, KaafilManagerApp, type KaafilManagerAppProps, type KaafilManagerAppTabKey, ManagerChecklistSection, type ManagerChecklistSectionProps, ManagerCloseoutSection, type ManagerCloseoutSectionProps, ManagerDocumentsSection, type ManagerDocumentsSectionProps, ManagerFab, type ManagerFabProps, ManagerFloatLedgerSection, type ManagerFloatLedgerSectionProps, ManagerFormsSection, type ManagerFormsSectionProps, ManagerItinerarySection, type ManagerItinerarySectionProps, ManagerManifestSection, type ManagerManifestSectionProps, ManagerMeSection, type ManagerMeSectionProps, ManagerMoneySection, type ManagerMoneySectionProps, ManagerNotificationsSection, type ManagerNotificationsSectionProps, ManagerNowSection, type ManagerNowSectionProps, type ManagerNowSectionUIProps, ManagerOverviewSection, type ManagerOverviewSectionProps, ManagerPickupsSection, type ManagerPickupsSectionProps, ManagerRoomingSection, type ManagerRoomingSectionProps, ManagerRosterSection, type ManagerRosterSectionProps, ManagerShell, type ManagerShellHeaderBack, type ManagerShellHeaderConfig, type ManagerShellHeaderPage, type ManagerShellProps, type ManagerShellTab, ManagerSyncCenterSection, type ManagerSyncCenterSectionProps, type ManagerTodayEngaged, type ManagerTodayIdle, ManagerTravellerProfileSection, type ManagerTravellerProfileSectionProps, type ManagerTripEventType, ManagerTripSection, type ManagerTripSectionProps, type ManagerTripTabKey, ManagerVehiclesSection, type ManagerVehiclesSectionProps, ManagerVendorsSection, type ManagerVendorsSectionProps, type ManifestBookingGroup, type ManifestBookingStatus, type ManifestDiet, type ManifestTraveller, PickupManifestResult, type RoomingAutoAssignResult, type RoomingBed, type RoomingOccupantRow, type RoomingRoom, type RoomingStayWindow, type SeatingOccupantRow, type SeatingSeatSlot, type SeatingVehicle, TravellerFormResponseRow, TripFormRow, type TripListRowProps, TripVendorRow, type VendorCategory };
|