@devtravelcode/widget-native 1.0.2 → 1.0.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.
Files changed (32) hide show
  1. package/dist/App.js +8 -5
  2. package/dist/modules/hooks/useHotelMapData.d.ts +1 -1
  3. package/dist/modules/hooks/useHotelMapData.js +26 -32
  4. package/dist/modules/search-form/AgeSelector.js +4 -1
  5. package/dist/modules/search-form/NationalityInput.js +7 -3
  6. package/dist/modules/search-form/TimePicker.js +4 -3
  7. package/dist/modules/search-form/flight/AirlinesSelector.js +7 -3
  8. package/dist/modules/search-form/flight/DatePicker.js +14 -2
  9. package/dist/modules/search-form/flight/FlightSearchForm.js +2 -1
  10. package/dist/modules/search-form/flight/LocationInput.js +6 -2
  11. package/dist/modules/search-form/flight/PassengersPicker.js +9 -4
  12. package/dist/modules/search-form/flight/SwitchLocationBtn.js +4 -1
  13. package/dist/modules/search-form/flight/flight-filters/FiltersContent.d.ts +1 -0
  14. package/dist/modules/search-form/flight/flight-filters/FiltersContent.js +14 -13
  15. package/dist/modules/search-form/flight/flight-filters/FlightFiltersDynamic.js +3 -2
  16. package/dist/modules/search-form/flight/flight-filters/RangeBlock.d.ts +1 -0
  17. package/dist/modules/search-form/flight/flight-filters/RangeBlock.js +5 -3
  18. package/dist/modules/search-form/flight/flight-results/FlightCard.js +3 -2
  19. package/dist/modules/search-form/flight/flight-results/FlightPriceBlock.js +4 -1
  20. package/dist/modules/search-form/flight/flight-results/ProvidersLoader.js +4 -1
  21. package/dist/modules/search-form/hotel/GuestSelector.js +14 -9
  22. package/dist/modules/search-form/hotel/HotelLocation.js +6 -2
  23. package/dist/modules/search-form/hotel/HotelResults.d.ts +1 -0
  24. package/dist/modules/search-form/hotel/HotelResults.js +32 -6
  25. package/dist/modules/search-form/hotel/components/HotelCard.d.ts +1 -0
  26. package/dist/modules/search-form/hotel/components/HotelCard.js +39 -5
  27. package/dist/modules/search-form/hotel/components/HotelList.d.ts +1 -0
  28. package/dist/modules/search-form/hotel/components/HotelList.js +2 -2
  29. package/dist/modules/search-form/hotel/components/HotelMap.js +40 -9
  30. package/dist/modules/search-form/hotel/hotel-filters/HotelFilters.js +12 -5
  31. package/index.ts +7 -0
  32. package/package.json +2 -2
@@ -3,9 +3,10 @@ import { View, Text, TouchableOpacity, Switch, StyleSheet, } from "react-native"
3
3
  import RangeBlock from "./RangeBlock";
4
4
  import { Colors, Spacing, FontSize, BorderRadius } from "../../../../theme/colors";
5
5
  const SectionTitle = ({ title }) => (_jsx(View, { style: styles.sectionHeader, children: _jsx(Text, { style: styles.sectionTitle, children: title }) }));
