Last active
September 7, 2023 23:11
-
-
Save jonathasborges1/2162c72d666daf218855baf20b3210a4 to your computer and use it in GitHub Desktop.
TextFieldMultiSelect.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from "react"; | |
import Autocomplete, { | |
AutocompleteRenderInputParams, | |
} from "@mui/material/Autocomplete"; | |
import { Checkbox, IconButton, Grid, Typography, Box } from "@mui/material"; | |
import TextField from "@mui/material/TextField"; | |
import { useTheme } from "@material-ui/core"; | |
import { ArrowDownSelectIcon } from "@components/Icons"; | |
interface Option { | |
value: string; | |
label: string; | |
} | |
interface TextFieldMultiSelectProps { | |
label?: string; | |
options: Option[]; | |
onChange?: (e: Option[]) => void; | |
} | |
const TextFieldMultiSelect: React.FC<TextFieldMultiSelectProps> = ({ | |
options, | |
...props | |
}) => { | |
const theme = useTheme(); | |
const [selectedOptions, setSelectedOptions] = useState<Option[]>([]); | |
const [isMenuOpen, setIsMenuOpen] = useState(true); | |
const handleOptionChange = (_event, newOptions: Option[]) => { | |
// Verifica se "Todos" esta contido na lista | |
const isAllSelected = newOptions.some((option) => option.value === "todos"); | |
// Verifique se "Todos" foi selecionado | |
const optionTodosIsSelected = _event.target?.innerText.includes("Todos"); | |
let optionsResult: Option[] = []; | |
// Cenario 1 - Clicou em "Todos" entao marca todas as opcoes disponives | |
if (optionTodosIsSelected && isAllSelected) { | |
optionsResult = options; | |
setSelectedOptions(optionsResult); | |
} | |
// Cenario 2 - Clicou em todos pelo segunda vez entao desmarca todas as opcoes disponives | |
if (optionTodosIsSelected && !isAllSelected) { | |
optionsResult = []; | |
setSelectedOptions(optionsResult); | |
} | |
// Cenario 3 - Clicou em todos e depois desmarcou algum opcao | |
if (isAllSelected && !optionTodosIsSelected) { | |
optionsResult = newOptions.filter((op) => op.value !== "todos"); | |
setSelectedOptions(optionsResult); | |
} | |
// Cenario 4 - Opcao "Todos" esta desmarcado | |
if (!isAllSelected && !optionTodosIsSelected) { | |
optionsResult = newOptions; | |
setSelectedOptions(optionsResult); | |
} | |
// remove a opcao "Todos" da lista (se existir) e envia para o componente pai | |
props.onChange && | |
props.onChange(optionsResult.filter((op) => op.value !== "todos")); | |
}; | |
const handleOpenMenu = () => { | |
setIsMenuOpen(true); | |
}; | |
const handleCloseMenu = () => { | |
setIsMenuOpen(false); | |
}; | |
const handleIconButtonMenu = () => { | |
setIsMenuOpen(!isMenuOpen); | |
}; | |
const customRenderOptionsLabel = (options: Option[]) => { | |
if (options.find((op) => op.value === "todos")) return "Todos"; | |
const optionsLabel = options.map((option) => { | |
return option.label; | |
}); | |
return optionsLabel.join(" / "); | |
}; | |
return ( | |
<Autocomplete | |
open={isMenuOpen} | |
onOpen={handleOpenMenu} | |
onClose={handleCloseMenu} | |
multiple | |
id="multi-select" | |
options={options} | |
value={selectedOptions} | |
onChange={handleOptionChange} | |
getOptionLabel={(option) => option.label} | |
renderInput={(params: AutocompleteRenderInputParams) => ( | |
<Grid container justifyContent={"end"} sx={{ border: "0px solid red" }}> | |
<TextField | |
{...params} | |
className="TextField-select-custom" | |
label={props.label} //"Selecione opções" | |
variant="outlined" | |
fullWidth | |
sx={{ | |
border: "0px solid red", | |
"& svg": { display: "none" }, | |
"& .MuiAutocomplete-inputRoot": { | |
border: "0px solid blue", | |
padding: "1rem 0rem 1rem 1rem !important", | |
margin: 0, | |
}, | |
"& .MuiInputLabel-shrink": { | |
fontWeight: 700, | |
fontSize: "1.4rem", | |
letterSpacing: "1.5px", | |
background: "white", | |
}, | |
"& label": { | |
fontSize: "1.2rem", | |
fontFamily: theme.typography.fontFamily, | |
color: `rgba(0, 0, 0, 0.50)`, | |
}, | |
"& fieldset": { | |
border: "1px solid rgba(114, 101, 81, 0.40)", | |
borderRadius: 1, | |
}, | |
"& input": { | |
maxWidth: "min-content", | |
minWidth: "min-content", | |
}, | |
}} | |
/> | |
<IconButton | |
onClick={handleIconButtonMenu} | |
sx={{ position: "absolute", margin: "1rem 1rem 1rem 0rem" }} | |
> | |
<ArrowDownSelectIcon sx={{ fontSize: 11 }} />{" "} | |
{/* Ícone personalizado */} | |
</IconButton> | |
</Grid> | |
)} | |
renderOption={(props, option, { selected }) => ( | |
<li {...props} style={{ border: "0px solid red", cursor: "pointer" }}> | |
<div style={{ display: "flex", alignItems: "center" }}> | |
<Checkbox | |
style={{ | |
color: selected ? "red" : "inherit", | |
pointerEvents: "none", | |
}} | |
checked={selected} | |
/> | |
<Typography | |
sx={{ | |
fontFamily: theme.typography.fontFamily, | |
}} | |
> | |
{option.label} | |
</Typography> | |
</div> | |
</li> | |
)} | |
disableCloseOnSelect | |
isOptionEqualToValue={(option: Option, value: Option) => | |
option.value === value.value | |
} | |
// renderiza os valores selecionados no componente textField | |
renderTags={(value: Option[], getTagProps) => ( | |
<Box | |
sx={{ | |
border: "0px solid red", | |
display: "flex", | |
maxWidth: "90%", // Set maximum width | |
whiteSpace: "nowrap", // Prevent text from wrapping | |
}} | |
> | |
<Typography | |
variant="body2" | |
sx={{ | |
fontSize: { lg: "1.2rem" }, | |
border: "0px solid blue", | |
fontFamily: theme.typography.fontFamily, | |
fontWeight: 500, | |
padding: "1px", | |
marginX: "8px", | |
overflow: "hidden", // Hide overflow content | |
textOverflow: "ellipsis", // Display ellipsis for overflow | |
}} | |
> | |
{customRenderOptionsLabel(value)} | |
</Typography> | |
</Box> | |
)} | |
/> | |
); | |
}; | |
export default TextFieldMultiSelect; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment