Browse Source

init aircall boilerplate

master
karan-at-speer 3 years ago
commit
ad019a9f37
13 changed files with 5430 additions and 0 deletions
  1. +3
    -0
      .babelrc
  2. +3
    -0
      .gitignore
  3. +61
    -0
      README.md
  4. +31
    -0
      package.json
  5. +15
    -0
      public/index.html
  6. +17
    -0
      src/App.jsx
  7. +25
    -0
      src/Header.jsx
  8. +25
    -0
      src/css/app.css
  9. +15
    -0
      src/css/body.css
  10. +12
    -0
      src/css/header.css
  11. +6
    -0
      src/index.js
  12. +34
    -0
      webpack.config.js
  13. +5183
    -0
      yarn.lock

+ 3
- 0
.babelrc View File

@@ -0,0 +1,3 @@
{
"presets": ["env", "react"]
}

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
node_modules
dist
yarn-error.log

+ 61
- 0
README.md View File

@@ -0,0 +1,61 @@
## Summary

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, etc).

The app will have two different components:
- **Activity Feed** - simple list of calls
- **Activity Detail** - detail of a call
- **Archive** - the final user should be able to archive a call. The call will no longer be displayed on the Activity Feed.

Show us what you can do in 24 hours. You will be assessed on the following parameters:
- Focus on design (Pay attention to the UI/UX and transitions)
- Best React Practices
- Code Readability and Maintainability

After you're done with the assignment, please submit a link to the **GitHub/Bitbucket repository** (make sure it's public) with your code **AND** a deployment link where our recruiters can interact with the live version. You can use freely available tools like **Netlify, Vercel, Heroku, etc** to deploy your React application.

**Note:** Submissions without a valid repository and deployment link will be removed from any further consideration.

To give you an idea, here's what our app looks like:


![app](https://user-images.githubusercontent.com/630714/29357034-763d7216-8276-11e7-8bcb-e77d9645dfcc.png)

## Installation

We're using [yarn](https://yarnpkg.com) here:

```
yarn install
yarn start
```

## API documentation

### Routes

Here is the API address: https://aircall-job.herokuapp.com.

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.

- **GET** - https://aircall-job.herokuapp.com/activities: get calls to display in the Activity Feed
- **GET** - https://aircall-job.herokuapp.com/activities/:id: retrieve a specific call details
- **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:
```
{
is_archived: true
}
```
- **GET** - https://aircall-job.herokuapp.com/reset: Reset all calls to initial state (usefull if you archived all calls).

### Call object

- **id** - unique ID of call
- **created_at** - creation date
- **direction** - `inbound` or `outbound` call
- **from** - caller's number
- **to** - callee's number
- **via** - Aircall number used for the call
- **duration** - duration of a call (in seconds)
- **is_archived** - call is archived or not
- **call_type** - can be a `missed`, `answered` or `voicemail` call.

+ 31
- 0
package.json View File

@@ -0,0 +1,31 @@
{
"name": "frontend-hiring-challenge",
"version": "1.0.0",
"description": "Leap test",
"main": "index.js",
"repository": "",
"author": "",
"license": "",
"private": false,
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
},
"dependencies": {
"react": "^16.3.1",
"react-dom": "^16.3.1"
},
"devDependencies": {
"babel-core": "6.26.*",
"babel-loader": "7.1.*",
"babel-preset-env": "1.7.0",
"babel-preset-react": "6.24.*",
"css-loader": "2.1.*",
"html-loader": "0.5.*",
"html-webpack-plugin": "3.2.*",
"style-loader": "0.23.*",
"webpack": "4.29.*",
"webpack-cli": "3.2.*",
"webpack-dev-server": "3.1.*"
}
}

+ 15
- 0
public/index.html View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">

<head>
<title>Aircall</title>

<meta charset="utf-8">
<meta property="description" name="description" content="">
</head>

<body>
<div id="app"></div>
</body>

</html>

+ 17
- 0
src/App.jsx View File

@@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom';

import Header from './Header.jsx';

const App = () => {
return (
<div className='container'>
<Header/>
<div className="container-view">Some activities should be here</div>
</div>
);
};

