Skip to content

Commit

Permalink
Merge pull request #221 from bettersg/feature/218-update-instructionpage
Browse files Browse the repository at this point in the history
Feature/218 update instructionpage
  • Loading branch information
neozhixuan authored Dec 21, 2023
2 parents a91aacb + 109f6b7 commit f3e2660
Show file tree
Hide file tree
Showing 104 changed files with 362 additions and 182 deletions.
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

0 comments on commit f3e2660

Please sign in to comment.