Nuzwa's picture
Update index.html
299c958 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Edu Assess Pro - smart Exam Paper Designer</title>
<!-- Poppins 400/600/700 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* =======================
1) Design Tokens (exact)
======================= */
:root{
--primary-color-start: #4F46E5;
--primary-color-end: #8B5CF6;
--background-color: #f8f9fc;
--container-bg: #ffffff;
--text-color: #1f2937;
--label-color: #374151;
--border-color: #d1d5db;
--shadow-color: rgba(0, 0, 0, 0.08);
/* Fixed colors (don’t change) */
--fixed-outer-border: #e5e7eb;
--fixed-subtitle: #6b7280;
--fixed-inputs-bg: #f9fafb;
--fixed-text-on-primary: #fff;
--fixed-focus-shadow: rgba(79,70,229,.15);
--fixed-btn-shadow: rgba(0,0,0,.10);
--fixed-btn-hover-shadow: rgba(0,0,0,.15);
--fixed-secondary-bg: #111827;
--fixed-pre-bg: #0f172a;
--fixed-pre-border: #1f2937;
--fixed-toast-shadow: rgba(0,0,0,.2);
}
/* =======================
2) Base Layout & Typography
======================= */
html,body{height:100%}
body{
padding:1rem; display:flex; justify-content:center; align-items:flex-start;
min-height:100vh; background:var(--background-color); color:var(--text-color);
font-family:"Poppins", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Arial, "Apple Color Emoji", "Segoe UI Emoji";
font-size:1rem;
}
.container{
max-width:820px; width:100%; background:var(--container-bg); padding:2rem; border-radius:16px;
box-shadow:0 10px 30px var(--shadow-color); border:1px solid var(--fixed-outer-border);
}
@media (max-width:600px){ .container{ padding:1.25rem; } }
h1{
font-size:2rem; font-weight:700; margin:0 0 .75rem 0; text-align:center;
background:linear-gradient(90deg,var(--primary-color-start),var(--primary-color-end));
-webkit-background-clip:text; background-clip:text; -webkit-text-fill-color:transparent;
}
.subtitle{ font-size:.9rem; color:var(--fixed-subtitle); text-align:center; margin-bottom:.75rem; }
label{ font-weight:600; color:var(--label-color); margin-top:1rem; margin-bottom:.4rem; font-size:.95rem; display:block; }
.row{ display:grid; grid-template-columns:1fr 1fr; gap:.75rem 1rem; }
.actions{ display:grid; grid-template-columns:1fr 1fr; gap:.75rem; margin-top:1.25rem; }
/* =======================
4) Inputs / Textareas / Selects (uniform)
======================= */
.field, select, textarea{
width:100%; padding:.8rem 1rem; border-radius:10px; border:1px solid var(--border-color);
background:var(--fixed-inputs-bg); transition:all .2s; font-size:1rem;
}
.field:focus, select:focus, textarea:focus{
outline:none; border-color:var(--primary-color-start); box-shadow:0 0 0 3px var(--fixed-focus-shadow); background:#fff;
}
/* Select (custom chevron) */
select{
-webkit-appearance:none; -moz-appearance:none; appearance:none;
padding-right:2.25rem;
background-image:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none"><path d="M6 8l4 4 4-4" stroke="%234F46E5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>');
background-repeat:no-repeat; background-position:right .75rem center; background-size:14px;
}
select::-ms-expand{ display:none; }
select:disabled{ opacity:.6; cursor:not-allowed; }
textarea{ min-height:110px; resize:vertical; }
/* =======================
5) Buttons
======================= */
.btn{
display:inline-flex; align-items:center; justify-content:center; gap:.5rem; cursor:pointer; user-select:none;
background:linear-gradient(90deg, var(--primary-color-start), var(--primary-color-end));
color:var(--fixed-text-on-primary); padding:.9rem 1.2rem; border:none; border-radius:10px; width:100%;
font-weight:700; font-size:1.05rem; box-shadow:0 4px 15px var(--fixed-btn-shadow); transition:transform .15s ease, box-shadow .15s ease;
}
.btn:hover{ transform:translateY(-2px); box-shadow:0 7px 20px var(--fixed-btn-hover-shadow); }
.btn:active{ transform:translateY(0); }
.btn.secondary{ background:var(--fixed-secondary-bg); }
/* =======================
6) Output & Toast
======================= */
pre#output{
background:var(--fixed-pre-bg); color:#e5e7eb; padding:1rem 1.25rem; border-radius:12px; margin-top:1rem;
border:1px solid var(--fixed-pre-border); font-size:.92rem; line-height:1.6; white-space:pre-wrap; word-break:break-word;
}
.toast{
position:fixed; right:16px; bottom:16px; background:var(--fixed-secondary-bg); color:#fff;
padding:10px 12px; border-radius:10px; box-shadow:0 8px 20px var(--fixed-toast-shadow);
opacity:0; transform:translateY(10px); transition:opacity .2s, transform .2s; z-index:50;
}
.toast.show{ opacity:1; transform:translateY(0); }
/* A hidden test log area (will not alter layout) */
#testlog{ display:none; }
</style>
</head>
<body>
<div class="container" role="application" aria-label="Prompt builder">
<h1>EduPaper Pro - Exam Paper Designer</h1>
<p class="subtitle">Fill the fields to generate a <strong> text prompt</strong></p>
<div class="row">
<div>
<label for="grade">Grade</label>
<select id="grade" class="field">
<option>Grade 1</option><option>Grade 2</option><option>Grade 3</option><option>Grade 4</option>
<option>Grade 5</option><option>Grade 6</option><option>Grade 7</option><option>Grade 8</option>
<option selected>Grade 9</option><option>Grade 10</option><option>Grade 11</option><option>Grade 12</option>
</select>
</div>
<div>
<label for="subject">Subject</label>
<select id="subject" class="field">
<option>Mathematics</option><option>English</option><option>Urdu</option><option>Science</option>
<option selected>Physics</option><option>Chemistry</option><option>Biology</option><option>Computer Science</option>
<option>Islamiat</option><option>Pakistan Studies</option>
</select>
</div>
<div>
<label for="board">Board</label>
<select id="board" class="field">
<option>PCTB (Punjab)</option><option selected>FBISE (Federal)</option><option>Sindh Board</option>
<option>KPK Board</option><option>Balochistan Board</option><option>AKUEB</option>
</select>
</div>
<div>
<label for="testType">Test Type</label>
<select id="testType" class="field">
<option selected>Formative</option><option>Summative</option><option>Diagnostic</option>
</select>
</div>
<div>
<label for="questionType">Question Type</label>
<select id="questionType" class="field">
<option selected>MCQs</option><option>Short Questions</option><option>Long Questions</option>
<option>Practical/Diagram</option><option>Moral/Ethical</option><option>Islamic</option>
</select>
</div>
<div>
<label for="duration">Duration</label>
<select id="duration" class="field">
<option>30 minutes</option><option selected>45 minutes</option><option>60 minutes</option>
</select>
</div>
<div>
<label for="language">Language of Paper</label>
<select id="language" class="field">
<option value="">— Select —</option>
<option>English</option>
<option>Urdu</option>
<option>Bilingual</option>
</select>
</div>
<div>
<label for="bloom">Bloom's Taxonomy</label>
<select id="bloom" class="field">
<option value="no" selected>No</option>
<option value="yes">Yes (Varied Levels)</option>
</select>
</div>
<div>
<label for="bloomLevel">Bloom Level Emphasis (optional)</label>
<select id="bloomLevel" class="field">
<option value="">— Not specified —</option>
<option>Knowledge</option>
<option>Comprehension</option>
<option>Application</option>
<option>Analysis</option>
<option>Synthesis</option>
<option>Evaluation</option>
<option>Mixed/Varied</option>
</select>
</div>
<div>
<label for="mcqSelect">How many MCQs?</label>
<select id="mcqSelect" class="field">
<option value="">— Select —</option>
<option>10</option><option>15</option><option>20</option><option>25</option><option>30</option>
</select>
</div>
<div>
<label for="mcqCustom">Custom MCQs (optional)</label>
<input id="mcqCustom" class="field" type="number" min="1" step="1" placeholder="e.g., 18" />
</div>
<div>
<label for="difficulty">Difficulty (optional)</label>
<select id="difficulty" class="field">
<option value="">— Not specified —</option>
<option>Easy</option><option>Moderate</option><option>Hard</option><option>Mixed</option>
</select>
</div>
<div style="grid-column:1/-1">
<label for="topic">Topic (optional)</label>
<input id="topic" class="field" type="text" placeholder="Units 3–4" />
</div>
</div>
<div class="actions">
<button id="gen" class="btn" type="button" aria-label="Generate prompt from form">Generate Prompt</button>
<button id="copy" class="btn secondary" type="button" aria-label="Copy full prompt and open GPT">Copy Prompt and Paste Now</button>
</div>
<div class="actions" style="grid-template-columns:auto; justify-items:end; margin-top:.75rem">
<a id="open-gpt-fallback" href="https://chatgpt.com/g/g-68697e4c49508191b175d86830b34d85-eduassess-pro-smart-exam-paper-designer" target="_blank" rel="noopener noreferrer" class="btn secondary" style="display:none; width:auto; min-width:14ch; padding:.7rem 1rem;">Open GPT</a>
</div>
<pre id="output" aria-live="polite" aria-atomic="true"></pre>
<pre id="testlog"></pre>
</div>
<div id="toast" class="toast" role="status" aria-live="polite">Copied!</div>
<script>
// ===== Config & helpers =====
const CUSTOM_GPT_URL = "https://chatgpt.com/g/g-68697e4c49508191b175d86830b34d85-eduassess-pro-smart-exam-paper-designer";
const $ = (s)=>document.querySelector(s);
function normalizeInt(v){
const n = parseInt(v, 10);
return Number.isFinite(n) && n > 0 ? n : null;
}
// Build plain-text prompt
function buildPrompt(){
const grade = $('#grade').value;
const subject = $('#subject').value;
const board = $('#board').value;
const testType = $('#testType').value;
const questionType = $('#questionType').value;
const duration = $('#duration').value;
const topic = ($('#topic').value || '').trim();
const language = $('#language').value; // may be '' (not specified)
const bloom = $('#bloom').value; // 'yes' | 'no'
const bloomLevel = $('#bloomLevel').value; // '' or specific
const mcqSel = normalizeInt($('#mcqSelect').value);
const mcqCustom = normalizeInt($('#mcqCustom').value);
const mcqs = mcqCustom ?? mcqSel; // custom overrides select
const difficulty = $('#difficulty').value; // may be ''
let p = `I need a ${testType} paper for ${grade} - ${subject}, Board: ${board}.`;
p += ` Question Type: ${questionType}.`;
if(duration) p += ` Duration: ${duration}.`;
if(typeof mcqs === 'number') p += ` MCQs: ${mcqs}.`;
if(language) p += ` Language: ${language}.`;
if(bloom === 'yes') p += ` Include Bloom's taxonomy: Yes.`;
if(bloomLevel) p += ` Bloom emphasis: ${bloomLevel}.`;
if(difficulty) p += ` Difficulty: ${difficulty}.`;
if(topic) p += ` Topic: ${topic}.`;
return p;
}
function showToast(msg){
const t = $('#toast');
t.textContent = msg;
t.classList.add('show');
setTimeout(()=>t.classList.remove('show'), 1800);
}
// ===== UI actions =====
$('#gen').addEventListener('click', ()=>{
const prompt = buildPrompt();
$('#output').textContent = prompt; // plain text prompt output
});
$('#copy').addEventListener('click', async ()=>{
const prompt = $('#output').textContent || buildPrompt();
// Try to open immediately (user gesture)
const popup = window.open(CUSTOM_GPT_URL, '_blank', 'noopener,noreferrer');
try{ await navigator.clipboard.writeText(prompt); }catch(e){}
showToast(popup ? 'Copied & Opening GPT...' : 'Copied! Tap Open GPT');
const link = $('#open-gpt-fallback');
if(link){ link.style.display = 'inline-flex'; link.focus(); }
});
// ===== Minimal tests (keep old behavior intact) =====
(function runTests(){
const log = [];
const save = {
grade: $('#grade').value,
subject: $('#subject').value,
board: $('#board').value,
testType: $('#testType').value,
questionType: $('#questionType').value,
duration: $('#duration').value,
topic: $('#topic').value,
language: $('#language').value,
bloom: $('#bloom').value,
bloomLevel: $('#bloomLevel').value,
mcqSelect: $('#mcqSelect').value,
mcqCustom: $('#mcqCustom').value,
difficulty: $('#difficulty').value
};
// Ensure new fields do NOT change legacy prompt when left blank/No
$('#grade').value = 'Grade 9';
$('#subject').value = 'Physics';
$('#board').value = 'FBISE (Federal)';
$('#testType').value = 'Formative';
$('#questionType').value = 'MCQs';
$('#duration').value = '45 minutes';
$('#topic').value = '';
$('#language').value = '';
$('#bloom').value = 'no';
$('#bloomLevel').value = '';
$('#mcqSelect').value = '';
$('#mcqCustom').value = '';
$('#difficulty').value = '';
let out = buildPrompt();
const expected1 = 'I need a Formative paper for Grade 9 - Physics, Board: FBISE (Federal). Question Type: MCQs. Duration: 45 minutes.';
console.assert(out === expected1, 'Test 1 failed', {out, expected1});
log.push((out === expected1 ? '✅' : '❌') + ' Test 1: legacy prompt unchanged');
// Test 2: With topic only
$('#topic').value = 'Unit 2 (Dynamics)';
out = buildPrompt();
const expected2 = expected1 + ' Topic: Unit 2 (Dynamics).';
console.assert(out === expected2, 'Test 2 failed', {out, expected2});
log.push((out === expected2 ? '✅' : '❌') + ' Test 2: topic appends');
// Test 3: New fields engaged
$('#language').value = 'English';
$('#bloom').value = 'yes';
$('#bloomLevel').value = 'Application';
$('#mcqSelect').value = '20';
$('#difficulty').value = 'Moderate';
out = buildPrompt();
const expected3 = expected2 + ' MCQs: 20. Language: English. Include Bloom\'s taxonomy: Yes. Bloom emphasis: Application. Difficulty: Moderate.';
console.assert(out === expected3, 'Test 3 failed', {out, expected3});
log.push((out === expected3 ? '✅' : '❌') + ' Test 3: new fields appended');
// Restore original values
$('#grade').value = save.grade;
$('#subject').value = save.subject;
$('#board').value = save.board;
$('#testType').value = save.testType;
$('#questionType').value = save.questionType;
$('#duration').value = save.duration;
$('#topic').value = save.topic;
$('#language').value = save.language;
$('#bloom').value = save.bloom;
$('#bloomLevel').value = save.bloomLevel;
$('#mcqSelect').value = save.mcqSelect;
$('#mcqCustom').value = save.mcqCustom;
$('#difficulty').value = save.difficulty;
const tl = document.getElementById('testlog');
if(tl){ tl.textContent = log.join('\n'); }
})();
</script>
</body>
</html>