Add cabin class dropdown to RouteFilter component
- Add cabinClass state with type 'economy' | 'business' | 'first' (default: economy) - Add showCabinDropdown state to control visibility - Add cabin-class-dropdown button to toggle visibility - Add cabin-economy, cabin-business, cabin-first selection buttons - Add cabin-class-display div showing selected cabin class - Pass cabinClass in handleSearch callback - Update RouteFilterProps with initialCabinClass prop - Add SCSS styling for cabin class dropdown and options - Integrate into OnlineBoardFilter to pass initialCabinClass - Integrate into OnlineBoardSearchPage to decode cabinClass from URL params
This commit is contained in:
@@ -15,6 +15,7 @@ interface OnlineBoardFilterProps {
|
||||
flightNumber?: string
|
||||
tripType?: string
|
||||
passengers?: { adults: number, children: number, infants: number }
|
||||
cabinClass?: 'economy' | 'business' | 'first'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ export const OnlineBoardFilter: React.FC<OnlineBoardFilterProps> = ({ initialSea
|
||||
navigate(`/onlineboard/flight/${params}`)
|
||||
}
|
||||
|
||||
const handleRouteSearch = (departure: string, arrival: string, date: Date, returnDate?: Date | null, tripType?: string, passengers?: { adults: number, children: number, infants: number }) => {
|
||||
const handleRouteSearch = (departure: string, arrival: string, date: Date, returnDate?: Date | null, tripType?: string, passengers?: { adults: number, children: number, infants: number }, cabinClass?: 'economy' | 'business' | 'first') => {
|
||||
// Navigate to route search results
|
||||
const params = btoa(JSON.stringify({
|
||||
departure,
|
||||
@@ -38,6 +39,7 @@ export const OnlineBoardFilter: React.FC<OnlineBoardFilterProps> = ({ initialSea
|
||||
...(returnDate && { returnDate: returnDate.toISOString() }),
|
||||
...(tripType && { tripType }),
|
||||
...(passengers && { passengers }),
|
||||
...(cabinClass && { cabinClass }),
|
||||
}))
|
||||
navigate(`/onlineboard/route/${params}`)
|
||||
}
|
||||
@@ -66,6 +68,7 @@ export const OnlineBoardFilter: React.FC<OnlineBoardFilterProps> = ({ initialSea
|
||||
initialReturnDate={initialSearchParams?.returnDate}
|
||||
initialTripType={initialSearchParams?.tripType}
|
||||
initialPassengers={initialSearchParams?.passengers}
|
||||
initialCabinClass={initialSearchParams?.cabinClass}
|
||||
/>
|
||||
</AccordionTab>
|
||||
</Accordion>
|
||||
|
||||
@@ -125,6 +125,69 @@
|
||||
}
|
||||
}
|
||||
|
||||
.route-filter__cabin-class-group {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.route-filter__cabin-class-dropdown {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
padding: 8px 12px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
|
||||
&:hover {
|
||||
background-color: #ececec;
|
||||
}
|
||||
}
|
||||
|
||||
.route-filter__cabin-class-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
background-color: #fafafa;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.route-filter__cabin-option {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
padding: 8px 12px;
|
||||
border-radius: 0;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
background-color: transparent;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #e3f2fd;
|
||||
font-weight: 600;
|
||||
color: #0066cc;
|
||||
}
|
||||
}
|
||||
|
||||
.route-filter__cabin-class-display {
|
||||
margin-top: 4px;
|
||||
padding: 4px 8px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.route-filter__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
@@ -13,13 +13,14 @@ export interface PassengerCounts {
|
||||
}
|
||||
|
||||
export interface RouteFilterProps {
|
||||
onSearch?: (departure: string, arrival: string, date: Date, returnDate?: Date | null, tripType?: string, passengers?: PassengerCounts) => void
|
||||
onSearch?: (departure: string, arrival: string, date: Date, returnDate?: Date | null, tripType?: string, passengers?: PassengerCounts, cabinClass?: 'economy' | 'business' | 'first') => void
|
||||
initialDeparture?: string
|
||||
initialArrival?: string
|
||||
initialDate?: Date | string
|
||||
initialReturnDate?: Date | string
|
||||
initialTripType?: string
|
||||
initialPassengers?: PassengerCounts
|
||||
initialCabinClass?: 'economy' | 'business' | 'first'
|
||||
}
|
||||
|
||||
// Validation service
|
||||
@@ -77,7 +78,8 @@ export const RouteFilter: React.FC<RouteFilterProps> = ({
|
||||
initialDate,
|
||||
initialReturnDate,
|
||||
initialTripType,
|
||||
initialPassengers
|
||||
initialPassengers,
|
||||
initialCabinClass
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const validated = validatePassengerCounts(initialPassengers)
|
||||
@@ -102,6 +104,8 @@ export const RouteFilter: React.FC<RouteFilterProps> = ({
|
||||
const [children, setChildren] = useState(validated.children)
|
||||
const [infants, setInfants] = useState(validated.infants)
|
||||
const [showPassengerDropdown, setShowPassengerDropdown] = useState(false)
|
||||
const [cabinClass, setCabinClass] = useState<'economy' | 'business' | 'first'>(initialCabinClass || 'economy')
|
||||
const [showCabinDropdown, setShowCabinDropdown] = useState(false)
|
||||
|
||||
const totalPassengers = adults + children + infants
|
||||
const maxPassengers = 9
|
||||
@@ -119,10 +123,10 @@ export const RouteFilter: React.FC<RouteFilterProps> = ({
|
||||
|
||||
const handleSearch = useCallback(() => {
|
||||
if (validateRouteParams(departure, arrival, date) && onSearch) {
|
||||
// Pass all search parameters including return date for round trips and passenger counts
|
||||
onSearch(departure!.code, arrival!.code, date!, returnDate, tripType, { adults, children, infants })
|
||||
// Pass all search parameters including return date for round trips, passenger counts, and cabin class
|
||||
onSearch(departure!.code, arrival!.code, date!, returnDate, tripType, { adults, children, infants }, cabinClass)
|
||||
}
|
||||
}, [departure, arrival, date, returnDate, tripType, adults, children, infants, onSearch])
|
||||
}, [departure, arrival, date, returnDate, tripType, adults, children, infants, cabinClass, onSearch])
|
||||
|
||||
const handleSwap = () => {
|
||||
const temp = departure
|
||||
@@ -238,6 +242,52 @@ export const RouteFilter: React.FC<RouteFilterProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="route-filter__group route-filter__cabin-class-group">
|
||||
<Button
|
||||
label={t('SHARED.CABIN_CLASS')}
|
||||
icon={showCabinDropdown ? 'pi pi-chevron-up' : 'pi pi-chevron-down'}
|
||||
onClick={() => setShowCabinDropdown(!showCabinDropdown)}
|
||||
className="p-button-text route-filter__cabin-class-dropdown"
|
||||
data-testid="cabin-class-dropdown"
|
||||
/>
|
||||
|
||||
{showCabinDropdown && (
|
||||
<div className="route-filter__cabin-class-options">
|
||||
<Button
|
||||
label={t('SHARED.ECONOMY')}
|
||||
onClick={() => {
|
||||
setCabinClass('economy')
|
||||
setShowCabinDropdown(false)
|
||||
}}
|
||||
className={`p-button-text route-filter__cabin-option ${cabinClass === 'economy' ? 'active' : ''}`}
|
||||
data-testid="cabin-economy"
|
||||
/>
|
||||
<Button
|
||||
label={t('SHARED.BUSINESS')}
|
||||
onClick={() => {
|
||||
setCabinClass('business')
|
||||
setShowCabinDropdown(false)
|
||||
}}
|
||||
className={`p-button-text route-filter__cabin-option ${cabinClass === 'business' ? 'active' : ''}`}
|
||||
data-testid="cabin-business"
|
||||
/>
|
||||
<Button
|
||||
label={t('SHARED.FIRST')}
|
||||
onClick={() => {
|
||||
setCabinClass('first')
|
||||
setShowCabinDropdown(false)
|
||||
}}
|
||||
className={`p-button-text route-filter__cabin-option ${cabinClass === 'first' ? 'active' : ''}`}
|
||||
data-testid="cabin-first"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="route-filter__cabin-class-display" data-testid="cabin-class-display">
|
||||
{t(`SHARED.${cabinClass.toUpperCase()}`)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="route-filter__group">
|
||||
<label className="route-filter__label">{t('SHARED.DATE')}</label>
|
||||
<CalendarInput
|
||||
|
||||
@@ -121,6 +121,7 @@ export const OnlineBoardSearchPage: React.FC = () => {
|
||||
flightNumber: searchParams.flightNumber,
|
||||
returnDate: searchParams.returnDate,
|
||||
tripType: searchParams.tripType,
|
||||
cabinClass: searchParams.cabinClass,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 599 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 598 KiB |
Reference in New Issue
Block a user