Introduction

I would like to thank you beforehand for your time and patience to read this big chunk of text, and also to apologize for writing this much.
Although being very short in time, less than three days total, it was a wonderful experience to exercise and play using this little project! I hope you enjoy (:

Project Description

How to run

npm install
npm run dev

General-Purpose

Even having a limited scope to act upon, from what I can see it's very unlikely that you would have an app that would render just a screen, and would have a single functionality like this. Having this in mind, I designed the app architecture to resemble more a real App, by this meaning that scalability and reusability were taken in accountability.

Design

Ideally, in a rainbow-colored world (<3), it would be needed to study the desired image that we would want to promote to our customers, and then decide visual identity to back-up the App. But, as I know my time is short, and the purpose of this test isn't necessarily to test my UI designing skills, I got the colors and general feeling inspiration directly from Marvel's website (https://www.marvel.com/) :D

Pages

The app ended up with two pages:

Characters List (/characters):

The list of Marvel characters.
Images

  • The user can search with text and the page has also pagination.
  • The search and pagination are maintained between route navigation.
  • Every time some search is performed, the app store the search parameters inside the store. In the next search, if the sent parameters are the same, the app will avoid performing the same search and will just return the stored values.

    This wouldn't work well in a scope where more volatile data would need to be updated constantly.

  • When the user clicks inside a card, he'll be redirected to the Character page

View Character (/characters/:characterId)

Here the user will have access to the basic characters basic info (name, description, and thumbnail), and also Comics, Series, Events, and Stories related to that character.
Images

  • Each section of the page loads independently
  • If you access the same character two times, the App will recognize it by the id and will avoid fetching all the data once again.
  • When the user clicks inside some of the cards linked to the character, the App will open a new tab aimed to some url containing details of this resource. This data is retrieved from Marvel's API.

Folder Structure

SRC - front-end

Disclaimers

  • I've chosen to build the folder structure to group files by domain/feature standard. In my opinion, it isolates better the possible unwanted outcomes when updating code, as related files are grouped and the programmer can check them easily. Also, it makes much easier to organize integration and also unit testing.
  • I put a package.json file attached to every component with a {main:"<filename>"} config inside them, just to be able to import the components directly by the folder's path. I find a little annoying to specify the filename two times, every time.

    I could've done this naming each main JSX file as index.js but, this way, I easily get lost among the files while debugging

CSS structure

I'm fond of the practice of the component as an autonomous unit inside the application. To achieve this, I decided to make use of the package styled-components, as it would make it possible to isolate my components completely and I would also be able to make use of SCSS features inside it.

  • If I had more time, I would like to put all colors and common styles inside the ~/assets/styles/theme to access them dinamically and make it easier to modify the whole app design easier.

Testing

Unfortunately, as already pointed out tha my time ran short, I didn't manage to build the component tests in time. :,(
Anyways, I'll continue to finish them after delivering this version.


src/containers

In this folder, I decided to put components that would be data-heavy, manipulate a lot of data, and wouldn't be focused on presentational and styling roles. In the end, they ended up holding my two app "pages".


src/components

Here I put the "presentational" components. Components that don't manipulate data but hold most of the styling of the app.


src/store: Redux store structure

  • For the folders, I separated the concerns using the domain/feature folders standard.
  • For the files inside the feature folder, I used the redux "ducks" pattern a little modified.

    Although knowing that one possible drawback of this practice could be the confusion generated by giant files (action-types, reducer, actions and middleware together), I found that the advantage of not having to jump between a lot of files while managing the store was worth it.

  • Aside from that, each feature folder has it's separated selectors file. I decided to do that because of their quantity and also because, in my opinion, they aren't enough semantically close to be with the reducer structure itself.

src/router

Here I stored all route specs, inside the routes.js file, and also de switch component, which imported all the specified routes and generated the needed components.


src/assets

General assets of the application, including:

  • Images
  • Icons
  • Styles
  • Fonts

src/services

Here I stored all the Axios calls to be used by our redux middlewares to fetch data from the server


SERVER - back-end

I structured my folders here by function, not by feature like in the front-end. I decided to do this because, from what I can see, there's more code-sharing between different "features" inside the back-end, and they're more linked in their functions.

Disclaimers

  • The tokens are stored inside the .env.local file, in the root directory
  • As there's a limit of 3000 calls by token inside Marvel's API, there's an environment variable named USE_MOCKED_VALUES that will activate or deactivate the use of a mocked model to get the values
  • As this test being aimed for front-ends, I skipped the stop of building an authentication middleware

server/routes

Here I put all my server routes, one file by each feature and then an index one, in which I grouped all of them to be exported as only one setup function


server/controllers

The layer to communicate between the front-end and the database, in our case the Marvel's API


server/models

Although not being exactly models, I decided to separate all our communication with the pseudo-database, the Marvel's API, here.