import { ThemeType, useTheme } from "../../theme"; import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react"; import { View, Text, TouchableOpacity, StyleSheet, StyleProp, ViewStyle, TextStyle, } from "react-native"; import { Ionicons } from "@expo/vector-icons"; import CustomInput from "../Input/Input"; import DateRangePicker from "../DateRangePicker/DateRangePicker"; import SuggestionList from "../Suggestions/SuggestionList"; import { FlightSuggestions, FormInputType } from "./types"; import { TextInput } from "react-native-gesture-handler"; // --- Helper Types --- type LocationData = string; // --- Component Props --- export interface FlightFormProps { initialFromLocation?: LocationData; initialToLocation?: LocationData; initialDepartureDate?: string; // Expect YYYY-MM-DD string initialReturnDate?: string; // Expect YYYY-MM-DD string onInputFocus?: (input: FormInputType) => void; onSwapPress?: ( currentFrom: LocationData | undefined, currentTo: LocationData | undefined ) => void; onSearchPress?: (details: { from: LocationData | undefined; to: LocationData | undefined; departure: string | undefined; // Send YYYY-MM-DD return?: string | undefined; // Send YYYY-MM-DD }) => void; onTextChange?: (text: string) => void; onSelectionChange?: (details: { from: LocationData | undefined; to: LocationData | undefined; departure: string | undefined; // Send YYYY-MM-DD return?: string | undefined; // Send YYYY-MM-DD }) => void; fromLabel?: string; fromPlaceholder?: string; toLabel?: string; toPlaceholder?: string; departureLabel?: string; returnLabel?: string; swapIconName?: keyof typeof Ionicons.glyphMap; searchIconName?: keyof typeof Ionicons.glyphMap; calendarThemeOverrides?: object; // Passed to DateRangePicker isOneWay?: boolean; suggestionData?: FlightSuggestions[]; // --- Style Props --- containerStyle?: StyleProp; inputGroupContainerStyle?: StyleProp; inputWrapperStyle?: StyleProp; customInputContainerStyle?: StyleProp; inputStyle?: StyleProp; labelStyle?: StyleProp; swapButtonContainerStyle?: StyleProp; swapButtonStyle?: StyleProp; swapIconStyle?: StyleProp; departureRowStyle?: StyleProp; searchButtonStyle?: StyleProp; searchIconStyle?: StyleProp; // DateRangePicker specific styles (passed down) dateRangePickerOuterContainerStyle?: StyleProp; dateRangePickerLabelStyle?: StyleProp; dateRangePickerInputGroupStyle?: StyleProp; dateRangePickerCalendarContainerStyle?: StyleProp; dateRangePickerInputContainerStyle?: StyleProp; // SuggestionList specific styles suggestionListContainerStyle?: StyleProp; // Styles for the default suggestion item rendering suggestionItemGroupStyle?: StyleProp; suggestionCityRowStyle?: StyleProp; suggestionCityIconStyle?: StyleProp; suggestionCityTextStyle?: StyleProp; suggestionAirportTouchableStyle?: StyleProp; suggestionAirportIconStyle?: StyleProp; suggestionAirportTextStyle?: StyleProp; } // --- Component --- const FlightForm: React.FC = ({ initialFromLocation = "Beirut, Beirut Intl Arpt - BEY", initialToLocation = "Dubai, Dubai Intl Arpt - DXB", initialDepartureDate, initialReturnDate, onSwapPress, onSearchPress, onInputFocus, onTextChange, fromLabel = "FROM", toLabel = "TO", fromPlaceholder = "From Where?", toPlaceholder = "To Where?", departureLabel = "DEPARTURE", returnLabel = "RETURN", swapIconName = "swap-horizontal", searchIconName = "search", calendarThemeOverrides = {}, isOneWay, suggestionData, // Style Props containerStyle, inputGroupContainerStyle, inputWrapperStyle, customInputContainerStyle, // Renamed from inputStyle for clarity labelStyle, swapButtonContainerStyle, swapButtonStyle, swapIconStyle, departureRowStyle, searchButtonStyle, searchIconStyle, dateRangePickerOuterContainerStyle, dateRangePickerLabelStyle, dateRangePickerInputGroupStyle, dateRangePickerCalendarContainerStyle, suggestionListContainerStyle, suggestionItemGroupStyle, suggestionCityRowStyle, suggestionCityIconStyle, suggestionCityTextStyle, suggestionAirportTouchableStyle, suggestionAirportIconStyle, suggestionAirportTextStyle, inputStyle, onSelectionChange, dateRangePickerInputContainerStyle, }) => { const { theme, isRTL } = useTheme(); const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]); const toLocationInput = useRef(null); const fromLocationInput = useRef(null); // --- State --- const [fromLocation, setFromLocation] = useState( initialFromLocation ); const [toLocation, setToLocation] = useState( initialToLocation ); const [departureDate, setDepartureDate] = useState( initialDepartureDate ); const [returnDate, setReturnDate] = useState( initialReturnDate ); const [focusedInput, setFocusedInput] = useState(); // --- Handlers --- const handleSwap = useCallback(() => { const currentFrom = fromLocation; const currentTo = toLocation; setFromLocation(currentTo); setToLocation(currentFrom); onSwapPress?.(currentFrom, currentTo); }, [fromLocation, toLocation, onSwapPress]); useEffect(() => { onSelectionChange?.({ from: fromLocation, to: toLocation, departure: departureDate, return: isOneWay ? undefined : returnDate, }); }, [ fromLocation, toLocation, departureDate, returnDate, isOneWay, onSelectionChange, ]); const handleSearch = useCallback(() => { onSearchPress?.({ from: fromLocation, to: toLocation, departure: departureDate, return: isOneWay ? undefined : returnDate, // Only send return if not one way }); }, [ fromLocation, toLocation, departureDate, returnDate, isOneWay, onSearchPress, ]); // --- Default Suggestion Renderer (Now Stylable) --- const suggestionRenderItem = (item: FlightSuggestions) => ( {item.city} {item.airports.map((airport, index) => ( { if (focusedInput == FormInputType.FLIGHT_TO) { setToLocation(airport); toLocationInput.current?.blur(); } else { setFromLocation(airport); fromLocationInput.current?.blur(); } }} > {airport} ))} ); return ( { setFromLocation(text); onTextChange?.(text); }} inputStyle={inputStyle} label={fromLabel} value={fromLocation} labelStyle={[styles.label, labelStyle]} placeholder={fromPlaceholder} onFocus={() => { setFocusedInput(FormInputType.FLIGHT_FROM); onInputFocus?.(FormInputType.FLIGHT_FROM); }} onBlur={() => { setTimeout(() => { if (focusedInput === FormInputType.FLIGHT_FROM) { setFocusedInput(undefined); } }, 150); }} inputContainerStyle={customInputContainerStyle} /> {suggestionData && ( )} {onSwapPress && ( )} {/* Apply inputWrapperStyle */} { setToLocation(text); onTextChange?.(text); }} label={toLabel} value={toLocation} inputStyle={inputStyle} labelStyle={[styles.label, labelStyle]} placeholder={toPlaceholder} onFocus={() => { setFocusedInput(FormInputType.FLIGHT_TO); onInputFocus?.(FormInputType.FLIGHT_TO); }} onBlur={() => { setTimeout(() => { if (focusedInput === FormInputType.FLIGHT_TO) { setFocusedInput(undefined); } }, 150); }} inputContainerStyle={customInputContainerStyle} /> {suggestionData && ( )} {/* Apply departureRowStyle */} { setDepartureDate(d.departure); setReturnDate(d.return); }} isOneWay={isOneWay} // departureDate={initialDepartureDate} // initialReturnDate={initialReturnDate} /> {/* Search Button */} {onSearchPress && ( )} ); }; // --- Styles --- const themedStyles = (theme: ThemeType, isRTL: boolean) => StyleSheet.create({ container: { padding: 16, backgroundColor: theme.surface, borderBottomRightRadius: 8, borderBottomLeftRadius: 8, }, inputGroupContainer: { position: "relative", }, inputWrapper: { marginBottom: 15, position: "relative", }, label: { color: theme.labelText, fontSize: 12, fontWeight: "600", textTransform: "uppercase", textAlign: isRTL ? "right" : "left", marginBottom: 6, }, swapButtonContainer: { // Position swap button between the two input wrappers // position: "absolute", // left: 0, // right: 0, // top: "50%", // Adjust as needed based on CustomInput height // transform: [{ translateY: -18 }], // Half the button height alignItems: "center", // zIndex: 1, // Ensure button is clickable above inputs }, swapButton: { width: 36, height: 36, borderRadius: 18, backgroundColor: theme.surface, borderColor: theme.border, borderWidth: 1, justifyContent: "center", alignItems: "center", }, departureRow: { flexDirection: isRTL ? "row-reverse" : "row", alignItems: "flex-end", marginTop: 10, gap: 10, }, dateRangePickerOuterContainer: { flex: 1, }, searchButton: { backgroundColor: theme.primary, width: 50, height: 50, borderRadius: 8, justifyContent: "center", alignItems: "center", }, suggestionItemGroup: { paddingVertical: 8, paddingHorizontal: 12, borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: theme.border, backgroundColor: theme.surface, }, suggestionCityRow: { flexDirection: "row", alignItems: "center", gap: 10, marginBottom: 5, }, suggestionCityIcon: {}, suggestionCityText: { fontSize: 15, fontWeight: "600", color: theme.onSurface, }, suggestionAirportTouchable: { flexDirection: "row", alignItems: "center", gap: 10, paddingVertical: 4, marginLeft: 25, }, suggestionAirportIcon: {}, suggestionAirportText: { fontSize: 14, color: theme.onSurface, }, }); export default FlightForm;