Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(interview-feedback): update feedback result usage #2275

Merged
merged 4 commits into from
Aug 29, 2023
Merged
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
82 changes: 82 additions & 0 deletions client/src/components/Profile/LegacyScreeningFeedback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as React from 'react';
import { Tag, Typography, Table } from 'antd';
import { Rating } from 'components/Rating';
import { LegacyFeedback } from 'common/models/profile';
import { ENGLISH_LEVELS } from 'data/english';
import { CODING_LEVELS, SKILLS_LEVELS } from 'data/interviews/technical-screening';

const { Text } = Typography;

enum SKILL_NAME {
htmlCss = 'HTML/CSS',
dataStructures = 'Data structures',
common = 'Common of CS / Programming',
}

/**
* this feedback template will live here until we will migrate all feedbacks to new template
*/
export function LegacyScreeningFeedback({ feedback }: { feedback: LegacyFeedback }) {
const { comment, skills, programmingTask, english } = feedback;

const skillSet = [
...(Object.keys(skills) as any[]).map((key: keyof typeof skills) => ({
rating: skills[key],
name: SKILL_NAME[key],
key,
isNotCodeWritingLevel: true,
})),
{
rating: programmingTask.codeWritingLevel,
name: 'Code writing level',
key: 'codeWritingLevel',
isNotCodeWritingLevel: false,
},
];
const englishLevel = typeof english === 'number' ? ENGLISH_LEVELS[english] : english;

return (
<>
{comment && (
<p style={{ marginBottom: 20 }}>
<Text strong>Comment: </Text>
{comment}
</p>
)}
<p style={{ marginBottom: 5 }}>
Programming task(s): <br /> <Text code>{programmingTask.task}</Text>
</p>
<p style={{ marginBottom: 5 }}>
Has the student solved the task(s)?{' '}
{programmingTask.resolved === 1 ? (
<Tag color="green">Yes</Tag>
) : programmingTask.resolved === 2 ? (
<Tag color="orange">Yes (with tips)</Tag>
) : (
<Tag color="red">No</Tag>
)}
</p>
<p style={{ marginBottom: 5 }}>Comments about coding level: {programmingTask.comment}</p>
<p style={{ marginBottom: 5 }}>Estimated English level: {englishLevel?.toString().toUpperCase()}</p>
<Table
dataSource={skillSet}
size="small"
rowKey="key"
pagination={false}
columns={[
{
dataIndex: 'name',
ellipsis: true,
width: '30%',
},
{
dataIndex: 'rating',
render: (rating, record) => (
<Rating rating={rating} tooltips={record.isNotCodeWritingLevel ? SKILLS_LEVELS : CODING_LEVELS} />
),
},
]}
/>
</>
);
}
8 changes: 5 additions & 3 deletions client/src/components/Profile/PreScreeningIviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import PreScreeningIviewModal from './PreScreeningIviewModal';
const { Text } = Typography;

import { QuestionCircleOutlined, FullscreenOutlined } from '@ant-design/icons';
import { getRating } from 'domain/interview';

