Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/218 update instructionpage #221

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/api/onemap/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { OneMapResponse } from "./types";

export const fetchAddresses = async (searchValue: string): Promise<OneMapResponse> => {
try {
const url = `https://developers.onemap.sg/commonapi/search?searchVal=${searchValue}&returnGeom=Y&getAddrDetails=Y&pageNum=1`;
const url = `https://www.onemap.gov.sg/api/common/elastic/search?searchVal=${searchValue}&returnGeom=Y&getAddrDetails=Y&pageNum=1`;
const res = await axios.get<OneMapResponse>(url, {
headers: {
Accept: "application/json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,64 @@ import { useSheetyData } from "hooks/useSheetyData";
import { AccordionDisplayProps } from ".";
import InstructionsCarousel from "./InstructionsCarousel";
import { InstructionsTag } from "./InstructionsTag";
import { useState } from "react";

const DisplayAccordion = ({ items, handleAccordionClick, recyclable }: AccordionDisplayProps) => {
const DisplayAccordion = ({ items, recyclable }: AccordionDisplayProps) => {
const { getItemCategory } = useSheetyData();
const lastIndex = items.length - 1;

// Use an array of state variables to track hover and expanded state for each accordion
const [accordionStates, setAccordionStates] = useState(
items.map(() => ({ isHovered: false, isExpanded: false })),
);
// Function to handle accordion hover
const handleAccordionHover = (index: number, isHovered: boolean, isExpanded: boolean) => {
setAccordionStates((prevState) =>
prevState.map((state, i) => ({
...state,
isHovered: i === index ? isHovered : state.isHovered,
isExpanded: i === index ? isExpanded : state.isExpanded,
})),
);
};

return (
<Accordion allowMultiple allowToggle mt={1}>
<Accordion allowMultiple mt={1}>
{items.map((item, index) => {
const category = getItemCategory(item.title);
const { isHovered, isExpanded } = accordionStates[index];
return (
<AccordionItem key={index} border={"0px"}>
<h2>
<AccordionButton
roundedTop={index === 0 ? "lg" : "none"}
roundedBottom={index === lastIndex ? "lg" : "none"}
border={"1px"}
borderTop={index !== 0 ? "0px" : "1px"}
roundedTop={index === 0 ? "md" : "none"}
roundedBottom={
!isExpanded ? (index === lastIndex ? "md" : "none") : "none"
}
// borderTop={index !== 0 ? "1px" : "0px"}
borderColor={"gray.400"}
_expanded={{ bg: "teal", color: "white" }}
onClick={() => handleAccordionClick(index)}
onClick={() => {
handleAccordionHover(index, true, !isExpanded);
}}
_hover={{ bg: "teal", color: "white" }}
onMouseEnter={() => handleAccordionHover(index, true, isExpanded)}
onMouseLeave={() => handleAccordionHover(index, false, isExpanded)}
style={{
boxShadow:
index === 0 && index !== lastIndex
? "0px -5px 6px -6px rgba(0, 0, 0, 0.25), -5px 0px 6px -6px rgba(0, 0, 0, 0.25), 5px 0px 6px -6px rgba(0, 0, 0, 0.25)"
: "1px 2px 6px 0px rgb(0,0,0, 0.25)",
}}
>
<VStack as="span" flex="1" alignItems="flex-start">
<HStack textAlign="left">
<Image
src={`/icons/${category}.png`}
src={
isHovered || isExpanded
? `/whiteicons/${category}.png`
: `/icons/${category}.png`
}
w={5}
alt={`Icon for ${category}`}
/>
Expand All @@ -47,25 +79,28 @@ const DisplayAccordion = ({ items, handleAccordionClick, recyclable }: Accordion
</AccordionButton>
</h2>
<AccordionPanel
border="1px"
borderColor={"gray.400"}
borderInline="1px"
borderColor={"teal"}
borderTop="0px"
roundedBottom={index === lastIndex ? "lg" : "none"}
borderBottom="1px"
roundedBottom="md"
bgColor={"#E0F0EF"}
px={4}
pt={4}
pb={0}
>
{recyclable ? (
item.contents && (
<Box p={4}>
<InstructionsCarousel items={item.contents} />
<Box>
{recyclable ? (
item.contents && <InstructionsCarousel items={item.contents} />
) : (
<Box pb={5}>
<Text as={"b"}>Why cannot recycle?</Text>
<Text mb={5}>{item.reason}</Text>
<Text as={"b"}>How to dispose properly?</Text>
<Text>{item.suggestion}</Text>
</Box>
)
) : (
<Box p={4}>
<Text as={"b"}>Why cannot recycle?</Text>
<Text mb={5}>{item.reason}</Text>
<Text as={"b"}>How to dispose properly?</Text>
<Text>{item.suggestion}</Text>
</Box>
)}
)}
</Box>
</AccordionPanel>
</AccordionItem>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Box, Button, Center, Flex, Text } from "@chakra-ui/react";
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
import { useState } from "react";

import { Carousel } from "react-responsive-carousel";
import "react-responsive-carousel/lib/styles/carousel.min.css";
import styles from "components/pickup/carousel.module.css";
import { SLIDES_INTERVAL_TIME } from "components/pickup/PickupCarousel";
const InstructionsCarousel = ({ items }: { items: string[] }) => {
const [currentIndex, setCurrentIndex] = useState(0);

Expand All @@ -14,24 +17,40 @@ const InstructionsCarousel = ({ items }: { items: string[] }) => {
};

return (
<>
<Flex align="center">
<Box flexGrow={1}>
<Text as="b" fontSize="lg">
Step {items.indexOf(items[currentIndex]) + 1} of {items.length}
</Text>
<Text>{items[currentIndex]}</Text>
</Box>
</Flex>
<Center>
<Button onClick={handlePrevClick} m={2}>
<ChevronLeftIcon />
</Button>
<Button onClick={handleNextClick} m={2}>
<ChevronRightIcon />
</Button>
</Center>
</>
<Carousel
showThumbs={false}
showStatus={false}
showArrows={false}
autoPlay
infiniteLoop
interval={SLIDES_INTERVAL_TIME}
renderIndicator={(clickHandler, isSelected, index) => {
return (
<li
onClick={clickHandler}
key={index}
role="button"
className={isSelected ? `${styles.ind} ${styles.active}` : styles.ind}
/>
);
}}
>
{items.map((item, idx) => {
return (
<Flex align="center" pb={10} key={idx}>
<Box flexGrow={1} width={"100%"}>
<Text textAlign={"left"}>
<Text as="b" fontSize="lg">
Step {idx + 1} of {items.length}
</Text>
</Text>

<Text textAlign={"left"}>{item}</Text>
</Box>
</Flex>
);
})}
</Carousel>
);
};

Expand Down
19 changes: 2 additions & 17 deletions client/components/instructions/InstructionsAccordion/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import DisplayAccordion from "./DisplayAccordion";

export type AccordionDisplayProps = {
items: AccordionProps[];
handleAccordionClick: (index: number) => void;
recyclable: boolean;
};

Expand All @@ -22,12 +21,6 @@ export type AccordionsProps = {
};

export const AccordionComp: React.FC<AccordionsProps> = ({ items }) => {
const [activeIndex, setActiveIndex] = useState<number | null>(null);

const handleAccordionClick = (index: number) => {
setActiveIndex((prevIndex) => (prevIndex === index ? null : index));
};

const unrecyclableItems = [] as AccordionProps[];
const recyclableItems = items.filter((item) => {
if (item.method === Methods.THROW) {
Expand All @@ -46,11 +39,7 @@ export const AccordionComp: React.FC<AccordionsProps> = ({ items }) => {
</Text>

{/* Non-recyclable accordion */}
<DisplayAccordion
items={unrecyclableItems}
handleAccordionClick={handleAccordionClick}
recyclable={false}
/>
<DisplayAccordion items={unrecyclableItems} recyclable={false} />
</Box>
)}
{recyclableItems.length > 0 && (
Expand All @@ -60,11 +49,7 @@ export const AccordionComp: React.FC<AccordionsProps> = ({ items }) => {
</Text>

{/* Recyclable accordion */}
<DisplayAccordion
items={recyclableItems}
handleAccordionClick={handleAccordionClick}
recyclable={true}
/>
<DisplayAccordion items={recyclableItems} recyclable={true} />
</Box>
)}
</>
Expand Down
10 changes: 1 addition & 9 deletions client/components/instructions/InstructionsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,13 @@ export const InstructionsHeader = ({ setPage }: Props) => {
<Box my={5}>
<HStack px={2} justifyContent={"space-between"} gap={5}>
<Button
w={"50%"}
w={"20%"}
leftIcon={<ArrowBackIcon />}
onClick={() => setPage(Pages.HOME)}
colorScheme="teal"
>
Back
</Button>
<Button
w={"50%"}
leftIcon={<RepeatIcon />}
onClick={() => setPage(Pages.HOME)}
colorScheme="teal"
>
Restart
</Button>
</HStack>
</Box>
);
Expand Down
31 changes: 22 additions & 9 deletions client/components/map/FilterPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { TItemSelection, TEmptyItem } from "app-context/SheetyContext/types";
import { OptionType } from "spa-pages";
import React, { ChangeEvent, PropsWithChildren } from "react";
import { Methods } from "api/sheety/enums";
import { useSheetyData } from "hooks/useSheetyData";

type FilterProps = {
isOpen: boolean;
Expand Down Expand Up @@ -79,9 +80,10 @@ export const FilterPanel = ({
/>
</FilterSection>

<FilterSection title="Sort by">
{/* Implementation still in consideration... */}
{/* <FilterSection title="Sort by">
<ChipRadioGroup items={["Nearest", "Most items"]} />
</FilterSection>
</FilterSection> */}

<FilterSection title="Max Distance" hideDivider={true}>
<HStack justify="space-between">
Expand Down Expand Up @@ -176,7 +178,9 @@ const ChipCheckbox = (props: CheckboxProps) => {
return (
<chakra.label {...htmlProps}>
<input {...getInputProps()} hidden />
<Chip isChecked={state.isChecked}>{props.value}</Chip>
<Chip value={props.value as string} isChecked={state.isChecked}>
{props.value}
</Chip>
</chakra.label>
);
};
Expand Down Expand Up @@ -219,15 +223,18 @@ const ChipRadio = (props: PropsWithChildren<UseRadioProps>) => {
};

const Chip = ({
value,
children,
isChecked,
darkBackground,
}: React.PropsWithChildren<{ isChecked: boolean; darkBackground?: boolean }>) => {
}: React.PropsWithChildren<{ isChecked: boolean; darkBackground?: boolean; value?: string }>) => {
const selectedColor = darkBackground ? "teal.500" : "teal.50";
const selectedTextColor = darkBackground ? "white" : "black";

const { getItemCategory } = useSheetyData();
const category = getItemCategory(value as string);
return (
<Text
<Flex
align="center"
bg="white"
borderRadius="full"
paddingX="10px"
Expand All @@ -237,9 +244,15 @@ const Chip = ({
border="1px solid #D6EAEA"
cursor="pointer"
whiteSpace="nowrap"
fontSize="12px"
>
{children}
</Text>
{category && (
<img
src={`/icons/${category}.png`}
alt={`${category} icon`}
style={{ width: "15px", height: "15px", marginRight: "8px" }}
/>
)}
<Text fontSize="12px">{children}</Text>
</Flex>
);
};
17 changes: 12 additions & 5 deletions client/components/map/Marker/MarkerIconWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,18 @@ const MarkerIconWrapper = ({
{label && <Text className="marker-text">{label}</Text>}

{category && (
<Image
className="marker-image"
src={`/icons/${category}.png`}
alt={`${category} icon`}
/>
<>
<Image
className="marker-circle"
src={"/blueicons/icon_circle.png"}
alt="Circle behind category icon"
/>
<Image
className="marker-image"
src={`/blueicons/${category}.png`}
alt={`${category} icon`}
/>
</>
)}
</Box>
);
Expand Down
Loading
Loading