Commit 669ca3f1 authored by Aravind RK's avatar Aravind RK

feat : Violation notification comes to admin/HR

parent 71897859
......@@ -33,7 +33,8 @@ const interviewSchema = new mongoose.Schema({
score: { type: Number, default: null },
totalMarks: { type: Number, default: null },
percentage: { type: Number, default: null },
completed: { type: Boolean, default: false }
completed: { type: Boolean, default: false },
violation: { type: Boolean, default: false }
}],
// Coding round
......
......@@ -40,6 +40,10 @@ const submissionSchema = new mongoose.Schema({
type: Number, // in seconds
default: 0
},
violation: {
type: Boolean,
default: false
},
submittedAt: {
type: Date,
default: Date.now
......
......@@ -145,7 +145,7 @@ router.get('/quiz/:quizId', async (req, res) => {
router.post('/quiz/:quizId/submit', async (req, res) => {
try {
const { quizId } = req.params;
const { answers, timeTaken } = req.body;
const { answers, timeTaken, violation } = req.body;
// Check if candidate already submitted
const existingSubmission = await Submission.findOne({
......@@ -192,7 +192,8 @@ router.post('/quiz/:quizId/submit', async (req, res) => {
score,
totalMarks,
percentage,
timeTaken: timeTaken || 0
timeTaken: timeTaken || 0,
violation: !!violation
});
// Update Interview if applicable
......@@ -204,7 +205,8 @@ router.post('/quiz/:quizId/submit', async (req, res) => {
'quizzes.$.score': score,
'quizzes.$.totalMarks': totalMarks,
'quizzes.$.percentage': percentage,
'quizzes.$.completed': true
'quizzes.$.completed': true,
'quizzes.$.violation': !!violation
}
}
);
......
......@@ -373,7 +373,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -202,7 +202,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -373,7 +373,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -202,7 +202,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -617,7 +617,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -307,7 +307,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -229,7 +229,7 @@ export class TakeQuizComponent implements OnInit, OnDestroy {
questionId, selectedAnswers
}));
this.quizService.submitQuiz(this.quiz().id, answersArray, timeTaken).subscribe({
this.quizService.submitQuiz(this.quiz().id, answersArray, timeTaken, isAutoSubmit).subscribe({
next: () => {
this.submitted.set(true);
this.submitting.set(false);
......
......@@ -618,7 +618,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -307,7 +307,12 @@
<div class="quiz-result-card">
<div class="qr-title">{{ q.title }}</div>
@if (q.completed) {
<div class="qr-score">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
<div class="qr-score" [class.violation]="q.violation">{{ q.score }}/{{ q.totalMarks }} ({{ q.percentage }}%)</div>
@if (q.violation) {
<div style="color: #ef4444; font-size: 11px; margin-top: 6px; display: flex; align-items: center; gap: 4px; font-weight: 500;">
<span class="material-symbols-rounded" style="font-size: 14px;">warning</span> Auto-submitted (Violation)
</div>
}
} @else {
<div class="qr-pending">Not Taken</div>
}
......
......@@ -175,8 +175,8 @@
return this.http.get(`${this.candidateUrl}/quiz/${quizId}`);
}
submitQuiz(quizId: string, answers: any[], timeTaken: number): Observable<any> {
return this.http.post(`${this.candidateUrl}/quiz/${quizId}/submit`, { answers, timeTaken });
submitQuiz(quizId: string, answers: any[], timeTaken: number, violation: boolean = false): Observable<any> {
return this.http.post(`${this.candidateUrl}/quiz/${quizId}/submit`, { answers, timeTaken, violation });
}
getCandidateProfile(): Observable<any> {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment