-
-
Notifications
You must be signed in to change notification settings - Fork 207
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
base: master
Are you sure you want to change the base?
fix: students interviews page #2575
Conversation
return data ? id : null; | ||
}); | ||
const requests = interviews.map(async ({ id }) => { | ||
const data = await courseService.getInterviewStudent(session.githubId, id.toString()).catch(() => null); |
There was a problem hiding this comment.
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');
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added that. Thanks β€οΈ
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 => { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 }) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Done β
const renderInterviewsList = () => { | ||
return interviews.map(interview => renderInterviewCard(interview)); | ||
}; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely! Thank you ππ» Done β
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> | ||
); | ||
}; |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 β
π’ Add
deploy
label if you want to deploy this Pull Request to staging environmentπ§ββοΈ Pull Request Naming Convention
area:*
label(s)π€ This is a ...
π 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
Solution:
Add visual feedback for different student interview status:
Example Status
No planned interviews
Registration not started
Student not registered
Mentor not assigned
Mentor assigned
Passed the interview and got the results
βοΈ Self Check before Merge