├── .babelrc ├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── src ├── App.jsx ├── Header.jsx ├── css │ ├── app.css │ ├── body.css │ └── header.css └── index.js ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | yarn-error.log 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [aircall.io](https://aircall.io) - Frontend technical test 2 | 3 | **This test is now deprecated. Please refer to [this one](https://github.com/aircall/frontend-hiring-test/blob/master/README.md) instead.** 4 | 5 | This test is a part of our hiring process at Aircall for [the Frontend Developer position](https://jobs.lever.co/aircall/c0fdd41e-a2a1-408d-ad08-890153518587). It should take you between 3 and 6 hours depending on your experience. 6 | 7 | **Feel free to apply! Drop us a line with your LinkedIn/GitHub/Twitter at jobs@aircall.io** 8 | 9 | ## Summary 10 | 11 | The goal of this test is to make you code a small ReactJS app. We have prepared a skeleton app for you, but please change whatever you want (CSS files, HTML structure, JS structure...). 12 | 13 | The app will have two different components: 14 | - **Activity Feed** - simple list of calls 15 | - **Activity Detail** - detail of a call 16 | 17 | Show us what you can do in 6 hours top :) Don't spend too much time on designing your app, our design team will hate it anyway. 18 | 19 | **Bonus:** the final user should be able to archive a call. The call will no longer be displayed on the Activity Feed. Please code that only if you have extra time. 20 | 21 | 22 | To give you an idea, here what our app looks like: 23 | 24 | 25 | ![app](https://user-images.githubusercontent.com/630714/29357034-763d7216-8276-11e7-8bcb-e77d9645dfcc.png) 26 | 27 | ## Installation 28 | 29 | We're using [yarn](https://yarnpkg.com) here: 30 | 31 | ``` 32 | yarn install 33 | yarn start 34 | ``` 35 | 36 | ## API documentation 37 | 38 | ### Routes 39 | 40 | Here is the API address: https://aircall-job.herokuapp.com. 41 | 42 | As you can see, it's hosted on a free Heroku server, which means that the first time you will fetch the API, it will take few seconds to answer. 43 | 44 | - **GET** - https://aircall-job.herokuapp.com/activities: get calls to display in the Activity Feed 45 | - **GET** - https://aircall-job.herokuapp.com/activities/:id: retrieve a specific call details 46 | - **POST** - https://aircall-job.herokuapp.com/activities/:id: update a call. The only field updatable is `is_archived (bool)`. You'll need to send a JSON in the request body: 47 | ``` 48 | { 49 | is_archived: true 50 | } 51 | ``` 52 | - **GET** - https://aircall-job.herokuapp.com/reset: Reset all calls to initial state (usefull if you archived all calls). 53 | 54 | ### Call object 55 | 56 | - **id** - unique ID of call 57 | - **created_at** - creation date 58 | - **direction** - `inbound` or `outbound` call 59 | - **from** - caller's number 60 | - **to** - callee's number 61 | - **via** - Aircall number used for the call 62 | - **duration** - duration of a call (in seconds) 63 | - **is_archived** - call is archived or not 64 | - **call_type** - can be a `missed`, `answered` or `voicemail` call. 65 | 66 | 67 | 68 | ## Submission 69 | 70 | Fork this repository and send us a pull request. We'll review it and get back to you in order to talk about your code! 71 | 72 | Contact us at jobs@aircall.io if you need more details. 73 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend-test-react", 3 | "version": "1.0.0", 4 | "description": "Technical test for Frontend Engineer position at Aircall", 5 | "main": "index.js", 6 | "repository": "https://github.com/aircall/frontend-test-react.git", 7 | "author": "Xavier Durand ", 8 | "license": "MIT", 9 | "private": false, 10 | "scripts": { 11 | "start": "webpack-dev-server --mode development --open", 12 | "build": "webpack --mode production" 13 | }, 14 | "dependencies": { 15 | "react": "^16.3.1", 16 | "react-dom": "^16.3.1" 17 | }, 18 | "devDependencies": { 19 | "babel-core": "6.26.*", 20 | "babel-loader": "7.1.*", 21 | "babel-preset-env": "1.7.0", 22 | "babel-preset-react": "6.24.*", 23 | "css-loader": "2.1.*", 24 | "html-loader": "0.5.*", 25 | "html-webpack-plugin": "3.2.*", 26 | "style-loader": "0.23.*", 27 | "webpack": "4.29.*", 28 | "webpack-cli": "3.2.*", 29 | "webpack-dev-server": "3.1.*" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Aircall Phone 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import Header from './Header.jsx'; 5 | 6 | const App = () => { 7 | return ( 8 |
9 |
10 |
Some activities should be here
11 |
12 | ); 13 | }; 14 | 15 | ReactDOM.render(, document.getElementById('app')); 16 | 17 | export default App; 18 | -------------------------------------------------------------------------------- /src/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Header = () => { 4 | return ( 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | ); 23 | }; 24 | 25 | export default Header; 26 | -------------------------------------------------------------------------------- /src/css/app.css: -------------------------------------------------------------------------------- 1 | #app { 2 | position: absolute; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | left: 0; 7 | top: 0; 8 | right: 0; 9 | bottom: 0; 10 | } 11 | 12 | #app .container { 13 | width: 376px; 14 | height: 666px; 15 | z-index: 100; 16 | 17 | background: white; 18 | border-radius: 3px; 19 | box-shadow: 0 0 5px 0 rgba(0, 0, 0, .9); 20 | } 21 | 22 | #app .container-view { 23 | padding: 20px; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/css/body.css: -------------------------------------------------------------------------------- 1 | html, body, h1, h2, h3, ul, li { 2 | margin: 0; 3 | padding: 0; 4 | border: 0; 5 | font: inherit; 6 | font-size: 100%; 7 | } 8 | 9 | body { 10 | background: #233142; 11 | font-family: helvetica, arial, sans-serif; 12 | font-size: 13px; 13 | color: #333333; 14 | line-height: 1; 15 | } 16 | -------------------------------------------------------------------------------- /src/css/header.css: -------------------------------------------------------------------------------- 1 | header { 2 | height: 40px; 3 | margin: 0 auto; 4 | padding: 20px 0; 5 | text-align: center; 6 | box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1); 7 | } 8 | 9 | header svg { 10 | display: block; 11 | width: 100%; height: 100%; 12 | } 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './css/body.css'; 2 | import './css/app.css'; 3 | import './css/header.css'; 4 | 5 | import App from './App.jsx'; 6 | 7 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebPackPlugin = require('html-webpack-plugin'); 2 | 3 | module.exports = { 4 | module: { 5 | rules: [ 6 | { 7 | test: /\.html$/, 8 | use: [ 9 | { 10 | loader: 'html-loader', 11 | options: { minimize: true } 12 | } 13 | ] 14 | }, 15 | { 16 | test: /\.css$/, 17 | use: [ 'style-loader', 'css-loader' ] 18 | }, 19 | { 20 | test: /\.(js|jsx)$/, 21 | exclude: /node_modules/, 22 | use: { 23 | loader: 'babel-loader' 24 | } 25 | } 26 | ] 27 | }, 28 | plugins: [ 29 | new HtmlWebPackPlugin({ 30 | template: "./public/index.html", 31 | filename: "./index.html" 32 | }) 33 | ] 34 | }; 35 | --------------------------------------------------------------------------------