Skip to content

Instantly share code, notes, and snippets.

@jonathasborges1
Created May 6, 2023 03:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathasborges1/111121a7c339acc2d25c45add1cd9044 to your computer and use it in GitHub Desktop.
Save jonathasborges1/111121a7c339acc2d25c45add1cd9044 to your computer and use it in GitHub Desktop.
MultipleSelectCheckBox component
import { useState, useMemo, useCallback, useEffect } from "react";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import {
FormControl,
Select,
MenuItem,
Checkbox,
Typography,
ListItemText,
} from "@mui/material";
import { useTheme } from "@mui/material/styles";
interface Option {
value: string;
label: string;
}
interface Props {
label: string;
options: Option[];
value: string[];
onChange: (values: string[]) => void;
}
const MultipleSelectCheckbox: React.FC<Props> = ({
label,
options,
value,
onChange,
}) => {
const theme = useTheme();
const [selectAll, setSelectAll] = useState<boolean>(false);
const [selectedValues, setSelectedValues] = useState<string[] | undefined>(value);
const handleSelectAll = () => {
if (selectAll) {
setSelectedValues([]);
setSelectAll(false);
} else {
setSelectedValues(options.map((option) => option.value));
setSelectAll(true);
}
};
const handleOptionChange = (optionValue: string, optionSelected: boolean) => {
setSelectedValues((prevSelectedValues) => {
if (optionSelected) {
if (prevSelectedValues?.includes(optionValue)) {
// Se a opção já estiver selecionada, não faz nada
return prevSelectedValues;
} else {
// Se a opção não estiver selecionada, adiciona à lista de selecionados
return prevSelectedValues
? [...prevSelectedValues, optionValue]
: [optionValue];
}
} else {
// Se a opção estiver sendo desmarcada, remove da lista de selecionados
return prevSelectedValues?.filter((value) => value !== optionValue);
}
});
};
const allOptionsSelected = useMemo(
() => selectedValues?.length === options.length || false,
[selectedValues, options]
);
const someOptionsSelected = useMemo(
() => selectedValues.length > 0 && !allOptionsSelected,
[selectedValues, allOptionsSelected]
);
const handle = useCallback(()=>{
onChange(selectedValues);
},[selectedValues])
useEffect(()=>{handle()},[])
return (
<FormControl sx={{ maxWidth: 241, minWidth: 241 }}>
{label && (
<Typography
fontFamily={"Open Sans"}
fontWeight={700}
color={"shadesOfDark.dark"}
mb={0.5}
>
{label}
</Typography>
)}
<Select
multiple
displayEmpty
placeholder={selectedValues?.length === 0 ? "Selecione" : ""}
value={selectedValues || []}
renderValue={(selected) => {
const allSelected =
Array.isArray(selected) && selected.length === options.length;
if (selected.length === 0) {
return "Selecione";
} else if (allSelected) {
return "Todos";
} else {
const selectedLabels = selectedValues?.map(
(value) => options.find((option) => option.value === value)?.label
);
return selectedLabels?.join(", ") || "";
}
}}
IconComponent={KeyboardArrowDownIcon}
sx={{
bgcolor: "background.paper",
border: "none",
borderRadius: 1,
padding: 0,
maxWidth: 200,
minWidth: 200,
height: 40,
"& .MuiInputBase-input::placeholder": {
color: "#888",
fontStyle: "italic",
opacity: 1,
},
"& .MuiSelect-root": {
backgroundColor: "transparent",
paddingLeft: 0,
paddingRight: 0,
"&:focus": {
backgroundColor: "transparent",
border: "none",
outline: "none !important",
},
},
"& .MuiSelect-icon": {
top: "calc(50% - 12px)",
},
}}
>
<MenuItem value="" disabled>
Selecione
</MenuItem>
<MenuItem
key="select-all"
aria-expanded={open ? "true" : undefined}
>
<label style={{ display: "flex", alignItems: "center" , width: "100%",cursor:"pointer", border:"0px solid red" }}>
<Checkbox
checked={allOptionsSelected}
indeterminate={someOptionsSelected}
onChange={handleSelectAll}
sx={{
"&.MuiCheckbox-colorPrimary": {
color: theme.palette.shadesOfDark.dark,
},
}}
/>
<ListItemText primary={"Todos"} />
</label>
</MenuItem>
{options.map((option) => (
<MenuItem
key={option.value}
value={option.value}
onClick={() => { handleOptionChange(option.value,!selectedValues.includes(option.value));
}}
sx={{
minWidth: 200,
fontSize: 14,
fontFamily: "Open Sans",
"&.Mui-selected": {
color: "shadesOfDark.dark",
backgroundColor: "shadesOfDark.ultraLight",
fontWeight: 700,
},
"&.Mui-selected:hover": {
backgroundColor: "shadesOfDark.ultraLight",
},
}}
>
<Checkbox
checked={selectedValues.includes(option.value)}
sx={{
"&.Mui-checked": {
color: theme.palette.shadesOfDark.dark,
},
}}
/>
<ListItemText primary={option.label} />
</MenuItem>
))}
</Select>
</FormControl>
);
};
export default MultipleSelectCheckbox;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment