Author: Amanuel Zeryihun
Live Link: https://king-prawn-app-wqtdz.ondigitalocean.app/
Full stack web application demonstrating UI best practices for modularity, component testing, file structure, state management, and general software design.
I chose to use React + Typescript + Vite for the client side and NodeJs for the API server.
I intended to create a docker-compose script to host the api and ui in a local container, but I ran into some issues with Vitest and didn't want to prolong my submission.
Running both the ui and api should be relatively straightforward.
(Use Node v18.17.1 or better)
-
Clone from the main branch.
-
Run
npm installin both sub-directories (ui and api). -
Setup the correct Environment Variables
- Store your Yelp API key as an environment variable
YELP_API_KEYin a.envfile from within theapifolder first before running the api server`. - Point the UI to your Apollo Client by defining the
VITE_APOLLO_CLIENT_URLin a.envfile from within theuifolder first before running the UI .
- Store your Yelp API key as an environment variable
-
Run the project
- First run the api
npm run startfrom within theapifolder (Note: You can view the Apollo graphql explorer at port:4000of your local version of the app.) - Then run the ui in dev mode:
npm run devfrom within theuifolder
- First run the api
-
Run UI tests
- Run
npm run testfrom within theuidirectory.
- Run
Although the project's scope is relatively small, I chose to employ best practices for my file structure that can accommodate feature and team growth. My approach is a hybrid between Domain Driven Design and Component Driven Design.
As such, I have two main sub-directories:
components/common, which as it sounds is where I store simple reusable components (such as the Radio dropdown picker component)components/featureswhich is where I store higher level components that drive business logic.
I place feature-specific sub-components in the component directory of the respective feature (e.g., /featureA/components/) when these sub-components are custom-made for the feature and are not intended for reuse in other parts of the application.
Component level tests are stored within each component's container folder.
I wrote my tests using Vitest in conjunction with Jest, and React testing library.
I wrote tests for all common and feature level components. I wrote the most extensive tests for FilterableTableComponent because that is where most of the complexity in the app lies. FilterableTableComponent tests are essentially e2e tests that make sure that data fetching and pagination act as expected in response to various user interactions with its constituent "atomic" components.
I chose to leverage Apollo GraphQL (server and client) to pass data between the server and client.
Apollo was extremely useful. I was able to generate typescript types that were consumable on the frontend which made the development process very comfortable.