Skip to content

Commit

Permalink
feat: Add metrics students panel
Browse files Browse the repository at this point in the history
  • Loading branch information
AuraAlba committed Dec 15, 2023
1 parent b799e1f commit bbb70d5
Show file tree
Hide file tree
Showing 12 changed files with 266 additions and 5 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"react": "16.14.0",
"react-dom": "16.14.0",
"react-intl": "^5.25.1",
"react-paragon-topaz": "^1.1.4",
"react-paragon-topaz": "^1.2.1",
"react-router": "5.2.1",
"react-router-dom": "5.3.0",
"regenerator-runtime": "0.13.11"
Expand Down
6 changes: 6 additions & 0 deletions src/assets/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@ $color-gray: #60646d;
$gradient-gray: rgba(247, 249, 253, 0.1);
$color-active-button: #989ba3;
$bg-main-color: white;
$gray-light: #dfe1e1;
$color-pink: #ffd0d7;
$color-green: #c4eacd;
$color-yellow: #f2f4be;
$color-purple: #e4b8d6;
$black-80: #333;
1 change: 1 addition & 0 deletions src/assets/global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
border: 1px solid #dfe1e1;
border-radius: 0.375rem;
padding: 20px 0;
box-shadow: 0px 3px 12px 0px rgba(0, 0, 0, 0.16);
}

.filter-container > div {
Expand Down
18 changes: 18 additions & 0 deletions src/features/Students/StudentsMetrics/_test_/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import { render } from '@testing-library/react';
import StudentsMetrics from 'features/Students/StudentsMetrics';
import '@testing-library/jest-dom/extend-expect';

describe('StudentsMetrics component', () => {
test('renders components', () => {
const { getByText } = render(
<StudentsMetrics />,
);

expect(getByText('This week')).toBeInTheDocument();
expect(getByText('Next week')).toBeInTheDocument();
expect(getByText('Next month')).toBeInTheDocument();
expect(getByText('New students registered')).toBeInTheDocument();
expect(getByText('Classes scheduled')).toBeInTheDocument();
});
});
52 changes: 52 additions & 0 deletions src/features/Students/StudentsMetrics/_test_/reducer.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
FETCH_METRICS_DATA_REQUEST,
FETCH_METRICS_DATA_SUCCESS,
FETCH_METRICS_DATA_FAILURE,
} from 'features/Students/actionTypes';
import { RequestStatus } from 'features/constants';
import reducer from 'features/Students/StudentsMetrics/reducer';

describe('Student filter reducers', () => {
const initialState = {
data: [],
status: RequestStatus.SUCCESS,
error: null,
};

test('should handle FETCH_METRICS_DATA_REQUEST', () => {
const state = {
...initialState,
status: RequestStatus.LOADING,
};
const action = {
type: FETCH_METRICS_DATA_REQUEST,
};
expect(reducer(state, action)).toEqual(state);
});

test('should handle FETCH_METRICS_DATA_SUCCESS', () => {
const state = {
...initialState,
status: RequestStatus.SUCCESS,
data: [],
};
const action = {
type: FETCH_METRICS_DATA_SUCCESS,
payload: [],
};
expect(reducer(state, action)).toEqual(state);
});

test('should handle FETCH_METRICS_DATA_FAILURE', () => {
const state = {
...initialState,
status: RequestStatus.ERROR,
error: '',
};
const action = {
type: FETCH_METRICS_DATA_FAILURE,
payload: '',
};
expect(reducer(state, action)).toEqual(state);
});
});
82 changes: 82 additions & 0 deletions src/features/Students/StudentsMetrics/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useEffect, useReducer } from 'react';
import { Card, CardGrid, ToggleButton } from '@edx/paragon';
import { ToggleButtonGroup } from 'react-paragon-topaz';
import { logError } from '@edx/frontend-platform/logging';
import { camelCaseObject } from '@edx/frontend-platform';
import { getMetricsStudents } from 'features/Students/data/api';
import { RequestStatus } from 'features/constants';
import reducer from 'features/Students/StudentsMetrics/reducer';
import {
FETCH_METRICS_DATA_REQUEST,
FETCH_METRICS_DATA_SUCCESS,
FETCH_METRICS_DATA_FAILURE,
} from 'features/Students/actionTypes';
import 'features/Students/StudentsMetrics/index.scss';

const initialState = {
data: [],
status: RequestStatus.SUCCESS,
error: null,
};

