Skip to content

Commit

Permalink
dropdown to
Browse files Browse the repository at this point in the history
 radio for map view + comments added & minor bu
g fixes
  • Loading branch information
jamesdoh0109 committed Dec 22, 2024
1 parent a4b8ff1 commit 896e9ec
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 210 deletions.
41 changes: 24 additions & 17 deletions frontend/plan/components/map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function toDegrees(radians: number): number {
return radians * (180 / Math.PI);
}

// calculate the center of all locations on the map view to center the map
function getGeographicCenter(
locations: Location[]
): [number, number] {
Expand All @@ -38,46 +39,52 @@ function getGeographicCenter(
y /= total;
z /= total;

const centralLongitude = Math.atan2(y, x);
const centralLongitude = toDegrees(Math.atan2(y, x));
const centralSquareRoot = Math.sqrt(x * x + y * y);
const centralLatitude = Math.atan2(z, centralSquareRoot);
const centralLatitude = toDegrees(Math.atan2(z, centralSquareRoot));

return [toDegrees(centralLatitude), toDegrees(centralLongitude)];
return [centralLatitude ? centralLatitude : 39.9515, centralLongitude ? centralLongitude : -75.1910];
}

function separateOverlappingPoints(points: Location[], offset = 0.0001) {
const validPoints = points.filter((p) => p.lat !== null && p.lng !== null) as Location[];

// group points by coordinates
const groupedPoints: Record<string, Location[]> = validPoints.reduce((acc, point) => {
const groupedPoints: Record<string, Location[]> = {};
validPoints.forEach((point) => {
const key = `${point.lat},${point.lng}`;
(acc[key] ||= []).push(point);
return acc;
}, {} as Record<string, Location[]>);
(groupedPoints[key] ||= []).push(point);
});

// adjust overlapping points
const adjustedPoints = Object.values(groupedPoints).flatMap((group) =>
group.length === 1
? group
? group // no adjustment needed if class in map view doesnt share locations with others
: group.map((point, index) => {
const angle = (2 * Math.PI * index) / group.length;
return {
...point,
lat: point.lat! + offset * Math.cos(angle),
lng: point.lng! + offset * Math.sin(angle),
};
})
/*
At a high level, if there are multiple classes in map view that have the exact same location,
we try to evenly distribute them around a "circle" centered on the original location.
The size of the circle is determined by offset.
*/
const angle = (2 * Math.PI * index) / group.length;
return {
...point,
lat: point.lat! + offset * Math.cos(angle),
lng: point.lng! + offset * Math.sin(angle),
};
})
);

// include points with null values
return [...adjustedPoints, ...points.filter((p) => p.lat === null || p.lng === null)];
return adjustedPoints;
}

interface InnerMapProps {
locations: Location[];
center: [number, number]
}

// need inner child component to use useMap hook to run on client
function InnerMap({ locations, center } :InnerMapProps) {
const map = useMap();

Expand All @@ -101,7 +108,7 @@ function InnerMap({ locations, center } :InnerMapProps) {
}

function Map({ locations, zoom }: MapProps) {
const center = getGeographicCenter(locations)
const center = getGeographicCenter(locations);

return (
<MapContainer
Expand Down
58 changes: 27 additions & 31 deletions frontend/plan/components/map/MapCourseItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import styled from "styled-components";
import { isMobile } from "react-device-detect";

const CourseCartItem = styled.div<{ $isMobile: boolean }>`
const CourseCartItem = styled.div<{
$isMobile: boolean;
$hasLocationData: boolean;
}>`
background: white;
transition: 250ms ease background;
cursor: pointer;
Expand All @@ -24,10 +27,13 @@ const CourseCartItem = styled.div<{ $isMobile: boolean }>`
&:hover i {
color: #d3d3d8;
}
${({ $hasLocationData }) =>
!$hasLocationData &&
`
opacity: 0.5;
`}
`;

const CourseDetailsContainer = styled.div``;

const Dot = styled.span<{ $color: string }>`
height: 5px;
width: 5px;
Expand All @@ -42,7 +48,7 @@ interface CourseDetailsProps {
start: number;
end: number;
room: string;
overlap: boolean;
hasLocationData: boolean;
}

const getTimeString = (start: number, end: number) => {
Expand All @@ -67,35 +73,24 @@ const CourseDetails = ({
start,
end,
room,
overlap,
hasLocationData,
}: CourseDetailsProps) => (
<CourseDetailsContainer>
<div>
<b>
<span>{id.replace(/-/g, " ")}</span>
</b>
<div style={{ fontSize: "0.8rem" }}>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div>
{overlap && (
<div className="popover is-popover-right">
<i
style={{
paddingRight: "5px",
color: "#c6c6c6",
}}
className="fas fa-calendar-times"
/>
<span className="popover-content">
Conflicts with schedule!
</span>
</div>
)}
{getTimeString(start, end)}
</div>
<div>{room ? room : "No room data"}</div>
</div>

<div
style={{
display: "flex",
fontSize: "0.8rem",
}}
>
<div>{getTimeString(start, end)}</div>
&nbsp;&nbsp;
<div>{room && hasLocationData ? room : "No room data"}</div>
</div>
</CourseDetailsContainer>
</div>
);

interface CartSectionProps {
Expand All @@ -104,7 +99,7 @@ interface CartSectionProps {
start: number;
end: number;
room: string;
overlap: boolean;
hasLocationData: boolean;
focusSection: (id: string) => void;
}

Expand All @@ -114,7 +109,7 @@ function MapCourseItem({
start,
end,
room,
overlap,
hasLocationData,
focusSection,
}: CartSectionProps) {
return (
Expand All @@ -123,6 +118,7 @@ function MapCourseItem({
id={id}
aria-checked="false"
$isMobile={isMobile}
$hasLocationData={hasLocationData}
onClick={() => {
const split = id.split("-");
focusSection(`${split[0]}-${split[1]}`);
Expand All @@ -134,7 +130,7 @@ function MapCourseItem({
start={start}
end={end}
room={room}
overlap={overlap}
hasLocationData={hasLocationData}
/>
</CourseCartItem>
);
Expand Down
143 changes: 0 additions & 143 deletions frontend/plan/components/map/MapDropdown.tsx

This file was deleted.

Loading

0 comments on commit 896e9ec

Please sign in to comment.