Skip to content
This repository has been archived by the owner on Sep 1, 2022. It is now read-only.

test(samuel-lambert): delivery #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/frontend-test.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
"build": "webpack --mode production"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"react": "^16.3.1",
"react-dom": "^16.3.1"
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"babel-core": "6.26.*",
Expand Down
17 changes: 12 additions & 5 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import React from 'react';
import ReactDOM from 'react-dom';

import {BrowserRouter as Router, Route} from 'react-router-dom';
import CallList from './components/CallList';
import "@babel/polyfill";
import CallDetail from './components/CallDetail';
import Header from './Header.jsx';

const App = () => {
return (
<div className='container'>
<Header/>
<div className="container-view">Some activities should be here</div>
</div>
<Router>
<div className='container'>
<Header/>
<Route path='/' exact component={CallList} />
<Route path='/:callId' exact component={CallDetail} />
</div>
</Router>

);
};

Expand Down
92 changes: 92 additions & 0 deletions src/components/CallDetail.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, {useEffect, useState} from 'react';
import {getCallDetail, updateCall} from "../services/api";
import Card from "@material-ui/core/Card";
import Typography from "@material-ui/core/Typography";
import CardContent from "@material-ui/core/CardContent";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Checkbox from "@material-ui/core/Checkbox";
import CallIcon from "@material-ui/icons/Call";
import CallMadeRoundedIcon from "@material-ui/icons/CallMadeRounded";
import CallReceivedRoundedIcon from "@material-ui/icons/CallReceivedRounded";
import Button from "@material-ui/core/Button";
import '../css/CallDetail.css'

const CallDetail = ({match, history}) => {
const [callDetail, setCallDetail] = useState([]);
const [values, setValues] = useState({isArchived: false});

useEffect(() => {
const getData = async() => {
const call = await getCallDetail(match.params.callId);
if (call.is_archived === true) {
setValues({isArchived: true})
}
return setCallDetail(call);
};
getData();
}, []);

const handleCheckBoxChange = (event) => {
const isArchived = event.target.checked;
const id = match.params.callId;
setValues({isArchived: isArchived});
updateCall(id, {is_archived: isArchived}).then(() => history.push({pathname: '/'}))
};

const date = new Date(callDetail.created_at);
const formattedDate = date.toDateString();
const formattedTime = date.toLocaleTimeString('fr-FR');

const handleRedirect = () => history.push({pathname: '/'});

return (
<div className="detailContainer">
<Button onClick={() => handleRedirect()} className="button">
Back to List
</Button>

{callDetail && (
<div className="detail">
<Card>
<CardContent>
<Typography variant="h5">
{callDetail.from}
</Typography>
<Typography variant="h6">
{callDetail.to ? `To: ${callDetail.to}` : `To: unknown`}
</Typography>
<Typography variant="body2">
{formattedDate}
</Typography>
<Typography variant="body1" >
{formattedTime}
</Typography>
<Typography>
<CallIcon />
{callDetail.direction === 'outbound' ?
<CallMadeRoundedIcon fontSize="small" style={callDetail.call_type === 'answered' ? {color: 'green'} : {color: 'red'}} /> :
<CallReceivedRoundedIcon fontSize="small" style={callDetail.call_type === 'answered' ? {color: 'green'} : {color: 'red'}} />
}
</Typography>
<Typography variant="body2" color="textSecondary">
{`Duration: ${callDetail.duration} seconds`}
</Typography>
<Typography variant="body2">
{`Via: ${callDetail.via}`}
</Typography>
<FormControlLabel
control={<Checkbox checked={values.isArchived} onChange={handleCheckBoxChange} name='isArchived' />}
label="Archive"
labelPlacement="start"
/>
</CardContent>
</Card>
</div>

)}

</div>
)
};

export default CallDetail
129 changes: 129 additions & 0 deletions src/components/CallList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React, {useEffect, useState} from 'react';
import {getCallList, resetList} from '../services/api';
import List from '@material-ui/core/List';
import ListItem from "@material-ui/core/ListItem";
import ButtonGroup from "@material-ui/core/ButtonGroup";
import Button from "@material-ui/core/Button";
import CallIcon from '@material-ui/icons/Call';
import CallMadeRoundedIcon from '@material-ui/icons/CallMadeRounded';
import CallReceivedRoundedIcon from '@material-ui/icons/CallReceivedRounded';
import Badge from "@material-ui/core/Badge";
import {makeStyles} from "@material-ui/core/styles";
import '../css/CallList.css'
import Typography from "@material-ui/core/Typography";

