Skip to content

Commit

Permalink
Removed unused dependency
Browse files Browse the repository at this point in the history
  • Loading branch information
TheNaubit committed Nov 18, 2022
1 parent 585b253 commit da77a6f
Show file tree
Hide file tree
Showing 34 changed files with 1,386 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# .npmrc
engine-strict=true
10 changes: 10 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules
# Ignore artifacts:
build
coverage
.gitignore
.npmrc
.prettierignore
yarn.lock
package-lock.json
pnpm-lock.json
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
21 changes: 21 additions & 0 deletions craco.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import path from "path";

const config = {
webpack: {
alias: {
"@assets": path.resolve(__dirname, "src/assets"),
"@styles": path.resolve(__dirname, "src/styles"),
"@utils": path.resolve(__dirname, "src/utils"),
"@components": path.resolve(__dirname, "src/components"),
"@pages": path.resolve(__dirname, "src/pages"),
"@constants": path.resolve(__dirname, "src/constants.ts"),
"@types": path.resolve(__dirname, "src/types"),
"@api": path.resolve(__dirname, "src/api"),
"@hooks": path.resolve(__dirname, "src/hooks"),
"@theme": path.resolve(__dirname, "src/theme.ts"),
"@contexts": path.resolve(__dirname, "src/contexts"),
},
},
};

export default config;
12 changes: 12 additions & 0 deletions prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"semi": true,
"printWidth": 70,
"tabWidth": 2,
"singleQuote": true,
"bracketSpacing": true,
"jsxBracketSameLine": false,
"useTabs": false,
"arrowParens": "avoid",
"jsxSingleQuote": true,
"trailingComma": "all"
}
1 change: 1 addition & 0 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./usersAPI";
17 changes: 17 additions & 0 deletions src/api/usersAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { BASE_USERS_API_URL } from "@constants";
import axios from "axios";
import { IRandomUserResponse } from "types/user";
import urlcat from "urlcat";

/**
* It takes an object with a property called `results` that is a number (the number of random users to
* get from the server), and returns a promise that
* resolves to an object with a property called `results` that is an array of objects (IUser objects)
* @param - results - the number of users to return
* @returns An object with a property called data that is of type IRandomUserResponse
*/
export function getRandomUsers({ results = 1 }: { results?: number }) {
const queryURL = urlcat(BASE_USERS_API_URL, `/`, { results });

return axios.get(queryURL).then((res) => res.data as IRandomUserResponse);
}
1 change: 1 addition & 0 deletions src/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/marker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/marker_active.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 69 additions & 0 deletions src/components/AlertDialog/AlertDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import {
Dialog,
DialogContent,
DialogContentText,
DialogActions,
Button,
} from "@mui/material";
import { useMemo } from "react";

interface IAlertDialog {
text: string;
isOpen: boolean;
onCancel?: () => void;
onContinue?: () => void;
btnCancelText?: string;
btnContinueText?: string;
}

/**
* AlertDialog is a function that returns a Material UI Dialog component that displays a message and
* two buttons
* @param {IAlertDialog} - IAlertDialog
* @returns A React component.
*/
export function AlertDialog({
text,
isOpen,
onCancel,
onContinue,
btnCancelText,
btnContinueText,
}: IAlertDialog) {
/**
* _handleOnClickCancel() is a function that calls the onCancel prop if onCancel is a function.
*/
function _handleOnClickCancel() {
if (typeof onCancel === "function") onCancel();
}

/**
* _handleOnClickContinue() is a function that calls the onContinue prop if it is a function.
*/
function _handleOnClickContinue() {
if (typeof onContinue === "function") onContinue();
}

const _btnTextCancel = useMemo(
() => btnCancelText ?? "Cancel",
[btnCancelText]
);
const _btnTextContinue = useMemo(
() => btnContinueText ?? "Continue",
[btnContinueText]
);

return (
<Dialog open={isOpen} onClose={_handleOnClickCancel}>
<DialogContent>
<DialogContentText>{text}</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={_handleOnClickCancel}>{_btnTextCancel}</Button>
<Button onClick={_handleOnClickContinue} autoFocus>
{_btnTextContinue}
</Button>
</DialogActions>
</Dialog>
);
}
1 change: 1 addition & 0 deletions src/components/AlertDialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./AlertDialog";
166 changes: 166 additions & 0 deletions src/components/OLMap/OLMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { useEffect, useMemo, useRef } from "react";
import Map from "ol/Map";
import View from "ol/View";
import "../../../node_modules/ol/ol.css";
import { Box } from "@mui/material";
import TileLayer from "ol/layer/Tile";
import OSM from "ol/source/OSM";
import VectorLayer from "ol/layer/Vector";
import VectorSource from "ol/source/Vector";
import { Feature } from "ol";
import { Point } from "ol/geom";
import { fromLonLat } from "ol/proj";
import Style from "ol/style/Style";
import Icon from "ol/style/Icon";

