Skip to content

Design Patterns

Sven Ligensa edited this page Aug 20, 2024 · 2 revisions

This section details some programming patterns occurring repeatedly in the code.

localStorage

The localStorage is used to store data on the client side and is used for the following attributes:

  1. authToken: Sent in the Authorization field of the header in requests to the API. It is set upon login and afterwards needed for every single query.
  2. projectId: Stores the ID of the current project for further requests.
  3. cityName: Used to construct the correct URL.
  4. projectType: Used for conditional rendering.
  5. email: Used to display email in Settings page. (Remark: Better to fetch it from the backend)

Fetching Data From Backend

All requests are made in a useEffect hook, which does not depend on any other state, i.e., it is executed when the component mounts. When fetching any data, the authToken has to be included in the request. Data successfully fetched from the backend is stored in the component's state (via useState). The handling of responses indicating that an error occurred in the request should be improved.

Conditional Rendering of Components

Some components take longer when loading, e.g., because data has to be fetched from the backend. While this still takes time, the rest of the page (showing data which has already been loaded) can already be displayed. As a placeholder, the LoadingComponent is rendered, while the data is not fetched.

Checking whether the data has been loaded can be done by having a loading state, which is initially true and set to false when the request to the backend succeeded. The loading component is then rendered via: if (loading) return <LoadingComponent />

Another way is to check whether another state, which should be updated by the request, is still null/undefined and conditionally render depending on that. An example can be found in the file for rendering the Map page (/app/projects/[city]/trash/map/page.tsx), where the rendering of the Map component depends on the existence of centerCoordinates, initialZoom, fillThresholds, and batteryThresholds, which are set after querying the values from the backend.

Tooltips

Tooltips contain additional information which appears when hovering over a specific area. They are implemented via giving the CSS class info-tooltip to the element which the user can hover over, and the class info-tooltip-text to the element which should be shown on hover. For graphics, the class chart-tooltip is used, which is styled a bit differently.

Graphics

The LineChart and NoiseChart commponent are structured very similarly. They define a D3 chart, which is rendered as an SVG element. The yAxis is "detached" so that it is visible regardless of the scroll of the graphic. The graphic is scrolled to the right (newest data), when it is mounted. Dynamic loading of data is not supported, we always fetch the whole history.

The Heatmap component is implemented as a React component which was inspired by https://www.react-graph-gallery.com/heatmap. The components HeatmapFillLevel and HeatmapBatteryLevel are only used for generating different mock data, so they will be obsolete and can be replaced by Heatmap, when the real data is fetched from the backend.

Map

The Map component is used twice, in the Map and Route Planning page. Its behavior is determined by the MapProps, which are passed to the component upon initialization. It includes the trashbinData (coordinates, fill level, etc. of all trashbins to be displayed), centerCoordinates (coordinates where the map is centered on), initialZoom (initial zoom level of the map), fillThresholds (when to display the bins as green, yellow, or red), batteryThresholds (when to display the battery level as green, yellow, or red), onTrashbinClick (what should happen, when the user clicks on the trashbin), and isRoutePlanning (whether we are in route planning mode or not). Further attributes, which are only set when isRoutePlanning is true are tripStartEnd (where the roundtrip to empty the bins starts and ends), selectedBins (which bins are currently selected for the route to be optimized), optimizedBins (selectedBins in the optimized order, which is computed by solving the TSP problem with help of the Open Source Routing Machine (OSRM)), and showRoute (indicating whether the optimal route should be shown on the map).

Clone this wiki locally