Skip to content

admin and candidate prefinal commit - #2

Open
AbdulPIO wants to merge 1 commit into
mainfrom
admin-candidate-prefinal
Open

admin and candidate prefinal commit#2
AbdulPIO wants to merge 1 commit into
mainfrom
admin-candidate-prefinal

Conversation

@AbdulPIO

Copy link
Copy Markdown
Owner

No description provided.

@AbdulPIO
AbdulPIO requested a review from avishekdr July 22, 2025 06:53
console.log('Candidates loaded: ');

this.candidates = [...attended, ...notAttended];
this.candidates = [...(attended || []), ...(notAttended || [])];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
this.candidates = [...(attended || []), ...(notAttended || [])];
this.candidates = attended.concat(notAttented);

@AbdulPIO
AbdulPIO requested a review from shubhangi-pio July 29, 2025 10:14
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

delete this file as there is no use as of now

next: (count) => this.activeExams = count,
error: (err) => console.error(err)
error: (err) => {
console.error(err)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove console

next: (count) => this.totalCandidates = count,
error: (err) => console.error(err)
error: (err) => {
console.error(err);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove console

error: () => {
this.snackBar.open('Failed to load completed exams.', '', { duration: 5000 });
error: (err) => {
this.snackBar.open(err?.error?.message || 'Failed to load completed exams.', '', { duration: 5000 });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

{ } should be use if there are multiple linse, on above only single line present so use instead error: (err) => this.snackBar.open(err?.error?.message || 'Failed to load completed exams.', '', { duration: 5000 });

position: relative;
}
.submit-btn mat-spinner {
margin: 0 !important;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Try to avoid important here

}
.submit-btn mat-spinner {
margin: 0 !important;
position: static !important;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

here also

this.examForm.get('title')?.valueChanges.subscribe((title: string) => {
if (title && title.trim().length > 0) {
const generatedKey = this.generateExamKey(title);
this.examForm.get('key')?.setValue(generatedKey, { emitEvent: false });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this.examForm.get('key')?.setValue(this.generateExamKey(title), { emitEvent: false });

},
error: () => {
this.snackBar.open('Failed to load categories', 'Close', {
error: (err) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

{ } remove , seems there is single line

})),
};

console.log(examPayload)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove console log

return errorMessages[errorKey];
}
}
if (control?.hasError('required')) return 'This field is required';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

From Line 344 to 354, replaced with below one as repeated if (control?.hasError(...)) checks
const errors = control.errors;
if (errors['required']) return 'This field is required';
if (errors['min']) return Minimum value is ${errors['min'].min};
if (errors['max']) return Maximum value is ${errors['max'].max};
if (errors['minlength']) return Minimum length is ${errors['minlength'].requiredLength};
if (errors['maxlength']) return Maximum length is ${errors['maxlength'].requiredLength};
if (errors['pattern']) return 'Must be exactly 10 alphanumeric characters';

.upload-button mat-spinner {
width: 20px;
height: 20px;
margin: 0 !important;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

try to avoid !important

font-weight: 700;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(59, 24, 119, 0.08);
background: #3b1877 !important;

@shubhangi-pio shubhangi-pio Jul 29, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

try to avoid !important in this file

const token = this.route.snapshot.queryParamMap.get('token');
if (token) {
this.http.get(`${environment.apiBaseUrl}/auth/verify-email?token=${token}`).subscribe({
next: (res: any) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

give proper type here instead of any

this.router.navigate(['/landing']);
}

resendVerificationLink() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if this function not in use then remove it

padding: 12px 36px;
margin-bottom: 18px;
font-weight: 600;
background: #7c4dff !important;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

try to avoid !important in file

.logo {
font-size: 80px;
color: #3b1877;
background: none !important;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

try to avoid !important in file

this.loading = false;
console.log(this.registrationForm.value);
const errorMessage = err?.error?.message || 'Registration failed.';
console.log(errorMessage);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove console from here

this.loading = true;
this.candidateRegService.register(this.registrationForm.value).subscribe({
next: () => {
console.log(this.registrationForm.value);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove console from here

const email = this.registrationForm.get('email')?.value;
if (email) {
this.candidateRegService.resendVerification(email).subscribe({
next: () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove { } around single line

next: () => {
this.snackBar.open('A new verification link has been sent to your email.', 'OK', { duration: 5000 });
},
error: (err) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove { } around single line

}
}

goToLanding() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove this function

>
{{ loading ? 'Registering...' : 'Register' }}
</button>
<button

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

From Line 100 to 107 replace with below one, Use routerLink if navigation is static and router.navigate() if navigation needs to be conditional
mat-raised-button
type="button"
class="go-home-btn"
[routerLink] = "['/landing']"
>
Go to Homepage

getStatus(index: number): 'not-seen' | 'seen-not-answered' | 'answered' | 'review' {
const q = this.questions[index];
if (!q) return 'not-seen';
if (this.answers[q.id]?.answer) return 'answered';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

const answer = this.answers[q.id];
if (answer?.answer) return 'answered';

const q = this.questions[index];
if (!q) return 'not-seen';
if (this.answers[q.id]?.answer) return 'answered';
if (this.answers[q.id]?.markedForReview) return 'review';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if (answer?.markedForReview) return 'review';

return this.http.post<any>(`${environment.apiBaseUrl}/candidate`, candidate).pipe(
tap((res) => {
const token = res?.data?.jwtToken || res?.data || res?.jwtToken || res;
if (token) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Instead of if use : token && localStorage.setItem('jwt_token', token);

// Get candidates by exam ID and status
getCandidatesByExamAndStatus(examId: number, status: string): Observable<Candidate[]> {
const url = `${this.apiUrl}/exam/${examId}/candidate?candidateStatus=${status}`;
return this.http.get<any>(url).pipe(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

use proper type here instead of any

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove any data types within file and use proper types

@shubhangi-pio shubhangi-pio left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@AbdulPIO Work on changes

@@ -88,10 +88,10 @@ export class UploadQuestionsComponent {
this.uploading = false;
let errorMsg = 'Failed to upload question. Please try again';
if (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not required to check this condition, you can directly write let message = errorResponse?.error?.message || 'Failed to upload question. Please try again';

next: (res) => {
this.loading = false;
// Save response data to sessionStorage for exam window
if (res && res.data) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if (res && res.data) {
if (res?.data) {

ngOnInit(): void {
const token = this.route.snapshot.queryParamMap.get('token');
if (token) {
this.http.get(`${environment.apiBaseUrl}/auth/verify-email?token=${token}`).subscribe({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why writing API call in component, define the API calls in a function in service & use that function in component for clean code

this.examService.saveExamSessionData(sessionData);

this.answers = {};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

REMOVE EXTRA BLANK LINES FROM FILE

const examData = this.examService.getExamDataFromSession();
examData.timeLeft = this.timeLeft;
this.examService.saveExamDataToSession(examData);
if (this.timeLeft === 15 * 60) {

@avishekdr avishekdr Jul 31, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

15*60 these type of values are called magic numbers. store this in a const variable and call the variable rather than writing directly to follow a standard. check this in whole file

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the standard way to define a interceptor file name is NAME.interceptor.ts

resendVerification(email: string): Observable<any> {
return this.http.post<any>(
`${environment.apiBaseUrl}/auth/send-verification-link?email=${encodeURIComponent(email)}`,
{}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
{}
null

this sounds better



logout() {
localStorage.removeItem('jwt_token');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
localStorage.removeItem('jwt_token');
localStorage.clear();

this will ensure to remove all items from local storage. also check if anything is to be removed from session storage or not

}

logout() {
localStorage.removeItem('jwt_token');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I noticed another logout() function above, why not create 1 single logout() function and use everywhere.

@avishekdr avishekdr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@AbdulPIO look after the comments

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