From efc2b24d5bce3b7a5ef6ba692eefea4591c25ba1 Mon Sep 17 00:00:00 2001 From: Inga Date: Fri, 17 Nov 2023 04:57:44 +0000 Subject: [PATCH] added solution info to README --- README.md | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/README.md b/README.md index e241697..72ff0ca 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +--- +gitea: none +include_toc: true +--- + ## Assignment **Challenge** @@ -15,3 +20,72 @@ We'd expect a senior web developer to manage to complete this challenge in a few Send us the sources as a ZIP file, a link to the hosted solution ready to use, and let us know what you have learned while developing. ![design](challenge.png) + +## Solution + +As komoot website says, "[challenge] definitely is a great chance to learn something new", so I decided to try `preact` instead of `react` here, +after hearing about it from Xe Iaso (who sadly stopped development of xer Xeact). + +It was definitely an experience setting up a project with `preact` (their defaults regarding linting and typechecking are not exactly sensible), +but also the resulting bundle is just 64KB, gzipped (42 of which is Leaflet). +And all the actual code should be compatible with Facebook's `react` as well. + +Since using third-party react components is disallowed by this challenge, I only use the following third-party libraries: + +1. `preact` itself; +2. `Leaflet` (non-react package), to avoid having to integrate with OSM myself, manually, + which would take unreasonable amount of time and also not something I would look forward for); +3. `nanoid`, to generate random IDs to identify waypoints; +4. `Sortable.js` (non-react package), because there is no way in hell I'm going to try to implement drag and drop myself in a cross-platform way; I have life; +5. `@dwayneparton/geojson-to-gpx`, an unpopular but tiny (2KB) package to create gpx files + (as opposed to much more popular `gpx-builder` which is 584KB with all its dependencies); +6. `file-saver`, because implementing my own in a cross-platform way would be a waste of time. + +### How to run + +For development: `npm run dev`. + +For release build that does not require any interactivity on server, `npm run start-release` +(which lints and typechecks and tests everything, builds the project into static bundles in `dist/`, and serves static files from `dist` directory). + +### Limitations, notes + +While the original task didn't mention it, it seemed like a good idea to make markers draggable (in order to be able to change the position of an existing marker). +Alas, `Leaflet` only supports dragging natively for ordinary markers, and in order to comply with the appearance on the screenshot above, +I had to use circle markers which do not support dragging natively. +It could be implemented, but to do it in a cross-platform way and to cover all edge cases would require a lot of effort and time I didn't have, +and would make this solution much less readable. + +The original task also didn't mention how are people going to orient themselves in the marker list. +Considering that it should have drag&drop, it is an especially important matter, since they are all just called "Waypoint #number", +and presumably reordering should renumber all waypoints. +So if an user drags "Waypoint 4" in place of "Waypoint 1", the left section will not change visually, only the route on the map will change, +and this is very very confusing. +So I also added displaying of four first characters of immutable waypoint key in order to make user experience better. + +I also added "move up" and "move down" buttons for every marker, because for some people it can be much easier to use compared to drag&drop. + +The final design only remotely resembles the screenshot above, because I'm not a designer and I spent too much time on actually implementing the logic already. + +There are tests for non-`preact` code (collection-related methods and main reducer, with 100% code coverage), +but not for any react components or the app as a whole, +because dealing with map GUI automatically is difficult enough, and I didn't have nearly enough time. + +Components in this solution interact with each other via props, an alternative would be to use react contexts or redux maybe, +but the current implementation is simple enough and it works. + +Tested manually in latest Firefox, not tested in Chromium or Chromium-based browsers. + +### What I have learned + +1. That if W3C / WhatWG were not controlled by corporations, we would probably have native standard widespread easy-to-use APIs for sortable lists and file saving, + but instead we have a lot of features for advertising and other stuff that make it + [impossible](https://drewdevault.com/2020/03/18/Reckless-limitless-scope) to implement a new browser (probably on purpose) + (I didn't learn the second part, but I was unpleasantly surprised at the state of affairs with drag&drop and with file saving). +2. That the most popular library for building gpx files is also the most bloated; +3. Also this was the most `useEffect`s I've written in a while (in order to integrate with `Leaflet` and `Sortable.js`); +4. How to (relatively easy) add a map to my application (thanks to `Leaflet`); +5. How to configure application created from `preact` template to use strict eslint checking and strict typechecking + (out of the box it has no linting and no typechecking at all) + which requires, among other things, adding a bunch of explicit babel dev dependencies, + disabling jest linting and using a customized eslint-config-preact for that.