related-ui-components 2.7.5 → 2.7.7
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 +17 -57
- package/lib/module/app.js.map +1 -1
- package/lib/module/components/CarouselCardStack/CarouselCardStack.js +99 -81
- package/lib/module/components/CarouselCardStack/CarouselCardStack.js.map +1 -1
- package/lib/module/components/TravelBooking/FlightSummary.js +219 -112
- package/lib/module/components/TravelBooking/FlightSummary.js.map +1 -1
- package/lib/module/components/TravelBooking/HotelSummary.js +168 -37
- package/lib/module/components/TravelBooking/HotelSummary.js.map +1 -1
- package/lib/module/components/TravelBooking/SummaryBar.js +239 -172
- package/lib/module/components/TravelBooking/SummaryBar.js.map +1 -1
- package/lib/module/components/TravelBooking/TravelBooking.js +407 -241
- package/lib/module/components/TravelBooking/TravelBooking.js.map +1 -1
- package/lib/module/components/TravelBooking/index.js +5 -4
- package/lib/module/components/TravelBooking/index.js.map +1 -1
- package/lib/typescript/src/app.d.ts.map +1 -1
- package/lib/typescript/src/components/CarouselCardStack/CarouselCardStack.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/FlightSummary.d.ts +25 -11
- package/lib/typescript/src/components/TravelBooking/FlightSummary.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/HotelSummary.d.ts +14 -0
- package/lib/typescript/src/components/TravelBooking/HotelSummary.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/SummaryBar.d.ts +1 -16
- package/lib/typescript/src/components/TravelBooking/SummaryBar.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/TravelBooking.d.ts +1 -83
- package/lib/typescript/src/components/TravelBooking/TravelBooking.d.ts.map +1 -1
- package/lib/typescript/src/components/TravelBooking/index.d.ts +0 -4
- package/lib/typescript/src/components/TravelBooking/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/app.tsx +18 -39
- package/src/components/CarouselCardStack/CarouselCardStack.tsx +130 -120
- package/src/components/TravelBooking/FlightSummary.tsx +264 -164
- package/src/components/TravelBooking/HotelSummary.tsx +243 -76
- package/src/components/TravelBooking/SummaryBar.tsx +239 -239
- package/src/components/TravelBooking/TravelBooking.tsx +407 -407
- package/src/components/TravelBooking/index.ts +4 -4
- package/src/index.ts +1 -1
|
@@ -3,37 +3,49 @@ import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
3
3
|
import {
|
|
4
4
|
StyleProp,
|
|
5
5
|
StyleSheet,
|
|
6
|
+
Text,
|
|
6
7
|
TouchableOpacity,
|
|
7
8
|
View,
|
|
8
9
|
ViewStyle,
|
|
9
10
|
TextStyle,
|
|
10
11
|
} from "react-native";
|
|
11
12
|
import { NumericStepper, NumericStepperProps } from "../NumericStepper";
|
|
12
|
-
import
|
|
13
|
+
import RNPickerSelect from "react-native-picker-select";
|
|
14
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
15
|
+
|
|
16
|
+
// --- TYPE DEFINITIONS (Updated) ---
|
|
13
17
|
|
|
14
18
|
export interface PassengerConfig {
|
|
15
|
-
key:
|
|
19
|
+
key: "adults" | "children" | "infants";
|
|
16
20
|
name: string;
|
|
17
21
|
description: string;
|
|
18
22
|
defaultValue: number;
|
|
19
23
|
minValue: number;
|
|
20
24
|
maxValue?: number;
|
|
25
|
+
// Age range for children/infants
|
|
26
|
+
ageRange?: { min: number; max: number };
|
|
27
|
+
defaultAge?: number;
|
|
21
28
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
value: string;
|
|
28
|
-
name: string;
|
|
29
|
+
|
|
30
|
+
// Represents an individual child or infant with a selectable age
|
|
31
|
+
export interface IndividualPassenger {
|
|
32
|
+
id: string;
|
|
33
|
+
age: number;
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
// Updated FlightSelection to handle individual passengers
|
|
31
37
|
export interface FlightSelection {
|
|
32
38
|
flightType: string;
|
|
33
39
|
flightClass: string;
|
|
34
|
-
passengers:
|
|
40
|
+
passengers: {
|
|
41
|
+
adults: number;
|
|
42
|
+
children: IndividualPassenger[];
|
|
43
|
+
infants: IndividualPassenger[];
|
|
44
|
+
};
|
|
35
45
|
}
|
|
36
46
|
|
|
47
|
+
// --- CONFIGURATION ---
|
|
48
|
+
|
|
37
49
|
const DEFAULT_PASSENGERS: PassengerConfig[] = [
|
|
38
50
|
{
|
|
39
51
|
key: "adults",
|
|
@@ -49,7 +61,9 @@ const DEFAULT_PASSENGERS: PassengerConfig[] = [
|
|
|
49
61
|
description: "2 - 11 years old",
|
|
50
62
|
defaultValue: 0,
|
|
51
63
|
minValue: 0,
|
|
52
|
-
maxValue:
|
|
64
|
+
maxValue: 6,
|
|
65
|
+
ageRange: { min: 2, max: 11 },
|
|
66
|
+
defaultAge: 5,
|
|
53
67
|
},
|
|
54
68
|
{
|
|
55
69
|
key: "infants",
|
|
@@ -57,43 +71,55 @@ const DEFAULT_PASSENGERS: PassengerConfig[] = [
|
|
|
57
71
|
description: "0 - 1 years old",
|
|
58
72
|
defaultValue: 0,
|
|
59
73
|
minValue: 0,
|
|
60
|
-
maxValue:
|
|
74
|
+
maxValue: 4,
|
|
75
|
+
ageRange: { min: 0, max: 1 },
|
|
76
|
+
defaultAge: 0,
|
|
61
77
|
},
|
|
62
78
|
];
|
|
63
|
-
|
|
79
|
+
|
|
80
|
+
const DEFAULT_FLIGHT_TYPES = [
|
|
64
81
|
{ value: "ROUND_TRIP", name: "Round trip" },
|
|
65
82
|
{ value: "ONE_WAY", name: "One way" },
|
|
66
83
|
];
|
|
67
|
-
const DEFAULT_FLIGHT_CLASSES
|
|
84
|
+
const DEFAULT_FLIGHT_CLASSES = [
|
|
68
85
|
{ value: "ECONOMY", name: "Economy" },
|
|
69
86
|
{ value: "BUSINESS", name: "Business" },
|
|
70
87
|
{ value: "FIRST", name: "First" },
|
|
71
88
|
];
|
|
72
89
|
|
|
73
|
-
|
|
90
|
+
// --- HELPER FUNCTION ---
|
|
91
|
+
const getInitialPassengerState = (
|
|
74
92
|
config: PassengerConfig[]
|
|
75
|
-
):
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
): FlightSelection["passengers"] => {
|
|
94
|
+
return {
|
|
95
|
+
adults: config.find((p) => p.key === "adults")?.defaultValue ?? 1,
|
|
96
|
+
children: Array.from(
|
|
97
|
+
{ length: config.find((p) => p.key === "children")?.defaultValue ?? 0 },
|
|
98
|
+
(_, i) => ({
|
|
99
|
+
id: `child_${i}_${Date.now()}`,
|
|
100
|
+
age: config.find((p) => p.key === "children")?.defaultAge ?? 2,
|
|
101
|
+
})
|
|
102
|
+
),
|
|
103
|
+
infants: Array.from(
|
|
104
|
+
{ length: config.find((p) => p.key === "infants")?.defaultValue ?? 0 },
|
|
105
|
+
(_, i) => ({
|
|
106
|
+
id: `infant_${i}_${Date.now()}`,
|
|
107
|
+
age: config.find((p) => p.key === "infants")?.defaultAge ?? 0,
|
|
108
|
+
})
|
|
109
|
+
),
|
|
110
|
+
};
|
|
80
111
|
};
|
|
81
112
|
|
|
82
|
-
// ---
|
|
113
|
+
// --- PROPS INTERFACE ---
|
|
83
114
|
export interface FlightSummaryProps {
|
|
84
|
-
// Data Props
|
|
85
115
|
passengersData?: PassengerConfig[];
|
|
86
|
-
flightTypesData?:
|
|
87
|
-
flightClassesData?:
|
|
88
|
-
|
|
116
|
+
flightTypesData?: { value: string; name: string }[];
|
|
117
|
+
flightClassesData?: { value: string; name: string }[];
|
|
89
118
|
flightTypeLabel?: string;
|
|
90
119
|
flightClassLabel?: string;
|
|
91
|
-
|
|
92
|
-
// State & Callbacks
|
|
93
|
-
selection?: FlightSelection; // Renamed from 'selection' for clarity
|
|
120
|
+
selection?: FlightSelection;
|
|
94
121
|
onSelectionChange?: (details: FlightSelection) => void;
|
|
95
|
-
|
|
96
|
-
// Style Props
|
|
122
|
+
formatPassengerAgeLabel?: (passengerType: string, index: number) => string;
|
|
97
123
|
containerStyle?: StyleProp<ViewStyle>;
|
|
98
124
|
buttonGroupContainerStyle?: StyleProp<ViewStyle>;
|
|
99
125
|
buttonStyle?: StyleProp<ViewStyle>;
|
|
@@ -106,26 +132,24 @@ export interface FlightSummaryProps {
|
|
|
106
132
|
passengerNameStyle?: StyleProp<TextStyle>;
|
|
107
133
|
passengerDescriptionStyle?: StyleProp<TextStyle>;
|
|
108
134
|
labelStyle?: StyleProp<TextStyle>;
|
|
109
|
-
|
|
110
|
-
|
|
135
|
+
agePickerRowStyle?: StyleProp<ViewStyle>;
|
|
136
|
+
agePickerLabelStyle?: StyleProp<TextStyle>;
|
|
111
137
|
stepperContainerStyle?: NumericStepperProps["style"];
|
|
112
138
|
stepperButtonStyle?: NumericStepperProps["buttonStyle"];
|
|
113
139
|
stepperButtonTextStyle?: NumericStepperProps["buttonTextStyle"];
|
|
114
140
|
stepperValueTextStyle?: NumericStepperProps["valueTextStyle"];
|
|
115
141
|
}
|
|
116
142
|
|
|
117
|
-
// ---
|
|
143
|
+
// --- COMPONENT IMPLEMENTATION ---
|
|
118
144
|
const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
119
|
-
// Data
|
|
120
145
|
passengersData: passengersProp = DEFAULT_PASSENGERS,
|
|
121
146
|
flightTypesData: flightTypesProp = DEFAULT_FLIGHT_TYPES,
|
|
122
147
|
flightClassesData: flightClassesProp = DEFAULT_FLIGHT_CLASSES,
|
|
123
148
|
flightClassLabel = "Class",
|
|
124
149
|
flightTypeLabel = "Type",
|
|
125
|
-
// State & Callbacks
|
|
126
150
|
selection,
|
|
127
151
|
onSelectionChange,
|
|
128
|
-
|
|
152
|
+
formatPassengerAgeLabel = (passengerType, index) => `${passengerType} ${index} Age`,
|
|
129
153
|
containerStyle,
|
|
130
154
|
buttonGroupContainerStyle,
|
|
131
155
|
buttonStyle,
|
|
@@ -137,11 +161,13 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
137
161
|
passengerLabelContainerStyle,
|
|
138
162
|
passengerNameStyle,
|
|
139
163
|
passengerDescriptionStyle,
|
|
164
|
+
labelStyle,
|
|
165
|
+
agePickerRowStyle,
|
|
166
|
+
agePickerLabelStyle,
|
|
140
167
|
stepperContainerStyle,
|
|
141
168
|
stepperButtonStyle,
|
|
142
169
|
stepperButtonTextStyle,
|
|
143
170
|
stepperValueTextStyle,
|
|
144
|
-
labelStyle,
|
|
145
171
|
}) => {
|
|
146
172
|
const { theme, isRTL } = useTheme();
|
|
147
173
|
const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]);
|
|
@@ -156,97 +182,90 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
156
182
|
const [selectedFlightClass, setSelectedFlightClass] = useState<string>(
|
|
157
183
|
selection?.flightClass ?? flightClasses[0].value
|
|
158
184
|
);
|
|
159
|
-
const [
|
|
160
|
-
|
|
161
|
-
>(selection?.passengers ?? getInitialPassengerCounts(passengersConfig));
|
|
162
|
-
|
|
163
|
-
const handleFlightTypeSelect = useCallback(
|
|
164
|
-
(type: FlightTypeConfig) => {
|
|
165
|
-
setSelectedFlightType(type.value);
|
|
166
|
-
|
|
167
|
-
const newState: FlightSelection = {
|
|
168
|
-
flightType: type.value,
|
|
169
|
-
flightClass: selectedFlightClass,
|
|
170
|
-
passengers: passengerCounts,
|
|
171
|
-
};
|
|
172
|
-
onSelectionChange?.(newState);
|
|
173
|
-
},
|
|
174
|
-
[selectedFlightClass, passengerCounts, onSelectionChange]
|
|
185
|
+
const [passengers, setPassengers] = useState<FlightSelection["passengers"]>(
|
|
186
|
+
selection?.passengers ?? getInitialPassengerState(passengersConfig)
|
|
175
187
|
);
|
|
176
188
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
189
|
+
// Memoize the state to be sent upwards
|
|
190
|
+
const currentSelection = useMemo(
|
|
191
|
+
() => ({
|
|
192
|
+
flightType: selectedFlightType,
|
|
193
|
+
flightClass: selectedFlightClass,
|
|
194
|
+
passengers,
|
|
195
|
+
}),
|
|
196
|
+
[selectedFlightType, selectedFlightClass, passengers]
|
|
197
|
+
);
|
|
184
198
|
|
|
185
|
-
|
|
186
|
-
|
|
199
|
+
// Effect to call onSelectionChange when the memoized state changes
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
onSelectionChange?.(currentSelection);
|
|
202
|
+
}, [currentSelection, onSelectionChange]);
|
|
187
203
|
|
|
188
|
-
|
|
204
|
+
const handlePassengerCountChange = useCallback(
|
|
205
|
+
(
|
|
206
|
+
key: "adults" | "children" | "infants",
|
|
207
|
+
action: "increment" | "decrement"
|
|
208
|
+
) => {
|
|
209
|
+
setPassengers((prev) => {
|
|
210
|
+
const config = passengersConfig.find((p) => p.key === key);
|
|
211
|
+
if (!config) return prev;
|
|
189
212
|
|
|
190
|
-
let
|
|
191
|
-
if (action === "increment") {
|
|
192
|
-
newValue = Math.min(maxValue, currentVal + 1);
|
|
193
|
-
} else if (action === "decrement") {
|
|
194
|
-
newValue = Math.max(minValue, currentVal - 1);
|
|
195
|
-
}
|
|
213
|
+
let newPassengersState = { ...prev };
|
|
196
214
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
215
|
+
if (key === "adults") {
|
|
216
|
+
const currentVal = prev.adults;
|
|
217
|
+
const min = config.minValue;
|
|
218
|
+
const max = config.maxValue ?? 99;
|
|
219
|
+
let newValue = currentVal;
|
|
220
|
+
if (action === "increment") newValue = Math.min(max, currentVal + 1);
|
|
221
|
+
else newValue = Math.max(min, currentVal - 1);
|
|
222
|
+
newPassengersState.adults = newValue;
|
|
223
|
+
} else {
|
|
224
|
+
// Handle children and infants (arrays)
|
|
225
|
+
const currentArray = prev[key];
|
|
226
|
+
if (action === "increment") {
|
|
227
|
+
if (currentArray.length < (config.maxValue ?? 99)) {
|
|
228
|
+
const newPassenger: IndividualPassenger = {
|
|
229
|
+
id: `${key}_${Date.now()}`,
|
|
230
|
+
age: config.defaultAge ?? 0,
|
|
231
|
+
};
|
|
232
|
+
newPassengersState[key] = [...currentArray, newPassenger];
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
if (currentArray.length > config.minValue) {
|
|
236
|
+
newPassengersState[key] = currentArray.slice(0, -1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
200
239
|
}
|
|
201
|
-
|
|
202
|
-
const newCounts = { ...prevCounts, [passengerKey]: newValue };
|
|
203
|
-
const newState: FlightSelection = {
|
|
204
|
-
flightType: selectedFlightType,
|
|
205
|
-
flightClass: selectedFlightClass,
|
|
206
|
-
passengers: newCounts,
|
|
207
|
-
};
|
|
208
|
-
onSelectionChange?.(newState);
|
|
209
|
-
return newCounts;
|
|
240
|
+
return newPassengersState;
|
|
210
241
|
});
|
|
211
242
|
},
|
|
212
|
-
[
|
|
213
|
-
passengersConfig,
|
|
214
|
-
selectedFlightType,
|
|
215
|
-
selectedFlightClass,
|
|
216
|
-
onSelectionChange,
|
|
217
|
-
// No dependency on passengerCounts due to updater function usage
|
|
218
|
-
]
|
|
243
|
+
[passengersConfig]
|
|
219
244
|
);
|
|
220
245
|
|
|
221
|
-
const
|
|
222
|
-
(
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
246
|
+
const handleIndividualAgeChange = useCallback(
|
|
247
|
+
(key: "children" | "infants", id: string, newAge: number) => {
|
|
248
|
+
// Prevent update if newAge is null/undefined (from picker placeholder)
|
|
249
|
+
if (newAge === null || newAge === undefined) return;
|
|
250
|
+
|
|
251
|
+
setPassengers((prev) => {
|
|
252
|
+
const newArray = prev[key].map((p) =>
|
|
253
|
+
p.id === id ? { ...p, age: newAge } : p
|
|
254
|
+
);
|
|
255
|
+
return { ...prev, [key]: newArray };
|
|
256
|
+
});
|
|
230
257
|
},
|
|
231
|
-
[
|
|
258
|
+
[]
|
|
232
259
|
);
|
|
233
260
|
|
|
234
|
-
// --- Render Helpers ---
|
|
235
261
|
const renderButtonGroup = (
|
|
236
|
-
items:
|
|
262
|
+
items: any[],
|
|
237
263
|
selectedValue: string,
|
|
238
|
-
onSelect: (item:
|
|
264
|
+
onSelect: (item: any) => void,
|
|
239
265
|
label?: string
|
|
240
266
|
) => (
|
|
241
|
-
<View>
|
|
242
|
-
<Text
|
|
243
|
-
style={[
|
|
244
|
-
{ color: theme.labelText, fontSize: 12, marginBottom: 6 },
|
|
245
|
-
labelStyle,
|
|
246
|
-
]}
|
|
247
|
-
>
|
|
248
|
-
{label}
|
|
249
|
-
</Text>
|
|
267
|
+
<View style={styles.sectionContainer}>
|
|
268
|
+
<Text style={[styles.sectionLabel, labelStyle]}>{label}</Text>
|
|
250
269
|
<View style={[styles.buttonGroupContainer, buttonGroupContainerStyle]}>
|
|
251
270
|
{items.map((item) => {
|
|
252
271
|
const isSelected = item.value === selectedValue;
|
|
@@ -279,71 +298,117 @@ const FlightSummary: React.FC<FlightSummaryProps> = ({
|
|
|
279
298
|
</View>
|
|
280
299
|
);
|
|
281
300
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
301
|
+
// Helper to generate age items for the picker
|
|
302
|
+
const getAgePickerItems = (config: PassengerConfig | undefined) => {
|
|
303
|
+
if (!config?.ageRange) return [];
|
|
304
|
+
const { min, max } = config.ageRange;
|
|
305
|
+
return Array.from({ length: max - min + 1 }, (_, i) => ({
|
|
306
|
+
label: `${min + i}`,
|
|
307
|
+
value: min + i,
|
|
308
|
+
}));
|
|
309
|
+
};
|
|
289
310
|
|
|
290
311
|
return (
|
|
291
312
|
<View style={[styles.container, containerStyle]}>
|
|
292
|
-
{/* Flight Type */}
|
|
293
313
|
{renderButtonGroup(
|
|
294
314
|
flightTypes,
|
|
295
315
|
selectedFlightType,
|
|
296
|
-
|
|
316
|
+
(item) => setSelectedFlightType(item.value),
|
|
297
317
|
flightTypeLabel
|
|
298
318
|
)}
|
|
299
319
|
|
|
300
|
-
{/* Passengers */}
|
|
301
320
|
<View style={[styles.passengerSection, passengerSectionStyle]}>
|
|
302
|
-
{passengersConfig.map((
|
|
303
|
-
<View
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
passengerLabelContainerStyle,
|
|
311
|
-
]}
|
|
312
|
-
>
|
|
313
|
-
<Text style={[styles.passengerName, passengerNameStyle]}>
|
|
314
|
-
{passenger.name}
|
|
315
|
-
</Text>
|
|
316
|
-
<Text
|
|
317
|
-
style={[styles.passengerDescription, passengerDescriptionStyle]}
|
|
321
|
+
{passengersConfig.map((config) => (
|
|
322
|
+
<View key={config.key}>
|
|
323
|
+
<View style={[styles.passengerRow, passengerRowStyle]}>
|
|
324
|
+
<View
|
|
325
|
+
style={[
|
|
326
|
+
styles.passengerLabelContainer,
|
|
327
|
+
passengerLabelContainerStyle,
|
|
328
|
+
]}
|
|
318
329
|
>
|
|
319
|
-
{
|
|
320
|
-
|
|
330
|
+
<Text style={[styles.passengerName, passengerNameStyle]}>
|
|
331
|
+
{config.name}
|
|
332
|
+
</Text>
|
|
333
|
+
<Text
|
|
334
|
+
style={[
|
|
335
|
+
styles.passengerDescription,
|
|
336
|
+
passengerDescriptionStyle,
|
|
337
|
+
]}
|
|
338
|
+
>
|
|
339
|
+
{config.description}
|
|
340
|
+
</Text>
|
|
341
|
+
</View>
|
|
342
|
+
<NumericStepper
|
|
343
|
+
value={
|
|
344
|
+
config.key === "adults"
|
|
345
|
+
? passengers.adults
|
|
346
|
+
: passengers[config.key].length
|
|
347
|
+
}
|
|
348
|
+
minValue={config.minValue}
|
|
349
|
+
maxValue={config.maxValue}
|
|
350
|
+
onIncrement={() =>
|
|
351
|
+
handlePassengerCountChange(config.key, "increment")
|
|
352
|
+
}
|
|
353
|
+
onDecrement={() =>
|
|
354
|
+
handlePassengerCountChange(config.key, "decrement")
|
|
355
|
+
}
|
|
356
|
+
style={stepperContainerStyle}
|
|
357
|
+
buttonStyle={stepperButtonStyle}
|
|
358
|
+
buttonTextStyle={stepperButtonTextStyle}
|
|
359
|
+
valueTextStyle={stepperValueTextStyle}
|
|
360
|
+
/>
|
|
321
361
|
</View>
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
362
|
+
|
|
363
|
+
{/* Render age pickers for each child/infant */}
|
|
364
|
+
{(config.key === "children" || config.key === "infants") &&
|
|
365
|
+
passengers[config.key].map((passenger, index) => (
|
|
366
|
+
<View
|
|
367
|
+
key={passenger.id}
|
|
368
|
+
style={[styles.agePickerRow, agePickerRowStyle]}
|
|
369
|
+
>
|
|
370
|
+
<Text style={[styles.agePickerLabel, agePickerLabelStyle]}>
|
|
371
|
+
{" "}
|
|
372
|
+
{formatPassengerAgeLabel(config.name, index + 1)}
|
|
373
|
+
</Text>
|
|
374
|
+
<View style={styles.pickerContainer}>
|
|
375
|
+
<RNPickerSelect
|
|
376
|
+
value={passenger.age}
|
|
377
|
+
onValueChange={(value) =>
|
|
378
|
+
handleIndividualAgeChange(
|
|
379
|
+
config.key as any,
|
|
380
|
+
passenger.id,
|
|
381
|
+
value
|
|
382
|
+
)
|
|
383
|
+
}
|
|
384
|
+
items={getAgePickerItems(config)}
|
|
385
|
+
placeholder={{}}
|
|
386
|
+
style={{
|
|
387
|
+
inputIOS: styles.pickerInput,
|
|
388
|
+
inputAndroid: styles.pickerInput,
|
|
389
|
+
iconContainer: styles.pickerIconContainer,
|
|
390
|
+
}}
|
|
391
|
+
textInputProps={{ pointerEvents: "none" }}
|
|
392
|
+
useNativeAndroidPickerStyle={false}
|
|
393
|
+
Icon={() => (
|
|
394
|
+
<Ionicons
|
|
395
|
+
name="chevron-down"
|
|
396
|
+
size={20}
|
|
397
|
+
color={theme.helper}
|
|
398
|
+
/>
|
|
399
|
+
)}
|
|
400
|
+
/>
|
|
401
|
+
</View>
|
|
402
|
+
</View>
|
|
403
|
+
))}
|
|
338
404
|
</View>
|
|
339
405
|
))}
|
|
340
406
|
</View>
|
|
341
407
|
|
|
342
|
-
{/* Flight Class */}
|
|
343
408
|
{renderButtonGroup(
|
|
344
409
|
flightClasses,
|
|
345
410
|
selectedFlightClass,
|
|
346
|
-
|
|
411
|
+
(item) => setSelectedFlightClass(item.value),
|
|
347
412
|
flightClassLabel
|
|
348
413
|
)}
|
|
349
414
|
</View>
|
|
@@ -356,11 +421,18 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
356
421
|
backgroundColor: theme.surface,
|
|
357
422
|
padding: 16,
|
|
358
423
|
},
|
|
424
|
+
sectionContainer: {
|
|
425
|
+
marginBottom: 20,
|
|
426
|
+
},
|
|
427
|
+
sectionLabel: {
|
|
428
|
+
color: theme.labelText,
|
|
429
|
+
fontSize: 12,
|
|
430
|
+
fontWeight: "600",
|
|
431
|
+
textTransform: "uppercase",
|
|
432
|
+
marginBottom: 8,
|
|
433
|
+
},
|
|
359
434
|
buttonGroupContainer: {
|
|
360
435
|
flexDirection: "row",
|
|
361
|
-
// marginBottom: 10,
|
|
362
|
-
marginTop: 5,
|
|
363
|
-
justifyContent: "flex-start",
|
|
364
436
|
flexWrap: "wrap",
|
|
365
437
|
gap: 8,
|
|
366
438
|
},
|
|
@@ -384,7 +456,6 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
384
456
|
selectedButtonText: {
|
|
385
457
|
color: theme.onPrimary,
|
|
386
458
|
fontWeight: "bold",
|
|
387
|
-
fontSize: 14,
|
|
388
459
|
},
|
|
389
460
|
passengerSection: {
|
|
390
461
|
marginVertical: 15,
|
|
@@ -396,14 +467,11 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
396
467
|
paddingVertical: 10,
|
|
397
468
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
398
469
|
borderBottomColor: theme.divider,
|
|
399
|
-
// Remove width: '100%' unless absolutely necessary
|
|
400
470
|
},
|
|
401
471
|
passengerLabelContainer: {
|
|
402
472
|
flexDirection: "column",
|
|
403
473
|
alignItems: "flex-start",
|
|
404
474
|
flexShrink: 1,
|
|
405
|
-
// marginRight: isRTL ? 0 : 8,
|
|
406
|
-
// marginLeft: isRTL ? 8 : 0,
|
|
407
475
|
},
|
|
408
476
|
passengerName: {
|
|
409
477
|
fontSize: 16,
|
|
@@ -412,9 +480,41 @@ const themedStyles = (theme: ThemeType, isRTL: boolean) =>
|
|
|
412
480
|
},
|
|
413
481
|
passengerDescription: {
|
|
414
482
|
fontSize: 12,
|
|
415
|
-
color: theme.
|
|
483
|
+
color: theme.helper,
|
|
416
484
|
opacity: 0.8,
|
|
417
485
|
},
|
|
486
|
+
agePickerRow: {
|
|
487
|
+
flexDirection: "row",
|
|
488
|
+
alignItems: "center",
|
|
489
|
+
justifyContent: "space-between",
|
|
490
|
+
paddingVertical: 8,
|
|
491
|
+
paddingHorizontal: 16,
|
|
492
|
+
backgroundColor: theme.background,
|
|
493
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
494
|
+
borderColor: theme.divider,
|
|
495
|
+
},
|
|
496
|
+
agePickerLabel: {
|
|
497
|
+
fontSize: 14,
|
|
498
|
+
color: theme.onBackground,
|
|
499
|
+
},
|
|
500
|
+
pickerContainer: {
|
|
501
|
+
width: 120,
|
|
502
|
+
height: 40,
|
|
503
|
+
borderWidth: 1,
|
|
504
|
+
borderColor: theme.border,
|
|
505
|
+
borderRadius: 8,
|
|
506
|
+
justifyContent: "center",
|
|
507
|
+
},
|
|
508
|
+
pickerInput: {
|
|
509
|
+
fontSize: 14,
|
|
510
|
+
paddingHorizontal: 10,
|
|
511
|
+
paddingVertical: 8,
|
|
512
|
+
color: theme.onSurface,
|
|
513
|
+
},
|
|
514
|
+
pickerIconContainer: {
|
|
515
|
+
top: 10,
|
|
516
|
+
right: 10,
|
|
517
|
+
},
|
|
418
518
|
});
|
|
419
519
|
|
|
420
520
|
export default FlightSummary;
|