6
- const RadioOption = ({ label, selected, onPress }) => (_jsxs(TouchableOpacity, { style: styles.radioRow, onPress: onPress, activeOpacity: 0.7, children: [_jsx(View, { style: [styles.radioOuter, selected && styles.radioOuterSelected], children: selected && _jsx(View, { style: styles.radioInner }) }), _jsx(Text, { style: styles.radioLabel, children: label })] }));
7
- const CheckboxOption = ({ label, checked, onPress }) => (_jsxs(TouchableOpacity, { style: styles.checkboxRow, onPress: onPress, activeOpacity: 0.7, children: [_jsx(View, { style: [styles.checkboxOuter, checked && styles.checkboxChecked], children: checked && _jsx(Text, { style: styles.checkboxMark, children: "\u2713" }) }), _jsx(Text, { style: styles.checkboxLabel, children: label })] }));
8
- const FiltersContent = ({ has, openSections, toggleSection, getValue, handleRangeChange, handleInputChange, getRangeStyle, formatTime, formatDuration, airlines, translations, currencySign, dateTimeFormat, maxDayMinutes, onRangeDragStart, onRangeDragEnd, }) => {
6
+ const RadioOption = ({ label, selected, onPress, color }) => (_jsxs(TouchableOpacity, { style: styles.radioRow, onPress: onPress, activeOpacity: 0.7, children: [_jsx(View, { style: [styles.radioOuter, selected && styles.radioOuterSelected, selected && color ? { borderColor: color } : null], children: selected && _jsx(View, { style: [styles.radioInner, color ? { backgroundColor: color } : null] }) }), _jsx(Text, { style: styles.radioLabel, children: label })] }));
7
+ const CheckboxOption = ({ label, checked, onPress, color }) => (_jsxs(TouchableOpacity, { style: styles.checkboxRow, onPress: onPress, activeOpacity: 0.7, children: [_jsx(View, { style: [styles.checkboxOuter, checked && styles.checkboxChecked, checked && color ? { backgroundColor: color, borderColor: color } : null], children: checked && _jsx(Text, { style: styles.checkboxMark, children: "\u2713" }) }), _jsx(Text, { style: styles.checkboxLabel, children: label })] }));
8
+ const FiltersContent = ({ has, openSections, toggleSection, getValue, handleRangeChange, handleInputChange, getRangeStyle, formatTime, formatDuration, airlines, translations, currencySign, dateTimeFormat, maxDayMinutes, onRangeDragStart, onRangeDragEnd, accentColor, }) => {
9
+ const ac = accentColor || Colors.primary;
9
10
  const transferLabels = [
10
11
  translations["filter_any"] || "Any",
11
12
  translations["filter_nonstop"] || "Nonstop",
@@ -20,20 +21,20 @@ const FiltersContent = ({ has, openSections, toggleSection, getValue, handleRang
20
21
  ];
21
22
  const baggageValues = ["all", "1", "0"];
22
23
  const transferValues = ["all", "0", "1", "2", "3"];
23
- return (_jsxs(View, { style: styles.container, children: [_jsx(Text, { style: styles.title, children: translations["filters_title"] || "Filters" }), (has("minprice") || has("maxprice")) && (_jsx(RangeBlock, { title: translations["filter_price"] || "Price", minName: "minprice", maxName: "maxprice", maxValue: 1000, step: 10, open: openSections.includes("price"), toggle: () => toggleSection("price"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: (v) => `${v} ${currencySign}`, isShow: true, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), has("baggage") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_baggage"] || "Baggage" }), _jsx(View, { style: styles.sectionContent, children: baggageLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("baggage", "all") === baggageValues[i], onPress: () => handleInputChange("baggage", baggageValues[i]) }, i))) })] })), has("transfer") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_transfer_outbound"] || "Stops (outbound)" }), _jsx(View, { style: styles.sectionContent, children: transferLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("transfer", "all") === transferValues[i], onPress: () => handleInputChange("transfer", transferValues[i]) }, i))) })] })), has("transferReturn") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_transfer_return"] || "Stops (return)" }), _jsx(View, { style: styles.sectionContent, children: transferLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("transferReturn", "all") === transferValues[i], onPress: () => handleInputChange("transferReturn", transferValues[i]) }, i))) })] })), has("charter") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_charter"] || "Charter" }), _jsxs(View, { style: styles.toggleRow, children: [_jsx(Text, { style: styles.toggleLabel, children: translations["filter_charter_toggle"] || "Charter" }), _jsx(Switch, { value: !!getValue("charter", 0), onValueChange: (val) => handleInputChange("charter", val ? 1 : 0), trackColor: { false: Colors.border, true: Colors.primary }, thumbColor: Colors.white, ios_backgroundColor: Colors.border })] })] })), has("changeAirport") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_no_airport_change"] || "No airport change" }), _jsxs(View, { style: styles.toggleRow, children: [_jsx(Text, { style: styles.toggleLabel, children: translations["filter_no_airport_change"] ||
24
- "No airport change" }), _jsx(Switch, { value: !!getValue("changeAirport", 0), onValueChange: (val) => handleInputChange("changeAirport", val ? 1 : 0), trackColor: { false: Colors.border, true: Colors.primary }, thumbColor: Colors.white, ios_backgroundColor: Colors.border })] })] })), (has("departureMin") || has("departureMax")) && (_jsx(RangeBlock, { title: translations["filter_departure_outbound"] ||
25
- "Departure time (outbound)", minName: "departureMin", maxName: "departureMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("departure"), toggle: () => toggleSection("departure"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("arrivalMin") || has("arrivalMax")) && (_jsx(RangeBlock, { title: translations["filter_arrival_outbound"] ||
26
- "Arrival time (outbound)", minName: "arrivalMin", maxName: "arrivalMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("arrival"), toggle: () => toggleSection("arrival"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("returnMin") || has("returnMax")) && (_jsx(RangeBlock, { title: translations["filter_departure_return"] ||
27
- "Departure time (return)", minName: "returnMin", maxName: "returnMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("return"), toggle: () => toggleSection("return"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("returnArrivalMin") || has("returnArrivalMax")) && (_jsx(RangeBlock, { title: translations["filter_arrival_return"] ||
28
- "Arrival time (return)", minName: "returnArrivalMin", maxName: "returnArrivalMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("returnArrival"), toggle: () => toggleSection("returnArrival"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("outboundStopTimeMin") || has("outboundStopTimeMax")) && (_jsx(RangeBlock, { title: translations["filter_stop_duration_outbound"] ||
29
- "Stop duration (outbound)", minName: "outboundStopTimeMin", maxName: "outboundStopTimeMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("outbound"), toggle: () => toggleSection("outbound"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("inboundStopTimeMin") || has("inboundStopTimeMax")) && (_jsx(RangeBlock, { title: translations["filter_stop_duration_inbound"] ||
30
- "Stop duration (return)", minName: "inboundStopTimeMin", maxName: "inboundStopTimeMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("inbound"), toggle: () => toggleSection("inbound"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), (has("durationMin") || has("durationMax")) && (_jsx(RangeBlock, { title: translations["filter_total_stop_duration"] ||
31
- "Total stop duration", minName: "durationMin", maxName: "durationMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("duration"), toggle: () => toggleSection("duration"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd })), has("airline") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_airlines"] || "Airlines" }), _jsxs(View, { style: styles.sectionContent, children: [Object.entries(airlines).map(([code, name]) => (_jsx(CheckboxOption, { label: name, checked: Array.isArray(getValue("airline", [])) &&
24
+ return (_jsxs(View, { style: styles.container, children: [_jsx(Text, { style: styles.title, children: translations["filters_title"] || "Filters" }), (has("minprice") || has("maxprice")) && (_jsx(RangeBlock, { title: translations["filter_price"] || "Price", minName: "minprice", maxName: "maxprice", maxValue: 1000, step: 10, open: openSections.includes("price"), toggle: () => toggleSection("price"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: (v) => `${v} ${currencySign}`, isShow: true, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), has("baggage") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_baggage"] || "Baggage" }), _jsx(View, { style: styles.sectionContent, children: baggageLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("baggage", "all") === baggageValues[i], onPress: () => handleInputChange("baggage", baggageValues[i]), color: ac }, i))) })] })), has("transfer") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_transfer_outbound"] || "Stops (outbound)" }), _jsx(View, { style: styles.sectionContent, children: transferLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("transfer", "all") === transferValues[i], onPress: () => handleInputChange("transfer", transferValues[i]), color: ac }, i))) })] })), has("transferReturn") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_transfer_return"] || "Stops (return)" }), _jsx(View, { style: styles.sectionContent, children: transferLabels.map((label, i) => (_jsx(RadioOption, { label: label, selected: getValue("transferReturn", "all") === transferValues[i], onPress: () => handleInputChange("transferReturn", transferValues[i]), color: ac }, i))) })] })), has("charter") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_charter"] || "Charter" }), _jsxs(View, { style: styles.toggleRow, children: [_jsx(Text, { style: styles.toggleLabel, children: translations["filter_charter_toggle"] || "Charter" }), _jsx(Switch, { value: !!getValue("charter", 0), onValueChange: (val) => handleInputChange("charter", val ? 1 : 0), trackColor: { false: Colors.border, true: ac }, thumbColor: Colors.white, ios_backgroundColor: Colors.border })] })] })), has("changeAirport") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_no_airport_change"] || "No airport change" }), _jsxs(View, { style: styles.toggleRow, children: [_jsx(Text, { style: styles.toggleLabel, children: translations["filter_no_airport_change"] ||
25
+ "No airport change" }), _jsx(Switch, { value: !!getValue("changeAirport", 0), onValueChange: (val) => handleInputChange("changeAirport", val ? 1 : 0), trackColor: { false: Colors.border, true: ac }, thumbColor: Colors.white, ios_backgroundColor: Colors.border })] })] })), (has("departureMin") || has("departureMax")) && (_jsx(RangeBlock, { title: translations["filter_departure_outbound"] ||
26
+ "Departure time (outbound)", minName: "departureMin", maxName: "departureMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("departure"), toggle: () => toggleSection("departure"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("arrivalMin") || has("arrivalMax")) && (_jsx(RangeBlock, { title: translations["filter_arrival_outbound"] ||
27
+ "Arrival time (outbound)", minName: "arrivalMin", maxName: "arrivalMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("arrival"), toggle: () => toggleSection("arrival"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("returnMin") || has("returnMax")) && (_jsx(RangeBlock, { title: translations["filter_departure_return"] ||
28
+ "Departure time (return)", minName: "returnMin", maxName: "returnMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("return"), toggle: () => toggleSection("return"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("returnArrivalMin") || has("returnArrivalMax")) && (_jsx(RangeBlock, { title: translations["filter_arrival_return"] ||
29
+ "Arrival time (return)", minName: "returnArrivalMin", maxName: "returnArrivalMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("returnArrival"), toggle: () => toggleSection("returnArrival"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatTime, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("outboundStopTimeMin") || has("outboundStopTimeMax")) && (_jsx(RangeBlock, { title: translations["filter_stop_duration_outbound"] ||
30
+ "Stop duration (outbound)", minName: "outboundStopTimeMin", maxName: "outboundStopTimeMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("outbound"), toggle: () => toggleSection("outbound"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("inboundStopTimeMin") || has("inboundStopTimeMax")) && (_jsx(RangeBlock, { title: translations["filter_stop_duration_inbound"] ||
31
+ "Stop duration (return)", minName: "inboundStopTimeMin", maxName: "inboundStopTimeMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("inbound"), toggle: () => toggleSection("inbound"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), (has("durationMin") || has("durationMax")) && (_jsx(RangeBlock, { title: translations["filter_total_stop_duration"] ||
32
+ "Total stop duration", minName: "durationMin", maxName: "durationMax", maxValue: maxDayMinutes, step: 15, open: openSections.includes("duration"), toggle: () => toggleSection("duration"), getValue: getValue, handleRangeChange: handleRangeChange, getRangeStyle: getRangeStyle, formatter: formatDuration, isShow: false, onDragStart: onRangeDragStart, onDragEnd: onRangeDragEnd, accentColor: ac })), has("airline") && (_jsxs(View, { style: styles.section, children: [_jsx(SectionTitle, { title: translations["filter_airlines"] || "Airlines" }), _jsxs(View, { style: styles.sectionContent, children: [Object.entries(airlines).map(([code, name]) => (_jsx(CheckboxOption, { label: name, checked: Array.isArray(getValue("airline", [])) &&
32
33
  getValue("airline", []).includes(code), onPress: () => handleInputChange("airline", {
33
34
  code,
34
35
  checked: !(Array.isArray(getValue("airline", [])) &&
35
36
  getValue("airline", []).includes(code)),
36
- }) }, code))), _jsx(TouchableOpacity, { style: styles.clearButton, onPress: () => handleInputChange("airline", []), activeOpacity: 0.7, children: _jsx(Text, { style: styles.clearButtonText, children: translations["clear_all"] || "Clear all" }) })] })] }))] }));
37
+ }), color: ac }, code))), _jsx(TouchableOpacity, { style: styles.clearButton, onPress: () => handleInputChange("airline", []), activeOpacity: 0.7, children: _jsx(Text, { style: styles.clearButtonText, children: translations["clear_all"] || "Clear all" }) })] })] }))] }));
37
38
  };