ReactDOM.render(<App/>, document.getElementById('app'));

export default App;

+ 25
- 0
src/Header.jsx View File

@@ -0,0 +1,25 @@
import React from 'react';

const Header = () => {
return (
<header>
<svg width='486px' height='168px' viewBox='0 0 486 168' version='1.1' xmlns='http://www.w3.org/2000/svg'>
<g stroke='none' strokeWidth='1' fill='none' fillRule='evenodd'>
<g transform='translate(207.000000, 24.000000)'>
<rect fill='#424242' x='270' y='6' width='9' height='90' rx='4.5'/>
<rect fill='#424242' x='249' y='6' width='9' height='90' rx='4.5'/>
<path d='M228,44.5757016 L228,40.5097518 C228,38.0190847 230.019776,36 232.5,36 C234.985281,36 237,38.0134641 237,40.5097518 L237,91.4902482 C237,93.9809153 234.980224,96 232.5,96 C230.014719,96 228,93.9865359 228,91.4902482 L228,87.4242984 C222.588748,92.729045 215.17636,96 207,96 C190.431458,96 177,82.5685425 177,66 C177,49.4314575 190.431458,36 207,36 C215.17636,36 222.588748,39.270955 228,44.5757016 Z M207,87 C218.59798,87 228,77.5979797 228,66 C228,54.4020203 218.59798,45 207,45 C195.40202,45 186,54.4020203 186,66 C186,77.5979797 195.40202,87 207,87 Z' fill='#424242'/>
<path d='M171.566757,44.4332432 C159.655766,32.5222523 140.344234,32.5222523 128.433243,44.4332432 C116.522252,56.3442341 116.522252,75.6557659 128.433243,87.5667568 C140.344234,99.4777477 159.655766,99.4777477 171.566757,87.5667568 C173.324116,85.8093975 173.324116,82.9601551 171.566757,81.2027958 C169.809398,79.4454365 166.960155,79.4454365 165.202796,81.2027958 C156.806524,89.5990681 143.193476,89.5990681 134.797204,81.2027958 C126.400932,72.8065235 126.400932,59.1934765 134.797204,50.7972042 C143.193476,42.4009319 156.806524,42.4009319 165.202796,50.7972042 C166.960155,52.5545635 169.809398,52.5545635 171.566757,50.7972042 C173.324116,49.0398449 173.324116,46.1906025 171.566757,44.4332432 Z' fill='#424242' fillRule='nonzero'/>
<path d='M102,41.650086 L102,40.5097518 C102,38.0190847 99.9802243,36 97.5,36 C95.0147186,36 93,38.0134641 93,40.5097518 L93,91.4902482 C93,93.9809153 95.0197757,96 97.5,96 C99.9852814,96 102,93.9865359 102,91.4902482 L102,65.0800149 C102.269821,52.772034 107.976408,45.0292969 116.914551,45.0292969 C119.399832,45.0292969 121.414551,43.0145782 121.414551,40.5292969 C121.414551,38.0440155 119.399832,36.0292969 116.914551,36.0292969 C110.916968,36.0292969 105.88006,38.0781857 102,41.650086 L102,41.650086 Z' fill='#424242'/>
<rect fill='#424242' x='72' y='36' width='9' height='60' rx='4.5'/>
<circle fill='#2AC420' cx='76.5' cy='10.5' r='10.5'/>
<path d='M51,44.5757016 L51,40.5097518 C51,38.0190847 53.0197757,36 55.5,36 C57.9852814,36 60,38.0134641 60,40.5097518 L60,91.4902482 C60,93.9809153 57.9802243,96 55.5,96 C53.0147186,96 51,93.9865359 51,91.4902482 L51,87.4242984 C45.588748,92.729045 38.1763602,96 30,96 C13.4314575,96 0,82.5685425 0,66 C0,49.4314575 13.4314575,36 30,36 C38.1763602,36 45.588748,39.270955 51,44.5757016 Z M30,87 C41.5979797,87 51,77.5979797 51,66 C51,54.4020203 41.5979797,45 30,45 C18.4020203,45 9,54.4020203 9,66 C9,77.5979797 18.4020203,87 30,87 Z' fill='#424242'/>
</g>
<path d='M84,168 C37.8,168 0,130.2 0,84 C0,37.8 37.8,0 84,0 C130.2,0 168,37.8 168,84 C168,130.2 130.2,168 84,168 Z M84,12 C44.4,12 12,44.4 12,84 C12,123.6 44.4,156 84,156 C123.6,156 156,123.6 156,84 C156,44.4 123.6,12 84,12 Z M122.342895,100.615799 C120.353028,98.7917542 118.031517,97.4651764 115.710006,96.3044208 C112.227739,94.6461985 107.08725,91.9930429 103.273338,94.4803763 C101.946761,95.3094874 100.951827,96.8018875 99.7910717,97.7968209 C98.2986716,99.2892209 96.6404493,100.781621 94.6505826,101.776554 C86.1936489,106.087932 75.0835595,104.263888 68.1190259,97.7968209 C64.1392924,93.6512651 61.651959,87.6816649 61.8177812,81.8778869 C61.9836034,77.4006867 63.4760035,72.7576643 66.2949814,69.1095752 C67.455737,67.6171752 68.948137,66.2905973 70.2747149,64.7981973 C71.6012927,63.4716194 72.4304039,61.9792194 72.4304039,59.9893526 C72.4304039,57.5020192 71.2696482,55.180508 70.2747149,52.8589968 C69.2797815,50.7033078 68.2848481,48.3817966 66.7924481,46.5577521 C65.4658702,44.7337075 63.4760035,42.7438408 61.3203145,41.9147296 C60.3253811,41.5830852 59.3304477,41.4172629 58.3355144,41.7489074 C57.0089365,42.0805519 56.0140032,43.0754852 55.0190698,43.9045964 C50.7076918,47.221041 46.2304916,51.0349522 44.0748027,56.0096191 C40.4267136,63.9690861 42.0849359,73.0893087 45.2355583,80.8829535 C48.8836473,89.6715316 54.8532476,97.6309986 61.8177812,104.098066 C65.9633369,108.243621 70.6063593,112.057533 75.5810262,115.208155 C82.0480931,119.187888 89.5100935,122.504333 97.137916,123.333444 C102.444227,123.996733 108.082183,123.167622 112.725206,120.680289 C114.715072,119.519533 116.539117,118.192955 118.197339,116.534733 C120.021384,114.710688 122.01125,112.720821 123.50365,110.730955 C124.498584,109.570199 125.825162,108.409444 125.990984,106.585399 C126.156806,104.263888 124.001117,102.108199 122.342895,100.615799 Z' fill='#2AC420'/>
</g>
</svg>
</header>
);
};

