Oviya commited on
Commit
9dcf30d
·
1 Parent(s): e664319

chore: update grammar chat endpoint + config

Browse files
src/app/chat/api.service.ts CHANGED
@@ -1,36 +1,3 @@
1
- /*import { Injectable } from '@angular/core';
2
- import { HttpClient } from '@angular/common/http';
3
- import { Observable } from 'rxjs';
4
-
5
- @Injectable({
6
- providedIn: 'root'
7
- })
8
- export class ApiService {
9
-
10
- //private apiUrl = 'http://127.0.0.1:5000'; // Flask backend URL
11
-
12
- private apiUrl = 'http://localhost:5000/explain-grammar';
13
-
14
- constructor(private http: HttpClient) { }
15
-
16
- // Method to send the grammar question and receive the explanation from Flask backend
17
- //askQuestion(question: string): Observable<any> {
18
- // const body = { topic: question }; // Prepare the request body
19
- // return this.http.post<any>(`${this.apiUrl}/explain-grammar`, body); // Call the Flask API and return the observable
20
- //}
21
-
22
- // Method to send the user's question to the Flask backend
23
- askQuestion(userInput: string): Observable<any> {
24
- const data = { topic: userInput }; // Assuming you're sending the user input as a topic
25
-
26
- return this.http.post<any>(this.apiUrl, data); // POST request to Flask backend
27
- }
28
-
29
- }
30
- */
31
-
32
-
33
-
34
 
35
  import { Injectable } from '@angular/core';
36
  import { HttpClient, HttpHeaders } from '@angular/common/http';
@@ -40,32 +7,16 @@ import { Observable } from 'rxjs';
40
  providedIn: 'root'
41
  })
42
  export class ApiService {
43
- private baseUrl = 'http://localhost:5012';
44
  //private apiUrl = 'http://localhost:5012/explain-grammar';
45
- constructor(private http: HttpClient) { }
46
-
47
-
48
- //askQuestion(userInput: string, sessionId: string | null): Observable<any> {
49
- // const headers = { 'Content-Type': 'application/json' };
50
-
51
- // // Include `session_id` in request only if available
52
- // const data = sessionId
53
- // ? { topic: userInput, session_id: sessionId }
54
- // : { topic: userInput };
55
-
56
- // console.log("Sending request to Flask:", this.apiUrl, data);
57
-
58
- // return this.http.post<any>(this.apiUrl, data, { headers });
59
- //}
60
-
61
- // Fetch grammar question suggestions
62
 
 
63
 
64
- //getGrammarSuggestions(input: string): Observable<any> {
65
- // const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
66
 
67
- // return this.http.post<any>(this.apiUrl, { topic: input }, { headers }); // ✅ Fix: Send input as "topic"
68
- //}
69
 
70
  askQuestion(userInput: string, sessionId: string | null): Observable<any> {
71
  const headers = { 'Content-Type': 'application/json' };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
  import { Injectable } from '@angular/core';
3
  import { HttpClient, HttpHeaders } from '@angular/common/http';
 
7
  providedIn: 'root'
8
  })