38
39
  const styles = StyleSheet.create({
39
40
  container: {
@@ -13,7 +13,8 @@ const FlightFiltersDynamic = ({ filters = [], airlines = {}, loading = false, se
13
13
  const [openSections, setOpenSections] = useState([]);
14
14
  const [isPopupOpen, setIsPopupOpen] = useState(false);
15
15
  const [scrollEnabled, setScrollEnabled] = useState(true);
16
- const { currency, dateTimeFormat } = useWidget();
16
+ const { currency, dateTimeFormat, colors } = useWidget();
17
+ const btnColor = colors.primary || Colors.primary;
17
18
  const currencySigns = {
18
19
  USD: "$",
19
20
  EUR: "\u20AC",
@@ -122,7 +123,7 @@ const FlightFiltersDynamic = ({ filters = [], airlines = {}, loading = false, se
122
123
  }
123
124
  if (!filters?.length || !sessionId)
124
125
  return null;
125
- return (_jsxs(View, { children: [_jsxs(TouchableOpacity, { style: styles.filterButton, onPress: () => setIsPopupOpen(true), activeOpacity: 0.7, children: [_jsxs(Svg, { width: 24, height: 20, viewBox: "0 0 24 20", fill: "none", children: [_jsx(Path, { d: "M18.5 4.1665H5.5C4.67157 4.1665 4 4.72615 4 5.4165C4 6.10686 4.67157 6.6665 5.5 6.6665H18.5C19.3284 6.6665 20 6.10686 20 5.4165C20 4.72615 19.3284 4.1665 18.5 4.1665Z", fill: Colors.primary }), _jsx(Path, { opacity: 0.3, fillRule: "evenodd", clipRule: "evenodd", d: "M7.5 9.1665H16.5C17.3284 9.1665 18 9.72615 18 10.4165C18 11.1069 17.3284 11.6665 16.5 11.6665H7.5C6.67157 11.6665 6 11.1069 6 10.4165C6 9.72615 6.67157 9.1665 7.5 9.1665ZM10.5 14.1665H13.5C14.3284 14.1665 15 14.7261 15 15.4165C15 16.1069 14.3284 16.6665 13.5 16.6665H10.5C9.67157 16.6665 9 16.1069 9 15.4165C9 14.7261 9.67157 14.1665 10.5 14.1665Z", fill: Colors.primary })] }), _jsx(Text, { style: styles.filterButtonText, children: translations["filters_title"] || "Filters" })] }), _jsx(Modal, { visible: isPopupOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: () => setIsPopupOpen(false), children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: () => setIsPopupOpen(false), hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsx(View, { style: styles.modalHeader, children: _jsx(Text, { style: styles.modalTitle, children: translations["filters_title"] || "Filters" }) }), _jsx(ScrollView, { style: styles.modalContent, contentContainerStyle: styles.modalContentInner, showsVerticalScrollIndicator: false, scrollEnabled: scrollEnabled, children: _jsx(FiltersContent, { has: has, openSections: openSections, toggleSection: toggleSection, getValue: getValue, handleRangeChange: handleRangeChange, handleInputChange: handleInputChange, getRangeStyle: getRangeStyle, formatTime: formatTime, formatDuration: formatDuration, airlines: airlines, translations: translations, currencySign: currencySign, dateTimeFormat: dateTimeFormat, maxDayMinutes: MAX_DAY_MINUTES, onRangeDragStart: () => setScrollEnabled(false), onRangeDragEnd: () => setScrollEnabled(true) }) }), _jsxs(View, { style: styles.modalFooter, children: [_jsx(TouchableOpacity, { style: styles.resetButton, onPress: handleReset, activeOpacity: 0.7, children: _jsx(Text, { style: styles.resetButtonText, children: translations["filter_reset_btn"] || "Reset" }) }), _jsx(TouchableOpacity, { style: styles.applyButton, onPress: handleApply, activeOpacity: 0.8, children: _jsx(Text, { style: styles.applyButtonText, children: translations["filter_apply_btn"] || "Apply" }) })] })] }) })] }));
126
+ return (_jsxs(View, { children: [_jsxs(TouchableOpacity, { style: styles.filterButton, onPress: () => setIsPopupOpen(true), activeOpacity: 0.7, children: [_jsxs(Svg, { width: 24, height: 20, viewBox: "0 0 24 20", fill: "none", children: [_jsx(Path, { d: "M18.5 4.1665H5.5C4.67157 4.1665 4 4.72615 4 5.4165C4 6.10686 4.67157 6.6665 5.5 6.6665H18.5C19.3284 6.6665 20 6.10686 20 5.4165C20 4.72615 19.3284 4.1665 18.5 4.1665Z", fill: btnColor }), _jsx(Path, { opacity: 0.3, fillRule: "evenodd", clipRule: "evenodd", d: "M7.5 9.1665H16.5C17.3284 9.1665 18 9.72615 18 10.4165C18 11.1069 17.3284 11.6665 16.5 11.6665H7.5C6.67157 11.6665 6 11.1069 6 10.4165C6 9.72615 6.67157 9.1665 7.5 9.1665ZM10.5 14.1665H13.5C14.3284 14.1665 15 14.7261 15 15.4165C15 16.1069 14.3284 16.6665 13.5 16.6665H10.5C9.67157 16.6665 9 16.1069 9 15.4165C9 14.7261 9.67157 14.1665 10.5 14.1665Z", fill: btnColor })] }), _jsx(Text, { style: styles.filterButtonText, children: translations["filters_title"] || "Filters" })] }), _jsx(Modal, { visible: isPopupOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: () => setIsPopupOpen(false), children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: () => setIsPopupOpen(false), hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsx(View, { style: styles.modalHeader, children: _jsx(Text, { style: styles.modalTitle, children: translations["filters_title"] || "Filters" }) }), _jsx(ScrollView, { style: styles.modalContent, contentContainerStyle: styles.modalContentInner, showsVerticalScrollIndicator: false, scrollEnabled: scrollEnabled, children: _jsx(FiltersContent, { has: has, openSections: openSections, toggleSection: toggleSection, getValue: getValue, handleRangeChange: handleRangeChange, handleInputChange: handleInputChange, getRangeStyle: getRangeStyle, formatTime: formatTime, formatDuration: formatDuration, airlines: airlines, translations: translations, currencySign: currencySign, dateTimeFormat: dateTimeFormat, maxDayMinutes: MAX_DAY_MINUTES, onRangeDragStart: () => setScrollEnabled(false), onRangeDragEnd: () => setScrollEnabled(true), accentColor: btnColor }) }), _jsxs(View, { style: styles.modalFooter, children: [_jsx(TouchableOpacity, { style: styles.resetButton, onPress: handleReset, activeOpacity: 0.7, children: _jsx(Text, { style: styles.resetButtonText, children: translations["filter_reset_btn"] || "Reset" }) }), _jsx(TouchableOpacity, { style: [styles.applyButton, { backgroundColor: btnColor }], onPress: handleApply, activeOpacity: 0.8, children: _jsx(Text, { style: styles.applyButtonText, children: translations["filter_apply_btn"] || "Apply" }) })] })] }) })] }));
126
127
  };
127
128
  const styles = StyleSheet.create({
128
129
  loadingContainer: {
@@ -17,6 +17,7 @@ type RangeBlockProps = {
17
17
  isShow: boolean;
18
18
  onDragStart?: () => void;
19
19
  onDragEnd?: () => void;
20
+ accentColor?: string;
20
21
  };
21
22
  declare const RangeBlock: React.FC<RangeBlockProps>;
22
23
  export default RangeBlock;
@@ -4,7 +4,8 @@ import { View, Text, PanResponder, StyleSheet, } from "react-native";
4
4
  import { Colors, Spacing, FontSize, BorderRadius } from "../../../../theme/colors";
5
5
  const THUMB_SIZE = 28;
6
6
  const TRACK_HEIGHT = 4;
7
- const RangeBlock = ({ title, minName, maxName, maxValue, step, getValue, handleRangeChange, formatter, onDragStart, onDragEnd, }) => {
7
+ const RangeBlock = ({ title, minName, maxName, maxValue, step, getValue, handleRangeChange, formatter, onDragStart, onDragEnd, accentColor, }) => {
8
+ const ac = accentColor || Colors.primary;
8
9
  const rawMin = getValue(minName, 0);
9
10
  const rawMax = getValue(maxName, maxValue);
10
11
  const currentMin = typeof rawMin === "string" ? parseFloat(rawMin) : rawMin;
@@ -91,13 +92,14 @@ const RangeBlock = ({ title, minName, maxName, maxValue, step, getValue, handleR
91
92
  {
92
93
  left: `${minPercent}%`,
93
94
  right: `${100 - maxPercent}%`,
95
+ backgroundColor: ac,
94
96
  },
95
97
  ] }), _jsx(View, { style: [
96
98
  styles.thumb,
97
- { left: `${minPercent}%`, marginLeft: -THUMB_SIZE / 2 },
99
+ { left: `${minPercent}%`, marginLeft: -THUMB_SIZE / 2, borderColor: ac },
98
100
  ], hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }, ...minPanResponder.panHandlers }), _jsx(View, { style: [
99
101
  styles.thumb,
100
- { left: `${maxPercent}%`, marginLeft: -THUMB_SIZE / 2 },
102
+ { left: `${maxPercent}%`, marginLeft: -THUMB_SIZE / 2, borderColor: ac },
101
103
  ], hitSlop: { top: 12, bottom: 12, left: 12, right: 12 }, ...maxPanResponder.panHandlers })] })] })] }));
102
104
  };
103
105
  const styles = StyleSheet.create({
@@ -101,7 +101,8 @@ const FlightCard = ({ item, loading, dictionaries, airlines, sessionId, translat
101
101
  setTooltipData(null);
102
102
  }, []);
103
103
  const chevronRotation = useRef(new Animated.Value(0)).current;
104
- const { config, dateTimeFormat } = useWidget();
104
+ const { config, dateTimeFormat, colors } = useWidget();
105
+ const btnColor = colors.primary || Colors.primary;
105
106
  const formatDuration = (dur) => {
106
107
  if (!dur)
107
108
  return "\u2014";
@@ -239,7 +240,7 @@ const FlightCard = ({ item, loading, dictionaries, airlines, sessionId, translat
239
240
  ], children: itinerary?.transfers > 0
240
241
  ? `${itinerary.transfers} ${translations["transfers"] || "Stops"}`
241
242
  : translations["direct_flight"] || "Direct" })] }), itinerary?.segments?.length ? (_jsx(FlightSegments, { segments: itinerary.segments, dictionaries: dictionaries, lang: lang, translations: translations, onShowTooltip: showTooltip, onDismissTooltip: dismissTooltip, activeTooltip: tooltipData?.label })) : (_jsx(Text, { style: styles.noSegmentsText, children: translations["no_segments"] || "No segment data" }))] }), _jsxs(View, { style: [styles.timeBlock, styles.timeBlockRight], children: [_jsx(Text, { style: styles.timeText, children: formatTimeByDateTimeFormat(lastSegment?.arrival?.at, dateTimeFormat) }), _jsx(Text, { style: styles.cityText, numberOfLines: 1, children: arrCity }), _jsx(Text, { style: styles.dateText, children: arrDate })] })] }) }, i));
