Skip to content
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
109 changes: 109 additions & 0 deletions src/components/PRGradingScreen/InlinePRSummary.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import PropTypes from 'prop-types';
import styles from './PRGradingScreen.module.css';

const GRADE_OPTIONS = [
{ label: 'Exceptional', value: 'Exceptional' },
{ label: 'Okay', value: 'Okay' },
{ label: 'Unsatisfactory', value: 'Unsatisfactory' },
{ label: 'Cannot find image', value: 'No Correct Image' },
];

const InlinePRSummary = ({ reviewer, onGradeChange, isFinalized, darkMode }) => {
const dm = darkMode ? styles['dark-mode'] : '';

if (!reviewer.gradedPrs || reviewer.gradedPrs.length === 0) {
return null;
}

return (
<tr className={styles['pr-grading-inline-summary-row']}>
<td colSpan={4} className={styles['pr-grading-inline-summary-cell']}>
<div className={`${styles['pr-grading-inline-summary-container']} ${dm}`}>
<table className={`${styles['pr-grading-inline-summary-table']} ${dm}`}>
<thead>
<tr>
<th
className={`${styles['pr-grading-inline-header-cell']} ${styles['pr-grading-inline-pr-col']} ${dm}`}
>
PR Number
</th>
{GRADE_OPTIONS.map(opt => (
<th
key={opt.value}
className={`${styles['pr-grading-inline-header-cell']} ${styles['pr-grading-inline-grade-col']} ${dm}`}
>
{opt.label}
</th>
))}
</tr>
</thead>
<tbody>
{reviewer.gradedPrs.map(pr => {
const isPair = pr.prNumbers.includes('+');
return (
<tr key={pr.id} className={styles['pr-grading-inline-item-row']}>
<td
className={`${styles['pr-grading-inline-data-cell']} ${styles['pr-grading-inline-pr-cell']} ${dm}`}
>
<span
className={`${styles['pr-grading-inline-pr-tag']} ${
isPair
? styles['pr-grading-inline-pair-tag']
: styles['pr-grading-inline-single-tag']
} ${dm}`}
>
{pr.prNumbers}
</span>
</td>
{GRADE_OPTIONS.map(opt => {
const isChecked =
pr.grade === opt.value ||
(opt.value === 'No Correct Image' && pr.grade === 'Cannot find image');
return (
<td
key={opt.value}
className={`${styles['pr-grading-inline-data-cell']} ${styles['pr-grading-pr-grading-inline-checkbox-cell']} ${dm}`}
>
<input
type="checkbox"
checked={isChecked}
disabled={isFinalized}
onChange={() => onGradeChange(reviewer.id, pr.id, opt.value)}
className={styles['pr-grading-inline-checkbox']}
aria-label={`${pr.prNumbers} ${opt.label}`}
/>
</td>
);
})}
</tr>
);
})}
</tbody>
</table>
</div>
</td>
</tr>
);
};

InlinePRSummary.propTypes = {
reviewer: PropTypes.shape({
id: PropTypes.string.isRequired,
gradedPrs: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
prNumbers: PropTypes.string.isRequired,
grade: PropTypes.string,
}),
).isRequired,
}).isRequired,
onGradeChange: PropTypes.func.isRequired,
isFinalized: PropTypes.bool.isRequired,
darkMode: PropTypes.bool,
};

InlinePRSummary.defaultProps = {
darkMode: false,
};

export default InlinePRSummary;
142 changes: 76 additions & 66 deletions src/components/PRGradingScreen/PRGradingScreen.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { useMemo, useState } from 'react';
import { Button, Card, Col, Container, Row } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import { v4 as uuidv4 } from 'uuid';
import styles from './PRGradingScreen.module.css';
import InlinePRSummary from './InlinePRSummary';

const PRGradingScreen = ({ teamData, reviewers }) => {
const darkMode = useSelector(state => state.theme.darkMode);
Expand Down Expand Up @@ -197,77 +198,86 @@ const PRGradingScreen = ({ teamData, reviewers }) => {
</td>
</tr>
) : (
/* Render each reviewer row followed by its inline summary component using React.Fragment */
filteredReviewers.map(reviewer => (
<tr key={reviewer.id}>
<td>{reviewer.reviewer}</td>

<td>
<input
type="number"
value={reviewer.gradedPrs.length}
readOnly
disabled={isFinalized}
className={`${styles['pr-grading-screen-pr-input']} ${dm}`}
/>
</td>
<React.Fragment key={reviewer.id}>
<tr>
<td>{reviewer.reviewer}</td>

<td>
<input
type="number"
value={reviewer.gradedPrs.length}
readOnly
disabled={isFinalized}
className={`${styles['pr-grading-screen-pr-input']} ${dm}`}
/>
</td>

<td>{reviewer.prsNeeded}</td>

<td className={styles['pr-grading-screen-td-numbers']}>
{reviewer.gradedPrs.map(pr => (
<span
key={pr.id}
role="button"
tabIndex={0}
className={`${styles['pr-grading-screen-pr-number']} ${
pr.prNumbers.includes('+') ? styles['pr-grading-screen-pair'] : ''
} ${dm}`}
onClick={() => handlePRNumberClick(reviewer.id)}
onKeyDown={e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handlePRNumberClick(reviewer.id);
}
}}
>
{pr.prNumbers}
</span>
))}

<td>{reviewer.prsNeeded}</td>

<td className={styles['pr-grading-screen-td-numbers']}>
{reviewer.gradedPrs.map(pr => (
<span
key={pr.id}
role="button"
tabIndex={0}
className={`${styles['pr-grading-screen-pr-number']} ${
pr.prNumbers.includes('+') ? styles['pr-grading-screen-pair'] : ''
} ${dm}`}
onClick={() => handlePRNumberClick(reviewer.id)}
onKeyDown={e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handlePRNumberClick(reviewer.id);
}
}}
>
{pr.prNumbers}
</span>
))}

{!isFinalized && activeInput !== reviewer.id && (
<Button
variant="success"
size="sm"
className={styles['pr-grading-screen-add-btn']}
onClick={() => handleAddNewClick(reviewer.id)}
>
+ Add new
</Button>
)}

{!isFinalized && activeInput === reviewer.id && (
<div className={styles['pr-grading-screen-input-container']}>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
className={styles['pr-grading-screen-pr-number-input']}
placeholder="1070 or 1070 + 1256"
/>
{!isFinalized && activeInput !== reviewer.id && (
<Button
variant="primary"
variant="success"
size="sm"
onClick={() => handleInputSubmit(reviewer.id)}
className={styles['pr-grading-screen-add-btn']}
onClick={() => handleAddNewClick(reviewer.id)}
>
Add
</Button>
<Button variant="secondary" size="sm" onClick={handleCancel}>
Cancel
+ Add new
</Button>
</div>
)}
</td>
</tr>
)}

{!isFinalized && activeInput === reviewer.id && (
<div className={styles['pr-grading-screen-input-container']}>
<input
type="text"
value={inputValue}
onChange={e => setInputValue(e.target.value)}
className={styles['pr-grading-screen-pr-number-input']}
placeholder="1070 or 1070 + 1256"
/>
<Button
variant="primary"
size="sm"
onClick={() => handleInputSubmit(reviewer.id)}
>
Add
</Button>
<Button variant="secondary" size="sm" onClick={handleCancel}>
Cancel
</Button>
</div>
)}
</td>
</tr>
<InlinePRSummary
reviewer={reviewer}
onGradeChange={handleGradeChange}
isFinalized={isFinalized}
darkMode={darkMode}
/>
</React.Fragment>
))
)}
</tbody>
Expand Down
Loading
Loading