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

fix: students interviews page #2575

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

stardustmeg
Copy link

@stardustmeg stardustmeg commented Jan 5, 2025

🟒 Add deploy label if you want to deploy this Pull Request to staging environment

πŸ§‘β€βš–οΈ Pull Request Naming Convention

  • Title should follow Conventional Commits
  • Do not put issue id in title
  • Do not put WIP in title. Use Draft PR functionality
  • Consider to add area:* label(s)
  • I followed naming convention rules

πŸ€” This is a ...

  • New feature
  • Bug fix
  • Performance optimization
  • Refactoring
  • Test Case
  • Documentation update
  • Other

πŸ”— Related issue link

Describe the source of requirement, like related issue link.

πŸ’‘ Background and solution

Background:
The student interviews page has been changed to improve user experience and maintainability. Previously, it was lacking some visual feedback on interviews details.
Additionally, there was an issue with technical screening registration that needed to be addressed to ensure the students could register and have a technical screening with a mentor.

Demonstration

gif

Solution:
Add visual feedback for different student interview status:

Example Status
  • No planned interviews
    No planned interviews

  • Registration not started
    Interview not started

  • Student not registered
    Student not registered

  • Mentor not assigned
    Mentor not assigned

  • Mentor assigned
    Results not available

  • Passed the interview and got the results
    Passed the interview

β˜‘οΈ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Database migration is added or not needed
  • Documentation is updated/provided or not needed
  • Changes are tested locally

return data ? id : null;
});
const requests = interviews.map(async ({ id }) => {
const data = await courseService.getInterviewStudent(session.githubId, id.toString()).catch(() => null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use try-catch to handle errors and add a notification to inform the user.

try {
  const data = await courseService.getInterviewStudent(session.githubId, id.toString());
} catch (error) {
  message.error('Something went wrong, please try reloading the page later');
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added that. Thanks ❀️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest catching once and showing only 1 error instead of multiple bubble for each error

Copy link
Author

@stardustmeg stardustmeg Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing this out once again. I might have misunderstood something. Replaced this with one outer try...catch block βœ…

return registeredInterviews.includes(id.toString());
};

const isRegistrationNotStarted = (interview: InterviewDto): boolean => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have helper function isInterviewRegistrationInProgress which can be used here. it uses 2 weeks buffer. I guess the logic should be the same

Copy link
Author

@stardustmeg stardustmeg Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I've seen this one. But I can't be sure about this, since some new functionality was added a couple of weeks ago and a registration date can be specified freely when the task is created by course admins, so I can't be sure it's always two weeks.
I might be missing something though. If that is the case, please, let me know.

@@ -161,6 +290,16 @@ function StatusLabel({ status }: { status: InterviewStatus }) {
}
}

function InterviewPeriod(props: { startDate: string; endDate: string }) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is the same component at client/src/modules/Mentor/pages/Interviews/components/InterviewPeriod.tsx Probably we can mvoe to domain/interviews and reuse

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right. Thanks! Done βœ…

return data ? id : null;
});
const requests = interviews.map(async ({ id }) => {
const data = await courseService.getInterviewStudent(session.githubId, id.toString()).catch(() => null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest catching once and showing only 1 error instead of multiple bubble for each error

const getInterviewCardDetails = (params: StudentInterviewDetails) => {
const { interviewPassed, isRegistered, registrationNotStarted, registrationStart } = params;

switch (true) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider replacing switch with multiple if statement. Since the switch cases use true, they are essentially conditionals, it would be cleaner to use just ifs

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Done βœ…

Comment on lines 253 to 255
const renderInterviewsList = () => {
return interviews.map(interview => renderInterviewCard(interview));
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The renderInterviewsList function seems unnecessary since it just maps over interviews and calls renderInterviewCard. Unless additional logic is planned, it might be cleaner to inline this mapping directly where it’s used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely! Thank you πŸ‘πŸ» Done βœ…

Comment on lines 123 to 251
const metaDescription = hasInterviewer || interviewPassed ? renderInterviewDetails(item) : renderExtra(interview);
const alertDescription = renderCardDescription({ interviewPassed, isRegistered, registrationNotStarted });
const { cardMessage } = getInterviewCardDetails({
interviewPassed,
isRegistered,
registrationNotStarted,
registrationStart,
});

return (
<Col key={id} xs={24} lg={12}>
<Card
bodyStyle={{ paddingTop: 0 }}
hoverable
title={
<Button type="link" href={descriptionUrl} target="_blank" style={{ padding: 0, fontWeight: 500 }}>
{name}
</Button>
}
extra={<InterviewPeriod startDate={startDate} endDate={endDate} shortDate />}
>
<Meta style={{ minHeight: 80, alignItems: 'center', textAlign: 'center' }} description={metaDescription} />

<Alert
message={<div style={{ minHeight: 50 }}>{cardMessage}</div>}
icon={<InfoCircleTwoTone />}
showIcon
type="info"
description={alertDescription}
style={{ minHeight: 275 }}
/>
</Card>
</Col>
);
};

const getInterviewCardDetails = (params: StudentInterviewDetails) => {
const { interviewPassed, isRegistered, registrationNotStarted, registrationStart } = params;

if (interviewPassed) {
return {
cardMessage: 'You have your interview result. Congratulations!',
backgroundImage: 'url(https://cdn.rs.school/sloths/cleaned/congratulations.svg)',
};
}

if (isRegistered) {
return {
cardMessage: 'You’re all set! Prepare for your upcoming interview.',
backgroundImage: 'url(https://cdn.rs.school/sloths/cleaned/its-a-good-job.svg)',
};
}

if (registrationNotStarted) {
return {
cardMessage: (
<div>
Remember to come back and register after{' '}
<span style={{ whiteSpace: 'nowrap' }}>{formatShortDate(registrationStart ?? '')}</span>!
</div>
),
backgroundImage: 'url(https://cdn.rs.school/sloths/cleaned/listening.svg)',
};
}

return {
cardMessage: 'Register and get ready for your exciting interview!',
backgroundImage: 'url(https://cdn.rs.school/sloths/cleaned/take-notes.svg)',
};
};

const renderCardDescription = (params: StudentInterviewDetails) => {
const { backgroundImage } = getInterviewCardDetails(params);
return (
<>
<div className={iconGroup.className} style={{ backgroundImage }} />
{iconGroup.styles}
</>
);
};

const renderInterviewDetails = (item: InterviewDetails) => {
const { interviewer, status, result } = item;

return (
<div style={{ padding: '8px 0' }}>
<Descriptions layout="vertical" size="small">
<Descriptions.Item label="Interviewer">
<GithubUserLink value={interviewer.githubId} />
</Descriptions.Item>
<Descriptions.Item label="Status">
<StatusLabel status={status} />
</Descriptions.Item>
<Descriptions.Item label="Result">
<b>{getInterviewResult(result as Decision) ?? '-'}</b>
</Descriptions.Item>
</Descriptions>
</div>
);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To improve readability and maintainability, I recommend breaking down this code into separate files under a modular folder structure. For example:

modules/
└── interview/
    └── student/
        β”œβ”€β”€ renderNoInterviews.tsx
        β”œβ”€β”€ renderInterviewCard.tsx
        β”œβ”€β”€ getInterviewCardDetails.ts
        β”œβ”€β”€ renderCardDescription.tsx
        β”œβ”€β”€ renderInterviewDetails.tsx

This is, of course, just a suggestion

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Added some single components βœ…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants