Skip to content
Draft
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
1 change: 1 addition & 0 deletions components/admin/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const DropdownMenu: React.FC<{ onChange?: (value: string) => void }> = ({
>
<option value="Delegation Dashboard">Delegation Dashboard</option>
<option value="Review Dashboard">Review Dashboard</option>
<option value="Interview Dashboard">Interview Dashboard</option>
</select>
</div>
);
Expand Down
202 changes: 202 additions & 0 deletions components/admin/InterviewTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { MuiThemeProvider } from "@material-ui/core/styles";
import { fetchGraphql } from "@utils/makegqlrequest";
import MUIDataTable from "mui-datatables";
import React, { useEffect, useState } from "react";
import { getInterviewTableColumns } from "./InterviewTableColumn";
import ApplicantRole from "entities/applicationRole";
import { ResumeIcon } from "@components/icons/resume.icon";
import { applicationTableQueries } from "graphql/queries";
import { getMuiTheme } from "utils/muidatatable";
import ExpandableRowTable from "./ExpandableRowTable";

interface TableProps {
activeRole?: ApplicantRole;
whichChoiceTab?: number;
setNumFirstChoiceEntries: (tab: number) => void;
numFirstChoiceEntries?: number;
setNumSecondChoiceEntries: (tab: number) => void;
numSecondChoiceEntries?: number;
}

const InterviewTable: React.FC<TableProps> = ({
activeRole,
whichChoiceTab,
setNumFirstChoiceEntries,
setNumSecondChoiceEntries,
}) => {
const [firstChoiceApplications, setFirstChoiceApplications] = useState<any[]>(
[],
);
const [secondChoiceApplications, setSecondChoiceApplications] = useState<
any[]
>([]);
useEffect(() => {
fetchApplicationsByRole();
}, [activeRole, whichChoiceTab]);

const fetchApplicationsByRole = async () => {
const currentRole = activeRole || ApplicantRole.vpe;
try {
const firstChoiceResult = await fetchGraphql(
applicationTableQueries.applicationsByRole,
{
role: currentRole,
},
);

const secondChoiceResult = await fetchGraphql(
applicationTableQueries.applicationsBySecondChoiceRole,
{
role: currentRole,
},
);
setFirstChoiceApplications(firstChoiceResult.data.applicationTable);
setNumFirstChoiceEntries(firstChoiceResult.data.applicationTable.length);

setSecondChoiceApplications(
secondChoiceResult.data.secondChoiceRoleApplicationTable,
);
setNumSecondChoiceEntries(
secondChoiceResult.data.secondChoiceRoleApplicationTable.length,
);
} catch (error) {
console.error("Error fetching applications:", error);
}
};

const createStudentRow = (application: any) => {
const app = application.application;

return {
id: app.id,
name: app.firstName + " " + app.lastName,
resume: (
<a target="_blank" href={app.resumeUrl} className="flex items-center">
<ResumeIcon />
<span className="ml-2 underline">View Resume</span>
</a>
),
term: app.academicYear,
program: app.program,
status: app.status,
secondChoice: app.secondChoiceRole,
secondChoiceStatus: app.secondChoiceStatus,
};
};

const getTableRows = () => {
if (!whichChoiceTab) {
return firstChoiceApplications.map(createStudentRow);
}
return secondChoiceApplications.map(createStudentRow);
};

const generateMockInnerData = () => {
return [
{
"Reviewer Name": "John Doe",
PFSG: 4,
"Team Player": 3,
D2L: 6,
Skill: 5,
"Skill Category": "junior",
"Reviewer Comments": "Great work presenting your case study.",
},
// Add as many objects as you want to simulate different rows
];
};

const renderExpandableRow = (
rowData: any,
rowMeta: { dataIndex: number },
) => {
const innerData = generateMockInnerData(); // Use mock data for testing
const application = {
secondChoiceRole: "Graphic Designer",
recommendForSecondChoice: true,
adminComments: "Great",
};

const innerColumns = [
{
name: "Reviewer Name",
options: { filter: false, sort: false },
},
{ name: "PFSG", options: { filter: false, sort: false } },
{ name: "Team Player", options: { filter: false, sort: false } },
{ name: "D2L", options: { filter: false, sort: false } },
{ name: "Skill", options: { filter: false, sort: false } },
{
name: "Skill Category",
options: { filter: false, sort: false },
},
{
name: "Reviewer Comments",
options: { filter: false, sort: false },
},
// You may add more columns as needed
];

return (
<React.Fragment>
<tr>
<td colSpan={8} className="p-5 px-10">
<div className="flex flex-col font-source text-base">
<ExpandableRowTable data={innerData} columns={innerColumns} />
<div className="flex items-start p-4 gap-120">
<div className="flex flex-col gap-2">
<div className="flex flex-row justify-center items-center gap-5">
<span className="text-blue font-semibold">2nd Choice:</span>
<p>{application.secondChoiceRole}</p>
</div>

<div className="flex items-center mt-2">
<input
type="checkbox"
checked={application.recommendForSecondChoice}
// onChange logic here
/>
<span className="ml-2">Recommend for 2nd Choice</span>
</div>
</div>
<div className="flex flex-col">
<span className="text-blue font-semibold">
Admin Comments:
</span>
<p>{application.adminComments}</p>
</div>
</div>
</div>
</td>
</tr>
<td colSpan={11} style={{ borderBottom: "1px solid #e0e0e0" }}></td>
</React.Fragment>
);
};

return (
<MuiThemeProvider theme={getMuiTheme()}>
<MUIDataTable
title=""
data={getTableRows()}
columns={getInterviewTableColumns()}
options={{
search: true,
viewColumns: false,
download: false,
print: false,
searchPlaceholder: "Search by name, reviewer, status, etc...",
filter: true,
selectableRows: "none",
sortFilterList: true,
expandableRows: true,
expandableRowsHeader: false,
expandableRowsOnClick: true,
renderExpandableRow: renderExpandableRow,
}}
/>
</MuiThemeProvider>
);
};

export default InterviewTable;
101 changes: 101 additions & 0 deletions components/admin/InterviewTableColumn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { MUIDataTableColumn } from "mui-datatables";
import { LinkIcon } from "@components/icons/link.icon";
import { Status, SkillCategory } from "@utils/muidatatable";
import { router } from "next/router";

export const getInterviewTableColumns = (): MUIDataTableColumn[] => {
const handleNameClick = (appId: string) => {
router.push(`/review?reviewId=${appId}`);
};

const columns: MUIDataTableColumn[] = [
{
name: "id",
options: {
display: "excluded",
filter: false,
searchable: false,
sort: false,
},
},
{
name: "name",
label: "Application",
options: {
filter: false,
// sortCompare: (order: "asc" | "desc") => createSortFunction(order),
searchable: true,
customBodyRender(value, tableMeta, updateValue) {
const appId = tableMeta.rowData[0];
return (
<div
onClick={() => handleNameClick(appId)}
className="flex items-center cursor-pointer"
>
<LinkIcon />
<span className="ml-2 underline">{value}</span>
</div>
);
},
},
},
{
name: "term",
label: "Term",
options: {
filter: false,
sort: true,
searchable: true,
},
},
{
name: "status",
label: "Status",
options: {
filter: true,
sort: true,
searchable: true,
filterOptions: {
names: [
"accepted",
"applied",
"interviewed",
"in review",
"pending",
"rejected",
],
},
filterType: "multiselect",
customBodyRender(value, tableMeta, updateValue) {
return <Status status={value} />;
},
},
},
{
name: "skillCategory",
label: "Skill Category",
options: {
filter: true,
sort: true,
searchable: true,
filterOptions: {
names: ["intermediate", "junior", "senior"],
},
filterType: "multiselect",
customBodyRender(value, tableMeta, updateValue) {
return <SkillCategory category={value} />;
},
},
},
{
name: "resume",
label: "Resume",
options: {
filter: false,
sort: true,
searchable: true,
},
},
];
return columns;
};
42 changes: 42 additions & 0 deletions components/admin/InterviewTableTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { FC } from "react";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";

interface TitleProps {
numFirstChoiceEntries?: number;
numSecondChoiceEntries?: number;
setWhichChoiceTab: (tab: number) => void;
whichChoiceTab?: number;
}
interface TabDescriptionProps {
title: string;
numEntries: number | undefined;
pillStyle: string;
}

interface SimpleTableTitleProps {
numEntries: number | undefined;
}

const InterviewTableTitle: React.FC<SimpleTableTitleProps> = ({ numEntries }) => {
const pillStyle =
"border-2 border-blue-100 text-blue rounded-full px-4 py-2 m-2 font-large inline-block";

return (
<div className="bg-sky rounded-t text-blue-300 text-base font-inter font-medium px-4 py-1 flex justify-between items-center">
<div
className="flex items-baseline"
style={{
color: "black",
textTransform: "none",
fontSize: 20,
width: 400,
}}
>
Applicants <span className={pillStyle}>{numEntries} Entries</span>
</div>
</div>
);
};

export default InterviewTableTitle;
Loading