const CallList = ({history}) => {
const [callList, setCallList] = useState([]);
const [filter, setFilter] = useState('calls');
const [reset, setReset] = useState(false)

const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
height: '100%',
backgroundColor: theme.palette.background.paper,
},
inline: {
display: 'inline'
},
}));

const classes = useStyles();

useEffect(() => {
const getData = async() => {

const calls = await getCallList();
if (calls && calls.length) {
if (filter === 'calls') {
const filteredCalls = calls.filter((call) => call.is_archived === false);
return setCallList(filteredCalls);
}
if (filter === 'archived') {
const filteredCalls = calls.filter((call) => call.is_archived === true);
return setCallList(filteredCalls);
}
}
return [];
};
getData();
}, [filter, reset]);

const redirect = (id) => history.push({pathname: `/${id}`, callId: id});

const toggleFilter = (filter) => {
setFilter(filter);
};

const handleReset = () => {
return resetList().then(() => setReset(!reset))
};
return (
<div className="listContainer">
<ButtonGroup className="buttons">
<Button color={filter === 'calls' ? 'primary' : 'default'} onClick={() => toggleFilter('calls')}>Activity</Button>
<Button color={filter === 'archived' ? 'primary' : 'default'} onClick={() => toggleFilter('archived')}>Archived</Button>
</ButtonGroup>

<div className="callList">
{!callList || callList.length === 0 && (
<div>No Calls</div>
)}
<List className={classes.root}>
{
callList && callList.length > 0 && callList.map((call, index) => {
const date = new Date(call.created_at);
const formattedDate = date.toDateString();
const formattedTime = date.toLocaleTimeString('fr-FR');
return (
<div key={`callItem${index}`}>
<Typography color="textSecondary">
{formattedDate}
</Typography>
<ListItem className="item" onClick={() => redirect(call.id)}>
<CallIcon />
{call.direction === 'outbound' ?
<CallMadeRoundedIcon fontSize="small" style={call.call_type === 'answered' ? {color: 'green'} : {color: 'red'}} /> :
<CallReceivedRoundedIcon fontSize="small" style={call.call_type === 'answered' ? {color: 'green'} : {color: 'red'}} />
}
<div className="itemSection">
<Typography variant="body1" >
{call.from}
</Typography>
<Typography variant="body2" color="textSecondary">
{call.to ? `To: ${call.to}` : `To: unknown`}
</Typography>
</div>
<div className="itemSection">
{formattedTime}
</div>

</ListItem>
</div>

)
}).sort((call1, call2) => {
const call1Date = new Date(call1.created_at);
const formattedDate1 = call1Date.toDateString();
const call2Date = new Date(call2.created_at);
const formattedDate2 = call2Date.toDateString();
return formattedDate1.localeCompare(formattedDate2)
})
}
</List>

</div>
{callList.length >= 1 && (
<div className="footer">
<Badge badgeContent={callList.length} color="error">
<CallIcon />
</Badge>
<Button onClick={() => handleReset()}>
Reset
</Button>
</div>
)}
</div>
)
};
export default CallList;
24 changes: 24 additions & 0 deletions src/css/CallDetail.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.detailContainer {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100%;
}

.detail {
display: flex;
flex-direction: column;
width: 90%
}

.button {
display: flex;
flex-direction: row;
justify-content: flex-start;
margin-bottom: 30% !important;
}

.itemSection {
padding: 10px;
}
42 changes: 42 additions & 0 deletions src/css/CallList.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.listContainer {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
}

.callList {
height: 500px;
width: 95%;
overflow: scroll;
}

.buttons {
padding: 10px;
}

.item {
display: flex;
flex-direction: row;
justify-content: space-between !important;

}

.itemSection {
display: flex;
flex-direction: column;
}

.item:hover {
background-color: lightgray;
opacity: 0.4;
cursor: pointer;
}

.footer {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 95%;
height: 30px;
}
4 changes: 3 additions & 1 deletion src/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@

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

background: white;
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import './css/body.css';
import './css/app.css';
import './css/header.css';
import "@babel/polyfill";

import App from './App.jsx';

Loading