From 8a177f53656743a9ba189eb43726a17dfefc807a Mon Sep 17 00:00:00 2001
From: "M. Reza Qorib" <rezaqorib96@gmail.com>
Date: Wed, 24 May 2017 09:38:03 +0700
Subject: [PATCH] So much things done. Create SupervisorPage, refactor TopMenu
 and Dashboard, add and refactor many testing files.

---
 assets/js/Dashboard.jsx                       |  41 +------
 assets/js/ProfilePage.jsx                     |   7 +-
 assets/js/SupervisorPage.jsx                  |  53 +++++++++
 assets/js/VacancyPage.jsx                     |   3 +-
 assets/js/__test__/Dashboard-test.jsx         |  23 +++-
 assets/js/__test__/SupervisorPage-test.jsx    |  58 ++++++++++
 assets/js/__test__/components/Footer-test.jsx |  12 ++
 .../js/__test__/components/TopMenu-test.jsx   |  23 +++-
 .../__test__/components/VacancyList-test.jsx  | 103 ++++++++----------
 assets/js/components/ApplicationList.jsx      |  55 ++++++++++
 assets/js/components/SupervisorPage.jsx       |  63 -----------
 assets/js/components/Tables.jsx               |  45 --------
 assets/js/components/TopMenu.jsx              |  97 +++++++++++------
 assets/js/index.jsx                           |   4 +-
 14 files changed, 336 insertions(+), 251 deletions(-)
 create mode 100644 assets/js/SupervisorPage.jsx
 create mode 100644 assets/js/__test__/SupervisorPage-test.jsx
 create mode 100644 assets/js/__test__/components/Footer-test.jsx
 create mode 100644 assets/js/components/ApplicationList.jsx
 delete mode 100644 assets/js/components/SupervisorPage.jsx
 delete mode 100644 assets/js/components/Tables.jsx

diff --git a/assets/js/Dashboard.jsx b/assets/js/Dashboard.jsx
index c5d95563..14b2e341 100755
--- a/assets/js/Dashboard.jsx
+++ b/assets/js/Dashboard.jsx
@@ -1,9 +1,6 @@
 import React from 'react';
 import TopMenu from './components/TopMenu';
-import Server from './lib/Server';
-
-
-const defaultPicture = 'http://semantic-ui.com/images/avatar/small/elliot.jpg';
+import Footer from './components/Footer';
 
 export default class Dashboard extends React.Component {
   static propTypes = {
@@ -16,43 +13,9 @@ export default class Dashboard extends React.Component {
     ]).isRequired,
   };
 
-  static getInfo(user) {
-    const adminRole = {
-      name: 'admin',
-      user: {
-        email: '',
-      },
-      photo: null,
-    };
-    const role = user.role;
-    if (role === 'student') {
-      return user.data.student;
-    } else if (role === 'company') {
-      return user.data.company;
-    }
-
-    return adminRole;
-  }
-
-  constructor(props) {
-    super(props);
-    /* istanbul ignore next */
-    const data = Dashboard.getInfo(this.props.user);
-    this.state = {
-      id: data.id,
-      name: data.name,
-      email: data.user.email,
-      photo: data.photo,
-    };
-  }
-
-
   render = () => (
     <div>
-      <TopMenu
-        name={this.state.name} email={this.state.email}
-        photo={this.state.photo ? this.state.photo : defaultPicture}
-      />
+      <TopMenu user={this.props.user} />
       {this.props.children}
     </div>
   )