9
  export class ApiService {
10
+ //private baseUrl = 'http://localhost:5012';
11
  //private apiUrl = 'http://localhost:5012/explain-grammar';
12
+ private baseUrl = location.hostname.endsWith('hf.space')
13
+ ? 'https://pykara-py-learn-backend.hf.space/media'
14
+ : 'http://localhost:5000/media';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ constructor(private http: HttpClient) { }
17
 
 
 
18
 
19
+
 
20
 
21
  askQuestion(userInput: string, sessionId: string | null): Observable<any> {
22
  const headers = { 'Content-Type': 'application/json' };
src/app/generate-questions/generate-questions.component.css CHANGED
@@ -1021,158 +1021,157 @@ h3 {
1021
 
1022
 
1023
  /*hint button css start here */
 
 
 
 
 
 
 
1024
 
1025
-
1026
- /* Tooltip Container */
1027
- .tooltip-container {
1028
- position: absolute;
1029
- top: 10vw; /* Adjust position relative to the viewport */
1030
- right: 6vw; /* Position the tooltip relative to the right */
1031
- background-color: #f8f9fa; /* Light background color */
1032
- color: black; /* Dark text color for contrast */
1033
- border-radius: 1vw; /* Rounded corners for responsiveness */
1034
- padding: 1.5vw; /* Padding for content */
1035
- width: 50vw; /* Tooltip width for responsiveness */
1036
- box-shadow: 0 0.4vw 0.8vw rgba(0, 0, 0, 0.2); /* Subtle shadow for visibility */
1037
- transition: opacity 0.3s ease-in-out; /* Smooth fade-in/out effect */
1038
- opacity: 0; /* Hidden by default */
1039
- z-index: 999; /* Ensure it appears above other elements */
1040
- font-size: 1vw; /* Font size relative to viewport width */
1041
- text-align: left; /* Align the text to the left */
1042
- word-wrap: break-word; /* Ensure long words wrap */
1043
- white-space: normal; /* Allow wrapping of long text */
1044
- }
1045
-
1046
- /* Tooltip when visible */
1047
- .tooltip-container.active {
1048
- opacity: 1; /* Make the tooltip visible */
1049
- }
1050
-
1051
- /* Tooltip Arrow (Triangle) */
1052
- .tooltip-container::after {
1053
- content: "";
1054
- position: absolute;
1055
- top: 14vw; /* Adjust arrow position in vw */
1056
- left: 49vw; /* Position the arrow relative to the tooltip */
1057
- border-width: 1vw; /* Adjust arrow size for responsiveness */
1058
- border-style: solid;
1059
- border-color: #f8f9fa transparent transparent transparent; /* Match arrow color with the tooltip */
1060
- }
1061
-
1062
- /* Close Button */
1063
- .tooltip-close-btn {
1064
- position: absolute;
1065
- top: 0.5vw; /* Vertical alignment for responsiveness */
1066
- right: 1vw; /* Horizontal alignment */
1067
- background: none;
1068
- border: none;
1069
- font-size: 1.2vw; /* Font size for responsiveness */
1070
- color: #333; /* Default color */
1071
  cursor: pointer;
1072
- font-weight: bold;
1073
- transition: color 0.2s ease; /* Hover effect transition */
 
 
1074
  }
1075
 
1076
- .tooltip-close-btn:hover {
1077
- color: #dc3545; /* Change color on hover */
 
1078
  }
1079
 
1080
- /* Responsive Design for 1366px */
1081
- @media (max-width: 1366px) {
1082
- .tooltip-container {
1083
- width: 40vw; /* Slightly increase width for 1366px screens */
1084
- padding: 1.2vw; /* Adjust padding */
1085
- font-size: 0.9vw; /* Reduce font size */
1086
  }
1087
 
1088
- .tooltip-container::after {
1089
- left: 38vw; /* Adjust arrow position */
1090
- }
1091
-
1092
- .tooltip-close-btn {
1093
- font-size: 1vw; /* Adjust close button size */
1094
- }
 
 
 
 
 
 
 
1095
  }
1096
 
1097
- /* Responsive Design for Smaller Screens (768px and below) */
1098
- @media (max-width: 768px) {
1099
- .tooltip-container {
1100
- width: 50vw; /* Adjust tooltip width */
1101
- padding: 2vw; /* Increase padding for smaller screens */
1102
- font-size: 1.2vw; /* Adjust font size for readability */
 
 
 
 
 
1103
  }
1104
 
1105
- .tooltip-container::after {
1106
- left: 47vw; /* Adjust arrow position */
1107
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1108
 
1109
- .tooltip-close-btn {
1110
- font-size: 1.5vw; /* Adjust close button size */
 
1111
  }
1112
- }
1113
 
1114
- /* Responsive Design for Very Small Screens (480px and below) */
1115
- @media (max-width: 480px) {
1116
- .tooltip-container {
1117
- width: 60vw; /* Increase width for smaller screens */
1118
- padding: 3vw; /* Add more padding */
1119
- font-size: 1.5vw; /* Larger font for readability */
1120
  }
1121
 
1122
- .tooltip-container::after {
1123
- left: 57vw; /* Adjust arrow position */
1124
- }
 
 
1125
 
1126
- .tooltip-close-btn {
1127
- font-size: 2vw; /* Adjust close button size */
1128
- }
1129
  }
1130
 
 
 
 
1131
 
 
 
 
 
 
 
 
1132
 
1133
- /* Zoom-in and zoom-out animation for hint button */
1134
- @keyframes hint-zoom {
1135
- 0% {
1136
- transform: scale(1);
 
1137
  }
1138
 
1139
- 50% {
1140
- transform: scale(1.2);
1141
- }
1142
- /* Slightly zoom in */
1143
- 100% {
1144
- transform: scale(1);
1145
  }
1146
  }
1147
 
1148
- .hint-toggle-btn {
1149
- background-color: #5c67f2;
1150
- color: white;
1151
- padding: 12px 18px;
1152
- font-size: 1.5rem;
1153
- border: none;
1154
- border-radius: 50%;
1155
- cursor: pointer;
1156
- transition: all 0.3s ease;
1157
- display: flex;
1158
- justify-content: center;
1159
- align-items: center;
1160
- width: 50px;
1161
- height: 50px;
1162
- }
1163
-
1164
- /* Apply zoom-in effect when hints are available */
1165
- .hint-toggle-btn.blink {
1166
- animation: hint-zoom 1s infinite alternate;
1167
  }
1168
 
1169
- /*.hint-item {
1170
- margin-bottom: 10px;*/ /* ✅ Adds spacing between each hint */
1171
- /*}*/
1172
-
 
 
 
1173
 
1174
- .hint-item {
1175
- margin-bottom: 1rem; /* ✅ One-line spacing between hints */
1176
- font-size: 1rem;
 
 
 
1177
  }
1178
-
 
1021
 
1022
 
1023
  /*hint button css start here */
1024
+ /* Anchor the i button on the right side of the screen (adjust as you like) */
1025
+ .hint-anchor {
1026
+ position: fixed; /* or absolute relative to a container */
1027
+ top: 30vh; /* vertical position */
1028
+ right: 33px; /* distance from right edge */
1029
+ z-index: 1101;
1030
+ }
1031
 
1032
+ /* i button design (compact circular) */
1033
+ .hint-toggle-btn {
1034
+ width: 56px;
1035
+ height: 56px;
1036
+ border-radius: 50%;
1037
+ border: 0;
1038
+ background: radial-gradient(120% 120% at 30% 20%, #18788f 0%, #006780 70%);
1039
+ color: #fff;
1040
+ font-weight: 800;
1041
+ font-size: 22px;
1042
+ line-height: 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1043
  cursor: pointer;
1044
+ box-shadow: 0 8px 24px rgba(0,0,0,.18);
1045
+ display: grid;
1046
+ place-items: center;
1047
+ transition: transform .18s ease, box-shadow .18s ease;
1048
  }
1049
 
1050
+ .hint-toggle-btn:hover {
1051
+ transform: translateY(-1px) scale(1.04);
1052
+ box-shadow: 0 12px 28px rgba(0,0,0,.22);
1053
  }
1054
 
1055
+ .hint-toggle-btn:focus-visible {
1056
+ outline: 3px solid rgba(0,103,128,.35);
1057
+ outline-offset: 3px;
 
 
 
1058
  }
1059
 
1060
+ /* Popover: opens to the LEFT of the i button */
1061
+ .hint-popover {
1062
+ position: absolute;
1063
+ top: 11vw;
1064
+ right: calc(100% + 35px);
1065
+ transform: translateY(-46%);
1066
+ width: min(51vw, 96vw);
1067
+ max-height: 67vh;
1068
+ background: #fff;
1069
+ border-radius: 12px;
1070
+ padding: 16px 20px;
1071
+ box-shadow: 0 12px 32px rgba(0, 0, 0, .25);
1072
+ animation: _ngcontent-ng-c2774789824_hint-slide-in .18s ease;
1073
+ border: 4px solid #009688;
1074
  }
1075
 
1076
+ /* Arrow pointing at the button */
1077
+ .hint-popover::before {
1078
+ content: "";
1079
+ position: absolute;
1080
+ top: 50%;
1081
+ right: -8px;
1082
+ width: 14px;
1083
+ height: 14px;
1084
+ background: #fff;
1085
+ transform: translateY(-50%) rotate(45deg);
1086
+ box-shadow: 2px -2px 8px rgba(0,0,0,.08);
1087
  }
1088
 
1089
+ /* Round close (X) inside the popover */
1090
+ .hint-close {
1091
+ position: absolute;
1092
+ top: 8px;
1093
+ right: 10px;
1094
+ width: 40px;
1095
+ height: 40px;
1096
+ border: 0;
1097
+ border-radius: 50%;
1098
+ background: #eeeeee;
1099
+ color: red;
1100
+ font-size: 2vw;
1101
+ line-height: 0.9;
1102
+ display: grid;
1103
+ place-items: center;
1104
+ cursor: pointer;
1105
+ transition: background .15s ease, transform .15s ease;
1106
+ font-weight: 900;
1107
+ }
1108
 
1109
+ .hint-close:hover {
1110
+ background: #e0e0e0;
1111
+ transform: scale(1.04);
1112
  }
 
1113
 
1114
+ .hint-close:focus-visible {
1115
+ outline: 3px solid rgba(0,103,128,.35);
1116
+ outline-offset: 2px;
 
 
 
1117
  }
1118
 
1119
+ /* List spacing */
1120
+ .hint-title {
1121
+ margin: 0 0 8px;
1122
+ font-size: 18px;
1123
+ }
1124
 
1125
+ .hint-list {
1126
+ margin: 0;
1127
+ padding-left: 1rem;
1128
  }
1129
 
1130
+ .hint-item {
1131
+ margin-bottom: .5rem;
1132
+ }
1133
 
1134
+ /* Transparent backdrop that closes on click */
1135
+ .hint-backdrop {
1136
+ position: fixed;
1137
+ inset: 0;
1138
+ background: transparent; /* no dim; only captures outside clicks */
1139
+ z-index: 1100;
1140
+ }
1141
 
1142
+ /* Entrance animation */
1143
+ @keyframes hint-slide-in {
1144
+ from {
1145
+ transform: translateY(-50%) translateX(8px);
1146
+ opacity: .0;
1147
  }
1148
 
1149
+ to {
1150
+ transform: translateY(-50%) translateX(0);
1151
+ opacity: 1;
 
 
 
1152
  }
1153
  }
1154
 
1155
+ /* Mobile: show popover above the button for better fit */
1156
+ @media (max-width: 640px) {
1157
+ .hint-anchor {
1158
+ right: 12px;
1159
+ bottom: 80px;
1160
+ top: auto;
 
 
 
 
 
 
 
 
 
 
 
 
 
1161
  }
1162
 
1163
+ .hint-popover {
1164
+ right: 0;
1165
+ bottom: calc(100% + 10px);
1166
+ top: auto;
1167
+ transform: none;
1168
+ width: min(94vw, 380px);
1169
+ }
1170
 
1171
+ .hint-popover::before {
1172
+ right: 12px;
1173
+ top: auto;
1174
+ bottom: -7px;
1175
+ transform: rotate(45deg);
1176
+ }
1177
  }
 
src/app/generate-questions/generate-questions.component.html CHANGED
@@ -99,14 +99,14 @@
99
  <div class="questions-container" *ngIf="questions.length > 0 && !isAllLevelsCompleted">
100
  <div class="quesHintbtn">
101
  <h2 class="section-title">📝 Questions</h2>
102
- <button *ngIf="isFirstAttemptDone && hints.length > 0"
103
- class="hint-toggle-btn"
104
- [class.blink]="hasNewHints"
105
- (click)="toggleHintMenu()">
106
- </button>
107
  </div>
108
 
109
-
110
 
111
 
112
 
@@ -139,21 +139,54 @@
139
  </div>
140
  </li>
141
  </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
 
 
 
 
 
 
143
 
144
 
145
- <!-- Tooltip for Hints (Only Show Incorrect Answers) -->
146
- <div *ngIf="isHintMenuVisible && hints.length > 0" class="tooltip-container active">
147
- <button class="tooltip-close-btn" (click)="toggleHintMenu()">×</button>
148
- <ul>
149
- <ng-container *ngFor="let hint of hints; let i = index">
150
- <li *ngIf="hint && hint.trim() !== '' && userAnswers[i] !== questionsWithAnswers[i]?.correctAnswer" class="hint-item">
151
- <strong>Hint for Question {{ i + 1 }}:</strong> {{ hint }}
152
- </li>
153
- </ng-container>
154
- </ul>
155
 
156
- </div>
157
  </div>
158
  </div>
159
 
 
99
  <div class="questions-container" *ngIf="questions.length > 0 && !isAllLevelsCompleted">
100
  <div class="quesHintbtn">
101
  <h2 class="section-title">📝 Questions</h2>
102
+ <!--<button *ngIf="isFirstAttemptDone && hints.length > 0"
103
+ class="hint-toggle-btn"
104
+ [class.blink]="hasNewHints"
105
+ (click)="toggleHintMenu()">
106
+ </button>-->
107
  </div>
108
 
109
+
110
 
111
 
112
 
 
139
  </div>
140
  </li>
141
  </ul>
142
+ <!-- Show the i button ONLY after first validation and when there are hints -->
143
+ <ng-container *ngIf="isFirstAttemptDone && hints?.length">
144
+ <div class="hint-anchor" (click)="$event.stopPropagation()">
145
+ <!-- i button -->
146
+ <button type="button"
147
+ class="hint-toggle-btn"
148
+ aria-haspopup="dialog"
149
+ [attr.aria-expanded]="isHintMenuVisible ? 'true' : 'false'"
150
+ aria-controls="hintsPanel"
151
+ (click)="toggleHintMenu()">
152
+
153
+ </button>
154
+
155
+ <!-- Popover opening to the LEFT -->
156
+ <section *ngIf="isHintMenuVisible"
157
+ id="hintsPanel"
158
+ class="hint-popover"
159
+ role="dialog"
160
+ aria-modal="true"
161
+ aria-label="Hints"
162
+ (click)="$event.stopPropagation()">
163
+ <button type="button"
164
+ class="hint-close"
165
+ aria-label="Close hints"
166
+ (click)="closeHints()">
167
+ ×
168
+ </button>
169
+
170
+ <h3 class="hint-title">Hints</h3>
171
+ <ul class="hint-list" role="list">
172
+ <ng-container *ngFor="let hint of hints; let i = index">
173
+ <li *ngIf="hint && hint.trim() !== '' && userAnswers[i] !== questionsWithAnswers[i]?.correctAnswer"
174
+ class="hint-item">
175
+ <strong>Hint for Question {{ i + 1 }}:</strong> {{ hint }}
176
+ </li>
177
+ </ng-container>
178
+ </ul>
179
+ </section>
180
+ </div>
181
 
182
+ <!-- Outside click closes it -->
183
+ <div *ngIf="isHintMenuVisible"
184
+ class="hint-backdrop"
185
+ (click)="closeHints()"></div>
186
+ </ng-container>
187
 
188
 
 
 
 
 
 
 
 
 
 
 
189
 
 
190
  </div>
191
  </div>
192
 
src/app/generate-questions/generate-questions.component.ts CHANGED
@@ -240,7 +240,7 @@ export class GenerateQuestionsComponent {
240
  this.isQuestionsGenerated = false;
241
  this.isTopicLocked = false;
242
  this.validated = false;
243
- this.currentDifficulty = 'easy';
244
  this.error = '';
245
  this.isGenerateDisabled = false;
246
  this.isResetDisabled = true;
@@ -319,7 +319,8 @@ export class GenerateQuestionsComponent {
319
  console.log(`✅ Correct answer for question ${index + 1}: ${this.userAnswers[index]}`);
320
  this.readonlyAnswers[index] = true;
321
  this.hints[index] = '';
322
- this.userAnswers[index] = correctAnswer;
 
323
  } else {
324
  console.log(`❌ Incorrect answer for question ${index + 1}: ${this.userAnswers[index]}`);
325
 
@@ -408,7 +409,11 @@ export class GenerateQuestionsComponent {
408
  }
409
 
410
  areAllCorrectAnswersDisplayed(): boolean {
411
- return this.userAnswers.every((answer, index) => answer === this.questionsWithAnswers[index].correctAnswer);
 
 
 
 
412
  }
413
 
414
  transitionDifficulty() {
@@ -537,12 +542,12 @@ export class GenerateQuestionsComponent {
537
 
538
 
539
 
540
- toggleHintMenu() {
541
- if (this.hints.length > 0) {
542
- this.isHintMenuVisible = !this.isHintMenuVisible; // Toggle only if hints exist
543
- console.log("Hint Menu Toggled:", this.isHintMenuVisible); // Debugging
544
- }
545
- }
546
 
547
 
548
 
@@ -592,8 +597,30 @@ export class GenerateQuestionsComponent {
592
 
593
 
594
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
595
 
 
 
 
 
 
596
 
 
597
 
598
  }
599
 
 
240
  this.isQuestionsGenerated = false;
241
  this.isTopicLocked = false;
242
  this.validated = false;
243
+ this.currentDifficulty = 'basic';
244
  this.error = '';
245
  this.isGenerateDisabled = false;
246
  this.isResetDisabled = true;
 
319
  console.log(`✅ Correct answer for question ${index + 1}: ${this.userAnswers[index]}`);
320
  this.readonlyAnswers[index] = true;
321
  this.hints[index] = '';
322
+ //this.userAnswers[index] = correctAnswer;
323
+ this.userAnswers[index] = this.questionsWithAnswers[index].correctAnswer;
324
  } else {
325
  console.log(`❌ Incorrect answer for question ${index + 1}: ${this.userAnswers[index]}`);
326
 
 
409
  }
410
 
411
  areAllCorrectAnswersDisplayed(): boolean {
412
+ return this.userAnswers.every((answer, index) =>
413
+ (answer ?? '').trim().toLowerCase() ===
414
+ (this.questionsWithAnswers[index]?.correctAnswer ?? '').trim().toLowerCase()
415
+ );
416
+
417
  }
418
 
419
  transitionDifficulty() {
 
542
 
543
 
544
 
545
+ //toggleHintMenu() {
546
+ // if (this.hints.length > 0) {
547
+ // this.isHintMenuVisible = !this.isHintMenuVisible; // Toggle only if hints exist
548
+ // console.log("Hint Menu Toggled:", this.isHintMenuVisible); // Debugging
549
+ // }
550
+ //}
551
 
552
 
553
 
 
597
 
598
 
599
 
600
+ closeHints(): void {
601
+ this.isHintMenuVisible = false;
602
+ this.hasNewHints = false; // optional: mark hints as seen
603
+ }
604
+
605
+ openHints(): void {
606
+ if (this.hints?.length) {
607
+ this.isHintMenuVisible = true;
608
+ this.hasNewHints = false;
609
+ }
610
+ }
611
+
612
+ /* Keep your existing toggle if you’re calling it from the i button */
613
+ toggleHintMenu(): void {
614
+ this.isHintMenuVisible ? this.closeHints() : this.openHints();
615
+ }
616
 
617
+ ///* Close on Esc key */
618
+ //@HostListener('document:keydown.escape')
619
+ //onEscClose(): void {
620
+ // if (this.isHintMenuVisible) this.closeHints();
621
+ //}
622
 
623
+
624
 
625
  }
626