const StudentsMetrics = () => {
const [state, dispatch] = useReducer(reducer, initialState);

const fetchMetricsData = async () => {
dispatch({ type: FETCH_METRICS_DATA_REQUEST });

try {
const response = camelCaseObject(await getMetricsStudents());
dispatch({ type: FETCH_METRICS_DATA_SUCCESS, payload: response });
} catch (error) {
dispatch({ type: FETCH_METRICS_DATA_FAILURE, payload: error });
logError(error);
}
};

useEffect(() => {
fetchMetricsData();
}, []);

return (
<div className="container-cards d-flex flex-column">
<ToggleButtonGroup type="radio" defaultValue={1} name="period">
<ToggleButton id="tbg-radio-1" value={1} variant="outline-primary">
This week
</ToggleButton>
<ToggleButton id="tbg-radio-2" value={2} variant="outline-primary">
Next week
</ToggleButton>
<ToggleButton id="tbg-radio-3" value={3} variant="outline-primary">
Next month
</ToggleButton>
</ToggleButtonGroup>
<CardGrid
columnSizes={{
xs: 12,
xl: 6,
}}
className="w-100"
>
<Card className="card-pink">
<Card.Header
title="New students registered"
/>
<Card.Section>
<div className="card-number">{state.data.newStudentsRegistered}</div>
</Card.Section>
</Card>
<Card className="card-green">
<Card.Header
title="Classes scheduled"
/>
<Card.Section>
<div className="card-number">{state.data.classesScheduled}</div>
</Card.Section>
</Card>
</CardGrid>
</div>
);
};

export default StudentsMetrics;
55 changes: 55 additions & 0 deletions src/features/Students/StudentsMetrics/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
@import "assets/colors.scss";

.container-cards {
border: 1px solid $gray-light;
padding: 2rem;
border-radius: 0.375rem;
margin-bottom: 2rem;
box-shadow: 0px 3px 12px 0px rgba(0, 0, 0, 0.16);

.pgn__card {
box-shadow: none;
min-height: 160px;

.pgn__card-header .pgn__card-header-content {
margin-top: 1rem;
}

.pgn__card-header .pgn__card-header-title-md {
font-size: 1rem;
text-align: center;
font-weight: 600;
color: $black-80;
}

.pgn__card-section {
text-align: center;
}
}

.card-pink {
background: $color-pink;
}

.card-green {
background: $color-green;
}

.card-yellow {
background: $color-yellow;
}

.card-purple {
background: $color-purple;
}

.card-number {
font-size: 44px;
color: $black-80;
}

.btn-group-tpz {
width: 45%;
margin-bottom: 2rem;
}
}
32 changes: 32 additions & 0 deletions src/features/Students/StudentsMetrics/reducer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
FETCH_METRICS_DATA_REQUEST,
FETCH_METRICS_DATA_SUCCESS,
FETCH_METRICS_DATA_FAILURE,
} from 'features/Students/actionTypes';
import { RequestStatus } from 'features/constants';

const reducer = (state, action) => {
switch (action.type) {
case FETCH_METRICS_DATA_REQUEST:
return {
...state,
status: RequestStatus.LOADING,
};
case FETCH_METRICS_DATA_SUCCESS:
return {
...state,
status: RequestStatus.SUCCESS,
data: action.payload,
};
case FETCH_METRICS_DATA_FAILURE:
return {
...state,
status: RequestStatus.ERROR,
error: action.payload,
};
default:
return state;
}
};

export default reducer;
2 changes: 2 additions & 0 deletions src/features/Students/StudentsPage/index.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getStudentbyInstitutionAdmin } from 'features/Students/data/api';
import { StudentsTable } from 'features/Students/StudentsTable/index';
import StudentsFilters from 'features/Students/StudentsFilters';
import StudentsMetrics from 'features/Students/StudentsMetrics';
import { RequestStatus } from 'features/constants';
import reducer from 'features/Students/StudentsPage/reducer';

Expand Down Expand Up @@ -60,6 +61,7 @@ const StudentsPage = () => {
return (
<Container size="xl">
<h1>Students</h1>
<StudentsMetrics />
<div className="page-content-container">
<StudentsFilters fetchData={fetchData} resetPagination={resetPagination} setFilters={setFilters} />
<StudentsTable
Expand Down
4 changes: 4 additions & 0 deletions src/features/Students/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ export const FETCH_CLASSES_DATA_REQUEST = 'FETCH_CLASSES_DATA_REQUEST';
export const FETCH_CLASSES_DATA_SUCCESS = 'FETCH_CLASSES_DATA_SUCCESS';
export const FETCH_CLASSES_DATA_FAILURE = 'FETCH_CLASSES_DATA_FAILURE';

export const FETCH_METRICS_DATA_REQUEST = 'FETCH_METRICS_DATA_REQUEST';
export const FETCH_METRICS_DATA_SUCCESS = 'FETCH_METRICS_DATA_SUCCESS';
export const FETCH_METRICS_DATA_FAILURE = 'FETCH_METRICS_DATA_FAILURE';

export const UPDATE_CURRENT_PAGE = 'UPDATE_CURRENT_PAGE';
9 changes: 9 additions & 0 deletions src/features/Students/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,17 @@ function getClassesByInstitution(institutionId, courseName) {
);
}

function getMetricsStudents() {
const metricsData = {
new_students_registered: '367',
classes_scheduled: '71%',
};
return metricsData;
}

export {
getStudentbyInstitutionAdmin,
handleEnrollments,
getClassesByInstitution,
getMetricsStudents,
};

0 comments on commit bbb70d5

Please sign in to comment.