diff --git a/assets/js/ProfilePage.jsx b/assets/js/ProfilePage.jsx
index 2700b8ac..564e2867 100644
--- a/assets/js/ProfilePage.jsx
+++ b/assets/js/ProfilePage.jsx
@@ -157,7 +157,7 @@ export default class ProfilePage extends React.Component {
             <Grid.Column width={7}>
               <Header as="h2" icon textAlign="center">
                 <br />
-                <Image src={this.state.photo ? this.state.photo : defaultPicture} size="medium" />
+                <Image src={this.state.photo || defaultPicture} size="medium" />
               </Header>
             </Grid.Column>
 
@@ -219,10 +219,7 @@ export default class ProfilePage extends React.Component {
 
                 <Container textAlign="center">
                       <div className="button-profile">
-                    <a href={this.state.resume ? this.state.resume : '#'} ><Button primary size="small">Resume</Button></a>
-                    { this.state.show_transcript &&
-                    <Button primary size="small">Transkrip</Button>
-                    }
+                    <a href={this.state.resume || '#'} ><Button primary size="small">Resume</Button></a>
                   </div>
                   <div>
                     <h4> Bagikan Transkrip : { this.state.bagikanTranskrip }</h4>
diff --git a/assets/js/SupervisorPage.jsx b/assets/js/SupervisorPage.jsx
new file mode 100644
index 00000000..4d4fe749
--- /dev/null
+++ b/assets/js/SupervisorPage.jsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { Header, Icon, Grid } from 'semantic-ui-react';
+import Pagination from './components/Pagination';
+import Server from './lib/Server';
+import ApplicationList from './components/ApplicationList';
+
+const cols = [
+    { key: 'StudentName', label: 'Nama' },
+    { key: 'StudentID', label: 'NPM' },
+    { key: 'Perusahaan', label: 'Perusahaan' },
+    { key: 'Posisi', label: 'Posisi' },
+    { key: 'Status', label: 'Status' },
+];
+
+export default class SupervisorPage extends React.Component {
+
+  constructor(props) {
+    super(props);
+    /* istanbul ignore next */
+    this.state = { list: [] };
+  }
+
+  componentDidMount() {
+    this.UserList();
+  }
+
+  UserList() {
+    Server.get('/student-applications/', false).then((data) => {
+      this.setState({ list: data.results });
+    });
+  }
+
+  render = () => {
+    return (
+      <Grid container columns="eleven" doubling>
+        <Grid.Row>
+          <br />
+        </Grid.Row>
+        <Grid.Row>
+          <Header as="h2">
+            <Icon name="list" />
+            Daftar Mahasiswa
+          </Header>
+        </Grid.Row>
+        <Grid.Row>
+          <div id="layout-content" className="layout-content-wrapper">
+            <Pagination url={'/student-applications/'} child={<ApplicationList cols={cols} />} />
+          </div>
+        </Grid.Row>
+      </Grid>
+    );
+  }
+}
diff --git a/assets/js/VacancyPage.jsx b/assets/js/VacancyPage.jsx
index 2201e5b3..2032db0e 100644
--- a/assets/js/VacancyPage.jsx
+++ b/assets/js/VacancyPage.jsx
@@ -3,7 +3,7 @@ import Tabs from './components/Tabs';
 import Pane from './components/Pane';
 import VacancyList from './components/VacancyList';
 import Pagination from './components/Pagination';
-import Applicants from './components/SupervisorPage';
+import Applicants from './SupervisorPage';
 
 export default class VacancyPage extends React.Component {
 
@@ -47,7 +47,6 @@ export default class VacancyPage extends React.Component {
                 />
               }
             />
-            <Applicants />
           </Pane>
           <Pane label="Lamaran saya" >
             <Pagination
diff --git a/assets/js/__test__/Dashboard-test.jsx b/assets/js/__test__/Dashboard-test.jsx
index 892fbabf..1e01baf0 100644
--- a/assets/js/__test__/Dashboard-test.jsx
+++ b/assets/js/__test__/Dashboard-test.jsx
@@ -90,7 +90,28 @@ describe('Dashboard', () => {
       email: '',
       is_staff: false,
       company: null,
-      supervisor: null,
+      supervisor: {
+        id: 3,
+        user: {
+          url: 'http://localhost:8000/api/users/9/',
+          username: 'muhammad.reza42',
+          email: 'muhammad.reza42@ui.ac.id',
+          is_staff: false,
+        },
+        name: 'Muhammad R.',
+        created: '2017-03-28T13:33:46.147241Z',
+        updated: '2017-03-28T13:33:46.148248Z',
+        npm: 1406543593,
+        resume: null,
+        phone_number: null,
+        bookmarked_vacancies: [
+          3,
+        ],
+        applied_vacancies: [
+          3,
+          1,
+        ],
+      },
       student: null,
     },
   };
diff --git a/assets/js/__test__/SupervisorPage-test.jsx b/assets/js/__test__/SupervisorPage-test.jsx
new file mode 100644
index 00000000..b2c7de81
--- /dev/null
+++ b/assets/js/__test__/SupervisorPage-test.jsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import ReactTestUtils from 'react-addons-test-utils';
+import fetchMock from 'fetch-mock';
+import SupervisorPage from '../SupervisorPage';
+
+describe('SupervisorPage', () => {
+  const data = {
+    count: 5,
+    next: null,
+    previous: null,
+    results: [
+      {
+        company_name: 'Tutuplapak',
+        name: 'Joshua Casey Darian Gunawan',
+        npm: 1406622616,
+        vacancy_name: 'Software Engineer',
+        status: 'accepted',
+      },
+      {
+        company_name: 'Tutuplapak',
+        name: 'Muhammad Reza Qorib',
+        npm: 1406543593,
+        vacancy_name: 'Software Engineer',
+        status: 'accepted',
+      },
+      {
+        company_name: 'Tutuplapak',
+        name: 'Muhammad Reza Qorib',
+        npm: 1406543593,
+        vacancy_name: 'Kepala Sekolah',
+        status: 'read',
+      },
+      {
+        company_name: 'company1',
+        name: 'Farhan Farasdak',
+        npm: 1406572321,
+        vacancy_name: 'Data Scientist',
+        status: 'new',
+      },
+      {
+        company_name: 'company1',
+        name: 'student2',
+        npm: 1406527513,
+        vacancy_name: 'Data Scientist',
+        status: 'new',
+      },
+    ],
+  };
+
+  fetchMock.get('*', data);
+
+  it('renders for admin without problem', () => {
+    const supervisorPage = ReactTestUtils.renderIntoDocument(
+      <SupervisorPage />);
+    expect(supervisorPage).to.exist;
+    fetchMock.restore();
+  });
+});
diff --git a/assets/js/__test__/components/Footer-test.jsx b/assets/js/__test__/components/Footer-test.jsx
new file mode 100644
index 00000000..d6cb3ee9
--- /dev/null
+++ b/assets/js/__test__/components/Footer-test.jsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import ReactTestUtils from 'react-addons-test-utils';
+import Footer from '../../components/Footer';
+
+describe('Footer', () => {
+
+  it('renders without problem', () => {
+    const footer = ReactTestUtils.renderIntoDocument(
+      <Footer params={{ id: 1 }} />);
+    expect(footer).to.exist;
+  });
+});
diff --git a/assets/js/__test__/components/TopMenu-test.jsx b/assets/js/__test__/components/TopMenu-test.jsx
index 7f841e10..b3398263 100644
--- a/assets/js/__test__/components/TopMenu-test.jsx
+++ b/assets/js/__test__/components/TopMenu-test.jsx
@@ -119,7 +119,28 @@ describe('TopMenu', () => {
       email: '',
       is_staff: false,
       company: null,
-      supervisor: null,
+      supervisor: {
+        id: 3,
+        user: {
+          url: 'http://localhost:8000/api/users/9/',
+          username: 'muhammad.reza42',
+          email: 'muhammad.reza42@ui.ac.id',
+          is_staff: false,
+        },
+        name: 'Muhammad R.',
+        created: '2017-03-28T13:33:46.147241Z',
+        updated: '2017-03-28T13:33:46.148248Z',
+        npm: 1406543593,
+        resume: null,
+        phone_number: null,
+        bookmarked_vacancies: [
+          3,
+        ],
+        applied_vacancies: [
+          3,
+          1,
+        ],
+      },
       student: null,
     },
   };
diff --git a/assets/js/__test__/components/VacancyList-test.jsx b/assets/js/__test__/components/VacancyList-test.jsx
index ee03b113..37389b29 100644
--- a/assets/js/__test__/components/VacancyList-test.jsx
+++ b/assets/js/__test__/components/VacancyList-test.jsx
@@ -35,7 +35,7 @@ describe('VacancyList', () => {
   };
 
   const studentUser = {
-    role: 'company',
+    role: 'student',
     data: {
       url: 'http://localhost:8001/api/users/8/',
       username: 'Tutuplapak',
@@ -69,6 +69,8 @@ describe('VacancyList', () => {
           1,
         ],
       },
+      company: null,
+      supervisor: null,
     },
   };
 
@@ -215,6 +217,38 @@ describe('VacancyList', () => {
     },
   ];
 
+  const response = [{
+    close_time: '2019-03-28T05:55:42Z',
+    company: {
+      address: 'kebayoran baru',
+      id: 1,
+      logo: null,
+      name: 'tutup lapak',
+    },
+    created: '2017-03-28T07:05:47.128672Z',
+    description: 'Lorem ipsum dolbh.',
+    id: 1,
+    name: 'Software Engineer',
+    open_time: '2017-03-28T05:55:38Z',
+    updated: '2017-03-28T07:34:13.122093Z',
+    verified: true,
+  }, {
+    close_time: '2019-03-28T05:55:42Z',
+    company: {
+      address: 'kebayoran baru',
+      id: 2,
+      logo: null,
+      name: 'tutup lapak',
+    },
+    created: '2017-03-28T07:05:47.128672Z',
+    description: 'Lorem ipsum dolbh.',
+    id: 2,
+    name: 'Software Engineer',
+    open_time: '2017-03-28T05:55:38Z',
+    updated: '2017-03-28T07:34:13.122093Z',
+    verified: true,
+  }];
+
   const response2 = [{
     close_time: '2019-03-28T05:55:42Z',
     company: {
@@ -235,96 +269,45 @@ describe('VacancyList', () => {
   it('renders without problem', () => {
     const vacancyList = ReactTestUtils.renderIntoDocument(
       <VacancyList items={newResponse} userId={1} user={studentUser} />);
+    vacancyList.generateVacancies();
     expect(vacancyList).to.exist;
   });
 
   it('renders without problem for company', () => {
     const vacancyList = ReactTestUtils.renderIntoDocument(
       <VacancyList items={newResponse} userId={1} user={companyUser} />);
+    vacancyList.generateVacancies();
     vacancyList.state.vacancies = newResponse;
     expect(vacancyList.generateVacancies()).to.exist;
   });
 
-  // it('renders with problem for company', () => {
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList type="company" userId={1} url="test" />);
-  //   vacancyList.state.vacancies = response;
-  //   expect(vacancyList.generateVacancies()).to.exist;
-  // });
-  //
-  // it('update bookmarks without problem', () => {
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList userId={1} url="test" />);
-  //   vacancyList.state.appliedList = [{ id: 1 }, { id: 3 }];
-  //   vacancyList.updateStatusList().then(() => {
-  //     expect(JSON.stringify(vacancyList.state.bookmarkList)).to.be.defined;
-  //   });
-  // });
-  //
-  // it('check applied vacancies without problem', () => {
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList userId={1} url="test" />);
-  //   vacancyList.updateStatusList().then(() => {
-  //     expect(JSON.stringify(vacancyList.state.bookmarkList)).to.be.defined;
-  //   });
-  // });
-  //
-  // it('renders marked bookmarked vacancies without problem', (done) => {
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList userId={1} url="test" />);
-  //   vacancyList.state.vacancies = response;
-  //   vacancyList.state.bookmarkList = [{ id: 5 }, { id: 3 }, { id: 1 }];
-  //   vacancyList.updateStatusList().then(() => {
-  //     expect(vacancyList.generateVacancies()).to.exist;
-  //     done();
-  //   }, () => done());
-  // });
-  //
-  // it('renders not marked vacancies without problem', () => {
-  //   fetchMock.get('*', response);
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList userId={1} url="test" />);
-  //   vacancyList.state.vacancies = response;
-  //   vacancyList.state.bookmarkList = [{ id: 6 }, { id: 4 }, { id: 2 }];
-  //   expect(vacancyList.generateVacancies()).to.exist;
-  //   fetchMock.restore();
-  // });
-  //
-  // it('success calling API', () => {
-  //   fetchMock.get('*', response);
-  //   const vacancyList = ReactTestUtils.renderIntoDocument(
-  //     <VacancyList userId={1} url="test" />);
-  //   vacancyList.state.vacancies = response;
-  //   expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response));
-  //   fetchMock.restore();
-  // });
-  //
   it('success delete vacancy', () => {
     fetchMock.restore();
     fetchMock.delete('*', response2);
+    fetchMock.get('*', newResponse);
     const vacancyList = ReactTestUtils.renderIntoDocument(
-      <VacancyList userId={1} url="test" deleteCallback={() => {}} user={companyUser} />);
+      <VacancyList items={newResponse} userId={1} deleteCallback={() => {}} user={companyUser} />);
     vacancyList.state.vacancies = newResponse;
     vacancyList.deleteVacancy(1).then(() => {
-      expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response));
+      expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(newResponse));
       fetchMock.restore();
     }, () => {
       fetchMock.restore();
     });
   });
 
