related-ui-components 2.1.8 → 2.2.0
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/lib/module/app.js +3 -7
- package/lib/module/app.js.map +1 -1
- package/lib/module/components/TravelBooking/CarRentalForm.js +17 -13
- package/lib/module/components/TravelBooking/CarRentalForm.js.map +1 -1
- package/lib/module/components/TravelBooking/FlightForm.js +19 -10
- package/lib/module/components/TravelBooking/FlightForm.js.map +1 -1
- package/lib/module/components/TravelBooking/FlightSummary.js +28 -17
- package/lib/module/components/TravelBooking/FlightSummary.js.map +1 -1
- package/lib/module/components/TravelBooking/HotelForm.js +12 -3
- package/lib/module/components/TravelBooking/HotelForm.js.map +1 -1
- package/lib/module/components/TravelBooking/index.js +18 -20
- package/lib/module/components/TravelBooking/index.js.map +1 -1
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/typescript/src/app.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/CarRentalForm.d.ts +8 -0
- package/lib/typescript/src/components/TravelBooking/CarRentalForm.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/FlightForm.d.ts +7 -0
- package/lib/typescript/src/components/TravelBooking/FlightForm.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/FlightSummary.d.ts +2 -0
- package/lib/typescript/src/components/TravelBooking/FlightSummary.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/HotelForm.d.ts +6 -0
- package/lib/typescript/src/components/TravelBooking/HotelForm.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/index.d.ts +17 -1
- package/lib/typescript/src/components/TravelBooking/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts +1 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/app.tsx +7 -1
- package/src/components/TravelBooking/CarRentalForm.tsx +96 -57
- package/src/components/TravelBooking/FlightForm.tsx +70 -47
- package/src/components/TravelBooking/FlightSummary.tsx +49 -40
- package/src/components/TravelBooking/HotelForm.tsx +71 -43
- package/src/components/TravelBooking/index.ts +17 -17
- package/src/components/index.ts +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ThemeType, useTheme } from "../../theme";
|
|
2
|
-
import React, { useCallback, useMemo, useRef, useState } from "react";
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import {
|
|
4
4
|
View,
|
|
5
5
|
Text,
|
|
@@ -39,6 +39,13 @@ export interface FlightFormProps {
|
|
|
39
39
|
}) => void;
|
|
40
40
|
onTextChange?: (text: string) => void;
|
|
41
41
|
|
|
42
|
+
onSelectionChange?: (details: {
|
|
43
|
+
from: LocationData | undefined;
|
|
44
|
+
to: LocationData | undefined;
|
|
45
|
+
departure: string | undefined; // Send YYYY-MM-DD
|
|
46
|
+
return?: string | undefined; // Send YYYY-MM-DD
|
|
47
|
+
}) => void;
|
|
48
|
+
|
|
42
49
|
fromLabel?: string;
|
|
43
50
|
fromPlaceholder?: string;
|
|
44
51
|
|
|
@@ -56,34 +63,35 @@ export interface FlightFormProps {
|
|
|
56
63
|
suggestionData?: FlightSuggestions[];
|
|
57
64
|
|
|
58
65
|
// --- Style Props ---
|
|
59
|
-
containerStyle?: StyleProp<ViewStyle>;
|
|
60
|
-
inputGroupContainerStyle?: StyleProp<ViewStyle>;
|
|
61
|
-
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
62
|
-
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
63
|
-
|
|
66
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
67
|
+
inputGroupContainerStyle?: StyleProp<ViewStyle>;
|
|
68
|
+
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
69
|
+
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
70
|
+
inputStyle?: StyleProp<ViewStyle>;
|
|
71
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
64
72
|
swapButtonContainerStyle?: StyleProp<ViewStyle>;
|
|
65
73
|
swapButtonStyle?: StyleProp<ViewStyle>;
|
|
66
74
|
swapIconStyle?: StyleProp<TextStyle>;
|
|
67
|
-
departureRowStyle?: StyleProp<ViewStyle>;
|
|
75
|
+
departureRowStyle?: StyleProp<ViewStyle>;
|
|
68
76
|
searchButtonStyle?: StyleProp<ViewStyle>;
|
|
69
|
-
searchIconStyle?: StyleProp<TextStyle>;
|
|
77
|
+
searchIconStyle?: StyleProp<TextStyle>;
|
|
70
78
|
|
|
71
79
|
// DateRangePicker specific styles (passed down)
|
|
72
80
|
dateRangePickerOuterContainerStyle?: StyleProp<ViewStyle>;
|
|
73
81
|
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
74
82
|
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
75
|
-
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
83
|
+
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
76
84
|
|
|
77
85
|
// SuggestionList specific styles
|
|
78
86
|
suggestionListContainerStyle?: StyleProp<ViewStyle>;
|
|
79
87
|
// Styles for the default suggestion item rendering
|
|
80
|
-
suggestionItemGroupStyle?: StyleProp<ViewStyle>;
|
|
81
|
-
suggestionCityRowStyle?: StyleProp<ViewStyle>;
|
|
82
|
-
suggestionCityIconStyle?: StyleProp<TextStyle>;
|
|
83
|
-
suggestionCityTextStyle?: StyleProp<TextStyle>;
|
|
88
|
+
suggestionItemGroupStyle?: StyleProp<ViewStyle>;
|
|
89
|
+
suggestionCityRowStyle?: StyleProp<ViewStyle>;
|
|
90
|
+
suggestionCityIconStyle?: StyleProp<TextStyle>;
|
|
91
|
+
suggestionCityTextStyle?: StyleProp<TextStyle>;
|
|
84
92
|
suggestionAirportTouchableStyle?: StyleProp<ViewStyle>;
|
|
85
93
|
suggestionAirportIconStyle?: StyleProp<TextStyle>;
|
|
86
|
-
suggestionAirportTextStyle?: StyleProp<TextStyle>;
|
|
94
|
+
suggestionAirportTextStyle?: StyleProp<TextStyle>;
|
|
87
95
|
}
|
|
88
96
|
// --- Component ---
|
|
89
97
|
const FlightForm: React.FC<FlightFormProps> = ({
|
|
@@ -130,6 +138,8 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
130
138
|
suggestionAirportTouchableStyle,
|
|
131
139
|
suggestionAirportIconStyle,
|
|
132
140
|
suggestionAirportTextStyle,
|
|
141
|
+
inputStyle,
|
|
142
|
+
onSelectionChange
|
|
133
143
|
}) => {
|
|
134
144
|
const { theme, isRTL } = useTheme();
|
|
135
145
|
const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]);
|
|
@@ -160,6 +170,15 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
160
170
|
onSwapPress?.(currentFrom, currentTo);
|
|
161
171
|
}, [fromLocation, toLocation, onSwapPress]);
|
|
162
172
|
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
onSelectionChange?.({
|
|
175
|
+
from: fromLocation,
|
|
176
|
+
to: toLocation,
|
|
177
|
+
departure: departureDate,
|
|
178
|
+
return: isOneWay ? undefined : returnDate,
|
|
179
|
+
});
|
|
180
|
+
}, [fromLocation, toLocation, departureDate, returnDate, isOneWay, onSelectionChange]);
|
|
181
|
+
|
|
163
182
|
const handleSearch = useCallback(() => {
|
|
164
183
|
onSearchPress?.({
|
|
165
184
|
from: fromLocation,
|
|
@@ -233,6 +252,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
233
252
|
setFromLocation(text);
|
|
234
253
|
onTextChange?.(text);
|
|
235
254
|
}}
|
|
255
|
+
inputStyle={inputStyle}
|
|
236
256
|
label={fromLabel}
|
|
237
257
|
value={fromLocation}
|
|
238
258
|
labelStyle={[styles.label, labelStyle]}
|
|
@@ -248,7 +268,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
248
268
|
}
|
|
249
269
|
}, 150);
|
|
250
270
|
}}
|
|
251
|
-
|
|
271
|
+
inputContainerStyle={customInputContainerStyle}
|
|
252
272
|
/>
|
|
253
273
|
{suggestionData && (
|
|
254
274
|
<SuggestionList
|
|
@@ -260,20 +280,22 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
260
280
|
)}
|
|
261
281
|
</View>
|
|
262
282
|
|
|
263
|
-
|
|
264
|
-
<
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
283
|
+
{onSwapPress && (
|
|
284
|
+
<View style={[styles.swapButtonContainer, swapButtonContainerStyle]}>
|
|
285
|
+
<TouchableOpacity
|
|
286
|
+
style={[styles.swapButton, swapButtonStyle]}
|
|
287
|
+
onPress={handleSwap}
|
|
288
|
+
activeOpacity={0.7}
|
|
289
|
+
>
|
|
290
|
+
<Ionicons
|
|
291
|
+
name={swapIconName}
|
|
292
|
+
size={20}
|
|
293
|
+
color={theme.onSurface}
|
|
294
|
+
style={swapIconStyle}
|
|
295
|
+
/>
|
|
296
|
+
</TouchableOpacity>
|
|
297
|
+
</View>
|
|
298
|
+
)}
|
|
277
299
|
|
|
278
300
|
{/* Apply inputWrapperStyle */}
|
|
279
301
|
<View style={[styles.inputWrapper, inputWrapperStyle]}>
|
|
@@ -285,6 +307,7 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
285
307
|
}}
|
|
286
308
|
label={toLabel}
|
|
287
309
|
value={toLocation}
|
|
310
|
+
inputStyle={inputStyle}
|
|
288
311
|
labelStyle={[styles.label, labelStyle]}
|
|
289
312
|
placeholder={toPlaceholder}
|
|
290
313
|
onFocus={() => {
|
|
@@ -292,15 +315,13 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
292
315
|
onInputFocus?.(FormInputType.FLIGHT_TO);
|
|
293
316
|
}}
|
|
294
317
|
onBlur={() => {
|
|
295
|
-
// Delay blur slightly to allow suggestion press
|
|
296
318
|
setTimeout(() => {
|
|
297
319
|
if (focusedInput === FormInputType.FLIGHT_TO) {
|
|
298
320
|
setFocusedInput(undefined);
|
|
299
321
|
}
|
|
300
322
|
}, 150);
|
|
301
323
|
}}
|
|
302
|
-
|
|
303
|
-
containerStyle={customInputContainerStyle}
|
|
324
|
+
inputContainerStyle={customInputContainerStyle}
|
|
304
325
|
/>
|
|
305
326
|
{suggestionData && (
|
|
306
327
|
<SuggestionList
|
|
@@ -320,13 +341,13 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
320
341
|
returnLabel={returnLabel}
|
|
321
342
|
departureLabel={departureLabel}
|
|
322
343
|
outerContainerStyle={[
|
|
323
|
-
styles.dateRangePickerOuterContainer,
|
|
344
|
+
styles.dateRangePickerOuterContainer,
|
|
324
345
|
dateRangePickerOuterContainerStyle,
|
|
325
346
|
]}
|
|
326
347
|
labelStyle={[labelStyle, dateRangePickerLabelStyle]}
|
|
327
348
|
inputGroupStyle={dateRangePickerInputGroupStyle}
|
|
328
|
-
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
329
|
-
calendarThemeOverrides={calendarThemeOverrides}
|
|
349
|
+
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
350
|
+
calendarThemeOverrides={calendarThemeOverrides}
|
|
330
351
|
onDatesChange={(d) => {
|
|
331
352
|
setDepartureDate(d.departure);
|
|
332
353
|
setReturnDate(d.return);
|
|
@@ -336,18 +357,20 @@ const FlightForm: React.FC<FlightFormProps> = ({
|
|
|
336
357
|
initialReturnDate={initialReturnDate}
|
|
337
358
|
/>
|
|
338
359
|
{/* Search Button */}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
360
|
+
{onSearchPress && (
|
|
361
|
+
<TouchableOpacity
|
|
362
|
+
style={[styles.searchButton, searchButtonStyle]}
|
|
363
|
+
onPress={handleSearch}
|
|
364
|
+
activeOpacity={0.8}
|
|
365
|
+
>
|
|
366
|
+
<Ionicons
|
|
367
|
+
name={searchIconName}
|
|
368
|
+
size={24}
|
|
369
|
+
color={theme.onPrimary}
|
|
370
|
+
style={searchIconStyle}
|
|
371
|
+
/>
|
|
372
|
+
</TouchableOpacity>
|
|
373
|
+
)}
|
|
351
374
|
</View>
|
|
352
375
|
</View>
|
|
353
376
|
);
|
|
@@ -71,6 +71,9 @@ export interface FlightSummaryProps {
|
|
|
71
71
|
flightTypesData?: string[];
|
|
72
72
|
flightClassesData?: string[];
|
|
73
73
|
|
|
74
|
+
flightTypeLabel?: string;
|
|
75
|
+
flightClassLabel?: string;
|
|
76
|
+
|
|
74
77
|
// State & Callbacks
|
|
75
78
|
selection?: FlightSelection; // Renamed from 'selection' for clarity
|
|
76
79
|
onSelectionChange?: (details: FlightSelection) => void;
|
|
@@ -100,6 +103,8 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
100
103
|
passengersData: passengersProp = DEFAULT_PASSENGERS,
|
|
101
104
|
flightTypesData: flightTypesProp = DEFAULT_FLIGHT_TYPES,
|
|
102
105
|
flightClassesData: flightClassesProp = DEFAULT_FLIGHT_CLASSES,
|
|
106
|
+
flightClassLabel = "Class",
|
|
107
|
+
flightTypeLabel = "Type",
|
|
103
108
|
// State & Callbacks
|
|
104
109
|
selection,
|
|
105
110
|
onSelectionChange,
|
|
@@ -133,9 +138,9 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
133
138
|
const [selectedFlightClass, setSelectedFlightClass] = useState<string>(
|
|
134
139
|
selection?.flightClass ?? flightClasses[0]
|
|
135
140
|
);
|
|
136
|
-
const [passengerCounts, setPassengerCounts] = useState<
|
|
137
|
-
|
|
138
|
-
);
|
|
141
|
+
const [passengerCounts, setPassengerCounts] = useState<
|
|
142
|
+
Record<string, number>
|
|
143
|
+
>(selection?.passengers ?? getInitialPassengerCounts(passengersConfig));
|
|
139
144
|
|
|
140
145
|
const handleFlightTypeSelect = useCallback(
|
|
141
146
|
(type: string) => {
|
|
@@ -162,8 +167,7 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
162
167
|
const currentVal = prevCounts[passengerKey];
|
|
163
168
|
const minValue = passengerInfo.minValue;
|
|
164
169
|
|
|
165
|
-
const maxValue =
|
|
166
|
-
passengerInfo.maxValue ?? 99;
|
|
170
|
+
const maxValue = passengerInfo.maxValue ?? 99;
|
|
167
171
|
|
|
168
172
|
let newValue = currentVal;
|
|
169
173
|
if (action === "increment") {
|
|
@@ -213,36 +217,42 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
213
217
|
const renderButtonGroup = (
|
|
214
218
|
items: string[],
|
|
215
219
|
selectedValue: string,
|
|
216
|
-
onSelect: (item: string) => void
|
|
220
|
+
onSelect: (item: string) => void,
|
|
221
|
+
label?: string
|
|
217
222
|
) => (
|
|
218
|
-
<View
|
|
219
|
-
{
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
isSelected && selectedButtonStyle,
|
|
229
|
-
]}
|
|
230
|
-
onPress={() => onSelect(item)}
|
|
231
|
-
activeOpacity={0.7}
|
|
232
|
-
>
|
|
233
|
-
<Text
|
|
223
|
+
<View>
|
|
224
|
+
<Text style={{ color: theme.labelText, fontSize: 12, marginBottom: 6 }}>
|
|
225
|
+
{label}
|
|
226
|
+
</Text>
|
|
227
|
+
<View style={[styles.buttonGroupContainer, buttonGroupContainerStyle]}>
|
|
228
|
+
{items.map((item) => {
|
|
229
|
+
const isSelected = item === selectedValue;
|
|
230
|
+
return (
|
|
231
|
+
<TouchableOpacity
|
|
232
|
+
key={item}
|
|
234
233
|
style={[
|
|
235
|
-
styles.
|
|
236
|
-
|
|
237
|
-
isSelected && styles.
|
|
238
|
-
isSelected &&
|
|
234
|
+
styles.button,
|
|
235
|
+
buttonStyle,
|
|
236
|
+
isSelected && styles.selectedButton,
|
|
237
|
+
isSelected && selectedButtonStyle,
|
|
239
238
|
]}
|
|
239
|
+
onPress={() => onSelect(item)}
|
|
240
|
+
activeOpacity={0.7}
|
|
240
241
|
>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
242
|
+
<Text
|
|
243
|
+
style={[
|
|
244
|
+
styles.buttonText,
|
|
245
|
+
buttonTextStyle,
|
|
246
|
+
isSelected && styles.selectedButtonText,
|
|
247
|
+
isSelected && selectedButtonTextStyle,
|
|
248
|
+
]}
|
|
249
|
+
>
|
|
250
|
+
{item}
|
|
251
|
+
</Text>
|
|
252
|
+
</TouchableOpacity>
|
|
253
|
+
);
|
|
254
|
+
})}
|
|
255
|
+
</View>
|
|
246
256
|
</View>
|
|
247
257
|
);
|
|
248
258
|
|
|
@@ -260,12 +270,13 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
260
270
|
{renderButtonGroup(
|
|
261
271
|
flightTypes,
|
|
262
272
|
selectedFlightType,
|
|
263
|
-
handleFlightTypeSelect
|
|
273
|
+
handleFlightTypeSelect,
|
|
274
|
+
flightTypeLabel
|
|
264
275
|
)}
|
|
265
276
|
|
|
266
277
|
{/* Passengers */}
|
|
267
278
|
<View style={[styles.passengerSection, passengerSectionStyle]}>
|
|
268
|
-
{passengersConfig.map((passenger) => (
|
|
279
|
+
{passengersConfig.map((passenger) => (
|
|
269
280
|
<View
|
|
270
281
|
key={passenger.key}
|
|
271
282
|
style={[styles.passengerRow, passengerRowStyle]}
|
|
@@ -280,10 +291,7 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
280
291
|
{passenger.name}
|
|
281
292
|
</Text>
|
|
282
293
|
<Text
|
|
283
|
-
style={[
|
|
284
|
-
styles.passengerDescription,
|
|
285
|
-
passengerDescriptionStyle,
|
|
286
|
-
]}
|
|
294
|
+
style={[styles.passengerDescription, passengerDescriptionStyle]}
|
|
287
295
|
>
|
|
288
296
|
{passenger.description}
|
|
289
297
|
</Text>
|
|
@@ -312,7 +320,8 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
312
320
|
{renderButtonGroup(
|
|
313
321
|
flightClasses,
|
|
314
322
|
selectedFlightClass,
|
|
315
|
-
handleFlightClassSelect
|
|
323
|
+
handleFlightClassSelect,
|
|
324
|
+
flightClassLabel
|
|
316
325
|
)}
|
|
317
326
|
</View>
|
|
318
327
|
);
|
|
@@ -326,7 +335,7 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
326
335
|
},
|
|
327
336
|
buttonGroupContainer: {
|
|
328
337
|
flexDirection: isRTL ? "row-reverse" : "row",
|
|
329
|
-
// marginBottom: 10,
|
|
338
|
+
// marginBottom: 10,
|
|
330
339
|
marginTop: 5,
|
|
331
340
|
justifyContent: "flex-start",
|
|
332
341
|
flexWrap: "wrap",
|
|
@@ -347,7 +356,7 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
347
356
|
buttonText: {
|
|
348
357
|
color: theme.onSurface,
|
|
349
358
|
fontWeight: "500",
|
|
350
|
-
fontSize: 14,
|
|
359
|
+
fontSize: 14,
|
|
351
360
|
},
|
|
352
361
|
selectedButtonText: {
|
|
353
362
|
color: theme.onPrimary,
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { ThemeType, useTheme } from "../../theme";
|
|
2
|
-
import React, {
|
|
2
|
+
import React, {
|
|
3
|
+
useCallback,
|
|
4
|
+
useEffect,
|
|
5
|
+
useMemo,
|
|
6
|
+
useRef,
|
|
7
|
+
useState,
|
|
8
|
+
} from "react";
|
|
3
9
|
import {
|
|
4
10
|
View,
|
|
5
11
|
Text,
|
|
@@ -15,8 +21,8 @@ import { Ionicons } from "@expo/vector-icons";
|
|
|
15
21
|
import CustomInput from "../Input/Input";
|
|
16
22
|
import DateRangePicker from "../DateRangePicker/DateRangePicker";
|
|
17
23
|
import { Picker } from "@react-native-picker/picker";
|
|
18
|
-
import SuggestionList from "../Suggestions/SuggestionList";
|
|
19
|
-
import { FormInputType, HotelSuggestions } from "./types";
|
|
24
|
+
import SuggestionList from "../Suggestions/SuggestionList";
|
|
25
|
+
import { FormInputType, HotelSuggestions } from "./types";
|
|
20
26
|
import { TextInput } from "react-native-gesture-handler";
|
|
21
27
|
|
|
22
28
|
// --- Helper Types ---
|
|
@@ -40,6 +46,13 @@ export interface HotelFormProps {
|
|
|
40
46
|
nationality: string | undefined;
|
|
41
47
|
}) => void;
|
|
42
48
|
|
|
49
|
+
onSelectionChange?: (details: {
|
|
50
|
+
destination: LocationData | undefined; // Renamed from destintation
|
|
51
|
+
checkin: string | undefined; // Send YYYY-MM-DD
|
|
52
|
+
checkout: string | undefined; // Send YYYY-MM-DD
|
|
53
|
+
nationality: string | undefined;
|
|
54
|
+
}) => void;
|
|
55
|
+
|
|
43
56
|
// Labels & Placeholders
|
|
44
57
|
destinationLabel?: string;
|
|
45
58
|
destinationPlaceholder?: string;
|
|
@@ -52,22 +65,22 @@ export interface HotelFormProps {
|
|
|
52
65
|
|
|
53
66
|
// Data & Config
|
|
54
67
|
suggestionData?: HotelSuggestions[];
|
|
55
|
-
nationalityData?: { label: string; value: string }[];
|
|
68
|
+
nationalityData?: { label: string; value: string }[];
|
|
56
69
|
calendarThemeOverrides?: object;
|
|
57
70
|
|
|
58
71
|
// --- Style Props ---
|
|
59
72
|
containerStyle?: StyleProp<ViewStyle>;
|
|
60
|
-
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
73
|
+
inputWrapperStyle?: StyleProp<ViewStyle>;
|
|
61
74
|
customInputContainerStyle?: StyleProp<ViewStyle>;
|
|
62
|
-
labelStyle?: StyleProp<TextStyle>;
|
|
63
|
-
checkoutRowStyle?: StyleProp<ViewStyle>;
|
|
75
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
76
|
+
checkoutRowStyle?: StyleProp<ViewStyle>;
|
|
64
77
|
searchButtonStyle?: StyleProp<ViewStyle>;
|
|
65
|
-
searchIconStyle?: StyleProp<TextStyle>;
|
|
78
|
+
searchIconStyle?: StyleProp<TextStyle>;
|
|
66
79
|
|
|
67
80
|
// DateRangePicker specific styles (passed down)
|
|
68
81
|
dateRangePickerOuterContainerStyle?: StyleProp<ViewStyle>;
|
|
69
|
-
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
70
|
-
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
82
|
+
dateRangePickerLabelStyle?: StyleProp<TextStyle>;
|
|
83
|
+
dateRangePickerInputGroupStyle?: StyleProp<ViewStyle>;
|
|
71
84
|
dateRangePickerCalendarContainerStyle?: StyleProp<ViewStyle>;
|
|
72
85
|
|
|
73
86
|
// SuggestionList specific styles
|
|
@@ -76,10 +89,10 @@ export interface HotelFormProps {
|
|
|
76
89
|
suggestionItemTextStyle?: StyleProp<TextStyle>;
|
|
77
90
|
|
|
78
91
|
// Nationality Picker specific styles
|
|
79
|
-
nationalityPickerWrapperStyle?: StyleProp<ViewStyle>;
|
|
80
|
-
nationalityPickerLabelStyle?: StyleProp<TextStyle>;
|
|
92
|
+
nationalityPickerWrapperStyle?: StyleProp<ViewStyle>;
|
|
93
|
+
nationalityPickerLabelStyle?: StyleProp<TextStyle>;
|
|
81
94
|
pickerContainerStyle?: StyleProp<ViewStyle>;
|
|
82
|
-
pickerStyle?: StyleProp<TextStyle>;
|
|
95
|
+
pickerStyle?: StyleProp<TextStyle>;
|
|
83
96
|
}
|
|
84
97
|
|
|
85
98
|
// Default Nationality Data (can be overridden by prop)
|
|
@@ -137,6 +150,7 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
137
150
|
nationalityPickerLabelStyle,
|
|
138
151
|
pickerContainerStyle,
|
|
139
152
|
pickerStyle,
|
|
153
|
+
onSelectionChange,
|
|
140
154
|
}) => {
|
|
141
155
|
const { theme, isRTL } = useTheme();
|
|
142
156
|
const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]);
|
|
@@ -158,6 +172,21 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
158
172
|
>(initialNationality);
|
|
159
173
|
const [focusedInput, setFocusedInput] = useState<FormInputType>();
|
|
160
174
|
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
onSelectionChange?.({
|
|
177
|
+
destination: destination,
|
|
178
|
+
checkin: checkinDate,
|
|
179
|
+
checkout: checkoutDate,
|
|
180
|
+
nationality: selectedNationality,
|
|
181
|
+
});
|
|
182
|
+
}, [
|
|
183
|
+
destination,
|
|
184
|
+
checkinDate,
|
|
185
|
+
checkoutDate,
|
|
186
|
+
selectedNationality,
|
|
187
|
+
onSelectionChange,
|
|
188
|
+
]);
|
|
189
|
+
|
|
161
190
|
// --- Handlers ---
|
|
162
191
|
const handleSearch = useCallback(() => {
|
|
163
192
|
onSearchPress?.({
|
|
@@ -236,8 +265,8 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
236
265
|
]}
|
|
237
266
|
labelStyle={[labelStyle, dateRangePickerLabelStyle]}
|
|
238
267
|
inputGroupStyle={dateRangePickerInputGroupStyle}
|
|
239
|
-
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
240
|
-
calendarThemeOverrides={calendarThemeOverrides}
|
|
268
|
+
calendarContainerStyle={dateRangePickerCalendarContainerStyle}
|
|
269
|
+
calendarThemeOverrides={calendarThemeOverrides}
|
|
241
270
|
onDatesChange={(d) => {
|
|
242
271
|
setCheckinDate(d.departure);
|
|
243
272
|
setCheckoutDate(d.return);
|
|
@@ -249,15 +278,12 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
249
278
|
|
|
250
279
|
<View style={[styles.checkoutRow, checkoutRowStyle]}>
|
|
251
280
|
<View
|
|
252
|
-
style={[
|
|
281
|
+
style={[
|
|
282
|
+
styles.nationalityPickerWrapper,
|
|
283
|
+
nationalityPickerWrapperStyle,
|
|
284
|
+
]}
|
|
253
285
|
>
|
|
254
|
-
<Text
|
|
255
|
-
style={[
|
|
256
|
-
styles.label,
|
|
257
|
-
labelStyle,
|
|
258
|
-
nationalityPickerLabelStyle,
|
|
259
|
-
]}
|
|
260
|
-
>
|
|
286
|
+
<Text style={[styles.label, labelStyle, nationalityPickerLabelStyle]}>
|
|
261
287
|
{nationalityLabel}
|
|
262
288
|
</Text>
|
|
263
289
|
<View style={[styles.pickerContainer, pickerContainerStyle]}>
|
|
@@ -269,7 +295,7 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
269
295
|
>
|
|
270
296
|
{nationalityData.map((nat) => (
|
|
271
297
|
<Picker.Item
|
|
272
|
-
key={nat.value || "placeholder"}
|
|
298
|
+
key={nat.value || "placeholder"}
|
|
273
299
|
label={nat.label}
|
|
274
300
|
value={nat.value}
|
|
275
301
|
enabled={nat.value !== undefined}
|
|
@@ -279,18 +305,20 @@ const HotelForm: React.FC<HotelFormProps> = ({
|
|
|
279
305
|
</View>
|
|
280
306
|
</View>
|
|
281
307
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
308
|
+
{onSearchPress && (
|
|
309
|
+
<TouchableOpacity
|
|
310
|
+
style={[styles.searchButton, searchButtonStyle]}
|
|
311
|
+
onPress={handleSearch}
|
|
312
|
+
activeOpacity={0.8}
|
|
313
|
+
>
|
|
314
|
+
<Ionicons
|
|
315
|
+
name={searchIconName}
|
|
316
|
+
size={24}
|
|
317
|
+
color={theme.onPrimary}
|
|
318
|
+
style={searchIconStyle}
|
|
319
|
+
/>
|
|
320
|
+
</TouchableOpacity>
|
|
321
|
+
)}
|
|
294
322
|
</View>
|
|
295
323
|
</View>
|
|
296
324
|
);
|
|
@@ -306,8 +334,8 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
306
334
|
borderBottomLeftRadius: 8,
|
|
307
335
|
},
|
|
308
336
|
inputWrapper: {
|
|
309
|
-
marginBottom: 15,
|
|
310
|
-
position: "relative",
|
|
337
|
+
marginBottom: 15,
|
|
338
|
+
position: "relative",
|
|
311
339
|
},
|
|
312
340
|
label: {
|
|
313
341
|
color: theme.labelText,
|
|
@@ -318,12 +346,12 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
318
346
|
marginBottom: 6,
|
|
319
347
|
},
|
|
320
348
|
dateRangePickerOuterContainer: {
|
|
321
|
-
marginTop: 10,
|
|
349
|
+
marginTop: 10,
|
|
322
350
|
},
|
|
323
351
|
checkoutRow: {
|
|
324
352
|
flexDirection: isRTL ? "row-reverse" : "row",
|
|
325
|
-
alignItems: "flex-end",
|
|
326
|
-
marginTop: 20,
|
|
353
|
+
alignItems: "flex-end",
|
|
354
|
+
marginTop: 20,
|
|
327
355
|
gap: 10,
|
|
328
356
|
},
|
|
329
357
|
nationalityPickerWrapper: {
|
|
@@ -334,8 +362,8 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
334
362
|
borderColor: theme.border,
|
|
335
363
|
borderRadius: 8,
|
|
336
364
|
backgroundColor: theme.surface,
|
|
337
|
-
justifyContent: "center",
|
|
338
|
-
height: 50,
|
|
365
|
+
justifyContent: "center",
|
|
366
|
+
height: 50,
|
|
339
367
|
},
|
|
340
368
|
picker: {
|
|
341
369
|
width: "100%",
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export { default, type TravelBookingProps } from "./TravelBooking";
|
|
3
|
+
export * from "./TravelBooking"
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
export { default as CarRentalForm, type CarRentalFormProps } from "./CarRentalForm";
|
|
6
|
+
export * from "./CarRentalForm"
|
|
7
|
+
export { default as FlightForm, type FlightFormProps } from "./FlightForm";
|
|
8
|
+
export * from "./FlightForm";
|
|
9
|
+
export { default as HotelForm, type HotelFormProps } from "./HotelForm";
|
|
10
|
+
export * from "./HotelForm";
|
|
11
|
+
export { default as SummaryBar, type SummaryBarProps, type SelectionCallbackDataType } from "./SummaryBar";
|
|
12
|
+
export * from "./SummaryBar";
|
|
13
|
+
export { default as TabSelector, type TabSelectorProps } from "./TabSelector";
|
|
14
|
+
export * from "./TabSelector"
|
|
15
|
+
export { default as FlightSummary, type FlightSummaryProps, type FlightSelection } from "./FlightSummary";
|
|
16
|
+
export * from "./FlightSummary"
|
|
17
|
+
export { default as HotelSummary, type HotelSummaryProps, type RoomState } from "./HotelSummary";
|
|
18
|
+
export * from "./HotelSummary"
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
export * from "./types";
|
package/src/components/index.ts
CHANGED