Skip to content

Commit

Permalink
convert item filter into a modal
Browse files Browse the repository at this point in the history
  • Loading branch information
nipuna-g committed Oct 21, 2023
1 parent 44c2bd0 commit 354dc35
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 86 deletions.
229 changes: 161 additions & 68 deletions client/components/map/FilterPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import {
Box,
VStack,
HStack,
Spacer,
Button,
Text,
Slider,
SliderTrack,
SliderFilledTrack,
SliderThumb,
Modal,
ModalContent,
ModalOverlay,
Divider,
CheckboxGroup,
Checkbox,
Stack,
Button,
Flex,
useCheckbox,
chakra,
CheckboxProps,
useCheckboxGroup,
} from "@chakra-ui/react";
import { XButton } from "./Buttons";
import { COLORS } from "theme";
import { TItemSelection, TEmptyItem } from "app-context/SheetyContext/types";
import { OptionType } from "spa-pages";
import { ChangeEvent } from "react";
import React, { ChangeEvent } from "react";
import { Methods } from "api/sheety/enums";

type FilterProps = {
isMobile: boolean | undefined;
setFilterShow: () => void;
isOpen: boolean;
filterApply: () => void;
handleSliderChange: (val: number) => void;
range: number;
Expand All @@ -32,86 +34,177 @@ type FilterProps = {
};

export const FilterPanel = ({
isMobile,
setFilterShow,
isOpen,
filterApply,
handleSliderChange,
range,
itemState,
selectOptions,
handleCheckboxChange,
}: FilterProps) => {
const selectedOptionsWithCheckedState = selectOptions.map((option) => {
const isChecked = itemState.some(
(item) => item.name === option.value && item.method === option.method,
);
return { ...option, isChecked };
});

return (
<Box
position={"fixed"}
height={isMobile ? "calc(92vh)" : "calc(90vh)"}
width={"100vw"}
bg="white"
zIndex={99999}
bottom={0}
overflowY={"scroll"}
overflowX={"hidden"}
>
<VStack p={7} w={"100vw"} gap={5}>
<HStack w="100%" justify="space-between">
<XButton onClick={setFilterShow} />
<Spacer />
<Button
color={COLORS.white}
bgColor={COLORS.Button.primary}
onClick={filterApply}
>
Apply
</Button>
</HStack>
<Modal isOpen={isOpen} onClose={() => undefined}>
<ModalOverlay />
<ModalContent maxWidth="calc(768px - 32px)" marginTop="140px" marginInline="4">
<FilterSection
title="Your items"
button={
<Button
size="sm"
color="white"
bgColor={COLORS.Button.primary}
onClick={filterApply}
>
Apply
</Button>
}
>
<PillBox
items={selectedOptionsWithCheckedState}
handleItemSelect={handleCheckboxChange}
/>
</FilterSection>

<FilterSection title="Sort by">
<HStack>
<Box
border="1px solid #D6EAEA"
background={COLORS.Button.primary}
padding={1}
borderRadius="full"
paddingInline={3}
color="white"
fontSize={12}
>
Nearest
</Box>
<Box
border="1px solid #D6EAEA"
padding={1}
borderRadius="full"
paddingInline={3}
fontSize={12}
>
Most items
</Box>
</HStack>
</FilterSection>

<VStack w="100%">
<Text w="100%" textAlign={"left"} fontWeight={"bold"}>
Distance
</Text>
<HStack w="80%" justify="space-between">
<FilterSection title="Max Distance" hideDivider={true}>
<HStack justify="space-between">
<Text>3km</Text>
<Text>10km</Text>
</HStack>
<Slider
min={30}
max={100}
w="80%"
aria-label="slider-ex-1"
defaultValue={range}
onChangeEnd={(val) => handleSliderChange(val)}
>
<SliderTrack>
<SliderFilledTrack />
<SliderFilledTrack background="#31979566" />
</SliderTrack>
<SliderThumb />
<SliderThumb background={COLORS.Button.primary} />
</Slider>
</VStack>
<Divider borderColor="gray.500" borderWidth="1px" />
<VStack align="flex-start" w="100%">
<Text textAlign={"left"} fontWeight={"bold"}>
Items
</Text>
<CheckboxGroup
colorScheme="blue"
defaultValue={itemState.map((item) => item.name)}
>
<Stack pl={1} spacing={3} direction={"column"}>
{selectOptions.map((item) => (
<Checkbox
onChange={(e) => handleCheckboxChange(e)}
key={item.idx}
data-key={item.idx}
value={item.value}
name={item.method}
>
{item.value}
</Checkbox>
))}
</Stack>
</CheckboxGroup>
</VStack>
</VStack>
</FilterSection>
</ModalContent>
</Modal>
);
};

function FilterSection({
title,
hideDivider,
button,
children,
}: React.PropsWithChildren<{ title: string; hideDivider?: boolean; button?: JSX.Element }>) {
return (
<Box w="100%" p={2} pb={0}>
<HStack justify="space-between" mb={3}>
<Text fontWeight={"bold"}>{title}</Text>
{button}
</HStack>
{children}
<Divider
background="gray.200"
h="1px"
marginBlock={4}
display={hideDivider ? "none" : "auto"}
/>
</Box>
);
}

type PillBoxItem = {
value: string;
method?: Methods;
isChecked: boolean;
};

const PillBox = ({
items,
handleItemSelect,
}: {
items: Array<PillBoxItem>;
handleItemSelect: (item: any) => void;
}) => {
const { getCheckboxProps } = useCheckboxGroup({
value: items.filter((item) => item.isChecked).map((item) => item.value),
});

return (
<Flex flex={1} gap={2} flexWrap="wrap" maxH="70px" overflow="auto">
{items.map((item) => (
<PillBoxItem
{...getCheckboxProps({
value: item.value,
name: item.method,
})}
onChange={handleItemSelect}
/>
))}

{items.map((item) => (
<PillBoxItem
{...getCheckboxProps({
value: item.value,
name: item.method,
})}
onChange={handleItemSelect}
/>
))}
</Flex>
);
};

const PillBoxItem = (props: CheckboxProps) => {
const { state, getInputProps, getLabelProps, htmlProps } = useCheckbox(props);

return (
<chakra.label {...htmlProps}>
<input {...getInputProps()} hidden />
<Text
bg="white"
borderRadius="full"
paddingX="10px"
paddingY="5px"
background={state.isChecked ? "#D6EAEA" : "white"}
border={state.isChecked ? "1px solid #D6EAEA" : "1px solid #D6EAEA"}
cursor="pointer"
whiteSpace="nowrap"
fontSize="12px"
{...getLabelProps()}
>
{props.value}
</Text>
</chakra.label>
);
};
33 changes: 15 additions & 18 deletions client/spa-pages/components/MapPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// General Imports
import { BasePage } from "layouts/BasePage";
import { Flex, VStack, Box, IconButton } from "@chakra-ui/react";
import { Flex, VStack, Box, IconButton, useDisclosure } from "@chakra-ui/react";
import { Dispatch, SetStateAction, useState } from "react";
import { Pages } from "spa-pages/pageEnums";
import { useUserInputs } from "hooks/useUserSelection";
Expand Down Expand Up @@ -78,7 +78,7 @@ const MapInner = ({ setPage }: Props) => {
////// States //////

// Filters
const [filterShow, setFilterShow] = useState(false);
const { isOpen: isFilterOpen, onOpen: onFilterOpen, onClose: onFilterClose } = useDisclosure();
const [range, setRange] = useState(60);
// const [isExpanded, setIsExpanded] = useState(false);

Expand Down Expand Up @@ -353,7 +353,7 @@ const MapInner = ({ setPage }: Props) => {

<MapHeaderButtons
setPage={setPage}
setFilterShow={setFilterShow}
onFilterOpen={onFilterOpen}
selectedOptions={selectedOptions}
selectOptions={selectOptions}
handleMultiselectOnChange={handleMultiselectOnChange}
Expand Down Expand Up @@ -398,18 +398,15 @@ const MapInner = ({ setPage }: Props) => {
getMatchingFacility={getMatchingFacility}
/>
)} */}
{filterShow && (
<FilterPanel
isMobile={isMobile}
setFilterShow={() => setFilterShow(true)}
filterApply={() => setFilterShow(false)}
handleSliderChange={handleSliderChange}
range={range}
itemState={itemState}
selectOptions={selectOptions}
handleCheckboxChange={handleCheckboxChange}
/>
)}
<FilterPanel
isOpen={isFilterOpen}
filterApply={() => onFilterClose()}
handleSliderChange={handleSliderChange}
range={range}
itemState={itemState}
selectOptions={selectOptions}
handleCheckboxChange={handleCheckboxChange}
/>
</BasePage>
);
};
Expand All @@ -423,15 +420,14 @@ export const MapPage = ({ setPage }: Props) => (

export const MapHeaderButtons = ({
setPage,
setFilterShow,
selectedOptions,
selectOptions,
handleMultiselectOnChange,
itemState,
handleChangedLocation,
onFilterOpen,
}: {
setPage: Dispatch<SetStateAction<Pages>>;
setFilterShow: Dispatch<SetStateAction<boolean>>;
selectedOptions: OptionType[];
selectOptions: OptionType[];
handleMultiselectOnChange: (
Expand All @@ -440,6 +436,7 @@ export const MapHeaderButtons = ({
) => void;
itemState: (TItemSelection | TEmptyItem)[];
handleChangedLocation: (itemEntry: (TItemSelection | TEmptyItem)[]) => void;
onFilterOpen: () => void;
}) => {
return (
<VStack
Expand Down Expand Up @@ -487,7 +484,7 @@ export const MapHeaderButtons = ({
handleMultiselectOnChange={handleMultiselectOnChange}
selectOptions={selectOptions}
/>
<FilterButton onClick={() => setFilterShow(true)} height="44px" />
<FilterButton onClick={onFilterOpen} height="44px" />
</Flex>
</VStack>
);
Expand Down

0 comments on commit 354dc35

Please sign in to comment.