diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..d301495 --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["@babel/preset-env", "@babel/preset-react"], + "plugins": ["@babel/plugin-transform-runtime"] +} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..dd5962a --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +dist +build/*.js +coverage/* \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..96d3451 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,29 @@ +{ + "env": { + "browser": true, + "amd": true, + "es6": true, + "node": true, + "jest/globals": true + }, + "extends": ["plugin:react/recommended", "airbnb", "plugin:jest/recommended", "prettier"], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 2023, + "sourceType": "module" + }, + "plugins": ["react"], + "rules": { + "import/prefer-default-export": "off", + "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], + "react/function-component-definition": [ + 2, + { + "namedComponents": "arrow-function", + "unnamedComponents": "arrow-function" + } + ] + } +} diff --git a/.gitignore b/.gitignore index f06235c..c39ccd6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ node_modules dist + +.*log +.env + +.DS_Store +. +.*cache \ No newline at end of file diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000..31354ec --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..36af219 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +npx lint-staged diff --git a/README.md b/README.md index c72c337..f207000 100644 --- a/README.md +++ b/README.md @@ -1,100 +1,126 @@ -# Stan Coding Challenge - -> Welcome to the Stan Coding Challenge! - -## Overview - -To complete this challenge, you will need to write a simple [React](https://facebook.github.io/react/) based web app, and provide us the source files to be built. - -The purpose of this challenge is to assess your **skills and approach to composing a simple web app** given a set of screens and an API feed. We will also assess the **generated HTML, CSS, and JS** output. +## The Challenge -This challenge is expected to take about 2-4 hours. +Build a sample project based on the screens provided. More Details on the challenge and the project can be found [here](./docs/PROJECT_README.md) -## The Challenge +## Technology Stack and Setup -It's pretty simple. Using the provided screens as a reference, you'll need to build a set of React components to render the app. You'll also need to request a JSON feed, filter that data, and use the relevant fields. +This project is built using the following technologies: -Although this is a basic exercise, we'll be looking for **simple, well-designed, performant, and tested code** in the submission. +- **React:** A JavaScript library for building user interfaces. +- **Webpack:** A module bundler for JavaScript applications. +- **Babel:** A JavaScript compiler for writing next-generation JavaScript. +- **React Router:** A library for handling navigation and routing in a React application. +- **Prettier:** An opinionated code formatter. +- **ESLint:** A tool for identifying and fixing problems in JavaScript code. +- **React Testing Library:** A testing utility for React applications. -Please include a `README` with setup instructions, and any tests or other documentation you created as part of your solution. +This project was built using React without the use of create-react-app. The configuration settings were done manually using webpack. -Also, add the following info to your `README`: +- **Webpack Configuration**: +**Entry Point**: The main entry point of the application is set to `src/index.jsx`, which is the starting point for bundling the application. +**Output**: The bundled JavaScript code is output to the `dist` folder, and the generated `bundle.js` file is referenced in the `index.html` file. +**Loaders**: + - **JavaScript/JSX**: Babel-loader is used to transpile modern JavaScript (ES6+) to a version compatible with most browsers. + - **CSS**: Style-loader and CSS-loader are used to handle styles in the project. + - **Images**: File-loader is configured to handle image files. +**Static Assets**: The `static` configuration in the development server points to both the `dist` and `assets` folders to serve static assets during development. +**Development Server**: The development server is set up to run on port 8000, with hot module replacement and live reloading for an efficient development workflow. +**Webpack Dev Server**: Configured to open the application in the default browser and enable hot module replacement. + **Resolve Extensions**: Webpack is configured to resolve file extensions like `.js`, `.jsx`, and `.json`. -- How did you decide on the technical and architectural choices used as part of your solution? -- Are there any improvements you could make to your submission? -- What would you do differently if you were allocated more time? +### Code Formatting and Linting -## Details +This project follows a consistent code style and adheres to best practices using Prettier and ESLint. -You will need to build the following 3 pages with React: +### Prettier -- A "Home" page -- A "Series" page -- A "Movies" page +[Prettier](https://prettier.io/) is a code formatter that ensures a consistent and clean code style across the project. The configuration for Prettier is defined in the `.prettierrc` file. -The deployable solution should be built in a folder named **`dist`** with an entry point file of **`index.html`**. +To format the code, run the following command: -Please create components for each part of the page (eg. header, content, footer, etc). -Assets are provided in the `assets` folder. +``` +npm run format +yarn format +``` -The pages should also be usable on mobile and tablet devices. +### ESLint -You can assume that you do not have to support legacy browsers without features such as `fetch` or `flexbox`. +[ESLint](https://eslint.org/) is a powerful JavaScript linter that helps identify and fix issues in the code. The ESLint configuration is specified in the .eslintrc file. -### "Home" Page +To lint the code, run the following command: -Refer to the [screens/1-home.jpg](./screens/1-home.jpg) screen. +``` +npm run lint +yarn lint +``` -This will be your `index.html` screen. +## Project Structure -You will need to display 2 tiles, which link to the "Series" page and the "Movies" page. +The project follows a standard React project structure with additional configuration for webpack. Here's an overview of the main directories and files: -### "Series" and "Movies" Pages +- **src**: Contains the source code of the React application. + - **components**: Reusable UI components. + - **hooks**: Custom hooks used in the application. + - **pages**: React components representing different pages of the app. + - **utils**: Utility functions or helper modules. + - **App.js**: The main component where the routes are defined. + - **index.js**: The entry point of the application. + - **index.css**: Global styles for the application. +- **public**: Static assets and the main HTML file. +- **assets**: Images and other static assets. +- **feed**: Sample JSON file. +- **dist**: Output folder for webpack (generated when we build the project). +- **node_modules**: Node.js modules installed by npm. +- **.babelrc**: Babel configuration file. +- **.eslintrc**: ESLint configuration file. +- **package.json**: Node.js package file. +- **webpack.config.js**: Webpack configuration file. -Refer to the [screens/2-series.jpg](./screens/2-series.jpg) and [screens/3-movies.jpg](./screens/3-movies.jpg) screens. +This structure helps maintain a clear separation between pages and reusable components, promoting modularity and maintainability. -For each page you will need to fetch this JSON feed [feed/sample.json](https://raw.githubusercontent.com/StreamCo/react-coding-challenge/master/feed/sample.json), then: -- Display the first 21 `entries` -- Where the entry has a `releaseYear` attribute value >= `2010` -- Sorted by the `title` attribute value in ascending alphanumeric order +## Getting Started +Follow these steps to set up and run the project locally. -For the "Series" page filter on: +- Clone the repository +- Install dependencies: +```yarn install``` -- Where the entry has a `programType` attribute value of `series` +- Start the development server: +```yarn start``` -For the "Movies" page filter on: +Open your browser and go to http://localhost:8000 -- Where the entry has a `programType` attribute value of `movie` -The attributes you should use to display the entries are: +## Testing +This project uses Jest and React Testing Library for testing. While the existing test suite covers certain scenarios, there is room for improvement and additional test coverage. +At the moment only the helpers and the hooks have been tested. -- `title` -- `images` → `Poster Art` → `url` +To run the tests -You will also need to handle the loading and error states of fetching the JSON feed: +``` +yarn test +yarn test:watch +``` -- "Loading" state [screens/1.1-loading.jpg](./screens/1.1-loading.jpg) -- "Error" state [screens/1.2-error.jpg](./screens/1.2-error.jpg) +## Styling -## FAQ +The styling for this project has been implemented without relying on third-party frameworks. It follows a modular structure, and each component has its dedicated CSS file for styling. The project utilizes responsive design principles, making it suitable for various screen sizes. -### What language, framework, build tool... should I use? +Styling is organized using modular CSS files associated with each component. This approach enhances maintainability and makes it easier to locate and update styles for specific components. -You may use whatever you like as long as the solution is built using [React](https://facebook.github.io/react/) or an equivalent library. +The project leverages Flexbox for layout, contributing to a flexible and responsive design. Whether viewed on desktop or mobile devices, the content adapts to the screen size, providing an optimal user experience. -We prefer it if you did not use any third party CSS frameworks. +## Routing -We also prefer the use of minimal dependencies. +The project follows a simple and intuitive routing structure to navigate through different sections. The main routes include: -## Useful Links +- **Home:** The default route is set to `/`, providing an overview or a landing page for the application. -- [Bitbucket](https://bitbucket.org/) - Source code hosting, with free private repositories for small teams. -- [Google Fonts - Raleway](https://fonts.google.com/?selection.family=Raleway) -- [React](https://facebook.github.io/react/) +- **Movies:** The `/movies` route displays content related to movies. Users can explore a curated list of movies.The list is not clickable and will not direct to other pages. -## Other Notes +- **Series:** The `/series` route is dedicated to showcasing TV series content. Users can discover a collection of TV series.The list is not clickable and will not direct to other pages. -Please send through any other code or projects that you're proud of and would like to share with us. +### Navigation -Any feedback on the coding challenge once you're done is also appreciated! +Navigation between these routes is achieved using the [React Router](https://reactrouter.com/) library. The navigation flow is designed to enhance user experience and provide seamless transitions between different sections of the application. \ No newline at end of file diff --git a/docs/PROJECT_README.md b/docs/PROJECT_README.md new file mode 100644 index 0000000..c72c337 --- /dev/null +++ b/docs/PROJECT_README.md @@ -0,0 +1,100 @@ +# Stan Coding Challenge + +> Welcome to the Stan Coding Challenge! + +## Overview + +To complete this challenge, you will need to write a simple [React](https://facebook.github.io/react/) based web app, and provide us the source files to be built. + +The purpose of this challenge is to assess your **skills and approach to composing a simple web app** given a set of screens and an API feed. We will also assess the **generated HTML, CSS, and JS** output. + +This challenge is expected to take about 2-4 hours. + +## The Challenge + +It's pretty simple. Using the provided screens as a reference, you'll need to build a set of React components to render the app. You'll also need to request a JSON feed, filter that data, and use the relevant fields. + +Although this is a basic exercise, we'll be looking for **simple, well-designed, performant, and tested code** in the submission. + +Please include a `README` with setup instructions, and any tests or other documentation you created as part of your solution. + +Also, add the following info to your `README`: + +- How did you decide on the technical and architectural choices used as part of your solution? +- Are there any improvements you could make to your submission? +- What would you do differently if you were allocated more time? + +## Details + +You will need to build the following 3 pages with React: + +- A "Home" page +- A "Series" page +- A "Movies" page + +The deployable solution should be built in a folder named **`dist`** with an entry point file of **`index.html`**. + +Please create components for each part of the page (eg. header, content, footer, etc). +Assets are provided in the `assets` folder. + +The pages should also be usable on mobile and tablet devices. + +You can assume that you do not have to support legacy browsers without features such as `fetch` or `flexbox`. + +### "Home" Page + +Refer to the [screens/1-home.jpg](./screens/1-home.jpg) screen. + +This will be your `index.html` screen. + +You will need to display 2 tiles, which link to the "Series" page and the "Movies" page. + +### "Series" and "Movies" Pages + +Refer to the [screens/2-series.jpg](./screens/2-series.jpg) and [screens/3-movies.jpg](./screens/3-movies.jpg) screens. + +For each page you will need to fetch this JSON feed [feed/sample.json](https://raw.githubusercontent.com/StreamCo/react-coding-challenge/master/feed/sample.json), then: + +- Display the first 21 `entries` +- Where the entry has a `releaseYear` attribute value >= `2010` +- Sorted by the `title` attribute value in ascending alphanumeric order + +For the "Series" page filter on: + +- Where the entry has a `programType` attribute value of `series` + +For the "Movies" page filter on: + +- Where the entry has a `programType` attribute value of `movie` + +The attributes you should use to display the entries are: + +- `title` +- `images` → `Poster Art` → `url` + +You will also need to handle the loading and error states of fetching the JSON feed: + +- "Loading" state [screens/1.1-loading.jpg](./screens/1.1-loading.jpg) +- "Error" state [screens/1.2-error.jpg](./screens/1.2-error.jpg) + +## FAQ + +### What language, framework, build tool... should I use? + +You may use whatever you like as long as the solution is built using [React](https://facebook.github.io/react/) or an equivalent library. + +We prefer it if you did not use any third party CSS frameworks. + +We also prefer the use of minimal dependencies. + +## Useful Links + +- [Bitbucket](https://bitbucket.org/) - Source code hosting, with free private repositories for small teams. +- [Google Fonts - Raleway](https://fonts.google.com/?selection.family=Raleway) +- [React](https://facebook.github.io/react/) + +## Other Notes + +Please send through any other code or projects that you're proud of and would like to share with us. + +Any feedback on the coding challenge once you're done is also appreciated! diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..db61ddb --- /dev/null +++ b/jest.config.js @@ -0,0 +1,4 @@ + +module.exports = { + testEnvironment: 'jsdom', +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..54d418c --- /dev/null +++ b/package.json @@ -0,0 +1,61 @@ +{ + "name": "react-coding-challenge", + "version": "1.0.0", + "description": "a basic react app for displaying series and movies", + "main": "index.js", + "repository": "https://github.com/ReenaRajani/react-coding-challenge.git", + "license": "MIT", + "scripts": { + "start": "webpack serve --mode development", + "build": "webpack --mode production", + "test": "jest ", + "test:watch": "jest --watch", + "lint": "eslint . --fix --max-warnings=0", + "format": "prettier . --write 'src/**/*.{js,jsx}'", + "prepare": "husky install" + }, + "dependencies": { + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.20.1" + }, + "devDependencies": { + "@babel/cli": "^7.23.4", + "@babel/core": "^7.23.5", + "@babel/plugin-transform-runtime": "^7.23.4", + "@babel/preset-env": "^7.23.5", + "@babel/preset-react": "^7.23.3", + "@babel/runtime": "^7.23.5", + "@testing-library/jest-dom": "^6.1.5", + "@testing-library/react": "^14.1.2", + "@testing-library/react-hooks": "^8.0.1", + "babel-loader": "^9.1.3", + "css-loader": "^6.8.1", + "eslint": "^7.32.0 || ^8.2.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^27.6.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0", + "file-loader": "^6.2.0", + "html-webpack-plugin": "^5.5.4", + "husky": ">=6", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "lint-staged": ">=10", + "path": "^0.12.7", + "prettier": "^3.1.0", + "style-loader": "^3.3.3", + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.15.1" + }, + "lint-staged": { + "*.js": "eslint --cache --fix", + "*.--write": "prettier --write" + } +} diff --git a/prettierrc.json b/prettierrc.json new file mode 100644 index 0000000..0e8c4c7 --- /dev/null +++ b/prettierrc.json @@ -0,0 +1,13 @@ +{ + "tabWidth": 2, + "useTabs": false, + "printWidth": 100, + "semi": true, + "trailingComma": "es5", + "singleQuote": true, + "endOfLine": "lf", + "jsxSingleQuote": false, + "bracketSpacing": true, + "jsxBracketSameLine": false, + "arrowParens": "always" +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..a0f9cea --- /dev/null +++ b/public/index.html @@ -0,0 +1,13 @@ + + + + + + + React App + + + +
+ + diff --git a/src/App.jsx b/src/App.jsx new file mode 100644 index 0000000..d43e96f --- /dev/null +++ b/src/App.jsx @@ -0,0 +1,17 @@ +import React from "react"; +import { Outlet } from "react-router-dom"; + +import { Navbar } from "./components/Navbar"; +import { Footer } from "./components/Footer"; + +const App = () => ( + <> + +
+ +
+