This project was bootstrapped with Create React App.
npm start
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
npm test
Launches the test runner in the interactive watch mode.
npm run build
Builds the app for production to the build
folder.
It's ready to be deployed
npm run deploy
Deploys app to github pages
npm run prettier
Runs prettier which will autofix codebase
To create SPA that renders one of the dashbird pages with ETA 5-8 hours
Main tasks:
- Set up a page layout and title
- Add tabs that contain the latest metric information and nonactive ones have sparkline.
- Add main chart with 3 different data series (negative bars, positive bars and line)
- Show chart legend and metrics under it. Main metric needs to be changing on the tab
Bonus tasks:
- Use Redux to manage state
- Add zoom to chart
- Add datetime picker (only partially workable)
- Use remote API
Extra:
- Loading states
- Ability to switch tabs and see different charts
I've used to React for view layer because it is flexible, simple, and able to provide good abstraction together with good performance. For state management I've chosen Flux architecture (it's cut Redux implementation), because it has one-way data flow, one centralized store, simple API, large community - a good fit for dashboard application. Also create-react-app able to generate project pretty fast, which will save some time. Also, DashBird uses react + redux in their day to day work, so it will be easier to assess test task as it is closer to real life.
In the beginning, I planned to use TDD, but after a deeper analysis of the task, I decided to skip tests almost fully in order to save some extra time and meet the deadline. I have all infra ready from create-react-app and 1 test that renders the whole app.
I decided to use typescript, it allows us to make code easier to maintain and understand, also it helps to prevent some bugs on compile step. Alternative to typescript can be TDD, with TDD we can stop worrying about most of the bugs that can be handled by TS, but sadly I did not have enough time to solve tasks in TDD way.
With bigger application, I usually prefer feature-folder approach to structure the codebase. But as the task is pretty small, I separated code by function. It will allow me in future easialy migrate to feature-folder structure, where components, rdx, styles, api leaves near to each other.
|-- public
|-- src
|---- api // data fetching logic and types
|---- state // all redux state management
|---- hooks // global custom react hooks
|---- components // reusable components
|---- widgets // main logic blocks of the app
I created a folder called api
where I have types.ts
- it contains type information about all data layer - in real life this type will be imported from server code (or generated by server team).
Inside index.ts
file I have created functions per each entity, these type-safe functions fetch and load data from the server.
In order to save some time, I decided to not use real external API. I emulated it by putting JSON files in to public
folder. These files are loaded in a way that would emulate real API, and in case I would decide to migrate to use expternal API in the furure it would be pretty easy to do.
For state management I decided to use redux
. Everything related to it lives in state
folder. Inside it, I used feature sub-folders, that emulate state structure – the idea is that we have sub-reducer, sub-actions, sub-selectors per feature.
Currently there are widgets and charts, these are two independent sub-feature inside redux with own sub-reducer, sub-actions, sub-selectors - it allows us to simplify readability and allows us to work with features in an easier way (smaller files, abstracted code).
For side effects, I decided to use redux-thunk
as most of our requests pretty simple. But everything structured in a way that it is easy to migrate to redux-observable or redux-saga in the future, if side-effects become more complex.
Main logic bloecks of the app live in widgets
folder. I put here the main logic blocks of the app - like widget for charts, widget for insights, etc. The idea is that widgets are more "smart" components, use async redux actions to fetch data,
then select this data, contain some business logic and redistribute all data to children. All non-reusable components and helper functions that widgets use, are structured within the widget folder. This way it is easier to develop new functionality, as all the code is very close.
I did some research of available component libraries, that couple be used for the task. I considered material-ui
, ant
and reach-ui
.
I decided not to use a pre-made components library. Here's why:
- They can increase the complexity of a small project, as to create a UI close to design I would need to interfere with the library's code
- Not everyone is familiar with the libabry I would choose, and with any of those there's some libabry-specific knowledge that can make code harder to understand
- The benefit for 1-page layout would be relatively small
- For you, as a reviewer, it would be easier to assess my coding skills
Most styles are implemented from scratch with SASS and css modules (built in create-react-app). I activly used css-grid and scss variables to make better and consistent layouts.
It is always hard to add intl support at the end, so I added react-intl in the begining as show case how it can be implemented. Also, as the Dashbird application can have users from different countries, I thought that it would be great for you to see how I am able to solve it. More about motivation you can read here
After short research, I decided to go with recharts (new library for me). Motivation:
- they are svg based, so it is easier to do some hacks to achieve the needed design and UX
- they have nice, extensible and understandable API
- they have good enough performance
For code style I am using prettier and eslint from create-react-app.
- Icons made by Those Icons from Flaticon
- rechats - charts lib for react
- date-fns
- typesafe-actions
Known issues:
1. No intermediate vertical ticks on xAxis for queue size chart I decided not to implement them to fit into the deadline. Overall, I know how to implement them and it would take additional 1 hour.
2. Missed part of functionality for date picker Datepicker works only visually. I did not add a logic that would filter out the chart and re-build it. Ideally, it should filter the chart if the date interval within current one, and fetch data if it is ouside.
3. Design difference There is some design differences with the mockup. For example, icons are not the same and some differences in spacing and chart are there as well.
4. Accessibility Unfortunately, I did not have time to make application fully accessible and test the accessibility. Where possible I tried to keep it in mind, but there's still a lot to improve
5. Code duplication Especially, in the chart functionality, there's a lot of code being duplicated. Ideally, I would love to extract some reused code outside.
6. Hardcoded values Somewhere in the code and CSS I have hardcoded values.
7. Inconsistent color palette Unfortunately, I was not able to find Dashbird's design system that I could follow. So in a lot of cases there are some assumprions or inconsistyent colors.
8. Only 1 test As I said before, I made a decision not to cover functionality with tests. But if it was a real life application, I would most definitely cover at least the main user flows with tests.
9. Fake API Currently fake API is used. Ideally, I would love to use a real API with data, but I could not find anything that is close enough quickly, so settled with the mocked API
10. Some minor bugs I have tested the flow and tried to fix all the issues. But there's definitely some bugs that I have missed.
Improvements:
- I'd like to have more tests and better overall coverage
- Use real API
- Finish calendar, so it would change the chart data
- Make design more coherent
- Add documentation on components
- Better loading states
ETA 5-8 hours
- Research - 1.5 hours
- General layout - 1 hours
- Workable charts and tab - 2 hours
- Fixing prototype according to requirments + other functionality(like calendar) - 4 hours
- Cleanup and refactoring 1 hour
- Readme - 0.5 hour
Total: 10 hours