import markerImage from "@assets/marker.png";
import markerActiveImage from "@assets/marker_active.png";

import { IUserPoint } from "@types";
import {
useMap,
useMapCenter,
useMapUserPoints,
useMapZoom,
} from "@hooks/mapContext";

/**
* It creates a map, sets it in the context, and updates it when the context changes
* @param - `children`: the (optional) children JSX Elements.
* @returns A box with a map inside of it.
*/
export const OLMap = ({ children }: { children?: JSX.Element }) => {
const { map, setMap } = useMap();
const { userPoints: mapUserPoints } = useMapUserPoints();
const { zoom: mapZoom } = useMapZoom();
const { center: mapCenter } = useMapCenter();

const mapId = useRef();

/* A memoized version of the selected user points. */
const selectedUserPoints: Array<IUserPoint> = useMemo(
() => mapUserPoints.filter((mapUserPoint) => mapUserPoint.isSelected),
[mapUserPoints]
);

/* A memoized version of the non-selected user points. */
const nonSelectedUserPoints: Array<IUserPoint> = useMemo(
() => mapUserPoints.filter((mapUserPoint) => !mapUserPoint.isSelected),
[mapUserPoints]
);

/* An effect to animate zoom and center changes in the map. */
useEffect(() => {
map.getView().animate({
zoom: mapZoom,
center: fromLonLat(mapCenter),
duration: 500,
});
}, [mapZoom, mapCenter, map]);

/** An effect somewhat tricky to update the map vector points based on the
* updated user points in a performant way (avoiding full re-renders when possible
* by updating only the modified points). */
useEffect(() => {
if (map.getAllLayers().length < 3) return;

const _layers = map.getAllLayers();

const selectedUsersLayerSource = (
_layers[1] as VectorLayer<VectorSource<Point>>
).getSource();

selectedUsersLayerSource?.clear();
selectedUsersLayerSource?.addFeatures(
selectedUserPoints.map(
(point) =>
new Feature({
geometry: new Point(fromLonLat(point.position)),
})
)
);
selectedUsersLayerSource?.changed();

const nonSelectedUsersLayerSource = (
_layers[2] as VectorLayer<VectorSource<Point>>
).getSource();
nonSelectedUsersLayerSource?.clear();
nonSelectedUsersLayerSource?.addFeatures(
nonSelectedUserPoints.map(
(point) =>
new Feature({
geometry: new Point(fromLonLat(point.position)),
})
)
);
nonSelectedUsersLayerSource?.changed();
}, [selectedUserPoints, nonSelectedUserPoints, map]);

/** This is the effect that creates the map var and sets it in the context.
* It will be triggered only if the context's map is null, to avoid re-renders
* and other issues.
*/
useEffect(() => {
const theMap = new Map({
layers: [
new TileLayer({
source: new OSM(),
}),
new VectorLayer({
source: new VectorSource({
features: [],
}),
style: new Style({
image: new Icon({
scale: 0.3,
anchor: [0.5, 0],
anchorOrigin: "bottom-left",
anchorXUnits: "fraction",
anchorYUnits: "pixels",
src: markerActiveImage,
}),
}),
}),
new VectorLayer({
source: new VectorSource({
features: [],
}),
style: new Style({
image: new Icon({
scale: 0.3,
anchor: [0.5, 0],
opacity: 1,
anchorOrigin: "bottom-left",
anchorXUnits: "fraction",
anchorYUnits: "pixels",
src: markerImage,
}),
}),
}),
],
view: new View({
center: mapCenter,
zoom: mapZoom,
}),
});
theMap.setTarget(mapId.current);
setMap(theMap);

return () => {
if (!theMap) return;
theMap.setTarget(undefined);
setMap(new Map());
};
// We disable here the eslint rule for exhaustive-deps since we only want this effect to be triggered
// when the component is mounted for the first time. So even if the linter recommends to add some
// dependencies to the useEffect, we don't really want to do it. And since I don't like to have useless
// warnings, we disable the rule for that line.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<Box ref={mapId} width="100%" height="100vh">
{children}
</Box>
);
};
1 change: 1 addition & 0 deletions src/components/OLMap/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./OLMap";
Loading

0 comments on commit da77a6f

Please sign in to comment.