Skip to content

Commit

Permalink
Flight flagger amends (#21)
Browse files Browse the repository at this point in the history
* Adds initial state to filters
* Numerous small style fixes
* Adds clear highlights functionality

---------

Co-authored-by: jackson <Jackson Hyde>
  • Loading branch information
jacksonhyde authored Jul 16, 2024
1 parent 8560ed9 commit 26eade3
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 110 deletions.
240 changes: 137 additions & 103 deletions src/components/FlightFlagger/FlightFlaggerFilters.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, {useState} from "react";
import { Grid, Typography, FormGroup, FormLabel, RadioGroup, Radio, FormControl, Collapse, InputLabel, OutlinedInput,InputAdornment, FormControlLabel, Autocomplete, Checkbox, TextField, Button, Paper, IconButton, Chip } from "@mui/material";
import { Grid, Typography, FormGroup, FormLabel, RadioGroup, Radio, FormControl, Collapse, InputLabel, OutlinedInput,InputAdornment, FormControlLabel, Autocomplete, Checkbox, TextField, Button, Paper, IconButton, Chip, Link } from "@mui/material";
import SearchIcon from '@mui/icons-material/Search';
import { ArrowRight } from "@mui/icons-material";
type AutocompleteOption = {

export type AutocompleteOption = {
title: string
}

type FormState = {
showTransitPaxNumber: boolean,
showNumberOfVisaNationals: boolean,
requireAllSelected: false,
requireAllSelected: boolean,
flightNumber: string
}

Expand All @@ -28,36 +29,56 @@ export interface IFlightFlaggerFilters {
submitCallback: (payload:SearchFilterPayload) => void,
showAllCallback: (event: React.ChangeEvent<HTMLInputElement>) => void,
onChangeInput: (searchTerm: string) => void,
initialState?: {
showTransitPaxNumber: boolean,
showNumberOfVisaNationals: boolean,
requireAllSelected: boolean,
flightNumber: string,
selectedNationalities: AutocompleteOption[],
selectedAgeGroups: AutocompleteOption[],
showFilters: boolean,
}
}

export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback, showAllCallback, onChangeInput}: IFlightFlaggerFilters) => {
export const FlightFlaggerFilters = ({
nationalities,
ageGroups,
submitCallback,
showAllCallback,
onChangeInput,
initialState,
}: IFlightFlaggerFilters) => {

const nationalitiesOptions = nationalities.map((nationality) => { return { title: nationality }});
const ageOptions = ageGroups.map((ageGroup) => { return { title: ageGroup }});

const [searchFlags, setSearchFlags] = useState<FormState>({
showTransitPaxNumber: false,
showNumberOfVisaNationals: false,
requireAllSelected: false,
flightNumber: ''
})
const [selectedNationalities, setSelectedNationalities] = useState<AutocompleteOption[]>([]);
const [selectedAgeGroups, setSelectedAgeGroups] = useState<AutocompleteOption[]>([]);
const [showFilters, setShowFilters] = useState<boolean>(false);
showTransitPaxNumber: initialState?.showTransitPaxNumber || false,
showNumberOfVisaNationals: initialState?.showNumberOfVisaNationals || false,
requireAllSelected: initialState?.requireAllSelected || false,
flightNumber: initialState?.flightNumber || '',
});
const [selectedNationalities, setSelectedNationalities] = useState<AutocompleteOption[]>(initialState?.selectedNationalities || []);
const [selectedAgeGroups, setSelectedAgeGroups] = useState<AutocompleteOption[]>(initialState?.selectedAgeGroups || []);
const [showFilters, setShowFilters] = useState<boolean>(initialState?.showFilters || false);

const isTouched = () => {
return (selectedNationalities.length !== 0) || (selectedAgeGroups.length !== 0) || searchFlags.showTransitPaxNumber || searchFlags.showNumberOfVisaNationals
}

