diff --git a/apps/frontend/src/components/map/Map.tsx b/apps/frontend/src/components/map/Map.tsx index 2682b35f..853d344f 100644 --- a/apps/frontend/src/components/map/Map.tsx +++ b/apps/frontend/src/components/map/Map.tsx @@ -7,6 +7,7 @@ import generateDiamondSVG from '../../images/markers/diamond'; import generateTriangleSVG from '../../images/markers/triangle'; import generateStarSVG from '../../images/markers/star'; import generatePentagonSVG from '../../images/markers/pentagon'; +import generateOtherSVG from '../../images/markers/other'; import PopupBox from '../mapIcon/PopupBox'; import { createRoot } from 'react-dom/client'; import { createPortal } from 'react-dom'; @@ -31,7 +32,9 @@ const iconGenerators = { 'Porous Paving': generateDiamondSVG, 'Tree Trench/Pit': generateStarSVG, 'Green Roof/Planter': generatePentagonSVG, - 'Other': generatePentagonSVG, + + 'Other': generateOtherSVG // Placeholder, will remove + } as const; type SymbolType = keyof typeof iconGenerators; @@ -50,7 +53,7 @@ function filterMarkers( if (selectedFeatures.length === 0) { markers.forEach((marker: google.maps.Marker) => { marker.setMap(map); - }); + }); tempMarkers = markers; } else { markers.forEach((marker: google.maps.Marker) => marker.setMap(null)); @@ -128,8 +131,18 @@ const Map: React.FC = ({ zoom, selectedFeatures, selectedStatuses }) = console.warn(`Unknown symbol type: ${symbolType}`); return; } + + + let typeColor = '#58585B'; + if (markerInfo.siteStatus === 'Available') { + typeColor = '#2D6A4F'; // Green + } else if (markerInfo.siteStatus === 'Adopted') { + typeColor = '#DFC22A'; // Yellow (match legend) + } else if (markerInfo.siteStatus === 'Inactive') { + typeColor = '#58585B'; // Gray + } + - const typeColor = markerInfo.siteStatus === 'Available' ? '#2D6A4F' : '#FB4D42'; const generateIcon = iconGenerators[symbolType]; const tempIcon = generateIcon(typeColor); const typeIcon = `data:image/svg+xml;utf8,${encodeURIComponent(tempIcon)}`; diff --git a/apps/frontend/src/components/map/MapLegend.tsx b/apps/frontend/src/components/map/MapLegend.tsx index 5e42bf69..c8d52f46 100644 --- a/apps/frontend/src/components/map/MapLegend.tsx +++ b/apps/frontend/src/components/map/MapLegend.tsx @@ -16,184 +16,99 @@ import circleSVG from '../../images/markers/circle.svg'; import diamondSVG from '../../images/markers/diamond.svg'; import starSVG from '../../images/markers/star.svg'; import pentagonSVG from '../../images/markers/pentagon.svg'; +import otherSVG from '../../images/markers/other.svg'; import { CheckboxOptionType } from 'antd/es/checkbox/Group'; +import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; + type CheckboxValueType = string | number | boolean; const Title = styled.h1` -font-size: 15px; -font-weight: bold; -font-family: Montserrat; -margin-top: 0px -margin-bottom: 0px; -color: #091F2F; -text-align: center; -`; - -const Heading = styled.h2` - color: rgba(88, 88, 91, 1); - text-align: center; - font-family: Lora; - font-size: 15px; - margin-top: 0px; - font-weight: 400; - line-height: 19px; - letter-spacing: 0em; - text-align: center; + font-size: 16px; /* Title remains 14px */ + font-weight: bold; + font-family: Montserrat; + margin-top: 10px; + margin-bottom: 5px; + color: #091F2F; + text-align: left; + padding-left: 5px; `; const MapLegendContainer = styled.div<{ isVisible: boolean }>` background: rgba(255, 253, 253, 1); - width: 247px; - gap: 20px; - padding-right: 0px; + width: 280px; position: relative; transition: height 0.3s ease; min-height: ${(props) => (props.isVisible ? '20px' : 'auto')}; - height: ${(props) => (props.isVisible ? '475px' : 'auto')}; - overflow: hidden; + max-height: ${(props) => (props.isVisible ? '600px' : 'auto')}; + overflow-y: auto; + padding-bottom: 30px; + padding: 25px 20px; `; const LegendItem = styled.div` - width: 100%; display: flex; - gap: 10px; - padding-left: 10px; align-items: center; - margin: 10px; + gap: 10px; + padding-left: 5px; + margin: 10px 0; `; const LegendImage = styled(Image)` + width: 21px; height: 20px; - width: 20px; - justify-content: center; display: inline-block; `; + const LegendText = styled.div` - margin-left: 15px; + font-family: 'Lora', serif; + font-size: 16px; /* Increased text to 16px */ + color: #000; + line-height: 1.3; `; -const FeatureContainer = styled.div` - width: 90%; - height: 284px; - margin: 10px; - padding-top: 10px; - background: rgba(242, 242, 242, 1); +const BoxedGroup = styled.div` + background-color: #F2F2F2; + padding: 8px; + margin: 10px 6px; + border-radius: 4px; + width: calc(100% - 12px); `; const StatusCheckbox = styled(Checkbox.Group)` - height: 12px; - width: 200px; - color: #fff; - border: line; - padding: 10px 20px; - cursor: pointer; - display: flex; - .ant-checkbox-checked .ant-checkbox-inner { - background-color: #e74c3c; - border-color: #e74c3c; - } -`; - -const StatusContainer = styled.div` - width: 206px; - height: 79px; - margin: 10px; - background: rgba(242, 242, 242, 1); -`; - -const StyledButton = styled.button<{ isSelected: boolean }>` - background-color: ${(props) => (props.isSelected ? '#45789C' : '#fff')}; - height: 36px; - width: 187px; - border-style: solid; - border-color: black; - padding: 10px 20px; - cursor: pointer; - font-size: 14px; - letter-spacing: 0em; - text-align: left; - align-items: center; - color: ${(props) => (props.isSelected ? '#fff' : 'rgba(24, 112, 188, 1)')}; - display: flex; - &:hover { - background-color: ${(props) => (props.isSelected ? '#45789C' : '#45789C')}; - color: ${(props) => (props.isSelected ? '#fff' : '#fff')}; - } -`; - -const StatusButton = styled.button<{ isSelected: boolean }>` - // background-color: ${(props) => (props.isSelected ? '#e74c3c' : '#fff')}; - height: 28px; - width: 187px; - // color: #fff; - border: none; - padding: 10px 20px; - cursor: pointer; - font-size: 16px; - font-family: Montserrat; - font-size: 14px; - font-weight: 600; - line-height: 17px; - letter-spacing: 0em; - text-align: center; - align-items: center; - color: rgba(40, 139, 228, 1); display: flex; + flex-direction: column; + padding-left: 5px; + gap: 5px; `; const ToggleContainer = styled.div<{ isVisible: boolean }>` cursor: pointer; - font-size: 18px; + font-size: 16px; position: absolute; - width: 247px; - height: 20px; - z-index: 1; + width: 280px; + height: 30px; display: flex; + align-items: center; justify-content: center; - background: #091f2f; + background: #0072C4; bottom: 0px; `; -const CaretDownStyled = styled(CaretDownOutlined)` - color: #ffffff; -`; - -const CaretUpStyled = styled(CaretUpOutlined)` - color: #ffffff; -`; - -const FullWidthSpace = styled(Space)` - width: 100%; -`; const statusSpan = (statusIcon: string, labelString: string): ReactNode => { + let color = '#000'; + if (labelString.toLowerCase().includes('adopted')) color = '#DFC22A'; + if (labelString.toLowerCase().includes('available')) color = '#2D6A4F'; + if (labelString.toLowerCase().includes('inactive')) color = '#58585B'; + return ( - - - - {labelString.replace(' Sites', '').toUpperCase()} + +
+ + {labelString} - + ); }; @@ -214,234 +129,143 @@ const MapLegend: React.FC = ({ }) => { const [isVisible, setIsVisible] = useState(true); - const options: CheckboxOptionType[] = SITE_STATUS_ROADMAP.map((option) => { - return { - label: statusSpan(option.image, option.label), - value: option.value, - }; + const allFeatureTypes = [ + 'Bioretention', + 'Rain Garden', + 'Bioswale', + 'Porous Paving', + 'Tree Trench/Pit', + 'Green Roof/Planter', + 'Other', + ]; + + useState(() => { + setSelectedFeatures(allFeatureTypes); + + const defaultStatus = SITE_STATUS_ROADMAP.find((s) => + s.label.toLowerCase().includes('available') + ); + if (defaultStatus) { + setSelectedStatuses([defaultStatus.value]); + } + + return; }); + const options: CheckboxOptionType[] = SITE_STATUS_ROADMAP.map((option) => ({ + label: statusSpan(option.image, option.label), + value: option.value, + })); + const toggleShowLegend = () => { setIsVisible((prev) => !prev); }; - const [availableIcon, adoptedIcon] = - icons ?? SITE_STATUS_ROADMAP.map((option) => option.image); - - const handleFeatureClick = (icon: string) => { - // Check if the icon is already selected - const isAlreadySelected = selectedFeatures.includes(icon); - - if (isAlreadySelected) { - // Deselect the icon - setSelectedFeatures((prevSelectedFeatures: string[]) => - prevSelectedFeatures.filter((selected) => selected !== icon), - ); - } else { - // Select the icon - setSelectedFeatures((prevSelectedFeatures: string[]) => [ - ...prevSelectedFeatures, - icon, - ]); - } + const handleFeatureClick = (feature: string) => { + setSelectedFeatures((prevSelected: string[]) => { + if (prevSelected.includes(feature)) { + return prevSelected.filter((f) => f !== feature); + } else { + return [...prevSelected, feature]; + } + }); }; + const CenteredIconWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 100%; +`; + const handleStatusClick = (values: CheckboxValueType[]) => { - // set selected statuses setSelectedStatuses(values); }; return ( - - -
-
- - FEATURE TYPE - - -
-
-
- Legend and Description - - + Feature Types + + {icons && ( - handleFeatureClick('Rain Garden')} - isSelected={selectedFeatures.includes('Rain Garden')} - > - - RAIN GARDEN - + handleFeatureClick('Bioretention')} /> )} + + Bioretention {icons && ( - handleFeatureClick('Bioswale')} - isSelected={selectedFeatures.includes('Bioswale')} - > - - BIOSWALE - + handleFeatureClick('Rain Garden')} /> )} + + Rain Garden {icons && ( - handleFeatureClick('Bioretention')} - isSelected={selectedFeatures.includes('Bioretention')} - > - - BIORETENTION - + handleFeatureClick('Bioswale')} /> )} + + Bioswale {icons && ( - handleFeatureClick('Porous Paving')} - isSelected={selectedFeatures.includes('Porous Paving')} - > - - POROUS PAVING - + handleFeatureClick('Porous Paving')} /> )} + + Porous Paving {icons && ( - handleFeatureClick('Tree Trench/Pit')} - isSelected={selectedFeatures.includes('Tree Trench/Pit')} - > - - TREE TRENCH/PIT - + handleFeatureClick('Tree Trench/Pit')} /> )} + + Tree Trench / Planter {icons && ( - handleFeatureClick('Green Roof/Planter')} - isSelected={selectedFeatures.includes('Green Roof/Planter')} - > - - GREEN ROOF/PLANTER - + handleFeatureClick('Green Roof/Planter')} /> )} + + Green Roof / Planter - - {icons && ( - - handleStatusClick(values as CheckboxValueType[]) - } - value={selectedStatuses} - options={options} - /> + handleFeatureClick('Other')}/> )} + + Other - + + + + Status + + + handleStatusClick(values as CheckboxValueType[])} value={selectedStatuses} options={options} /> +
+ - {isVisible ? ( - - ) : ( - - )} - + + + + +
); }; diff --git a/apps/frontend/src/images/markers/circle.svg b/apps/frontend/src/images/markers/circle.svg index e32bc76f..2eaeab55 100644 --- a/apps/frontend/src/images/markers/circle.svg +++ b/apps/frontend/src/images/markers/circle.svg @@ -1,4 +1,3 @@ - - + diff --git a/apps/frontend/src/images/markers/diamond.svg b/apps/frontend/src/images/markers/diamond.svg index 36976ed8..f900dfc8 100644 --- a/apps/frontend/src/images/markers/diamond.svg +++ b/apps/frontend/src/images/markers/diamond.svg @@ -1,4 +1,3 @@ - - + diff --git a/apps/frontend/src/images/markers/other.svg b/apps/frontend/src/images/markers/other.svg new file mode 100644 index 00000000..73cf37ce --- /dev/null +++ b/apps/frontend/src/images/markers/other.svg @@ -0,0 +1,3 @@ + + + diff --git a/apps/frontend/src/images/markers/other.tsx b/apps/frontend/src/images/markers/other.tsx new file mode 100644 index 00000000..238fbd2e --- /dev/null +++ b/apps/frontend/src/images/markers/other.tsx @@ -0,0 +1,9 @@ +export default function generateOtherSVG(color: string) { + return ` + + + + + `; +} + diff --git a/apps/frontend/src/images/markers/pentagon.svg b/apps/frontend/src/images/markers/pentagon.svg index f382372a..f05f5339 100644 --- a/apps/frontend/src/images/markers/pentagon.svg +++ b/apps/frontend/src/images/markers/pentagon.svg @@ -1,4 +1,3 @@ - - + diff --git a/apps/frontend/src/images/markers/square.svg b/apps/frontend/src/images/markers/square.svg index 44bf4fe9..1089c9ea 100644 --- a/apps/frontend/src/images/markers/square.svg +++ b/apps/frontend/src/images/markers/square.svg @@ -1,6 +1,3 @@ - - + - - diff --git a/apps/frontend/src/images/markers/star.svg b/apps/frontend/src/images/markers/star.svg index 73cf2307..d4a05521 100644 --- a/apps/frontend/src/images/markers/star.svg +++ b/apps/frontend/src/images/markers/star.svg @@ -1,4 +1,3 @@ - - + diff --git a/apps/frontend/src/images/markers/triangle.svg b/apps/frontend/src/images/markers/triangle.svg index ca69290f..00d35499 100644 --- a/apps/frontend/src/images/markers/triangle.svg +++ b/apps/frontend/src/images/markers/triangle.svg @@ -1,4 +1,3 @@ - - +