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 { TextInput } from "react-native-gesture-handler"; import { CarSuggestions, FormInputType } from "./types"; import RNPickerSelect from "react-native-picker-select"; export const mockCarSuggestions: CarSuggestions[] = [ { id: 1, city: "Beirut", country: "Lebanon", value: "BEIRUT, LEBANON" }, { id: 2, city: "Dubai", country: "UAE", value: "DUBAI, UAE" }, { id: 3, city: "London", country: "UK", value: "LONDON, UK" }, { id: 4, city: "Paris", country: "France", value: "PARIS, FRANCE" }, { id: 5, city: "New York", country: "USA", value: "NEW YORK, USA" }, ]; type LocationData = string; export interface CarRentalFormProps { initialFromLocation?: LocationData; initialToLocation?: LocationData; initialPickupDate?: string; initialDropoffDate?: string; onTextChange?: (text: string) => void; onInputFocus?: (input: FormInputType) => void; onSwapPress?: ( currentFrom: LocationData | undefined, currentTo: LocationData | undefined ) => void; onSearchPress?: (details: { from: LocationData | undefined; to: LocationData | undefined; pickup: string | undefined; dropoff: string | undefined; driverAge: number | undefined; }) => void; onSelectionChange?: (details: { from: LocationData | undefined; to: LocationData | undefined; pickup: string | undefined; dropoff: string | undefined; driverAge: number | undefined; }) => void; fromLabel?: string; fromPlaceholder?: string; toLabel?: string; toPlaceholder?: string; pickupLabel?: string; dropoffLabel?: string; swapIconName?: keyof typeof Ionicons.glyphMap; searchIconName?: keyof typeof Ionicons.glyphMap; calendarThemeOverrides?: object; // Passed to DateRangePicker ageLabel?: string; isOneWay?: boolean; suggestionData?: CarSuggestions[]; // --- Style Props --- containerStyle?: StyleProp; inputGroupContainerStyle?: StyleProp; inputWrapperStyle?: StyleProp; inputGroupStyle?: StyleProp; labelStyle?: StyleProp; swapButtonContainerStyle?: StyleProp; swapButtonStyle?: StyleProp; swapIconStyle?: StyleProp; pickupRowStyle?: StyleProp; searchButtonStyle?: StyleProp; searchIconStyle?: StyleProp; // DateRangePicker specific styles (passed down) dateRangePickerOuterContainerStyle?: StyleProp; dateRangePickerLabelStyle?: StyleProp; dateRangePickerInputGroupStyle?: StyleProp; dateRangePickerCalendarContainerStyle?: StyleProp; dateRangePickerInputContainerStyle?: StyleProp; // SuggestionList specific styles (passed down / used in renderItem) suggestionListContainerStyle?: StyleProp; suggestionItemStyle?: StyleProp; suggestionItemTextStyle?: StyleProp; // Age Picker specific styles agePickerWrapperStyle?: StyleProp; agePickerLabelStyle?: StyleProp; agePickerPlaceholder?: string; agePickerPlaceholderColor?: string; pickerContainerStyle?: StyleProp; pickerStyle?: StyleProp; } // --- Component --- const CarRentalForm: React.FC = ({ initialFromLocation, initialToLocation, initialPickupDate, initialDropoffDate, onSwapPress, onSearchPress, fromLabel = "PICK-UP", toLabel = "DROP-OFF", fromPlaceholder = "From Where?", toPlaceholder = "To Where?", pickupLabel = "PICK-UP DATE", dropoffLabel = "DROP-OFF DATE", swapIconName = "swap-horizontal", searchIconName = "search", calendarThemeOverrides = {}, containerStyle, inputGroupContainerStyle, // Added inputWrapperStyle, // Added inputGroupStyle, labelStyle, swapButtonContainerStyle, swapButtonStyle, swapIconStyle, pickupRowStyle, searchButtonStyle, searchIconStyle, isOneWay, suggestionData, onInputFocus, onTextChange, dateRangePickerOuterContainerStyle, dateRangePickerLabelStyle, dateRangePickerInputGroupStyle, dateRangePickerCalendarContainerStyle, suggestionListContainerStyle, suggestionItemStyle, suggestionItemTextStyle, agePickerWrapperStyle, agePickerLabelStyle, pickerContainerStyle, pickerStyle, onSelectionChange, ageLabel = "Driver's Age", agePickerPlaceholder = "Select Age...", agePickerPlaceholderColor, dateRangePickerInputContainerStyle, }) => { const { theme, isRTL } = useTheme(); const styles = useMemo(() => themedStyles(theme, isRTL), [theme, isRTL]); const fromInputRef = useRef(null); const toInputRef = useRef(null); // --- State --- const [fromLocation, setFromLocation] = useState( initialFromLocation ); const [toLocation, setToLocation] = useState( initialToLocation ); const [pickupDate, setPickupDate] = useState( initialPickupDate ); const [dropoffDate, setDropoffDate] = useState( initialDropoffDate ); const [age, setAge] = useState(); const [focusedInput, setFocusedInput] = useState(); useEffect(() => { onSelectionChange?.({ from: fromLocation, to: toLocation, pickup: pickupDate, dropoff: dropoffDate, driverAge: age, }); }, [ fromLocation, toLocation, pickupDate, dropoffDate, age, onSelectionChange, ]); // --- Handlers --- const handleSwap = useCallback(() => { const currentFrom = fromLocation; const currentTo = toLocation; setFromLocation(currentTo); setToLocation(currentFrom); onSwapPress?.(currentFrom, currentTo); }, [fromLocation, toLocation, onSwapPress]); const handleSearch = useCallback(() => { onSearchPress?.({ from: fromLocation, to: toLocation, pickup: pickupDate, dropoff: dropoffDate, driverAge: age, }); }, [fromLocation, toLocation, pickupDate, dropoffDate, age, onSearchPress]); // --- Shared Suggestion Render Item --- const suggestionRenderItem = (item: CarSuggestions) => ( { if (focusedInput === FormInputType.CAR_PICKUP) { setFromLocation(item.value); fromInputRef.current?.blur(); } else if (focusedInput === FormInputType.CAR_DROP_OFF) { setToLocation(item.value); toInputRef.current?.blur(); } }} style={[styles.suggestionItem, suggestionItemStyle]} > {item.value} ); return ( {/* Apply inputGroupContainerStyle */} {/* Apply inputWrapperStyle */} { onTextChange?.(t); setFromLocation(t); }} label={fromLabel} value={fromLocation} labelStyle={[styles.label, labelStyle]} placeholder={fromPlaceholder} onFocus={() => { onInputFocus?.(FormInputType.CAR_PICKUP); setFocusedInput(FormInputType.CAR_PICKUP); }} onBlur={() => { // Delay blur slightly to allow suggestion press setTimeout(() => { if (focusedInput === FormInputType.CAR_PICKUP) { setFocusedInput(undefined); } }, 150); }} containerStyle={inputGroupStyle} /> {suggestionData && ( )} {onSwapPress && ( )} {/* Apply inputWrapperStyle */} { setToLocation(t); onTextChange?.(t); }} label={toLabel} value={toLocation} labelStyle={[styles.label, labelStyle]} placeholder={toPlaceholder} onFocus={() => { onInputFocus?.(FormInputType.CAR_DROP_OFF); setFocusedInput(FormInputType.CAR_DROP_OFF); }} onBlur={() => { setTimeout(() => { if (focusedInput === FormInputType.CAR_DROP_OFF) { setFocusedInput(undefined); } }, 150); }} containerStyle={inputGroupStyle} /> {suggestionData && ( )} { setDropoffDate(d.return); setPickupDate(d.departure); }} isOneWay={isOneWay} /> {ageLabel} i + 21).map( (n) => ({ label: n.toString(), value: n, }) )} onValueChange={setAge} placeholder={{ label: agePickerPlaceholder, color: agePickerPlaceholderColor, }} /> {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: { // // Centering the button between the input wrappers // position: "absolute", // left: 0, // right: 0, // top: "50%", // Position roughly in the middle vertically // transform: [{ translateY: -18 }], // Adjust based on button height / 2 alignItems: "center", // zIndex: 1, // Ensure swap button is above inputs if they overlap slightly }, swapButton: { width: 36, height: 36, borderRadius: 18, backgroundColor: theme.surface, borderColor: theme.border, borderWidth: 1, justifyContent: "center", alignItems: "center", }, dateRangePickerOuterContainer: { marginTop: 10, // Default margin, can be overridden }, pickupRow: { flexDirection: isRTL ? "row-reverse" : "row", alignItems: "flex-end", marginTop: 20, gap: 10, }, agePickerWrapper: { flex: 1, }, pickerContainer: { borderWidth: 1, borderColor: theme.border, borderRadius: 8, backgroundColor: theme.surface, justifyContent: "center", height: 50, }, picker: { width: "100%", color: theme.onSurface, }, searchButton: { backgroundColor: theme.primary, width: 50, height: 50, borderRadius: 8, justifyContent: "center", alignItems: "center", }, suggestionItem: { padding: 12, borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: theme.border, backgroundColor: theme.surface, }, suggestionItemText: { fontSize: 14, color: theme.onSurface, }, }); export default CarRentalForm;