export default Header;

+ 25
- 0
src/css/app.css View File

@@ -0,0 +1,25 @@
#app {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
left: 0;
top: 0;
right: 0;
bottom: 0;
}

#app .container {
width: 376px;
height: 666px;
z-index: 100;

background: white;
border-radius: 3px;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, .9);
}

#app .container-view {
padding: 20px;
}


+ 15
- 0
src/css/body.css View File

@@ -0,0 +1,15 @@
html, body, h1, h2, h3, ul, li {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-size: 100%;
}

body {
background: #233142;
font-family: helvetica, arial, sans-serif;
font-size: 13px;
color: #333333;
line-height: 1;
}

+ 12
- 0
src/css/header.css View File

@@ -0,0 +1,12 @@
header {
height: 40px;
margin: 0 auto;
padding: 20px 0;
text-align: center;
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
}

header svg {
display: block;
width: 100%; height: 100%;
}

+ 6
- 0
src/index.js View File

@@ -0,0 +1,6 @@
import './css/body.css';
import './css/app.css';
import './css/header.css';

import App from './App.jsx';


+ 34
- 0
webpack.config.js View File

@@ -0,0 +1,34 @@
const HtmlWebPackPlugin = require('html-webpack-plugin');

module.exports = {
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: 'html-loader',
options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html"
})
]
};

+ 5183
- 0
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save