-  it('fails delete vacancy', () => {
+  it('fails delete vacancy', (done) => {
     fetchMock.restore();
     fetchMock.delete('*', 404);
     const vacancyList = ReactTestUtils.renderIntoDocument(
       <VacancyList userId={1} items={newResponse} user={companyUser} deleteCallback={() => {}} />,
     );
-    vacancyList.state.vacancies = newResponse;
+    vacancyList.state.vacancies = response;
     vacancyList.deleteVacancy(1).then(() => {
       fetchMock.restore();
       done();
     }, () => {
-      expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(newResponse));
+      expect(JSON.stringify(vacancyList.state.vacancies)).to.equal(JSON.stringify(response));
       fetchMock.restore();
       done();
     });
diff --git a/assets/js/components/ApplicationList.jsx b/assets/js/components/ApplicationList.jsx
new file mode 100644
index 00000000..bf2decbd
--- /dev/null
+++ b/assets/js/components/ApplicationList.jsx
@@ -0,0 +1,55 @@
+import React from 'react';
+import { Table } from 'semantic-ui-react';
+
+export default class ApplicationList extends React.Component {
+  static propTypes = {
+    cols: React.PropTypes.any.isRequired,
+    items: React.PropTypes.any,
+  };
+
+  static defaultProps = {
+    items: [],
+  };
+
+  generateHeaders() {
+    const cols2 = this.props.cols;  // [{key, label}]
+
+        // generate our header (th) cell components
+    return cols2.map(colData =>
+      <Table.HeaderCell singleLine key={colData.key}> {colData.label} </Table.HeaderCell>
+     );
+  }
+
+  generateRows() {
+    return this.props.items.map(item =>
+      (
+        <Table.Row key={`${item.npm}_${item.company}_${item.position}_${item.status}_row`}>
+          <Table.Cell key={`${item.name}_name`}> {item.name} </Table.Cell>
+          <Table.Cell key={`${item.name}_npm`}> {item.npm} </Table.Cell>
+          <Table.Cell key={`${item.name}_company`}>
+            {item.company_name}
+          </Table.Cell>
+          <Table.Cell key={`${item.name}_position`}>
+            {item.vacancy_name}
+          </Table.Cell>
+          <Table.Cell key={`${item.name}_status`}>
+            {item.status}
+          </Table.Cell>
+        </Table.Row>
+      )
+    );
+  }
+
+  render() {
+    return (
+      <Table celled padded>
+        <Table.Header >
+          <Table.Row>
+            {this.generateHeaders()}
+          </Table.Row>
+        </Table.Header>
+        <Table.Body>{this.generateRows()}</Table.Body>
+      </Table>
+    );
+  }
+}
diff --git a/assets/js/components/SupervisorPage.jsx b/assets/js/components/SupervisorPage.jsx
deleted file mode 100644
index ad2062ce..00000000
--- a/assets/js/components/SupervisorPage.jsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import React from 'react';
-import { Header, Icon } from 'semantic-ui-react';
-import Tables from './Tables';
-import Server from '../lib/Server';
-
-const cols = [
-    { key: 'StudentName', label: 'Students Name' },
-    { key: 'Perusahaan', label: 'Perusahaan' },
-    { key: 'Posisi', label: 'Posisi' },
-    { key: 'Status', label: 'Status' },
-];
-
-const data2 = [
-    { id: 1, StudentName: 'John Doe', Perusahaan: 'Jalanloka', Posisi: 'Software Engineer', Status: 'Melamar' },
-    { id: 2, StudentName: 'Clark Kent', Perusahaan: 'Tutuplapak', Posisi: 'Data Scientist', Status: 'Diterima' },
-    { id: 3, StudentName: 'Rosamund Pike', Perusahaan: 'Tutuplapak', Posisi: 'System Analyst', Status: 'Diterima' },
-    { id: 4, StudentName: 'Melissa Benoist', Perusahaan: 'Blabla', Posisi: 'Data Scientist', Status: 'Melamar' },
-];
-
-
-export default class Applicants extends React.Component {
-
-  constructor(props) {
-    super(props);
-
-    this.state = { list: [] };
-  }
-
-  componentDidMount() {
-    this.UserList();
-  }
-
-  UserList() {
-    Server.get('/student-applications/', false).then((data) => {
-      this.setState({ list: data.results });
-    });
-  }
-
-  render() {
-    const list = this.state.list.map((item, i) => <div>
-      <h1>{item.name}</h1>
-      <span>{item.npm}, {item.email}</span>
-    </div>);
-    return (
-
-      <div className="home-dosen">
-        <Header as="h2">
-          <Icon name="list" />
-          <Header.Content>
-              Daftar Mahasiswa
-            </Header.Content>
-        </Header>
-
-
-        <div id="layout-content" className="layout-content-wrapper">
-          <Tables cols={cols} data={data2} />
-          <div className="panel-list">{ list }</div>
-        </div>
-      </div>
-
-    );
-  }
-}
diff --git a/assets/js/components/Tables.jsx b/assets/js/components/Tables.jsx
deleted file mode 100644
index 8d56cfa5..00000000
--- a/assets/js/components/Tables.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import React from 'react';
-import { Table } from 'semantic-ui-react';
-
-export default class Tables extends React.Component {
-  static propTypes = {
-    cols: React.PropTypes.any.isRequired,
-    data: React.PropTypes.any.isRequired,
-  };
-
-  generateHeaders() {
-    const cols2 = this.props.cols;  // [{key, label}]
-
-        // generate our header (th) cell components
-    return cols2.map(colData => <Table.HeaderCell singleLine key={colData.key}> {colData.label} </Table.HeaderCell>
-     , error => error.then(() => ('Gagal mendapatkan informasi data')),
-    );
-  }
-
-
-  generateRows() {
-    const cols3 = this.props.cols;  // [{key, label}]
-    const data2 = this.props.data;
-
-    return data2.map((item) => {
-            // handle the column data within each row
-      const cells = cols3.map(colData =>
-                // colData.key might be "firstName"
-        <Table.Cell> {item[colData.key]} </Table.Cell>);
-      return <Table.Row key={item.id}> {cells} </Table.Row>;
-    });
-  }
-
-  render() {
-    return (
-      <Table celled padded>
-        <Table.Header >
-          <Table.Row>
-            {this.generateHeaders()}
-          </Table.Row>
-        </Table.Header>
-        <Table.Body>{this.generateRows()}</Table.Body>
-      </Table>
-    );
-  }
-}
diff --git a/assets/js/components/TopMenu.jsx b/assets/js/components/TopMenu.jsx
index b5bc1f27..b3662174 100644
--- a/assets/js/components/TopMenu.jsx
+++ b/assets/js/components/TopMenu.jsx
@@ -4,67 +4,96 @@ import { Link, browserHistory } from 'react-router';
 import Server from '../lib/Server';
 import Storage from '../lib/Storage';
 
-const defaultImage = 'http://semantic-ui.com/images/avatar/small/elliot.jpg';
+const defaultPicture = 'http://semantic-ui.com/images/avatar/small/elliot.jpg';
 
 export default class TopMenu extends React.Component {
 
+  static getInfo(user) {
+    const adminRole = {
+      name: 'admin',
+      user: {
+        email: '',
+      },
+      photo: null,
+    };
+    const role = user.role;
+    if (role === 'student') {
+      return user.data.student;
+    } else if (role === 'company') {
+      return user.data.company;
+    } else if (role === 'supervisor') {
+      return user.data.supervisor;
+    }
+
+    return adminRole;
+  }
+
   static propTypes = {
-    // user: React.PropTypes.object.isRequired,
-    name: React.PropTypes.string.isRequired,
-    email: React.PropTypes.string.isRequired,
-    photo: React.PropTypes.any.isRequired,
+    user: React.PropTypes.object.isRequired,
   };
 
   constructor(props) {
     super(props);
     /* istanbul ignore next */
-    // console.log(this.props.user);
     this.state = { activeItem: 'home' };
     this.logout = this.logout.bind(this);
+    this.logoutCompany = this.logoutCompany.bind(this);
   }
 
   handleItemClick = (e, { name }) => this.setState({ activeItem: name });
 
-  logout = () => {
+  logout = (e) => {
+    e.preventDefault();
     Server.get('/api-auth/logout/?next=/', true).then(() => {
       Storage.clear();
       browserHistory.push('/login');
     });
   };
 
-
+  logoutCompany = /* istanbul ignore next */ (e) => {
+    e.preventDefault();
+    const userData = Storage.get('user-data');
+    userData.company = null;
+    Storage.set('user-data', userData);
+    window.location.replace('/home');
+  };
 
   render() {
     const { activeItem } = this.state;
-
+    const data = TopMenu.getInfo(this.props.user);
     return (
-      <Menu color="blue" pointing secondary>
-        <Image as="a" size="small" src="/assets/img/logo.png" href="/" />
-        <Menu.Menu position="right">
-          <Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} />
-          <Menu.Item as={Link} to="/profil" name="profile" onClick={this.handleItemClick} />
-          <Menu.Item>
-            <Popup
-              trigger={<Image
-                as={Link} to="/profil"
-                src={this.props.photo ? this.props.photo : defaultImage} avatar
-                onClick={this.handleItemClick}
-              />}
-              flowing
-              hoverable
-            >
-
-              <Card
-                header={this.props.name}
-                description={this.props.email}
-              />
-              <Button as={Link} onClick={this.logout} name="logout" color="blue" size="tiny">Logout</Button>
+      <div>
+        { this.props.user.data.is_staff && this.props.user.data.company && (
+          <div className="admin-bar">
+            Anda login sebagai perusahaan: {this.props.user.data.company.name} (#{this.props.user.data.company.id}).
+            Untuk keluar, silahkan klik <a href="#" onClick={this.logoutCompany}> link ini</a>
+          </div>
+        )}
+        <Menu color="blue" pointing secondary>
+          <Image as="a" size="small" src="/assets/img/logo.png" href="/" />
+          <Menu.Menu position="right">
+            <Menu.Item as={Link} to="/home" name="home" active={activeItem === 'home'} onClick={this.handleItemClick} />
+            <Menu.Item>
+              <Popup
+                trigger={<Image
+                  as={Link} to="/profil" src={data.photo || defaultPicture} avatar
+                  onClick={this.handleItemClick}
+                />}
+                flowing
+                hoverable
+              >
+                <Card
+                  header={data.name}
+                  description={data.user.email}
+                />
+                <Button as={Link} onClick={this.logout} name="logout" color="blue" size="tiny">Logout</Button>
 
-            </Popup>
+              </Popup>
 
-          </Menu.Item>
-        </Menu.Menu>
-      </Menu>
+            </Menu.Item>
+          </Menu.Menu>
+        </Menu>
+      </div>
     );
   }
 }
diff --git a/assets/js/index.jsx b/assets/js/index.jsx
index 625b87d6..218b6933 100644
--- a/assets/js/index.jsx
+++ b/assets/js/index.jsx
@@ -13,6 +13,7 @@ import ApplicantPage from './ApplicantPage';
 import TranscriptPage from './TranscriptPage';
 import AdminVacancyPage from './AdminVacancyPage';
 import CompanyPage from './CompanyPage';
+import SupervisorPage from './SupervisorPage'
 
 export default class App extends React.Component {
 
@@ -91,7 +92,7 @@ export default class App extends React.Component {
   render() {
     const staff = this.authorization(['admin']);
     const student = this.authorization(['admin', 'student']);
-    // const supervisor = this.authorization(['admin', 'supervisor']);
+    const supervisor = this.authorization(['admin', 'supervisor']);
     const company = this.authorization(['admin', 'company']);
     const commonUser = this.authorization(['admin', 'student', 'company']);
     const grownups = this.authorization(['admin', 'company', 'supervisor']);
@@ -112,6 +113,7 @@ export default class App extends React.Component {
           <Route path="/mahasiswa/:id" component={grownups(ProfilePage)} />
           <Route path="/perusahaan/:id" component={facultyMember(CompanyProfile)} />
           <Route path="/perusahaan" component={staff(CompanyPage)} />
+          <Route path="/rekap" component={supervisor(SupervisorPage)} />
           <Route path="/transkrip/:id" component={facultyMember(CompanyProfile)} />
         </Route>
         <Route path="/home" onEnter={this.handleHome} />
-- 
GitLab