@@ -2,8 +2,8 @@ import { questions } from '../../data.js';
22import { jsPDF } from 'jspdf' ;
33
44export function render ( container ) {
5- const style = document . createElement ( 'style' ) ;
6- style . textContent = `
5+ const style = document . createElement ( 'style' ) ;
6+ style . textContent = `
77 .quiz-container {
88 max-width: 700px;
99 margin: 0 auto;
@@ -68,34 +68,34 @@ export function render(container) {
6868 text-decoration: line-through;
6969 }
7070 ` ;
71- container . appendChild ( style ) ;
71+ container . appendChild ( style ) ;
7272
73- let currentQ = 0 ;
74- let score = 0 ;
75- let userAnswers = [ ] ; // Store { qIdx, selectedIdx, isCorrect }
73+ let currentQ = 0 ;
74+ let score = 0 ;
75+ let userAnswers = [ ] ; // Store { qIdx, selectedIdx, isCorrect }
7676
77- const content = document . createElement ( 'div' ) ;
78- content . className = 'quiz-container' ;
77+ const content = document . createElement ( 'div' ) ;
78+ content . className = 'quiz-container' ;
7979
80- function showStart ( ) {
81- content . innerHTML = `
80+ function showStart ( ) {
81+ content . innerHTML = `
8282 <div class="question-box" style="text-align:center">
8383 <h2>Ready to Certify?</h2>
8484 <p>20 Questions. No Time Limit. 70% to Pass.</p>
8585 <button class="btn" id="start-btn" style="margin-top:20px">Start Assessment</button>
8686 </div>
8787 ` ;
88- content . querySelector ( '#start-btn' ) . addEventListener ( 'click' , showQuestion ) ;
89- }
88+ content . querySelector ( '#start-btn' ) . addEventListener ( 'click' , showQuestion ) ;
89+ }
9090
91- function showQuestion ( ) {
92- if ( currentQ >= questions . length ) {
93- showResult ( ) ;
94- return ;
95- }
91+ function showQuestion ( ) {
92+ if ( currentQ >= questions . length ) {
93+ showResult ( ) ;
94+ return ;
95+ }
9696
97- const q = questions [ currentQ ] ;
98- content . innerHTML = `
97+ const q = questions [ currentQ ] ;
98+ content . innerHTML = `
9999 <div class="question-box">
100100 <div style="margin-bottom:10px; color:#666">Question ${ currentQ + 1 } /${ questions . length } </div>
101101 <h3>${ q . q } </h3>
@@ -105,42 +105,42 @@ export function render(container) {
105105 </div>
106106 ` ;
107107
108- content . querySelectorAll ( '.option-btn' ) . forEach ( btn => {
109- btn . addEventListener ( 'click' , ( e ) => {
110- const selected = parseInt ( e . target . dataset . idx ) ;
111- const isCorrect = selected === q . a ;
112- if ( isCorrect ) score ++ ;
113-
114- userAnswers . push ( { qIdx : currentQ , selectedIdx : selected , isCorrect } ) ;
115-
116- currentQ ++ ;
117- showQuestion ( ) ;
118- } ) ;
119- } ) ;
120- }
121-
122- function showResult ( ) {
123- const percentage = ( score / questions . length ) * 100 ;
124- const passed = percentage >= 70 ;
125- const msg = passed ? 'Congratulations! You are a Domain Associate.' : 'Please review the material and try again.' ;
126-
127- // Build Review HTML
128- let reviewHtml = '<div class="review-list"><h3>Detailed Review</h3>' ;
129- userAnswers . forEach ( ans => {
130- const q = questions [ ans . qIdx ] ;
131- if ( ! ans . isCorrect ) {
132- reviewHtml += `
108+ content . querySelectorAll ( '.option-btn' ) . forEach ( btn => {
109+ btn . addEventListener ( 'click' , ( e ) => {
110+ const selected = parseInt ( e . target . dataset . idx ) ;
111+ const isCorrect = selected === q . a ;
112+ if ( isCorrect ) score ++ ;
113+
114+ userAnswers . push ( { qIdx : currentQ , selectedIdx : selected , isCorrect } ) ;
115+
116+ currentQ ++ ;
117+ showQuestion ( ) ;
118+ } ) ;
119+ } ) ;
120+ }
121+
122+ function showResult ( ) {
123+ const percentage = ( score / questions . length ) * 100 ;
124+ const passed = percentage >= 70 ;
125+ const msg = passed ? 'Congratulations! You are a Domain Associate.' : 'Please review the material and try again.' ;
126+
127+ // Build Review HTML
128+ let reviewHtml = '<div class="review-list"><h3>Detailed Review</h3>' ;
129+ userAnswers . forEach ( ans => {
130+ const q = questions [ ans . qIdx ] ;
131+ if ( ! ans . isCorrect ) {
132+ reviewHtml += `
133133 <div class="review-item wrong">
134134 <p><strong>Q${ ans . qIdx + 1 } :</strong> ${ q . q } </p>
135135 <p>Your Answer: <span class="wrong-ans">${ q . options [ ans . selectedIdx ] } </span></p>
136136 <p>Correct Answer: <span class="correct-ans">${ q . options [ q . a ] } </span></p>
137137 </div>
138138 ` ;
139- }
140- } ) ;
141- reviewHtml += '</div>' ;
139+ }
140+ } ) ;
141+ reviewHtml += '</div>' ;
142142
143- content . innerHTML = `
143+ content . innerHTML = `
144144 <div class="result-screen">
145145 <h2>Assessment Complete</h2>
146146 <div class="score-display">${ score } /${ questions . length } </div>
@@ -150,70 +150,75 @@ export function render(container) {
150150 </div>
151151 ` ;
152152
153- if ( passed ) {
154- content . querySelector ( '#cert-btn' ) . addEventListener ( 'click' , generateCertificate ) ;
155- } else {
156- content . querySelector ( '#retry-btn' ) . addEventListener ( 'click' , ( ) => {
157- currentQ = 0 ;
158- score = 0 ;
159- userAnswers = [ ] ;
160- showStart ( ) ;
161- } ) ;
162- }
163- }
164-
165- function generateCertificate ( ) {
166- const doc = new jsPDF ( {
167- orientation : 'landscape' ,
168- unit : 'mm' ,
169- format : 'a4'
170- } ) ;
171-
172- // Background (White)
173- doc . setFillColor ( 255 , 255 , 255 ) ;
174- doc . rect ( 0 , 0 , 297 , 210 , 'F' ) ;
175-
176- // Border
177- doc . setDrawColor ( 0 , 176 , 255 ) ; // Neon Cyan
178- doc . setLineWidth ( 3 ) ;
179- doc . rect ( 10 , 10 , 277 , 190 ) ;
180-
181- // Title
182- doc . setTextColor ( 0 , 176 , 255 ) ;
183- doc . setFont ( 'helvetica' , 'bold' ) ;
184- doc . setFontSize ( 40 ) ;
185- doc . text ( 'CERTIFICATE OF ACHIEVEMENT' , 148.5 , 50 , { align : 'center' } ) ;
186-
187- // Subtitle
188- doc . setTextColor ( 50 , 50 , 50 ) ;
189- doc . setFontSize ( 20 ) ;
190- doc . setFont ( 'helvetica' , 'normal' ) ;
191- doc . text ( 'This certifies that' , 148.5 , 80 , { align : 'center' } ) ;
192-
193- // Name
194- const name = prompt ( "Enter your name for the certificate:" , "Energy Professional" ) ;
195- if ( ! name ) return ;
196-
197- doc . setFontSize ( 30 ) ;
198- doc . setTextColor ( 255 , 109 , 0 ) ; // Solar Orange
199- doc . text ( name , 148.5 , 100 , { align : 'center' } ) ;
200-
201- // Description
202- doc . setTextColor ( 50 , 50 , 50 ) ;
203- doc . setFontSize ( 16 ) ;
204- doc . text ( 'Has successfully demonstrated mastery of' , 148.5 , 120 , { align : 'center' } ) ;
205- doc . text ( 'Energy Grid Physics, Economics, and Data Science' , 148.5 , 130 , { align : 'center' } ) ;
206-
207- // Score & Date
208- doc . setFontSize ( 12 ) ;
209- doc . setTextColor ( 100 , 100 , 100 ) ;
210- const date = new Date ( ) . toLocaleDateString ( ) ;
211- doc . text ( `Score: ${ score } /${ questions . length } (${ ( score / questions . length ) * 100 } %)` , 148.5 , 150 , { align : 'center' } ) ;
212- doc . text ( `Date: ${ date } ` , 148.5 , 160 , { align : 'center' } ) ;
213-
214- doc . save ( 'GridGuard_Certificate.pdf' ) ;
215- }
216-
217- container . appendChild ( content ) ;
218- showStart ( ) ;
153+ if ( passed ) {
154+ content . querySelector ( '#cert-btn' ) . addEventListener ( 'click' , generateCertificate ) ;
155+ } else {
156+ content . querySelector ( '#retry-btn' ) . addEventListener ( 'click' , ( ) => {
157+ currentQ = 0 ;
158+ score = 0 ;
159+ userAnswers = [ ] ;
160+ showStart ( ) ;
161+ } ) ;
162+ }
163+ }
164+
165+ function generateCertificate ( ) {
166+ const doc = new jsPDF ( {
167+ orientation : 'landscape' ,
168+ unit : 'mm' ,
169+ format : 'a4'
170+ } ) ;
171+
172+ // Background (White)
173+ doc . setFillColor ( 255 , 255 , 255 ) ;
174+ doc . rect ( 0 , 0 , 297 , 210 , 'F' ) ;
175+
176+ // Border
177+ doc . setDrawColor ( 0 , 176 , 255 ) ; // Neon Cyan
178+ doc . setLineWidth ( 3 ) ;
179+ doc . rect ( 10 , 10 , 277 , 190 ) ;
180+
181+ // Title
182+ doc . setTextColor ( 0 , 176 , 255 ) ;
183+ doc . setFont ( 'helvetica' , 'bold' ) ;
184+ doc . setFontSize ( 40 ) ;
185+ doc . text ( 'CERTIFICATE OF ACHIEVEMENT' , 148.5 , 50 , { align : 'center' } ) ;
186+
187+ // Subtitle
188+ doc . setTextColor ( 50 , 50 , 50 ) ;
189+ doc . setFontSize ( 20 ) ;
190+ doc . setFont ( 'helvetica' , 'normal' ) ;
191+ doc . text ( 'This certifies that' , 148.5 , 80 , { align : 'center' } ) ;
192+
193+ // Name
194+ const name = prompt ( "Enter your name for the certificate:" , "Energy Professional" ) ;
195+ if ( ! name ) return ;
196+
197+ doc . setFontSize ( 30 ) ;
198+ doc . setTextColor ( 255 , 109 , 0 ) ; // Solar Orange
199+ doc . text ( name , 148.5 , 100 , { align : 'center' } ) ;
200+
201+ // Description
202+ doc . setTextColor ( 50 , 50 , 50 ) ;
203+ doc . setFontSize ( 16 ) ;
204+ doc . text ( 'Demonstrated mastery in fundamentals of' , 148.5 , 120 , { align : 'center' } ) ;
205+ doc . text ( 'energy domain from an IPP perspective' , 148.5 , 130 , { align : 'center' } ) ;
206+
207+ // Score & Date
208+ doc . setFontSize ( 12 ) ;
209+ doc . setTextColor ( 100 , 100 , 100 ) ;
210+ const date = new Date ( ) . toLocaleDateString ( ) ;
211+ doc . text ( `Score: ${ score } /${ questions . length } (${ ( score / questions . length ) * 100 } %)` , 148.5 , 150 , { align : 'center' } ) ;
212+ doc . text ( `Date: ${ date } ` , 148.5 , 160 , { align : 'center' } ) ;
213+
214+ // Footer
215+ doc . setFontSize ( 14 ) ;
216+ doc . setTextColor ( 0 , 176 , 255 ) ; // Neon Cyan
217+ doc . text ( 'Now fearlessly grow in the energy industry.' , 148.5 , 180 , { align : 'center' } ) ;
218+
219+ doc . save ( `EnergyIntro_Certificate_${ name . replace ( / \s + / g, '_' ) } .pdf` ) ;
220+ }
221+
222+ container . appendChild ( content ) ;
223+ showStart ( ) ;
219224}
0 commit comments