diff --git a/.git-credentials b/.git-credentials new file mode 100644 index 0000000..d78ec0a --- /dev/null +++ b/.git-credentials @@ -0,0 +1,2 @@ +http://sultanbek_askaruly:ccaf3980723058bd093e312780c167c82b9a54e6@172.18.0.1%3a3300 +https://sultanbek_askaruly:ccaf3980723058bd093e312780c167c82b9a54e6@git.vibe42.kz diff --git a/contact.html b/contact.html index c1c142b..10a8fe9 100644 --- a/contact.html +++ b/contact.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • diff --git a/css/style.css b/css/style.css index 880bc8f..88b6daf 100644 --- a/css/style.css +++ b/css/style.css @@ -1014,6 +1014,167 @@ footer a:hover { } } +/* ===== PROGRESS PAGE ===== */ +.level-hero { + text-align: center; + padding: 48px 32px; + background: linear-gradient(135deg, var(--accent-50), var(--green-light)); + border-radius: 24px; + margin-bottom: 32px; +} + +.level-hero .level-icon { + font-size: 56px; + margin-bottom: 12px; +} + +.level-hero .level-title { + font-size: 36px; + font-weight: 800; + color: var(--accent); + margin-bottom: 4px; +} + +.level-hero .level-desc { + font-size: 16px; + color: var(--gray-500); + margin-bottom: 20px; +} + +.level-hero .level-xp-total { + font-size: 20px; + font-weight: 700; + color: var(--ink); +} + +.level-bar { + height: 12px; + background: var(--gray-100); + border-radius: 6px; + overflow: hidden; + max-width: 400px; + margin: 12px auto 0; +} + +.level-bar-fill { + height: 100%; + background: linear-gradient(90deg, var(--accent), var(--green)); + border-radius: 6px; + transition: width 0.6s ease; + width: 0%; +} + +.stat-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: 16px; + margin-bottom: 32px; +} + +.stat-card { + background: var(--white); + border: 1px solid var(--gray-100); + border-radius: 16px; + padding: 24px; + text-align: center; + box-shadow: var(--shadow); + transition: all 0.3s; +} + +.stat-card:hover { + transform: translateY(-3px); + box-shadow: var(--shadow-hover); +} + +.stat-card .stat-icon { + font-size: 28px; + margin-bottom: 8px; +} + +.stat-card .stat-value { + font-size: 28px; + font-weight: 800; + color: var(--accent); +} + +.stat-card .stat-label { + font-size: 13px; + color: var(--gray-500); + margin-top: 4px; +} + +.activity-list { + background: var(--white); + border: 1px solid var(--gray-100); + border-radius: 20px; + padding: 28px; + box-shadow: var(--shadow); +} + +.activity-list h3 { + font-size: 20px; + font-weight: 700; + margin-bottom: 16px; + display: flex; + align-items: center; + gap: 8px; +} + +.activity-item { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 0; + border-bottom: 1px solid var(--gray-100); + font-size: 15px; +} + +.activity-item:last-child { + border-bottom: none; +} + +.activity-item .act-icon { + width: 36px; + height: 36px; + background: var(--accent-50); + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 16px; + flex-shrink: 0; +} + +.activity-item .act-text { + flex: 1; + color: var(--gray-500); +} + +.activity-item .act-xp { + font-weight: 700; + color: var(--green); + font-size: 14px; +} + +.level-badge { + display: inline-flex; + align-items: center; + gap: 8px; + background: var(--accent-50); + padding: 6px 16px 6px 12px; + border-radius: 20px; + font-size: 13px; +} + +.level-badge .level-label { + font-weight: 700; + color: var(--accent); +} + +.level-badge .level-xp { + color: var(--gray-500); +} + /* ===== ANIMATIONS ===== */ @keyframes fadeInUp { from { opacity: 0; transform: translateY(20px); } diff --git a/exercises.html b/exercises.html index 2e3aef0..821aba9 100644 --- a/exercises.html +++ b/exercises.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • diff --git a/grammar.html b/grammar.html index 164f3ea..c6bb1c7 100644 --- a/grammar.html +++ b/grammar.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • diff --git a/index.html b/index.html index 7ef746f..d57cbeb 100644 --- a/index.html +++ b/index.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • @@ -79,6 +80,12 @@

    Listen to words and phrases spoken aloud. Practice your pronunciation and improve your speaking skills.

    Start Speaking +
    +
    📊
    +

    My Progress

    +

    Track your XP, level, and completed activities. Watch yourself improve from Beginner to Advanced!

    + View Progress +
    diff --git a/js/script.js b/js/script.js index dbbc8ab..54c6bb5 100644 --- a/js/script.js +++ b/js/script.js @@ -50,13 +50,14 @@ function checkExercise(btn) { if (isCorrect) { parent.classList.add('correct'); - feedback.textContent = 'Correct!'; + feedback.textContent = 'Correct! +10 XP'; feedback.className = 'feedback correct'; + var exId = exercise.getAttribute('data-ex-id') || exercise.querySelector('h3').textContent.trim(); + markExerciseDone(exId); } else { parent.classList.add('wrong'); feedback.textContent = 'Try again!'; feedback.className = 'feedback wrong'; - // Show correct answer options.forEach(function(opt) { const radio = opt.querySelector('input[type="radio"]'); if (radio && radio.value === 'true') { @@ -76,8 +77,10 @@ function checkFill(input) { if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); - feedback.textContent = 'Correct!'; + feedback.textContent = 'Correct! +10 XP'; feedback.className = 'feedback correct'; + var exId = input.closest('.exercise').getAttribute('data-ex-id') || input.closest('.exercise').querySelector('h3').textContent.trim(); + markExerciseDone(exId); } else { input.classList.add('wrong'); feedback.textContent = 'Try again! Correct answer: ' + answer; @@ -96,8 +99,10 @@ function checkTranslate(btn) { if (input.value.trim().toLowerCase() === answer.toLowerCase()) { input.classList.add('correct'); - feedback.textContent = 'Correct!'; + feedback.textContent = 'Correct! +10 XP'; feedback.className = 'feedback correct'; + var exId = exercise.getAttribute('data-ex-id') || exercise.querySelector('h3').textContent.trim(); + markExerciseDone(exId); } else { input.classList.add('wrong'); feedback.textContent = 'Try again! Correct answer: ' + answer; @@ -124,8 +129,10 @@ function checkMatch(btn) { }); if (allCorrect) { - feedback.textContent = 'All correct! Great job!'; + feedback.textContent = 'All correct! Great job! +10 XP'; feedback.className = 'feedback correct'; + var exId = exercise.getAttribute('data-ex-id') || exercise.querySelector('h3').textContent.trim(); + markExerciseDone(exId); } else { feedback.textContent = 'Some answers are wrong. Try again!'; feedback.className = 'feedback wrong'; @@ -146,12 +153,21 @@ function checkTest() { } }); + markTestDone(score, total); + + var data = getProgress(); + var info = getLevelProgress(data.xp); + const resultBox = document.getElementById('test-result'); const scoreDisplay = document.getElementById('score'); scoreDisplay.textContent = score + '/' + total; resultBox.classList.add('show'); - // Scroll to result + var detail = document.getElementById('test-detail'); + if (detail) { + detail.innerHTML = 'Level: ' + info.current.label + '  |  XP: ' + data.xp + '  |  Best: ' + data.bestTestScore + '/' + total + ''; + } + resultBox.scrollIntoView({ behavior: 'smooth' }); } @@ -184,6 +200,7 @@ function repeatWord(btn) { var word = btn.getAttribute('data-word'); speakWord(word, 0.8); btn.textContent = '🔊 Playing...'; + markWordListened(); setTimeout(function() { btn.textContent = '🔊 Listen'; }, 1500); } @@ -220,6 +237,107 @@ function speakPhrase(btn) { setTimeout(function() { btn.innerHTML = '🔊 Hear Phrase'; }, 1500); } +// --- Progress Tracking --- +var PROGRESS_KEY = 'english_easy_progress'; + +var LEVELS = [ + { min: 0, label: 'A0 Beginner', desc: 'You are just starting your English journey!' }, + { min: 50, label: 'A1 Starter', desc: 'You know basic words and phrases.' }, + { min: 150, label: 'A2 Elementary', desc: 'You can understand simple sentences.' }, + { min: 300, label: 'B1 Intermediate', desc: 'You can talk about familiar topics.' }, + { min: 500, label: 'B2 Upper Intermediate', desc: 'You can communicate fluently.' }, + { min: 800, label: 'C1 Advanced', desc: 'You understand complex texts and ideas.' } +]; + +function getProgress() { + var data = JSON.parse(localStorage.getItem(PROGRESS_KEY)); + if (!data) { + data = { + xp: 0, + exercisesDone: [], + testsDone: 0, + bestTestScore: 0, + lastTestScore: 0, + wordsListened: 0, + readingDone: [], + joined: new Date().toISOString().split('T')[0] + }; + localStorage.setItem(PROGRESS_KEY, JSON.stringify(data)); + } + return data; +} + +function saveProgress(data) { + localStorage.setItem(PROGRESS_KEY, JSON.stringify(data)); +} + +function addXP(amount, reason) { + var data = getProgress(); + data.xp += amount; + saveProgress(data); + updateLevelBadge(); + return data; +} + +function getLevel(xp) { + for (var i = LEVELS.length - 1; i >= 0; i--) { + if (xp >= LEVELS[i].min) return LEVELS[i]; + } + return LEVELS[0]; +} + +function getLevelProgress(xp) { + var current = getLevel(xp); + var nextMin = 9999; + for (var i = 0; i < LEVELS.length; i++) { + if (LEVELS[i].min > current.min) { + nextMin = LEVELS[i].min; + break; + } + } + var range = nextMin - current.min; + var progress = xp - current.min; + return { current: current, nextMin: nextMin, progress: progress, range: range, percent: range > 0 ? Math.min(100, Math.round(progress / range * 100)) : 100 }; +} + +function updateLevelBadge() { + var data = getProgress(); + var info = getLevelProgress(data.xp); + var badge = document.querySelector('.level-badge'); + if (badge) { + badge.innerHTML = '' + info.current.label + '' + data.xp + ' XP'; + } + var bar = document.querySelector('.level-bar-fill'); + if (bar) bar.style.width = info.percent + '%'; +} + +function markExerciseDone(id) { + var data = getProgress(); + if (data.exercisesDone.indexOf(id) === -1) { + data.exercisesDone.push(id); + data.xp += 10; + saveProgress(data); + } +} + +function markTestDone(score, total) { + var data = getProgress(); + data.testsDone++; + data.lastTestScore = score; + if (score > data.bestTestScore) data.bestTestScore = score; + data.xp += 15 + score * 2; + saveProgress(data); +} + +function markWordListened() { + var data = getProgress(); + data.wordsListened++; + if (data.wordsListened % 5 === 0) { + data.xp += 5; + saveProgress(data); + } +} + // --- Daily Reminder at 20:00 --- (function() { var LS_KEY = 'english_easy_daily'; diff --git a/progress.html b/progress.html new file mode 100644 index 0000000..734f144 --- /dev/null +++ b/progress.html @@ -0,0 +1,150 @@ + + + + + + My Progress — English Easy + + + +
    +
    + + + +
    +
    + + + +
    +
    + +
    +
    🌱
    +
    A0 Beginner
    +
    You are just starting your English journey!
    +
    0 XP
    +
    +
    + +
    +
    +
    +
    0
    +
    Exercises Done
    +
    +
    +
    📝
    +
    0
    +
    Tests Taken
    +
    +
    +
    🏆
    +
    +
    Best Test Score
    +
    +
    +
    🔊
    +
    0
    +
    Words Practiced
    +
    +
    + +
    +

    📋 Recent Activity

    +
    +
    👋
    Start learning to see your activity here!
    +
    +
    + +
    +
    + + + + + + + diff --git a/pronunciation.html b/pronunciation.html index 477af3b..9903bf8 100644 --- a/pronunciation.html +++ b/pronunciation.html @@ -117,6 +117,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • diff --git a/reading.html b/reading.html index a040e85..629ae8d 100644 --- a/reading.html +++ b/reading.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • diff --git a/tests.html b/tests.html index a6b9b56..39da83b 100644 --- a/tests.html +++ b/tests.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact
  • @@ -132,7 +133,7 @@
    0/10
    -

    Keep learning and try again!

    +

    Keep learning and try again!

    diff --git a/vocabulary.html b/vocabulary.html index 74af830..071f63a 100644 --- a/vocabulary.html +++ b/vocabulary.html @@ -20,6 +20,7 @@
  • Exercises
  • Tests
  • Reading
  • +
  • Progress
  • Contact