Skip to content

Commit

Permalink
Updated details dashboard logic to avoid merging 3 APIs and utilize f… (
Browse files Browse the repository at this point in the history
#488)

* Updated details dashboard logic to avoid merging 3 APIs and utilize funtions instead. Updated snapshot tests to accomodate new props associated with details dashboard ammendment. Minor name changes to old variables to be more specific

Co-authored-by: Guillermo Flores V <hello@gfloresv.dev>
Co-authored-by: Komal Kaur <kaur91499@gmail.com>
Co-authored-by: Utsab Saha <utsab.k.saha@gmail.com>
Co-authored-by: Edgar Peralta <https://github.com/EPeralta18>

* [CodeFactor] Apply fixes to commit 9a093f4

---------

Co-authored-by: Guillermo Flores V <hello@gfloresv.dev>
Co-authored-by: Komal Kaur <kaur91499@gmail.com>
Co-authored-by: Utsab Saha <utsab.k.saha@gmail.com>
Co-authored-by: codefactor-io <support@codefactor.io>
  • Loading branch information
5 people authored Jan 2, 2025
1 parent e28118d commit b9e5a4e
Show file tree
Hide file tree
Showing 9 changed files with 514 additions and 140 deletions.
16 changes: 11 additions & 5 deletions __tests__/components/dashtable_v2.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@ import { render } from '@testing-library/react';
import React from 'react';
import GlobalDashboardTable from '../../components/dashtable_v2.js';

import {studentData, certifications, classroomId, timestamps, totalChallenges} from '../../testing_data/testing-data';
import {
studentData,
classroomId,
studentsAreEnrolledInSuperblocks,
totalChallenges
} from '../../testing_data/testing-data';

describe('GlobalDashboardTable', () => {
// Define a fixed time in milliseconds
const fixedTime = new Date('2016-03-09T12:00:00Z').getTime();

// Spy on Date.prototype.getTime and mock its implementation
const getTimeSpy = jest.spyOn(Date.prototype, 'getTime').mockImplementation(() => fixedTime);
const getTimeSpy = jest
.spyOn(Date.prototype, 'getTime')
.mockImplementation(() => fixedTime);

// Restore the original getTime method after the test
afterEach(() => {
Expand All @@ -20,13 +27,12 @@ describe('GlobalDashboardTable', () => {
const { container } = render(
<GlobalDashboardTable
studentData={studentData}
certifications={certifications}
classroomId={classroomId}
totalChallenges={totalChallenges}
timestamps={timestamps}
studentsAreEnrolledInSuperblocks={studentsAreEnrolledInSuperblocks}
/>
);
expect(getTimeSpy).toHaveBeenCalled();
expect(container).toMatchSnapshot();
});
});
});
62 changes: 62 additions & 0 deletions components/DetailsCSS.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.student_header {
display: flex;
font-size: 1.1rem;
margin: 10px;
border-bottom: 2px solid purple;
color: navy;
font-weight: 100;
background-color: hsl(194, 35%, 76%);
max-width: fit-content;
}

.board_container {
border: 4px solid black;
padding: 10px;
margin: 0px 5px 1px;
background-color: grey;
color: white;
}

.list_container {
display: flex;

flex-direction: row;
align-items: center;
gap: 10px;
}

.list_container h1 {
font-weight: bold;
font-size: 1.2rem;
}
.list_container button {
font-size: 0.7rem;
text-transform: uppercase;
border: 1px solid navy;

padding: 5px 10px;
background-color: orange;
}

.list_container button:hover {
background-color: rgb(89, 103, 174);
color: white;
}
.inner_comp {
background-color: grey;
color: white;
}

.details_progress_stats {
background-color: rgb(27, 15, 86);
color: white;
display: flex;
flex-direction: row;
justify-content: space-between;
border: 1px solid rgb(93, 0, 255);
padding: 10px;
}

.detailsBlockTitle {
font-size: 1;
}
46 changes: 46 additions & 0 deletions components/DetailsDashboard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import styles from './DetailsCSS.module.css';
import DetailsDashboardList from './DetailsDashboardList';
//getStudentProgressInSuperblock

import { getStudentProgressInSuperblock } from '../util/api_proccesor';

export default function DetailsDashboard(props) {
const printSuperblockTitle = individualSuperblockJSON => {
let indexOfTitleInSuperblockTitlesArray =
props.superblocksDetailsJSONArray.indexOf(individualSuperblockJSON);
let superblockTitle =
props.superblockTitles[indexOfTitleInSuperblockTitlesArray];
return superblockTitle;
};

const superblockProgress = superblockDashedName => {
let studentProgress = props.studentData;

return getStudentProgressInSuperblock(
studentProgress,
superblockDashedName
);
};

return (
<>
{props.superblocksDetailsJSONArray.map((arrayOfBlockObjs, idx) => {
let index = props.superblocksDetailsJSONArray.indexOf(arrayOfBlockObjs);
let superblockDashedName =
props.superblocksDetailsJSONArray[index][0].superblock;
let progressInBlocks = superblockProgress(superblockDashedName);
let superblockTitle = printSuperblockTitle(arrayOfBlockObjs);
return (
<div key={idx} className={styles.board_container}>
<DetailsDashboardList
superblockTitle={superblockTitle}
blockData={arrayOfBlockObjs}
studentProgressInBlocks={progressInBlocks}
></DetailsDashboardList>
</div>
);
})}
</>
);
}
70 changes: 70 additions & 0 deletions components/DetailsDashboardList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { useState } from 'react';
import styles from './DetailsCSS.module.css';
import { getStudentTotalChallengesCompletedInBlock } from '../util/api_proccesor';

export default function DetailsDashboardList(props) {
const [hideDetails, setHideDetails] = useState(true);
const [buttonText, setButtonText] = useState('View details');

const handleShowDetails = () => {
if (hideDetails) {
setHideDetails(false);
} else {
setHideDetails(true);
}

handleButtonText(hideDetails);
};

const handleButtonText = hideDetails => {
if (hideDetails) {
setButtonText('View less');
} else {
setButtonText('View details');
}
};

const getStudentsProgressInBlock = blockName => {
return getStudentTotalChallengesCompletedInBlock(
props.studentProgressInBlocks,
blockName
);
};

return (
<>
<div className={styles.list_container}>
<h1>{props.superblockTitle} </h1>

<button onClick={handleShowDetails}>{buttonText}</button>
</div>
<div className={styles.inner_comp}>
{hideDetails ? (
''
) : (
<>
<ul>
<li>
{props.blockData.map((blockDetails, idx) => {
return (
<div className={styles.details_progress_stats} key={idx}>
<h1 className={styles.detailsBlockTitle}>
{blockDetails.blockName}
</h1>
<h1 className={styles.focus}>
{getStudentsProgressInBlock(blockDetails.selector) +
'/' +
blockDetails.allChallenges.length}
</h1>
</div>
);
})}
</li>
</ul>
</>
)}
</div>
</>
);
}
11 changes: 5 additions & 6 deletions components/dashtable_v2.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { useTable } from 'react-table';
import React from 'react';
import getStudentActivity from './studentActivity';
import { extractStudentCompletionTimestamps } from '../util/api_proccesor';

export default function GlobalDashboardTable(props) {
let grandTotalChallenges = props.totalChallenges;

let rawStudentSummary = props.studentData.map(studentJSON => {
let email = studentJSON.email;
let completionTimestamps = [];

props.timestamps.forEach(timestampObj => {
if (timestampObj.name === email) {
completionTimestamps = timestampObj.completedTimestamps;
}
});
completionTimestamps = extractStudentCompletionTimestamps(
studentJSON.certifications
);

let rawStudentActivity = {
recentCompletions: completionTimestamps
};

let studentActivity = getStudentActivity(rawStudentActivity);

let numCompletions = completionTimestamps.length;

let percentageCompletion = (
Expand Down
51 changes: 34 additions & 17 deletions pages/dashboard/v2/[id].js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { getSession } from 'next-auth/react';
import GlobalDashboardTable from '../../../components/dashtable_v2';
import React from 'react';
import {
createDashboardObject,
getTotalChallenges,
createSuperblockDashboardObject,
getTotalChallengesForSuperblocks,
getDashedNamesURLs,
getSuperBlockJsons,
formattedStudentData,
getCompletionTimestamps
fetchStudentData,
checkIfStudentHasProgressDataForSuperblocksSelectedByTeacher
} from '../../../util/api_proccesor';

export async function getServerSideProps(context) {
Expand Down Expand Up @@ -58,35 +58,52 @@ export async function getServerSideProps(context) {
}
});

let formattedStudentDataResponse = await formattedStudentData();

let timestamps = getCompletionTimestamps(formattedStudentDataResponse);

let superblockURLS = await getDashedNamesURLs(
certificationNumbers.fccCertifications
);

let superBlockJsons = await getSuperBlockJsons(superblockURLS);
let dashboardObjs = createDashboardObject(superBlockJsons);
let totalChallenges = getTotalChallenges(dashboardObjs);
let superBlockJsons = await getSuperBlockJsons(superblockURLS); // this is an array of urls
let dashboardObjs = await createSuperblockDashboardObject(superBlockJsons);

let totalChallenges = getTotalChallengesForSuperblocks(dashboardObjs);

let studentData = await fetchStudentData();

// Temporary check to map/accomodate hard-coded mock student data progress in unselected superblocks by teacher
let studentsAreEnrolledInSuperblocks =
checkIfStudentHasProgressDataForSuperblocksSelectedByTeacher(
studentData,
dashboardObjs
);
studentData.forEach(studentJSON => {
let indexToCheckProgress = studentData.indexOf(studentJSON);
let isStudentEnrolledInAtLeastOneSuperblock =
studentsAreEnrolledInSuperblocks[indexToCheckProgress].every(
val => val === true
);

if (!isStudentEnrolledInAtLeastOneSuperblock) {
studentData[indexToCheckProgress].certifications = [];
}
});

return {
props: {
userSession,
classroomId: context.params.id,
studentData: formattedStudentDataResponse,
studentData,
totalChallenges: totalChallenges,
timestamps: timestamps
studentsAreEnrolledInSuperblocks
}
};
}

export default function Home({
userSession,
studentData,
classroomId,
totalChallenges,
timestamps
studentData,
studentsAreEnrolledInSuperblocks
}) {
return (
<Layout>
Expand All @@ -106,10 +123,10 @@ export default function Home({
</div>
</Navbar>
<GlobalDashboardTable
studentData={studentData}
classroomId={classroomId}
timestamps={timestamps}
totalChallenges={totalChallenges}
studentData={studentData}
studentsAreEnrolledInSuperblocks={studentsAreEnrolledInSuperblocks}
></GlobalDashboardTable>
</>
)}
Expand Down
Loading

0 comments on commit b9e5a4e

Please sign in to comment.