type Props = {
data: StageInterviewDetailedFeedback[];
Expand Down Expand Up @@ -36,11 +37,12 @@ class PreScreeningIviewsCard extends React.PureComponent<Props, State> {
render() {
const interviews = this.props.data;
const { isPreScreeningIviewModalVisible, courseIndex } = this.state;
const interviewResult = interviews[courseIndex];

return (
<>
<PreScreeningIviewModal
feedback={interviews[courseIndex]}
interviewResult={interviewResult}
isVisible={isPreScreeningIviewModalVisible}
onHide={this.hidePreScreeningIviewModal}
/>
Expand All @@ -51,13 +53,13 @@ class PreScreeningIviewsCard extends React.PureComponent<Props, State> {
<List
itemLayout="horizontal"
dataSource={interviews}
renderItem={({ courseName, interviewer, rating, date, isGoodCandidate }, idx) => (
renderItem={({ courseName, interviewer, score, maxScore, date, isGoodCandidate, version }, idx) => (
<List.Item style={{ display: 'flex', justifyContent: 'space-between' }}>
<div style={{ flexGrow: 2 }}>
<p style={{ marginBottom: 0 }}>
<Text strong>{courseName}</Text>
</p>
<Rating rating={rating} />
<Rating rating={getRating(score, maxScore, version)} />
<p style={{ fontSize: 12, marginBottom: 5 }}>Date: {formatDate(date)}</p>
{isGoodCandidate != null ? (
<p style={{ fontSize: 12, marginBottom: 5 }}>
Expand Down
87 changes: 11 additions & 76 deletions client/src/components/Profile/PreScreeningIviewModal.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,22 @@
import * as React from 'react';
import { Modal, Tag, Typography, Table } from 'antd';
import { Modal, Tag } from 'antd';
import { formatDate } from 'services/formatter';
import { Rating } from 'components/Rating';
import { StageInterviewDetailedFeedback } from 'common/models/profile';
import { CODING_LEVELS, SKILLS_LEVELS, SKILL_NAME } from 'services/reference-data/stageInterview';
import { ENGLISH_LEVELS } from 'data/english';

const { Text } = Typography;
import { LegacyFeedback, StageInterviewDetailedFeedback } from 'common/models/profile';
import { LegacyScreeningFeedback } from './LegacyScreeningFeedback';
import { PrescreeningFeedback } from './PrescreeningFeedback';
import { getRating } from 'domain/interview';

type Props = {
feedback: StageInterviewDetailedFeedback;
interviewResult: StageInterviewDetailedFeedback;
isVisible: boolean;
onHide: () => void;
};

class PreScreeningIviewModal extends React.PureComponent<Props> {
render() {
const { feedback, isVisible, onHide } = this.props;
const {
courseName,
courseFullName,
date,
rating,
interviewer,
isGoodCandidate,
comment,
skills,
programmingTask,
english,
} = feedback;
const skillSet = [
...(Object.keys(skills) as any[]).map((key: keyof typeof skills) => ({
rating: skills[key],
name: SKILL_NAME[key],
key: `stageInterview-${courseName}-${date}-skills-${key}`,
isNotCodeWritingLevel: true,
})),
{
rating: programmingTask.codeWritingLevel,
name: 'Code writing level',
key: `stageInterview-${courseName}-${date}-skills-codeWritingLevel`,
isNotCodeWritingLevel: false,
},
];
const englishLevel = typeof english === 'number' ? ENGLISH_LEVELS[english] : english;
const { interviewResult, isVisible, onHide } = this.props;
const { courseFullName, date, score, interviewer, isGoodCandidate, feedback, version, maxScore } = interviewResult;
return (
<Modal
title={`${courseFullName} Pre-Screening Interview Feedback`}
Expand All @@ -52,7 +25,7 @@ class PreScreeningIviewModal extends React.PureComponent<Props> {
footer={null}
width={'80%'}
>
<Rating rating={rating} />
<Rating rating={getRating(score, maxScore, version)} />
<p style={{ marginBottom: 5 }}>Date: {formatDate(date)}</p>
{isGoodCandidate != null ? (
<p style={{ marginBottom: 5 }}>
Expand All @@ -62,46 +35,8 @@ class PreScreeningIviewModal extends React.PureComponent<Props> {
<p style={{ marginBottom: 20 }}>
Interviewer: <a href={`/profile?githubId=${interviewer.githubId}`}>{interviewer.name}</a>
</p>
{comment && (
<p style={{ marginBottom: 20 }}>
<Text strong>Comment: </Text>
{comment}
</p>
)}
<p style={{ marginBottom: 5 }}>
Programming task(s): <br /> <Text code>{programmingTask.task}</Text>
</p>
<p style={{ marginBottom: 5 }}>
Has the student solved the task(s)?{' '}
{programmingTask.resolved === 1 ? (
<Tag color="green">Yes</Tag>
) : programmingTask.resolved === 2 ? (
<Tag color="orange">Yes (with tips)</Tag>
) : (
<Tag color="red">No</Tag>
)}
</p>
<p style={{ marginBottom: 5 }}>Comments about coding level: {programmingTask.comment}</p>
<p style={{ marginBottom: 5 }}>Estimated English level: {englishLevel?.toString().toUpperCase()}</p>
<Table
dataSource={skillSet}
size="small"
rowKey="key"
pagination={false}
columns={[
{
dataIndex: 'name',
ellipsis: true,
width: '30%',
},
{
dataIndex: 'rating',
render: (rating, record) => (
<Rating rating={rating} tooltips={record.isNotCodeWritingLevel ? SKILLS_LEVELS : CODING_LEVELS} />
),
},
]}
/>
{version === 0 && <LegacyScreeningFeedback feedback={feedback as LegacyFeedback} />}
{version === 1 && <PrescreeningFeedback feedback={feedback} />}
</Modal>
);
}
Expand Down
126 changes: 126 additions & 0 deletions client/src/components/Profile/PrescreeningFeedback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Typography, Table, Row, Space } from 'antd';
import { Rating } from 'components/Rating';
import { StageInterviewDetailedFeedback } from 'common/models/profile';
import {
CODING_LEVELS,
FeedbackStepId,
InterviewFeedbackStepData,
InterviewFeedbackValues,
InterviewQuestion,
SKILLS_LEVELS,
} from 'data/interviews/technical-screening';

const { Text, Title } = Typography;

export function PrescreeningFeedback({ feedback }: { feedback: StageInterviewDetailedFeedback['feedback'] }) {
const { steps } = feedback as { steps: Record<FeedbackStepId, InterviewFeedbackStepData> };

const { theory, practice, english, decision, intro } = steps;
const isRejected = intro.values?.interviewResult === 'missed';

if (isRejected) {
return (
<Space direction="vertical">
{intro.values?.comment && (
<Space>
<Text strong>Comment: </Text>
<Text>{intro.values?.comment as string} </Text>
</Space>
)}
</Space>
);
}

return (
<>
<Space direction="vertical">
{decision.values?.redFlags && (
<Space>
<Text strong>Red flags: </Text>
<Text>{decision.values?.redFlags as string} </Text>
</Space>
)}
{decision.values?.comment && (
<Space>
<Text strong>Comment: </Text>
<Text>{decision.values?.comment as string} </Text>
</Space>
)}
{english.values && (
<>
<Space>
<Text strong>Certified level of English: </Text>
<Text>{english.values?.englishCertificate as string} </Text>
</Space>
<Space>
<Text strong>English level by interviewers opinion:</Text>
<Text>{english.values?.selfAssessment as string} </Text>
</Space>
</>
)}
{english.values?.comment && (
<Space>
<Text strong>Where did the student learn English: </Text>
<Text>{english.values?.comment as string} </Text>
</Space>
)}
<SkillSection skills={theory.values} title="Theory" tooltips={SKILLS_LEVELS} />
<SkillSection skills={practice.values} title="Practice" tooltips={CODING_LEVELS} />
</Space>
</>
);
}

function SkillSection({
skills,
title,
tooltips,
}: {
skills: InterviewFeedbackValues | undefined;
title: string;
tooltips: string[];
}) {
if (!skills) return null;

return (
<Space direction="vertical" style={{ marginBottom: 20 }}>
<Title level={4}>{title}</Title>
<SkillTable skills={skills.questions as InterviewQuestion[]} tooltips={tooltips} />
{skills.comment && (
<Row>
<Text strong>Comment: </Text>&nbsp;{skills.comment as string}
</Row>
)}
</Space>
);
}

function SkillTable({ skills, tooltips }: { skills: InterviewQuestion[]; tooltips: string[] }) {
return (
<Table
dataSource={skills}
size="small"
rowKey="key"
pagination={false}
columns={[
{
width: '60%',
render: (_, record) => (
<>
{record.topic && (
<Row>
<Text type="secondary">{record.topic}</Text>
</Row>
)}
<Text>{record.title}</Text>
</>
),
},
{
dataIndex: 'value',
render: rating => <Rating rating={rating} tooltips={tooltips} />,
},
]}
/>
);
}
Loading
Loading