diff --git a/client/src/Components/design-elements/StatusLabel.tsx b/client/src/Components/design-elements/StatusLabel.tsx index d50058378..c3fd089d7 100644 --- a/client/src/Components/design-elements/StatusLabel.tsx +++ b/client/src/Components/design-elements/StatusLabel.tsx @@ -93,3 +93,20 @@ export const ValueLabel = ({ value, text }: { value: ValueType; text: string }) ); }; + +export const ColoredLabel = ({ text, color }: { text: string; color: string }) => { + const theme = useTheme(); + + return ( + + {text} + + ); +}; diff --git a/client/src/Components/inputs/AutoComplete.tsx b/client/src/Components/inputs/AutoComplete.tsx index c98e8ff32..4822a805f 100644 --- a/client/src/Components/inputs/AutoComplete.tsx +++ b/client/src/Components/inputs/AutoComplete.tsx @@ -14,17 +14,19 @@ type AutoCompleteInputProps = Omit< renderInput?: AutocompleteProps["renderInput"]; fieldLabel?: string; required?: boolean; + renderOptionContent?: (option: any) => React.ReactNode; }; export const AutoCompleteInput = ({ fieldLabel, required, renderInput, + renderOptionContent, ...props }: AutoCompleteInputProps) => { const theme = useTheme(); const multiple = props.multiple; - + const { renderOption: customRenderOption, ...autocompleteProps } = props; const defaultRenderInput = (params: any) => ( option.id} renderTags={() => null} - renderOption={(props, option, { selected }) => { - const { key, ...optionProps } = props; - return ( - - { + const { key, ...optionProps } = props; + return ( + - {multiple && } - {option.name} - - - ); - }} + + {multiple && } + {renderOptionContent ? renderOptionContent(option) : option.name} + + + ); + }) + } sx={{ "&.MuiAutocomplete-root .MuiAutocomplete-input": { padding: `0 ${theme.spacing(5)}`, diff --git a/client/src/Components/monitors/ControlsFilter.tsx b/client/src/Components/monitors/ControlsFilter.tsx index a617d454c..196ef2042 100644 --- a/client/src/Components/monitors/ControlsFilter.tsx +++ b/client/src/Components/monitors/ControlsFilter.tsx @@ -1,9 +1,11 @@ import Stack from "@mui/material/Stack"; -import { Select, Button } from "@/Components/inputs"; +import { Select, Autocomplete, Button, TextField } from "@/Components/inputs"; +import { ColoredLabel } from "@/Components/design-elements"; import MenuItem from "@mui/material/MenuItem"; import useMediaQuery from "@mui/material/useMediaQuery"; import type { MonitorType } from "@/Types/Monitor"; +import type { Tag } from "@/Types/Tag"; import { Typography, useTheme } from "@mui/material"; import { useTranslation } from "react-i18next"; @@ -28,22 +30,34 @@ export const ControlsFilter = ({ setSelectedStatus, selectedState, setSelectedState, + tagOptions, + selectedTags, + setSelectedTags, onClearFilters, }: { showTypes?: boolean; selectedTypes?: MonitorType[]; setSelectedTypes?: React.Dispatch>; - selectedStatus: string; - setSelectedStatus: React.Dispatch>; - selectedState: string; - setSelectedState: React.Dispatch>; + selectedStatus?: string; + setSelectedStatus?: React.Dispatch>; + selectedState?: string; + setSelectedState?: React.Dispatch>; + tagOptions?: Tag[]; + selectedTags?: string[]; + setSelectedTags?: React.Dispatch>; onClearFilters: () => void; }) => { const theme = useTheme(); const { t } = useTranslation(); const isSmall = useMediaQuery(theme.breakpoints.down("md")); const isFilterActive = - (selectedTypes?.length ?? 0) > 0 || selectedStatus !== "" || selectedState !== ""; + (selectedTypes?.length ?? 0) > 0 || + Boolean(selectedStatus) || + Boolean(selectedState) || + (selectedTags?.length ?? 0) > 0; + const selectedTagObjects = (tagOptions ?? []).filter((tag) => + (selectedTags ?? []).includes(tag.id) + ); return ( )} - - + {setSelectedStatus && ( + + )} + {setSelectedState && ( + + )} + {tagOptions && setSelectedTags && ( + option.name} + onChange={(_: unknown, newValue: Tag[]) => { + setSelectedTags(newValue.map((tag) => tag.id)); + }} + isOptionEqualToValue={(option, value) => option.id === value.id} + renderOptionContent={(option) => ( + + )} + renderInput={(params) => ( + + )} + slotProps={{ + popper: { + sx: { width: "fit-content !important", minWidth: 280 }, + }, + }} + sx={{ minWidth: 180 }} + /> + )} {isFilterActive && (