@qite/tide-components 1.0.14-preview.1 → 1.0.14-preview.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ import { AgentPrintAction, CustomEntryStatusItem, DossierViewResult, FilterItem, NumberStringPair, PageResult, TideClientConfig } from '@qite/tide-client';
2
+ import { AgentEntriesColumn, AgentEntriesSort } from './types';
3
+ /** Agent endpoints need the member token, fall back to the one the Login component stored. */
4
+ export declare const withAgentToken: (config: TideClientConfig) => TideClientConfig;
5
+ /** False when the token is not a JWT or has expired. */
6
+ export declare const isAgentTokenValid: (token?: string) => boolean;
7
+ export declare const isUnauthorizedError: (error: unknown, token?: string) => boolean;
8
+ export interface AgentEntriesLookups {
9
+ entryStatuses: NumberStringPair[];
10
+ customEntryStatuses: CustomEntryStatusItem[];
11
+ printActions: AgentPrintAction[];
12
+ }
13
+ export declare const fetchLookups: (config: TideClientConfig, languageCode: string, signal: AbortSignal) => Promise<AgentEntriesLookups>;
14
+ /** Converts the raw filter inputs to the OData column filters understood by tide-client's createParams. */
15
+ export declare const buildFilterItem: (columns: AgentEntriesColumn[], filterValues: Record<string, string>, sort: AgentEntriesSort, page: number, take: number) => FilterItem;
16
+ export declare const fetchEntries: (config: TideClientConfig, filter: FilterItem, signal: AbortSignal) => Promise<PageResult<DossierViewResult>>;
17
+ /** Prints the entry and returns an object url to the resulting pdf. */
18
+ export declare const printEntry: (config: TideClientConfig, printActionId: number, entryId: number) => Promise<string>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { AgentEntriesProps } from './types';
3
+ declare const AgentEntries: React.FC<AgentEntriesProps>;
4
+ export default AgentEntries;
@@ -0,0 +1,27 @@
1
+ import { TideClientConfig } from '@qite/tide-client';
2
+ export interface AgentEntriesProps {
3
+ /** Tide connection. When no `token` is set, the agent token saved by the Login component (session/localStorage 'token') is used. */
4
+ tideClientConfig: TideClientConfig;
5
+ languageCode: string;
6
+ /** Title above the table, defaults to the translated "Bookings". */
7
+ title?: string;
8
+ /** Initial number of rows per page, defaults to 20. */
9
+ pageSize?: number;
10
+ /** Partial translation overrides, deep-merged over the built-in AGENT_ENTRIES translations. */
11
+ customTranslations?: any;
12
+ /** When set, a login button is shown when no agent is logged in or the session expired. */
13
+ onLogin?: () => void;
14
+ /** Called when the API rejects the agent token (e.g. expired). */
15
+ onUnauthorized?: () => void;
16
+ }
17
+ export type AgentEntriesColumnKind = 'text' | 'date' | 'number' | 'status' | 'customStatus';
18
+ export interface AgentEntriesColumn {
19
+ /** OData field name on the entry list (DossierViewResult). */
20
+ id: string;
21
+ kind: AgentEntriesColumnKind;
22
+ label: string;
23
+ }
24
+ export interface AgentEntriesSort {
25
+ name: string;
26
+ asc: boolean;
27
+ }
@@ -29,4 +29,5 @@ export interface NavbarProps {
29
29
  member?: MemberInfo;
30
30
  onLogin?: () => void;
31
31
  onLogout?: () => void;
32
+ onMyBookings?: () => void;
32
33
  }
@@ -8,6 +8,7 @@ import TideForm from './form';
8
8
  import SearchResults from './search-results';
9
9
  import ImageCardGrid from './content/image-card-grid';
10
10
  import Login from './content/login';
11
+ import AgentEntries from './content/agent-entries';
11
12
  import ImageWithTextSection from './content/image-with-text-section';
12
13
  import Slider from './content/components/slider';
13
14
  import PhotoGallery from './content/components/gallery';
@@ -21,9 +22,10 @@ export * from './content/header/types';
21
22
  export * from './content/footer/types';
22
23
  export * from './content/image-card-grid/types';
23
24
  export * from './content/login/types';
25
+ export * from './content/agent-entries/types';
24
26
  export * from './content/image-with-text-section/types';
25
27
  export * from './search-results/types';
26
28
  export * from './qsm/types';
27
29
  export * from './shared/types';
28
30
  export * from './content/featured-trips/types';
29
- export { BookingProduct, BookingWizard, QSM, SearchResults, Navbar, Header, Footer, ImageCardGrid, Login, ImageWithTextSection, Slider, PhotoGallery, Breadcrumbs, FAQ, FeaturedTrips, Spinner, ItineraryMapView, TideForm };
31
+ export { BookingProduct, BookingWizard, QSM, SearchResults, Navbar, Header, Footer, ImageCardGrid, Login, AgentEntries, ImageWithTextSection, Slider, PhotoGallery, Breadcrumbs, FAQ, FeaturedTrips, Spinner, ItineraryMapView, TideForm };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface TrajectCardRowProps {
3
+ selectionKey: string;
4
+ children: React.ReactNode;
5
+ }
6
+ declare const TrajectCardRow: React.FC<TrajectCardRowProps>;
7
+ export default TrajectCardRow;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-components",
3
- "version": "1.0.14-preview.1",
3
+ "version": "1.0.14-preview.3",
4
4
  "description": "React components for Tide (booking, product availability, form, ...)",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",
@@ -0,0 +1,336 @@
1
+ @use '../components/mixins' as mixins;
2
+
3
+ .agent-entries {
4
+ @include mixins.container-wide();
5
+ display: flex;
6
+ flex-direction: column;
7
+ gap: 12px;
8
+ padding-top: 30px;
9
+ padding-bottom: 60px;
10
+ color: var(--tide-booking-text-dark);
11
+
12
+ &__title {
13
+ margin: 0;
14
+ font-size: 22px;
15
+ font-weight: 400;
16
+ }
17
+
18
+ &__sr-only {
19
+ position: absolute;
20
+ width: 1px;
21
+ height: 1px;
22
+ padding: 0;
23
+ margin: -1px;
24
+ overflow: hidden;
25
+ clip: rect(0, 0, 0, 0);
26
+ border: 0;
27
+ }
28
+
29
+ &__icon {
30
+ width: 14px;
31
+ height: 14px;
32
+ }
33
+
34
+ &__card {
35
+ background-color: var(--tide-booking-white);
36
+ border-radius: 8px;
37
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
38
+ overflow: hidden;
39
+ transition: opacity 0.2s ease;
40
+
41
+ &--loading {
42
+ opacity: 0.6;
43
+ }
44
+ }
45
+
46
+ &__table-wrapper {
47
+ overflow-x: auto;
48
+ }
49
+
50
+ &__table {
51
+ width: 100%;
52
+ border-collapse: collapse;
53
+ font-size: var(--tide-booking-font-size-body);
54
+
55
+ th,
56
+ td {
57
+ padding: 8px 7px;
58
+ text-align: left;
59
+ vertical-align: middle;
60
+ white-space: nowrap;
61
+ }
62
+
63
+ thead th {
64
+ font-weight: 600;
65
+ border-bottom: 1px solid var(--tide-booking-gray-background-light);
66
+ }
67
+ }
68
+
69
+ &__sort {
70
+ display: inline-flex;
71
+ align-items: center;
72
+ gap: 6px;
73
+ padding: 4px 0;
74
+ border: none;
75
+ background: none;
76
+ font: inherit;
77
+ font-weight: 600;
78
+ color: inherit;
79
+ cursor: pointer;
80
+
81
+ &:hover {
82
+ color: var(--tide-booking-color-primary);
83
+ }
84
+ }
85
+
86
+ &__sort-icon {
87
+ width: 9px;
88
+ height: 12px;
89
+
90
+ &--desc {
91
+ transform: rotate(180deg);
92
+ }
93
+ }
94
+
95
+ &__filter-row th {
96
+ font-weight: 400;
97
+ }
98
+
99
+ // Nested under the row to win over the generic `#tide-content input` rules.
100
+ &__filter-row .agent-entries__filter {
101
+ width: 100%;
102
+ min-width: 90px;
103
+ height: 34px;
104
+ min-height: 34px;
105
+ padding: 4px 8px;
106
+ border: 1px solid var(--tide-booking-gray-medium);
107
+ border-radius: 4px;
108
+ background-color: var(--tide-booking-white);
109
+ font: inherit;
110
+ color: inherit;
111
+
112
+ &:focus {
113
+ outline: none;
114
+ border-color: var(--tide-booking-color-primary);
115
+ }
116
+ }
117
+
118
+ &__row {
119
+ background-color: var(--tide-booking-gray-xlight);
120
+
121
+ td {
122
+ border-bottom: 1px solid var(--tide-booking-gray-background-light);
123
+ }
124
+
125
+ &:hover,
126
+ &--expanded {
127
+ background-color: var(--tide-booking-color-primary-extra-fade);
128
+ }
129
+ }
130
+
131
+ &__table td.agent-entries__cell--date,
132
+ &__table td.agent-entries__cell--number {
133
+ text-align: right;
134
+ }
135
+
136
+ &__actions {
137
+ display: flex;
138
+ gap: 6px;
139
+ }
140
+
141
+ &__action {
142
+ display: inline-flex;
143
+ align-items: center;
144
+ justify-content: center;
145
+ width: 28px;
146
+ height: 28px;
147
+ padding: 0;
148
+ border: none;
149
+ border-radius: 4px;
150
+ background-color: var(--tide-booking-gray--medium-light);
151
+ color: var(--tide-booking-black);
152
+ cursor: pointer;
153
+
154
+ &:hover {
155
+ background-color: var(--tide-booking-gray-background-light);
156
+ }
157
+
158
+ &--primary {
159
+ background-color: var(--tide-booking-color-primary);
160
+ color: var(--tide-booking-white);
161
+
162
+ &:hover {
163
+ background-color: var(--tide-booking-color-primary-dark);
164
+ }
165
+ }
166
+
167
+ &:disabled {
168
+ opacity: 0.5;
169
+ cursor: progress;
170
+ }
171
+ }
172
+
173
+ &__empty {
174
+ padding: 24px 12px !important;
175
+ text-align: center !important;
176
+ color: var(--tide-booking-text-medium);
177
+ }
178
+
179
+ &__details-row > td {
180
+ padding: 0 !important;
181
+ white-space: normal !important;
182
+ border-bottom: 1px solid var(--tide-booking-gray-background-light);
183
+ background-color: var(--tide-booking-white);
184
+ }
185
+
186
+ &__details {
187
+ display: flex;
188
+ flex-direction: column;
189
+ gap: 16px;
190
+ padding: 16px 20px;
191
+
192
+ &__list {
193
+ display: grid;
194
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
195
+ gap: 12px 24px;
196
+ margin: 0;
197
+ }
198
+
199
+ &__item {
200
+ dt {
201
+ font-size: 12px;
202
+ color: var(--tide-booking-text-medium);
203
+ margin-bottom: 4px;
204
+ }
205
+
206
+ dd {
207
+ margin: 0;
208
+ line-height: 1.4;
209
+ }
210
+ }
211
+
212
+ &__prints {
213
+ display: flex;
214
+ flex-direction: column;
215
+ gap: 8px;
216
+
217
+ &__title {
218
+ font-size: 12px;
219
+ color: var(--tide-booking-text-medium);
220
+ }
221
+
222
+ &__buttons {
223
+ display: flex;
224
+ flex-wrap: wrap;
225
+ gap: 8px;
226
+ }
227
+ }
228
+ }
229
+
230
+ &__print-button {
231
+ display: inline-flex;
232
+ align-items: center;
233
+ gap: 8px;
234
+ padding: 8px 12px;
235
+ border: 1px solid var(--tide-booking-gray-medium);
236
+ border-radius: 4px;
237
+ background-color: var(--tide-booking-white);
238
+ font: inherit;
239
+ color: inherit;
240
+ cursor: pointer;
241
+
242
+ &:hover {
243
+ border-color: var(--tide-booking-color-primary);
244
+ color: var(--tide-booking-color-primary);
245
+ }
246
+
247
+ &:disabled {
248
+ opacity: 0.5;
249
+ cursor: progress;
250
+ }
251
+ }
252
+
253
+ &__footer {
254
+ display: flex;
255
+ align-items: center;
256
+ flex-wrap: wrap;
257
+ gap: 14px;
258
+ padding: 14px;
259
+ background-color: var(--tide-booking-gray-xlight);
260
+ font-size: 13px;
261
+ }
262
+
263
+ &__footer .agent-entries__page-size {
264
+ height: 36px;
265
+ min-height: 36px;
266
+ padding: 4px 8px;
267
+ border: 1px solid var(--tide-booking-gray-medium);
268
+ border-radius: 4px;
269
+ background-color: var(--tide-booking-white);
270
+ font: inherit;
271
+ font-size: 15px;
272
+ color: inherit;
273
+ }
274
+
275
+ &__pager {
276
+ display: flex;
277
+ align-items: center;
278
+ gap: 10px;
279
+ margin-left: auto;
280
+
281
+ &__button {
282
+ padding: 6px 12px;
283
+ border: 1px solid var(--tide-booking-gray-medium);
284
+ border-radius: 4px;
285
+ background-color: var(--tide-booking-white);
286
+ font: inherit;
287
+ color: inherit;
288
+ cursor: pointer;
289
+
290
+ &:hover:not(:disabled) {
291
+ border-color: var(--tide-booking-color-primary);
292
+ color: var(--tide-booking-color-primary);
293
+ }
294
+
295
+ &:disabled {
296
+ opacity: 0.4;
297
+ cursor: default;
298
+ }
299
+ }
300
+ }
301
+
302
+ &__message {
303
+ display: flex;
304
+ flex-direction: column;
305
+ align-items: flex-start;
306
+ gap: 16px;
307
+ padding: 24px;
308
+ background-color: var(--tide-booking-white);
309
+ border-radius: 8px;
310
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
311
+
312
+ p {
313
+ margin: 0;
314
+ }
315
+ }
316
+
317
+ &__error {
318
+ display: flex;
319
+ align-items: center;
320
+ justify-content: space-between;
321
+ gap: 12px;
322
+ padding: 10px 14px;
323
+ border-radius: 4px;
324
+ background-color: var(--tide-booking-invalid-light);
325
+ color: var(--tide-booking-invalid-dark);
326
+
327
+ &__close {
328
+ border: none;
329
+ background: none;
330
+ font-size: 18px;
331
+ line-height: 1;
332
+ color: inherit;
333
+ cursor: pointer;
334
+ }
335
+ }
336
+ }
@@ -24,6 +24,7 @@ body {
24
24
  @import './components/gallery';
25
25
  @import './components/faq';
26
26
  @import './components/login';
27
+ @import './components/agent-entries';
27
28
  @import './components/accordion';
28
29
  @import './components/footer';
29
30
  @import './components/error';