const handleSubmit = () => {
const submit = () => {
const ageGroupPayload: string[] = selectedAgeGroups.map((ageGroup: AutocompleteOption) => ageGroup.title)
const nationalityPayload: string[] = selectedNationalities.map((nationality: AutocompleteOption) => nationality.title)
submitCallback({
...searchFlags,
selectedNationalities: nationalityPayload,
selectedAgeGroups: ageGroupPayload,
});
setShowFilters(!showFilters)
}

const handleApply = () => {
submit()
setShowFilters(false)
}

const handleCheckboxChange = (event: React.ChangeEvent<HTMLInputElement>) => {
Expand All @@ -70,8 +91,6 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,

const handleTextInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const name: string = event.target.name
const ageGroupPayload: string[] = selectedAgeGroups.map((ageGroup: AutocompleteOption) => ageGroup.title)
const nationalityPayload: string[] = selectedNationalities.map((nationality: AutocompleteOption) => nationality.title)
setSearchFlags({
...searchFlags,
[name]: event.target.value
Expand All @@ -81,7 +100,7 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,

const handleInputSubmit = (event: React.KeyboardEvent<HTMLInputElement>) => {
if(event.key === 'Enter'){
handleSubmit()
submit()
}
}

Expand Down Expand Up @@ -120,6 +139,24 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,
return total;
}

const clearHighlights = () => {
const resetFilterPayload = {
...searchFlags,
showTransitPaxNumber: false,
showNumberOfVisaNationals: false,
requireAllSelected: false,
}
setSearchFlags(resetFilterPayload)
setSelectedNationalities([]);
setSelectedAgeGroups([]);

submitCallback({
...resetFilterPayload,
selectedNationalities: [],
selectedAgeGroups: [],
});
}

return <>
<Grid container sx={{backgroundColor: '#F3F5F9', width: '100%', ml:0, pt: 2}} flexWrap={{xs: 'wrap', md: 'nowrap'}} spacing={2}>
<Grid item flexGrow={0}>
Expand All @@ -133,18 +170,12 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,
onChange={handleTextInputChange}
onKeyDown={handleInputSubmit}
value={searchFlags.flightNumber}
placeholder="Enter flight number, origin or country"
placeholder="Enter flight, origin or country"
startAdornment={
<InputAdornment position="start">
<SearchIcon/>
</InputAdornment>
}
endAdornment={
<IconButton
color="primary">
<ArrowRight/>
</IconButton>
}
/>
</FormControl>
</Grid>
Expand All @@ -156,14 +187,16 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,
<InputLabel sx={{mb:1}}><strong>Highlight flights</strong></InputLabel>
<Button
data-testid="show-filters"
color={"primary"}
color={"secondary"}
onClick={() => toggleFilters()}
variant={ isTouched() ? "contained" : "outlined"}
disableElevation
variant={"outlined"}
sx={{
textTransform: 'none',
letterSpacing: 0,
whiteSpace: 'nowrap',
height: '40px'
height: '40px',
backgroundColor: '#fff'
}}
startIcon={<SearchIcon/>}
endIcon={<Chip
Expand Down Expand Up @@ -196,89 +229,90 @@ export const FlightFlaggerFilters = ({nationalities, ageGroups, submitCallback,
<Grid item xs={12} sx={{px:2, pb:2}}>
<Collapse in={showFilters} data-testid="flight-flagger-filters">
<Paper elevation={0} sx={{backgroundColor: '#fff', p:2, mt: 2}}>
<Grid item xs={12}>
<Typography sx={{mb:1}}><strong>Select pax info to reveal</strong></Typography>
</Grid>
<Grid item xs={12} sx={{mb: 2}}>
<Autocomplete
data-testid="nationalities-autocomplete"
multiple
id="nationalities"
options={nationalitiesOptions}
getOptionLabel={(option) => option.title}
defaultValue={[]}
filterSelectedOptions
isOptionEqualToValue={(option, value) => option.title === value.title}
onChange={(event, newValue) => {
setSelectedNationalities(newValue);
}}
renderInput={(params) => (
<TextField
{...params}
label="Nationalities"
placeholder="Enter of select a nationality"
/>
)}
/>
</Grid>
<Grid item xs={12}>
<Autocomplete
data-testid="age-autocomplete"
multiple
id="ageGroups"
options={ageOptions}
getOptionLabel={(option) => option.title}
defaultValue={[]}
filterSelectedOptions
isOptionEqualToValue={(option, value) => option.title === value.title}
onChange={(event, newValue) => {
setSelectedAgeGroups(newValue);
}}
renderInput={(params) => (
<TextField
{...params}
label="Age groups"
placeholder="Enter age groups"
/>
)}
/>
</Grid>
<Grid item xs={12}>
<FormGroup>
<FormControlLabel
control={
<Checkbox data-testid="show-transit-pax-check" checked={searchFlags.showTransitPaxNumber} onChange={handleCheckboxChange} name="showTransitPaxNumber" />
}
label="Show transit pax number"
/>
<FormControlLabel
control={
<Checkbox data-testid="show-visa-nationals-check" checked={searchFlags.showNumberOfVisaNationals} onChange={handleCheckboxChange} name="showNumberOfVisaNationals" />
}
label="Show number of visa nationals"
/>
<Paper elevation={0} sx={{py: 1, px:2, mt: 1, mb: 2}} variant="outlined">
<Grid container columnSpacing={2}>
<Grid item xs={12}>
<Typography sx={{mb:1}}><strong>Select pax info to reveal</strong></Typography>
</Grid>
<Grid item xs={12} sm={6} sx={{mb: 2}}>
<Autocomplete
data-testid="nationalities-autocomplete"
multiple
id="nationalities"
options={nationalitiesOptions}
getOptionLabel={(option) => option.title}
value={selectedNationalities}
defaultValue={[]}
filterSelectedOptions
isOptionEqualToValue={(option, value) => option.title === value.title}
onChange={(event, newValue) => {
setSelectedNationalities(newValue);
}}
renderInput={(params) => (
<TextField
{...params}
label="Nationalities"
placeholder="Enter or select nationalities"
/>
)}
/>
</Grid>
<Grid item xs={12} sm={6} >
<Autocomplete
data-testid="age-autocomplete"
multiple
id="ageGroups"
options={ageOptions}
getOptionLabel={(option) => option.title}
value={selectedAgeGroups}
defaultValue={[]}
filterSelectedOptions
isOptionEqualToValue={(option, value) => option.title === value.title}
onChange={(event, newValue) => {
setSelectedAgeGroups(newValue);
}}
renderInput={(params) => (
<TextField
{...params}
label="Age groups"
placeholder="Enter of select age groups"
/>
)}
/>
</Grid>
<Grid item xs={12}>
<FormGroup>
<FormControlLabel
control={
<Checkbox
data-testid="require-all-selected-check"
disabled={!isTouched()}
checked={searchFlags.requireAllSelected}
onChange={handleCheckboxChange}
name="requireAllSelected" />
<Checkbox data-testid="show-visa-nationals-check" checked={searchFlags.showNumberOfVisaNationals} onChange={handleCheckboxChange} name="showNumberOfVisaNationals" />
}
label="Only highlight flights with all selected info"
label="Show number of visa nationals"
/>
</Paper>
</FormGroup>
</Grid>
<Grid item xs={12}>
<Button variant='outlined' onClick={() => setShowFilters(false)} sx={{mr: 2}}>Close</Button>
<Button data-testid="flight-flagger-filter-submit" variant='contained' onClick={handleSubmit}>Apply Highlights</Button>
<Paper elevation={0} sx={{py: 1, px:2, mt: 1, mb: 2}} variant="outlined">
<FormControlLabel
control={
<Checkbox
data-testid="require-all-selected-check"
disabled={!isTouched()}
checked={searchFlags.requireAllSelected}
onChange={handleCheckboxChange}
name="requireAllSelected" />
}
label="Only highlight flights with all selected info"
/>
</Paper>
</FormGroup>
</Grid>
<Grid item xs={12}>
<Button variant='outlined' onClick={() => setShowFilters(false)} sx={{mr: 2}}>Close</Button>
<Button data-testid="flight-flagger-filter-submit" variant='contained' onClick={handleApply}>Apply Highlights</Button>
</Grid>
</Grid>
</Paper>
</Collapse>
{ isTouched() && <Typography sx={{mt:2,pr: 2}}><strong>Pax info highlighted - </strong>{ buildFilterString() }</Typography>}
{ isTouched() && <Typography sx={{mt:2,pr: 2}}>
<strong>Pax info highlighted - </strong>
{ buildFilterString() } - <Link data-testid="flight-flagger-clear-filters" onClick={() => clearHighlights()}>Clear all highlights</Link>
</Typography> }
</Grid>
</Grid></>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface IFlightHighlightChip {
}

const HighlightIcon = () => {
return <CustomHighlightIcon width={24} style={{marginLeft: '4px'}} />
return <CustomHighlightIcon style={{marginLeft: '4px', width: '25px'}} />
}

export const FlightHighlightChip = ({text}: IFlightHighlightChip) => {
Expand Down
Loading

0 comments on commit 26eade3

Please sign in to comment.