242
- }), _jsxs(View, { style: styles.priceSection, children: [_jsx(FlightBaggageToggle, { flight: flight, includeBaggage: includeBaggage, setIncludeBaggage: setIncludeBaggage, setDynamicPrice: setDynamicPrice, setBaggageText: setBaggageText, setBaggageImage: setBaggageImage, setBuyHref: setBuyHref, sessionId: sessionId, translations: translations, lang: lang }), _jsx(TouchableOpacity, { style: [styles.buyButton, loading && styles.buyButtonLoading], onPress: handleBuy, activeOpacity: 0.8, children: _jsxs(Text, { style: styles.buyButtonText, children: [translations["buy_for"] || "Buy for", " ", formattedText] }) }), availableSeats > 0 && (_jsxs(Text, { style: styles.seatsText, children: [translations["remaining"] || "Remaining", ": ", availableSeats, " ", translations["seats"] || "seats"] }))] }), _jsx(TouchableOpacity, { style: styles.detailsButton, onPress: toggleDetails, activeOpacity: 0.7, children: _jsx(Animated.View, { style: {
243
+ }), _jsxs(View, { style: styles.priceSection, children: [_jsx(FlightBaggageToggle, { flight: flight, includeBaggage: includeBaggage, setIncludeBaggage: setIncludeBaggage, setDynamicPrice: setDynamicPrice, setBaggageText: setBaggageText, setBaggageImage: setBaggageImage, setBuyHref: setBuyHref, sessionId: sessionId, translations: translations, lang: lang }), _jsx(TouchableOpacity, { style: [styles.buyButton, { backgroundColor: btnColor }, loading && styles.buyButtonLoading], onPress: handleBuy, activeOpacity: 0.8, children: _jsxs(Text, { style: styles.buyButtonText, children: [translations["buy_for"] || "Buy for", " ", formattedText] }) }), availableSeats > 0 && (_jsxs(Text, { style: styles.seatsText, children: [translations["remaining"] || "Remaining", ": ", availableSeats, " ", translations["seats"] || "seats"] }))] }), _jsx(TouchableOpacity, { style: styles.detailsButton, onPress: toggleDetails, activeOpacity: 0.7, children: _jsx(Animated.View, { style: {
243
244
  transform: [{ rotate: chevronRotateInterpolation }],
244
245
  }, children: _jsx(Svg, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", children: _jsx(Path, { fillRule: "evenodd", clipRule: "evenodd", d: "M3.05727 7.05687C3.57797 6.53617 4.42219 6.53617 4.94289 7.05687L12.0001 14.1141L19.0573 7.05687C19.578 6.53617 20.4222 6.53617 20.9429 7.05687C21.4636 7.57756 21.4636 8.42178 20.9429 8.94248L12.9429 16.9425C12.4222 17.4632 11.578 17.4632 11.0573 16.9425L3.05727 8.94248C2.53657 8.42179 2.53657 7.57757 3.05727 7.05687Z", fill: "#5B5D6C" }) }) }) }), _jsx(FlightAdditionalInfo, { show: showDetails, itineraries: itineraries, airlines: {
245
246
  [flight.airline]: {
@@ -1,10 +1,13 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
3
+ import { useWidget } from "../../../../context/WidgetContext";
3
4
  import { Colors, Spacing, FontSize, BorderRadius } from "../../../../theme/colors";
4
5
  const FlightPriceBlock = ({ price, currencySign = "", loading = false, onBuy, availableSeats = 0, translations, }) => {
6
+ const { colors } = useWidget();
7
+ const btnColor = colors.primary || Colors.primary;
5
8
  const formattedPrice = Number(price || 0).toFixed(2);
6
9
  const formattedText = `${currencySign}${formattedPrice}`;
7
- return (_jsxs(View, { style: styles.container, children: [_jsx(TouchableOpacity, { style: [styles.buyButton, loading && styles.buyButtonLoading], onPress: onBuy, activeOpacity: 0.8, disabled: loading, children: _jsxs(Text, { style: styles.buyButtonText, children: [translations["buy_for"] || "Buy for", " ", formattedText] }) }), availableSeats > 0 && (_jsxs(Text, { style: styles.seatsText, children: [translations["remaining"] || "Remaining", ": ", availableSeats, " ", translations["seats"] || "seats"] }))] }));
10
+ return (_jsxs(View, { style: styles.container, children: [_jsx(TouchableOpacity, { style: [styles.buyButton, { backgroundColor: btnColor }, loading && styles.buyButtonLoading], onPress: onBuy, activeOpacity: 0.8, disabled: loading, children: _jsxs(Text, { style: styles.buyButtonText, children: [translations["buy_for"] || "Buy for", " ", formattedText] }) }), availableSeats > 0 && (_jsxs(Text, { style: styles.seatsText, children: [translations["remaining"] || "Remaining", ": ", availableSeats, " ", translations["seats"] || "seats"] }))] }));
8
11
  };
9
12
  const styles = StyleSheet.create({
10
13
  container: {
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState, useRef } from "react";
3
3
  import { View, Text, Animated, StyleSheet } from "react-native";
4
+ import { useWidget } from "../../../../context/WidgetContext";
4
5
  import { Colors, Spacing, FontSize, BorderRadius } from "../../../../theme/colors";
5
6
  const AIRLINES = [
6
7
  "Lufthansa",
@@ -79,6 +80,8 @@ function shuffleArray(arr) {
79
80
  return a;
80
81
  }
81
82
  const ProvidersLoader = ({ active, type = "flights", translations, }) => {
83
+ const { colors } = useWidget();
84
+ const btnColor = colors.primary || Colors.primary;
82
85
  const configMap = {
83
86
  flights: {
84
87
  title: translations["loader_flights_title"] || "Searching flights",
@@ -179,7 +182,7 @@ const ProvidersLoader = ({ active, type = "flights", translations, }) => {
179
182
  inputRange: [0, 1],
180
183
  outputRange: ["0%", "100%"],
181
184
  });
182
- return (_jsx(Animated.View, { style: [styles.container, { opacity: fadeAnim }], children: _jsxs(View, { style: styles.content, children: [_jsxs(View, { style: styles.headerRow, children: [_jsx(View, { style: styles.counterBadge, children: _jsx(Text, { style: styles.counterText, children: counter }) }), _jsxs(View, { style: styles.textBlock, children: [_jsx(Text, { style: styles.title, children: config.title }), _jsxs(Animated.Text, { style: [styles.subtitle, { opacity: nameOpacity }], children: [config.subtitlePrefix, " ", names[index], "..."] })] })] }), _jsx(View, { style: styles.progressBackground, children: _jsx(Animated.View, { style: [styles.progressBar, { width: progressWidth }] }) })] }) }));
185
+ return (_jsx(Animated.View, { style: [styles.container, { opacity: fadeAnim }], children: _jsxs(View, { style: styles.content, children: [_jsxs(View, { style: styles.headerRow, children: [_jsx(View, { style: [styles.counterBadge, { backgroundColor: btnColor + '1A' }], children: _jsx(Text, { style: [styles.counterText, { color: btnColor }], children: counter }) }), _jsxs(View, { style: styles.textBlock, children: [_jsx(Text, { style: styles.title, children: config.title }), _jsxs(Animated.Text, { style: [styles.subtitle, { opacity: nameOpacity }], children: [config.subtitlePrefix, " ", names[index], "..."] })] })] }), _jsx(View, { style: styles.progressBackground, children: _jsx(Animated.View, { style: [styles.progressBar, { width: progressWidth, backgroundColor: btnColor }] }) })] }) }));
183
186
  };
184
187
  const styles = StyleSheet.create({
185
188
  container: {
@@ -3,13 +3,17 @@ import { useState, useEffect } from "react";
3
3
  import { View, Text, TouchableOpacity, Modal, ScrollView, StyleSheet, } from "react-native";
4
4
  import { useSafeAreaInsets } from "react-native-safe-area-context";
5
5
  import Svg, { Path } from "react-native-svg";
6
+ import { useWidget } from "../../../context/WidgetContext";
6
7
  import { Colors, Spacing, BorderRadius, FontSize } from "../../../theme/colors";
7
8
  import { CloseIcon } from "../../../store";
8
9
  import { formStyles } from "../../../theme/formStyles";
9
- const ChevronDown = () => (_jsx(Svg, { width: 20, height: 20, viewBox: "0 0 20 20", fill: "none", children: _jsx(Path, { d: "M5 8L10 12.5L15 8", stroke: Colors.primary, strokeWidth: 2, strokeLinecap: "round" }) }));
10
+ const ChevronDown = ({ color = Colors.primary }) => (_jsx(Svg, { width: 20, height: 20, viewBox: "0 0 20 20", fill: "none", children: _jsx(Path, { d: "M5 8L10 12.5L15 8", stroke: color, strokeWidth: 2, strokeLinecap: "round" }) }));
10
11
  const MAX_GUESTS = 20;
11
12
  const AGE_OPTIONS = Array.from({ length: 18 }, (_, i) => i);
12
13
  const GuestSelector = ({ value = [{ adults: 2, children: 0, childrenAges: [] }], onChange, translations, }) => {
14
+ const { colors } = useWidget();
15
+ const btnColor = colors.primary || Colors.primary;
16
+ const inputBg = colors.input || Colors.inputBg;
13
17
  const insets = useSafeAreaInsets();
14
18
  const [rooms, setRooms] = useState(value);
15
19
  const [isModalOpen, setIsModalOpen] = useState(false);
@@ -64,29 +68,30 @@ const GuestSelector = ({ value = [{ adults: 2, children: 0, childrenAges: [] }],
64
68
  const handleSave = () => {
65
69
  setIsModalOpen(false);
66
70
  };
67
- return (_jsxs(View, { children: [_jsxs(TouchableOpacity, { style: formStyles.inputTrigger, onPress: () => setIsModalOpen(true), activeOpacity: 0.8, children: [_jsx(Text, { style: formStyles.label, children: translations["hotel_form_guests"] || "Guests" }), _jsxs(View, { style: formStyles.inputTriggerRow, children: [_jsx(Text, { style: styles.selectorText, numberOfLines: 1, children: buttonText }), _jsx(ChevronDown, {})] })] }), _jsx(Modal, { visible: isModalOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: () => setIsModalOpen(false), children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: () => setIsModalOpen(false), hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsx(View, { style: styles.modalHeaderRow, children: _jsx(Text, { style: styles.modalTitle, children: translations["hotel_form_guests"] || "Guests" }) }), _jsxs(ScrollView, { style: styles.scrollView, contentContainerStyle: styles.scrollContent, showsVerticalScrollIndicator: false, children: [rooms.map((room, index) => (_jsxs(View, { style: styles.roomBlock, children: [_jsxs(View, { style: styles.roomHeader, children: [_jsxs(Text, { style: styles.roomTitle, children: [translations["hotel_room_label"] || "Room", " ", index + 1] }), rooms.length > 1 && (_jsx(TouchableOpacity, { onPress: () => removeRoom(index), activeOpacity: 0.7, children: _jsx(Text, { style: styles.removeText, children: translations["hotel_remove_room"] || "Remove" }) }))] }), _jsxs(View, { style: styles.counterRow, children: [_jsx(Text, { style: styles.counterLabel, children: translations["hotel_adults_title"] || "Adults" }), _jsxs(View, { style: styles.counterControls, children: [_jsx(TouchableOpacity, { style: [
71
+ return (_jsxs(View, { children: [_jsxs(TouchableOpacity, { style: [formStyles.inputTrigger, { backgroundColor: inputBg }], onPress: () => setIsModalOpen(true), activeOpacity: 0.8, children: [_jsx(Text, { style: formStyles.label, children: translations["hotel_form_guests"] || "Guests" }), _jsxs(View, { style: formStyles.inputTriggerRow, children: [_jsx(Text, { style: styles.selectorText, numberOfLines: 1, children: buttonText }), _jsx(ChevronDown, { color: btnColor })] })] }), _jsx(Modal, { visible: isModalOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: () => setIsModalOpen(false), children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: () => setIsModalOpen(false), hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsx(View, { style: styles.modalHeaderRow, children: _jsx(Text, { style: styles.modalTitle, children: translations["hotel_form_guests"] || "Guests" }) }), _jsxs(ScrollView, { style: styles.scrollView, contentContainerStyle: styles.scrollContent, showsVerticalScrollIndicator: false, children: [rooms.map((room, index) => (_jsxs(View, { style: styles.roomBlock, children: [_jsxs(View, { style: styles.roomHeader, children: [_jsxs(Text, { style: styles.roomTitle, children: [translations["hotel_room_label"] || "Room", " ", index + 1] }), rooms.length > 1 && (_jsx(TouchableOpacity, { onPress: () => removeRoom(index), activeOpacity: 0.7, children: _jsx(Text, { style: styles.removeText, children: translations["hotel_remove_room"] || "Remove" }) }))] }), _jsxs(View, { style: styles.counterRow, children: [_jsx(Text, { style: styles.counterLabel, children: translations["hotel_adults_title"] || "Adults" }), _jsxs(View, { style: styles.counterControls, children: [_jsx(TouchableOpacity, { style: [
68
72
  styles.counterButton,
69
73
  room.adults <= 1 && styles.counterButtonDisabled,
70
- ], onPress: () => updateRoom(index, "adults", -1), disabled: room.adults <= 1, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "-" }) }), _jsx(Text, { style: styles.counterValue, children: room.adults }), _jsx(TouchableOpacity, { style: [
74
+ ], onPress: () => updateRoom(index, "adults", -1), disabled: room.adults <= 1, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "-" }) }), _jsx(Text, { style: styles.counterValue, children: room.adults }), _jsx(TouchableOpacity, { style: [
71
75
  styles.counterButton,
72
76
  totalGuests >= MAX_GUESTS && styles.counterButtonDisabled,
73
- ], onPress: () => updateRoom(index, "adults", 1), disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "+" }) })] })] }), _jsxs(View, { style: styles.counterRow, children: [_jsx(Text, { style: styles.counterLabel, children: translations["hotel_children_title"] || "Children" }), _jsxs(View, { style: styles.counterControls, children: [_jsx(TouchableOpacity, { style: [
77
+ ], onPress: () => updateRoom(index, "adults", 1), disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "+" }) })] })] }), _jsxs(View, { style: styles.counterRow, children: [_jsx(Text, { style: styles.counterLabel, children: translations["hotel_children_title"] || "Children" }), _jsxs(View, { style: styles.counterControls, children: [_jsx(TouchableOpacity, { style: [
74
78
  styles.counterButton,
75
79
  room.children <= 0 && styles.counterButtonDisabled,
76
- ], onPress: () => updateRoom(index, "children", -1), disabled: room.children <= 0, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "-" }) }), _jsx(Text, { style: styles.counterValue, children: room.children }), _jsx(TouchableOpacity, { style: [
80
+ ], onPress: () => updateRoom(index, "children", -1), disabled: room.children <= 0, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "-" }) }), _jsx(Text, { style: styles.counterValue, children: room.children }), _jsx(TouchableOpacity, { style: [
77
81
  styles.counterButton,
78
82
  totalGuests >= MAX_GUESTS && styles.counterButtonDisabled,
79
- ], onPress: () => updateRoom(index, "children", 1), disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "+" }) })] })] }), room.children > 0 && (_jsxs(View, { style: styles.agesContainer, children: [_jsx(Text, { style: styles.agesTitle, children: translations["hotel_children_age_title"] ||
83
+ ], onPress: () => updateRoom(index, "children", 1), disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "+" }) })] })] }), room.children > 0 && (_jsxs(View, { style: styles.agesContainer, children: [_jsx(Text, { style: styles.agesTitle, children: translations["hotel_children_age_title"] ||
80
84
  "Specify children ages" }), _jsx(View, { style: styles.agesGrid, children: room.childrenAges.map((age, childIdx) => (_jsxs(View, { style: styles.ageSelector, children: [_jsxs(Text, { style: styles.ageLabel, children: [translations["hotel_child_label"] || "Child", " ", childIdx + 1] }), _jsxs(View, { style: styles.ageButtonsRow, children: [_jsx(TouchableOpacity, { style: [
81
85
  styles.ageAdjustButton,
82
86
  age <= 0 && styles.counterButtonDisabled,
83
- ], onPress: () => age > 0 && updateChildAge(index, childIdx, age - 1), disabled: age <= 0, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "-" }) }), _jsx(Text, { style: styles.ageValue, children: age }), _jsx(TouchableOpacity, { style: [
87
+ ], onPress: () => age > 0 && updateChildAge(index, childIdx, age - 1), disabled: age <= 0, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "-" }) }), _jsx(Text, { style: styles.ageValue, children: age }), _jsx(TouchableOpacity, { style: [
84
88
  styles.ageAdjustButton,
85
89
  age >= 17 && styles.counterButtonDisabled,
86
- ], onPress: () => age < 17 && updateChildAge(index, childIdx, age + 1), disabled: age >= 17, activeOpacity: 0.7, children: _jsx(Text, { style: styles.counterButtonText, children: "+" }) })] })] }, childIdx))) })] }))] }, index))), _jsx(TouchableOpacity, { style: [
90
+ ], onPress: () => age < 17 && updateChildAge(index, childIdx, age + 1), disabled: age >= 17, activeOpacity: 0.7, children: _jsx(Text, { style: [styles.counterButtonText, { color: btnColor }], children: "+" }) })] })] }, childIdx))) })] }))] }, index))), _jsx(TouchableOpacity, { style: [
87
91
  styles.addRoomButton,
92
+ { borderColor: btnColor },
88
93
  totalGuests >= MAX_GUESTS && styles.addRoomButtonDisabled,
89
- ], onPress: addRoom, disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsxs(Text, { style: styles.addRoomText, children: ["+ ", translations["hotel_add_room"] || "Add room"] }) })] }), _jsx(View, { style: styles.modalFooter, children: _jsx(TouchableOpacity, { style: styles.saveButton, onPress: handleSave, activeOpacity: 0.8, children: _jsx(Text, { style: styles.saveButtonText, children: translations["hotel_save_button"] || "Done" }) }) })] }) })] }));
94
+ ], onPress: addRoom, disabled: totalGuests >= MAX_GUESTS, activeOpacity: 0.7, children: _jsxs(Text, { style: [styles.addRoomText, { color: btnColor }], children: ["+ ", translations["hotel_add_room"] || "Add room"] }) })] }), _jsx(View, { style: styles.modalFooter, children: _jsx(TouchableOpacity, { style: [styles.saveButton, { backgroundColor: btnColor }], onPress: handleSave, activeOpacity: 0.8, children: _jsx(Text, { style: styles.saveButtonText, children: translations["hotel_save_button"] || "Done" }) }) })] }) })] }));
90
95
  };
91
96
  const styles = StyleSheet.create({
92
97
  selectorText: {
@@ -6,6 +6,7 @@ import Svg, { Circle, Path, Rect } from "react-native-svg";
6
6
  import { SvgUri } from "react-native-svg";
7
7
  import { useHotelLocations } from "../../hooks/useHotelLocations";
8
8
  import { CloseIcon } from "../../../store";
9
+ import { useWidget } from "../../../context/WidgetContext";
9
10
  import { Colors, Spacing, FontSize } from "../../../theme/colors";
10
11
  import { formStyles } from "../../../theme/formStyles";
11
12
  const POPULAR_HOTEL_LOCATIONS = [
@@ -18,8 +19,11 @@ const POPULAR_HOTEL_LOCATIONS = [
18
19
  const FLAG_BASE = "https://cdn.travel-code.com/images/remaster/flags";
19
20
  const RegionIcon = () => (_jsxs(Svg, { width: 20, height: 20, viewBox: "0 0 20 20", fill: "none", children: [_jsx(Path, { d: "M15.625 8.125C15.625 6.63316 15.0324 5.20242 13.9775 4.14752C12.9226 3.09263 11.4918 2.5 10 2.5C8.50816 2.5 7.07742 3.09263 6.02252 4.14752C4.96763 5.20242 4.375 6.63316 4.375 8.125C4.375 10.4325 6.22125 13.44 10 17.0425C13.7788 13.44 15.625 10.4325 15.625 8.125ZM10 18.75C5.41625 14.5838 3.125 11.0412 3.125 8.125C3.125 6.30164 3.84933 4.55295 5.13864 3.26364C6.42795 1.97433 8.17664 1.25 10 1.25C11.8234 1.25 13.572 1.97433 14.8614 3.26364C16.1507 4.55295 16.875 6.30164 16.875 8.125C16.875 11.0412 14.5838 14.5838 10 18.75Z", fill: "#ABABC8", stroke: "#ABABC8", strokeWidth: 0.25 }), _jsx(Path, { d: "M10 10C10.4973 10 10.9742 9.80246 11.3258 9.45083C11.6775 9.09919 11.875 8.62228 11.875 8.125C11.875 7.62772 11.6775 7.15081 11.3258 6.79917C10.9742 6.44754 10.4973 6.25 10 6.25C9.50272 6.25 9.02581 6.44754 8.67417 6.79917C8.32254 7.15081 8.125 7.62772 8.125 8.125C8.125 8.62228 8.32254 9.09919 8.67417 9.45083C9.02581 9.80246 9.50272 10 10 10ZM10 11.25C9.1712 11.25 8.37634 10.9208 7.79029 10.3347C7.20424 9.74866 6.875 8.9538 6.875 8.125C6.875 7.2962 7.20424 6.50134 7.79029 5.91529C8.37634 5.32924 9.1712 5 10 5C10.8288 5 11.6237 5.32924 12.2097 5.91529C12.7958 6.50134 13.125 7.2962 13.125 8.125C13.125 8.9538 12.7958 9.74866 12.2097 10.3347C11.6237 10.9208 10.8288 11.25 10 11.25Z", fill: "#ABABC8", stroke: "#ABABC8", strokeWidth: 0.25 })] }));
20
21
  const HotelBuildingIcon = () => (_jsxs(Svg, { width: 24, height: 24, viewBox: "0 0 24 24", fill: "none", children: [_jsx(Path, { d: "M16.8153 18.2691V3.72727C16.8153 2.22104 15.5942 1 14.088 1H5.72727C4.22104 1 3 2.22104 3 3.72727V22.5863", stroke: "#ABABC8", strokeWidth: 0.681818, strokeLinecap: "round" }), _jsx(Rect, { x: 7.32031, y: 5.31738, width: 1.72691, height: 1.72691, rx: 0.170455, fill: "#ABABC8" }), _jsx(Rect, { x: 7.32031, y: 8.771, width: 1.72691, height: 1.72691, rx: 0.170455, fill: "#ABABC8" }), _jsx(Rect, { x: 7.32031, y: 12.2249, width: 1.72691, height: 1.72691, rx: 0.170455, fill: "#ABABC8" }), _jsx(Rect, { x: 7.32031, y: 15.6787, width: 1.72691, height: 1.72691, rx: 0.170455, fill: "#ABABC8" }), _jsx(Rect, { x: 7.32031, y: 19.1323, width: 1.72691, height: 1.72691, rx: 0.170455, fill: "#ABABC8" }), _jsx(Path, { d: "M13.6822 5.31714C12.5525 5.31714 11.6367 6.23292 11.6367 7.36259V21.9044C11.6367 22.2809 11.942 22.5862 12.3185 22.5862H15.0977V19.3028C15.0977 19.2086 15.174 19.1323 15.2681 19.1323H18.381C18.4752 19.1323 18.5515 19.2086 18.5515 19.3028V22.5862H21.3163C21.6929 22.5862 21.9982 22.2809 21.9982 21.9044V7.36259C21.9982 6.23292 21.0824 5.31714 19.9527 5.31714H13.6822ZM14.2305 8.07793C14.2305 7.98379 14.3068 7.90747 14.4009 7.90747H15.7869C15.8811 7.90747 15.9574 7.98379 15.9574 8.07793V9.46392C15.9574 9.55806 15.8811 9.63438 15.7869 9.63438H14.4009C14.3068 9.63438 14.2305 9.55806 14.2305 9.46392V8.07793ZM17.8538 7.90747C17.7597 7.90747 17.6834 7.98379 17.6834 8.07793V9.46392C17.6834 9.55806 17.7597 9.63438 17.8538 9.63438H19.2398C19.334 9.63438 19.4103 9.55806 19.4103 9.46392V8.07793C19.4103 7.98379 19.334 7.90747 19.2398 7.90747H17.8538ZM14.2305 11.5318C14.2305 11.4376 14.3068 11.3613 14.4009 11.3613H15.7869C15.8811 11.3613 15.9574 11.4376 15.9574 11.5318V12.9178C15.9574 13.0119 15.8811 13.0882 15.7869 13.0882H14.4009C14.3068 13.0882 14.2305 13.0119 14.2305 12.9178V11.5318ZM17.8538 11.3613C17.7597 11.3613 17.6834 11.4376 17.6834 11.5318V12.9178C17.6834 13.0119 17.7597 13.0882 17.8538 13.0882H19.2398C19.334 13.0882 19.4103 13.0119 19.4103 12.9178V11.5318C19.4103 11.4376 19.334 11.3613 19.2398 11.3613H17.8538ZM14.2305 14.9856C14.2305 14.8915 14.3068 14.8152 14.4009 14.8152H15.7869C15.8811 14.8152 15.9574 14.8915 15.9574 14.9856V16.3716C15.9574 16.4657 15.8811 16.5421 15.7869 16.5421H14.4009C14.3068 16.5421 14.2305 16.4657 14.2305 16.3716V14.9856ZM17.8538 14.8152C17.7597 14.8152 17.6834 14.8915 17.6834 14.9856V16.3716C17.6834 16.4657 17.7597 16.5421 17.8538 16.5421H19.2398C19.334 16.5421 19.4103 16.4657 19.4103 16.3716V14.9856C19.4103 14.8915 19.334 14.8152 19.2398 14.8152H17.8538Z", fill: "#ABABC8", fillRule: "evenodd", clipRule: "evenodd" })] }));
21
- const SearchIcon = () => (_jsxs(Svg, { width: 19, height: 18, viewBox: "0 0 19 18", fill: "none", children: [_jsx(Circle, { cx: 7, cy: 7, r: 6, stroke: Colors.primary, strokeWidth: 2 }), _jsx(Path, { d: "M12 11L17.2857 16.0902", stroke: Colors.primary, strokeWidth: 2, strokeLinecap: "round" })] }));
22
+ const SearchIcon = ({ color = Colors.primary }) => (_jsxs(Svg, { width: 19, height: 18, viewBox: "0 0 19 18", fill: "none", children: [_jsx(Circle, { cx: 7, cy: 7, r: 6, stroke: color, strokeWidth: 2 }), _jsx(Path, { d: "M12 11L17.2857 16.0902", stroke: color, strokeWidth: 2, strokeLinecap: "round" })] }));
22
23
  const HotelLocation = ({ label, value, onChange, lang = "ru", translations, defaultItem, }) => {
24
+ const { colors } = useWidget();
25
+ const btnColor = colors.primary || Colors.primary;
26
+ const inputBg = colors.input || Colors.inputBg;
23
27
  const getLabel = (item) => lang === "en" ? item.nameEn || item.name : item.name;
24
28
  const getAddress = (item) => lang === "en" ? item.addressEn || item.address : item.address;
25
29
  const insets = useSafeAreaInsets();
@@ -73,7 +77,7 @@ const HotelLocation = ({ label, value, onChange, lang = "ru", translations, defa
73
77
  const countryName = getAddress(loc);
74
78
  return (_jsx(TouchableOpacity, { style: styles.locationItem, onPress: () => handleSelect(loc), activeOpacity: 0.7, children: _jsxs(View, { style: styles.locationItemContent, children: [_jsx(View, { style: styles.iconContainer, children: isHotel ? _jsx(HotelBuildingIcon, {}) : _jsx(RegionIcon, {}) }), _jsxs(View, { style: styles.locationInfo, children: [_jsx(Text, { style: styles.locationCity, numberOfLines: 1, children: cityName }), _jsxs(View, { style: styles.addressRow, children: [_jsx(SvgUri, { uri: `${FLAG_BASE}/${loc.countryCode}.svg`, width: 20, height: 14 }), _jsx(Text, { style: styles.locationAddress, numberOfLines: 1, children: countryName })] })] })] }) }));
75
79
  };
76
- return (_jsxs(_Fragment, { children: [_jsxs(TouchableOpacity, { style: formStyles.inputTrigger, onPress: () => setIsModalOpen(true), activeOpacity: 0.8, children: [_jsx(Text, { style: formStyles.label, children: label }), _jsx(View, { style: formStyles.inputTriggerRow, children: _jsx(Text, { style: [formStyles.inputTriggerText, !query && formStyles.inputTriggerPlaceholder], numberOfLines: 1, children: query || label }) })] }), _jsx(Modal, { visible: isModalOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: handleClose, children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: handleClose, hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsxs(View, { style: styles.searchHeader, children: [_jsx(SearchIcon, {}), _jsx(TextInput, { autoFocus: true, style: styles.searchInput, value: query, onChangeText: setQuery, placeholder: translations["location_popup_placeholder"] ||
80
+ return (_jsxs(_Fragment, { children: [_jsxs(TouchableOpacity, { style: [formStyles.inputTrigger, { backgroundColor: inputBg }], onPress: () => setIsModalOpen(true), activeOpacity: 0.8, children: [_jsx(Text, { style: formStyles.label, children: label }), _jsx(View, { style: formStyles.inputTriggerRow, children: _jsx(Text, { style: [formStyles.inputTriggerText, !query && formStyles.inputTriggerPlaceholder], numberOfLines: 1, children: query || label }) })] }), _jsx(Modal, { visible: isModalOpen, animationType: "slide", presentationStyle: "fullScreen", onRequestClose: handleClose, children: _jsxs(View, { style: [styles.modalContainer, { paddingTop: insets.top }], children: [_jsx(TouchableOpacity, { style: styles.closeButton, onPress: handleClose, hitSlop: { top: 8, bottom: 8, left: 8, right: 8 }, children: _jsx(CloseIcon, { size: 16 }) }), _jsxs(View, { style: styles.searchHeader, children: [_jsx(SearchIcon, { color: btnColor }), _jsx(TextInput, { autoFocus: true, style: styles.searchInput, value: query, onChangeText: setQuery, placeholder: translations["location_popup_placeholder"] ||
77
81
  "Enter city or hotel", placeholderTextColor: Colors.textTertiary, returnKeyType: "search" })] }), _jsxs(View, { style: styles.modalContent, children: [loading && (_jsxs(View, { style: styles.loadingContainer, children: [_jsx(ActivityIndicator, { size: "small", color: Colors.primary }), _jsx(Text, { style: styles.loadingText, children: translations["location_popup_loading"] || "Loading..." })] })), !loading && isSearching && !hasSearchResults && (_jsx(Text, { style: styles.noResults, children: translations["location_popup_no_results"] ||
78
82
  "Nothing found" })), !loading && showPopular && (_jsxs(_Fragment, { children: [_jsx(Text, { style: styles.sectionTitle, children: translations["popular_locations"] || "Popular destinations" }), _jsx(FlatList, { data: POPULAR_HOTEL_LOCATIONS, renderItem: ({ item }) => renderLocationItem(item, false), keyExtractor: (item) => item.id, keyboardShouldPersistTaps: "handled", showsVerticalScrollIndicator: false })] })), !loading && isSearching && hasSearchResults && (_jsx(SectionList, { sections: sections, renderSectionHeader: ({ section }) => (_jsx(Text, { style: styles.sectionTitle, children: section.title })), renderItem: ({ item, section }) => renderLocationItem(item, section.type === "hotels"), keyExtractor: (item) => item.id, keyboardShouldPersistTaps: "handled", showsVerticalScrollIndicator: false, stickySectionHeadersEnabled: false }))] })] }) })] }));
79
83
  };
@@ -16,6 +16,7 @@ type Props = {
16
16
  filterSearch?: (params: Record<string, any>) => void;
17
17
  currency?: string;
18
18
  headerComponent?: React.ReactElement;
19
+ streamCompleted?: boolean;
19
20
  };
20
21
  declare const HotelResults: React.FC<Props>;
21
22
  export default HotelResults;
@@ -7,12 +7,16 @@ import HotelsSkeleton from "./HotelsSkeleton";
7
7
  import HotelList from "./components/HotelList";
8
8
  import HotelEmptyState from "./components/HotelEmptyState";
9
9
  import HotelMap, { pinsFromOffers } from "./components/HotelMap";
10
+ import { useHotelMapData } from "../../hooks/useHotelMapData";
10
11
  import ProvidersLoader from "../flight/flight-results/ProvidersLoader";
11
12
  import Pagination from "../Pagination";
12
13
  import { HotelFilters, QUICK_FILTERS } from "./hotel-filters";
14
+ import { useWidget } from "../../../context/WidgetContext";
13
15
  import { Colors, Spacing, FontSize, BorderRadius } from "../../../theme/colors";
14
- const HotelResults = ({ offers, allHotels, loading, isStreaming = false, isPageLoading = false, error, translations, lang, searchParams = null, total = 0, offset = 0, limit = 20, fetchPage, filterSearch, currency = "USD", headerComponent, }) => {
16
+ const HotelResults = ({ offers, allHotels, loading, isStreaming = false, isPageLoading = false, error, translations, lang, searchParams = null, total = 0, offset = 0, limit = 20, fetchPage, filterSearch, currency = "USD", headerComponent, streamCompleted = false, }) => {
15
17
  const insets = useSafeAreaInsets();
18
+ const { colors } = useWidget();
19
+ const btnColor = colors.primary || Colors.primary;
16
20
  const [hasSearched, setHasSearched] = useState(false);
17
21
  const [localOffers, setLocalOffers] = useState(offers ?? []);
18
22
  const [isMapOpen, setIsMapOpen] = useState(false);
@@ -43,7 +47,7 @@ const HotelResults = ({ offers, allHotels, loading, isStreaming = false, isPageL
43
47
  if (offers && offers.length > 0) {
44
48
  setLocalOffers(offers);
45
49
  }
46
- else if (!loading && !isStreaming && !isPageLoading && offers?.length === 0) {
50
+ else if (offers?.length === 0) {
47
51
  setLocalOffers([]);
48
52
  }
49
53
  }, [offers, loading, isStreaming, isPageLoading]);
@@ -66,11 +70,33 @@ const HotelResults = ({ offers, allHotels, loading, isStreaming = false, isPageL
66
70
  }
67
71
  return { boards, payments, starRating };
68
72
  };
73
+ const hasAppliedFilters = activeFilters.length > 0 || popupValues !== null;
74
+ const shouldFetchMap = !!searchParams && streamCompleted && (hasSearched || hasAppliedFilters);
75
+ const { pins: apiPins } = useHotelMapData(searchParams, shouldFetchMap);
76
+ const hasFullDataset = (allHotels?.length ?? 0) > 0 && (allHotels?.length ?? 0) >= total;
77
+ const useStreamPins = hasFullDataset && !hasAppliedFilters && (allHotels ?? []).some((h) => h.latitude && h.longitude);
78
+ const apiMapPins = useMemo(() => {
79
+ if (apiPins.length === 0)
80
+ return [];
81
+ return apiPins.map((p) => ({
82
+ id: Number(p.id),
83
+ hotelId: Number(p.id),
84
+ lat: p.latitude,
85
+ lng: p.longitude,
86
+ price: p.total ?? 0,
87
+ currency,
88
+ name: "",
89
+ soldOut: p.soldOut,
90
+ }));
91
+ }, [apiPins, currency]);
69
92
  const mapPins = useMemo(() => {
70
- if (!allHotels || allHotels.length === 0)
93
+ const streamPins = allHotels && allHotels.length > 0 ? pinsFromOffers(allHotels, currency) : [];
94
+ if (streamPins.length === 0 && apiMapPins.length === 0)
71
95
  return [];
72
- return pinsFromOffers(allHotels, currency);
73
- }, [allHotels, currency]);
96
+ if (hasAppliedFilters)
97
+ return apiMapPins;
98
+ return useStreamPins ? streamPins : apiMapPins;
99
+ }, [allHotels, currency, useStreamPins, apiMapPins, hasAppliedFilters]);
74
100
  const hasResults = localOffers.length > 0;
75
101
  const showMapButton = hasResults && mapPins.length > 0 && !loadingInitial;
76
102
  const isEmptyResult = hasSearched && !loadingInitial && !loadingRefetch && !loading && !isStreaming && localOffers.length === 0;
@@ -246,7 +272,7 @@ const HotelResults = ({ offers, allHotels, loading, isStreaming = false, isPageL
246
272
  return null;
247
273
  return (_jsx(View, { style: styles.paginationWrapper, children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: handlePageChange }) }));
248
274
  };
249
- return (_jsxs(View, { style: styles.container, children: [loadingRefetch && (_jsxs(View, { style: styles.overlayLoader, children: [_jsx(ActivityIndicator, { size: "large", color: Colors.primary }), _jsx(Text, { style: styles.overlayText, children: translations["loading"] || "Loading..." })] })), _jsx(FlatList, { ref: listRef, data: !loadingInitial && hasResults && !isErrorState ? localOffers : [], renderItem: ({ item, index }) => (_jsx(HotelList, { offers: [item], translations: translations, lang: lang, onToggleDescription: () => handleToggleDescription(index) })), keyExtractor: (item, index) => String(item.id || item.propertyId || index), ListHeaderComponent: renderHeader(), ListFooterComponent: renderFooter(), contentContainerStyle: styles.listContent, showsVerticalScrollIndicator: false, removeClippedSubviews: true, maxToRenderPerBatch: 10, windowSize: 5 }), showMapButton && (_jsxs(TouchableOpacity, { style: styles.mapButton, onPress: () => setIsMapOpen(true), activeOpacity: 0.8, children: [_jsxs(Svg, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: Colors.white, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx(Polygon, { points: "1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6" }), _jsx(Line, { x1: 8, y1: 2, x2: 8, y2: 18 }), _jsx(Line, { x1: 16, y1: 6, x2: 16, y2: 22 })] }), _jsx(Text, { style: styles.mapButtonText, children: translations["map_button"] || "Map" })] })), isMapOpen && (_jsxs(View, { style: StyleSheet.absoluteFill, children: [_jsx(HotelMap, { pins: mapPins, allHotels: allHotels || [], streamCompleted: !isStreaming && !loading, loading: loading || isStreaming, translations: translations, lang: lang, searchParams: searchParams, onHotelSelect: (hotelId) => {
275
+ return (_jsxs(View, { style: styles.container, children: [loadingRefetch && (_jsxs(View, { style: styles.overlayLoader, children: [_jsx(ActivityIndicator, { size: "large", color: btnColor }), _jsx(Text, { style: styles.overlayText, children: translations["loading"] || "Loading..." })] })), _jsx(FlatList, { ref: listRef, data: !loadingInitial && hasResults && !isErrorState ? localOffers : [], renderItem: ({ item, index }) => (_jsx(HotelList, { offers: [item], translations: translations, lang: lang, searchParams: searchParams, onToggleDescription: () => handleToggleDescription(index) })), keyExtractor: (item, index) => String(item.id || item.propertyId || index), ListHeaderComponent: renderHeader(), ListFooterComponent: renderFooter(), contentContainerStyle: styles.listContent, showsVerticalScrollIndicator: false, removeClippedSubviews: true, maxToRenderPerBatch: 10, windowSize: 5 }), showMapButton && (_jsxs(TouchableOpacity, { style: [styles.mapButton, { backgroundColor: btnColor }], onPress: () => setIsMapOpen(true), activeOpacity: 0.8, children: [_jsxs(Svg, { width: 18, height: 18, viewBox: "0 0 24 24", fill: "none", stroke: Colors.white, strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx(Polygon, { points: "1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6" }), _jsx(Line, { x1: 8, y1: 2, x2: 8, y2: 18 }), _jsx(Line, { x1: 16, y1: 6, x2: 16, y2: 22 })] }), _jsx(Text, { style: styles.mapButtonText, children: translations["map_button"] || "Map" })] })), isMapOpen && (_jsxs(View, { style: StyleSheet.absoluteFill, children: [_jsx(HotelMap, { pins: mapPins, allHotels: allHotels || [], streamCompleted: !isStreaming && !loading, loading: loading || isStreaming, translations: translations, lang: lang, searchParams: searchParams, onHotelSelect: (hotelId) => {
250
276
  }, onRefreshSearch: () => {
251
277
  if (searchParams && filterSearch) {
252
278
  filterSearch(searchParams);
@@ -5,6 +5,7 @@ type HotelCardProps = {
5
5
  total: number;
6
6
  translations: Record<string, string>;
7
7
  lang: string;
8
+ searchParams?: Record<string, any> | null;
8
9
  onToggleDescription: () => void;
9
10
  };
10
11
  declare const HotelCard: React.FC<HotelCardProps>;
@@ -11,9 +11,43 @@ const starStyles = StyleSheet.create({
11
11
  color: "#F5A623",
12
12
  },
13
13
  });
14
- const HotelCard = ({ hotel, index, total, translations, lang, onToggleDescription, }) => {
14
+ const getBookingUrl = (hotel, searchParams, basketLink, token, lang) => {
15
+ if (!hotel)
16
+ return "#";
17
+ const HOST = basketLink || "https://travel-code.com";
18
+ if (!searchParams) {
19
+ return `${HOST}${hotel.url || "#"}&accessToken=${token}&language=${lang}`;
20
+ }
21
+ const propertyId = hotel.propertyId || hotel.id;
22
+ if (!propertyId) {
23
+ return `${HOST}${hotel.url || "#"}&accessToken=${token}&language=${lang}`;
24
+ }
25
+ const partnerId = hotel.partnerId || hotel.pId || 0;
26
+ const guestsClean = (searchParams.guests || []).map((r) => {
27
+ const g = { adults: r.adults };
28
+ if (r.children > 0) {
29
+ g.children = r.children;
30
+ if (r.childrenAges?.length)
31
+ g.childrenAges = r.childrenAges;
32
+ }
33
+ return g;
34
+ });
35
+ const guestsB64 = btoa(JSON.stringify(guestsClean));
36
+ const params = new URLSearchParams({
37
+ checkinDate: searchParams.checkin || "",
38
+ checkoutDate: searchParams.checkout || "",
39
+ guests: guestsB64,
40
+ nationality: searchParams.countryCode || "",
41
+ partner: "0",
42
+ cpPartner: String(partnerId),
43
+ location: String(searchParams.location || ""),
44
+ });
45
+ return `${HOST}/hotels/${propertyId}?${params.toString()}&accessToken=${token}&language=${lang}`;
46
+ };
47
+ const HotelCard = ({ hotel, index, total, translations, lang, searchParams, onToggleDescription, }) => {
15
48
  const token = useApiToken();
16
- const { config } = useWidget();
49
+ const { config, colors } = useWidget();
50
+ const btnColor = colors.primary || Colors.primary;
17
51
  const name = hotel.hotelNames?.mainName || hotel.propertyName || hotel.name || "Unnamed";
18
52
  const address = hotel.address || "";
19
53
  const description = hotel.description || "";
@@ -26,8 +60,8 @@ const HotelCard = ({ hotel, index, total, translations, lang, onToggleDescriptio
26
60
  const isSoldOut = hotel.soldOut === true;
27
61
  const currencySign = hotel.currencySign || "$";
28
62
  const heroImages = hotel.heroImages || [];
29
- const HOST_URL = config?.additional?.basket_link?.trim() || "https://travel-code.com";
30
- const url = `${HOST_URL}${hotel.url || "#"}&accessToken=${token}&language=${lang}`;
63
+ const basketLink = config?.additional?.basket_link?.trim() || "https://travel-code.com";
64
+ const url = getBookingUrl(hotel, searchParams, basketLink, token, lang);
31
65
  const handleOpenUrl = () => {
32
66
  Linking.openURL(url).catch(() => { });
33
67
  };
@@ -42,7 +76,7 @@ const HotelCard = ({ hotel, index, total, translations, lang, onToggleDescriptio
42
76
  "Only 1 room left at this price" })), hotel.availableRooms > 1 && hotel.availableRooms < 5 && (_jsx(Text, { style: styles.warningText, children: translations["hotels_only_few_rooms"]
43
77
  ? translations["hotels_only_few_rooms"].replace("{availableRooms}", String(hotel.availableRooms))
44
78
  : `Only ${hotel.availableRooms} rooms left at this price` }))] }), _jsx(View, { style: styles.priceSection, children: isSoldOut ? (_jsx(View, { style: styles.soldOutBlock, children: _jsx(Text, { style: styles.soldOutText, children: translations["hotels_sold_out"] || "Sold Out" }) })) : (_jsxs(_Fragment, { children: [hotel.refundable && (_jsx(Text, { style: styles.refundableText, children: translations["hotels_refundable"] || "Free cancellation" })), _jsxs(View, { style: styles.priceBlock, children: [_jsxs(Text, { style: styles.nightlyPrice, children: [currencySign, nightlyPrice, _jsxs(Text, { style: styles.perNightLabel, children: [" ", translations["hotels_price_per_night"] || "/ night"] })] }), _jsxs(Text, { style: styles.totalPriceText, children: [translations["hotels_total_price"] || "Total:", " ", currencySign, totalPrice] }), _jsx(Text, { style: styles.taxesText, children: translations["hotels_taxes_included"] ||
45
- "(incl. taxes & fees)" })] }), ratingValue ? (_jsxs(View, { style: styles.ratingBlock, children: [_jsx(View, { style: [styles.ratingBadge, { backgroundColor: parseFloat(ratingValue) >= 4 ? '#1a8917' : Colors.textTertiary }], children: _jsx(Text, { style: styles.ratingBadgeText, children: ratingValue }) }), _jsxs(View, { children: [_jsx(Text, { style: styles.ratingLabel, children: ratingText }), reviewsCount > 0 && (_jsxs(Text, { style: styles.ratingCount, children: [reviewsCount, " ", translations["hotels_reviews"] || "reviews"] }))] })] })) : null, _jsx(TouchableOpacity, { style: styles.viewButton, onPress: handleOpenUrl, activeOpacity: 0.8, children: _jsx(Text, { style: styles.viewButtonText, children: translations["hotels_view_button"] || "View deal" }) })] })) })] }));
79
+ "(incl. taxes & fees)" })] }), ratingValue ? (_jsxs(View, { style: styles.ratingBlock, children: [_jsx(View, { style: [styles.ratingBadge, { backgroundColor: parseFloat(ratingValue) >= 4 ? '#1a8917' : Colors.textTertiary }], children: _jsx(Text, { style: styles.ratingBadgeText, children: ratingValue }) }), _jsxs(View, { children: [_jsx(Text, { style: styles.ratingLabel, children: ratingText }), reviewsCount > 0 && (_jsxs(Text, { style: styles.ratingCount, children: [reviewsCount, " ", translations["hotels_reviews"] || "reviews"] }))] })] })) : null, _jsx(TouchableOpacity, { style: [styles.viewButton, { backgroundColor: btnColor }], onPress: handleOpenUrl, activeOpacity: 0.8, children: _jsx(Text, { style: styles.viewButtonText, children: translations["hotels_view_button"] || "View deal" }) })] })) })] }));
46
80
  };
47
81
  const styles = StyleSheet.create({
48
82
  card: {
@@ -3,6 +3,7 @@ type HotelListProps = {
3
3
  offers: any[];
4
4
  translations: Record<string, string>;
5
5
  lang: string;
6
+ searchParams?: Record<string, any> | null;
6
7
  onToggleDescription: (hotelIndex: number) => void;
7
8
  };
8
9
  declare const HotelList: React.FC<HotelListProps>;
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { View, StyleSheet } from "react-native";
3
3
  import HotelCard from "./HotelCard";
4
- const HotelList = ({ offers, translations, lang, onToggleDescription, }) => {
5
- return (_jsx(View, { style: styles.container, children: offers.map((hotel, index) => (_jsx(HotelCard, { hotel: hotel, index: index, total: offers.length, translations: translations, lang: lang, onToggleDescription: () => onToggleDescription(index) }, String(hotel.id || hotel.propertyId || index)))) }));
4
+ const HotelList = ({ offers, translations, lang, searchParams, onToggleDescription, }) => {
5
+ return (_jsx(View, { style: styles.container, children: offers.map((hotel, index) => (_jsx(HotelCard, { hotel: hotel, index: index, total: offers.length, translations: translations, lang: lang, searchParams: searchParams, onToggleDescription: () => onToggleDescription(index) }, String(hotel.id || hotel.propertyId || index)))) }));
6
6
  };
7
7
  const styles = StyleSheet.create({
8
8
  container: {