milwright commited on
Commit
b88ba0c
Β·
1 Parent(s): ba941d6

feat: add welcome overlay for first-time user onboarding

Browse files

- Create welcomeOverlay.js with concise game explanation
- Explain data source (Project Gutenberg via HF Datasets)
- Mention AI model (Google Gemma 3 via OpenRouter)
- Clear instructions on how to play and progress
- Shows only once using localStorage, with reset option
- Integrate into app initialization with 500ms delay

Files changed (2) hide show
  1. src/app.js +7 -0
  2. src/welcomeOverlay.js +126 -0
src/app.js CHANGED
@@ -1,11 +1,13 @@
1
  // Main application entry point
2
  import ClozeGame from './clozeGameEngine.js';
3
  import ChatUI from './chatInterface.js';
 
4
 
5
  class App {
6
  constructor() {
7
  this.game = new ClozeGame();
8
  this.chatUI = new ChatUI(this.game);
 
9
  this.elements = {
10
  loading: document.getElementById('loading'),
11
  gameArea: document.getElementById('game-area'),
@@ -31,6 +33,11 @@ class App {
31
  await this.game.initialize();
32
  await this.startNewGame();
33
  this.showLoading(false);
 
 
 
 
 
34
  } catch (error) {
35
  console.error('Failed to initialize app:', error);
36
  this.showError('Failed to load the game. Please refresh and try again.');
 
1
  // Main application entry point
2
  import ClozeGame from './clozeGameEngine.js';
3
  import ChatUI from './chatInterface.js';
4
+ import WelcomeOverlay from './welcomeOverlay.js';
5
 
6
  class App {
7
  constructor() {
8
  this.game = new ClozeGame();
9
  this.chatUI = new ChatUI(this.game);
10
+ this.welcomeOverlay = new WelcomeOverlay();
11
  this.elements = {
12
  loading: document.getElementById('loading'),
13
  gameArea: document.getElementById('game-area'),
 
33
  await this.game.initialize();
34
  await this.startNewGame();
35
  this.showLoading(false);
36
+
37
+ // Show welcome overlay for first-time users
38
+ setTimeout(() => {
39
+ this.welcomeOverlay.show();
40
+ }, 500);
41
  } catch (error) {
42
  console.error('Failed to initialize app:', error);
43
  this.showError('Failed to load the game. Please refresh and try again.');
src/welcomeOverlay.js ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Welcome overlay for first-time users
2
+ class WelcomeOverlay {
3
+ constructor() {
4
+ this.isVisible = false;
5
+ this.hasBeenShown = localStorage.getItem('cloze-reader-welcomed') === 'true';
6
+ }
7
+
8
+ show() {
9
+ if (this.hasBeenShown) return;
10
+
11
+ this.isVisible = true;
12
+ const overlay = this.createOverlay();
13
+ document.body.appendChild(overlay);
14
+
15
+ // Animate in
16
+ requestAnimationFrame(() => {
17
+ overlay.style.opacity = '1';
18
+ });
19
+ }
20
+
21
+ createOverlay() {
22
+ const overlay = document.createElement('div');
23
+ overlay.className = 'welcome-overlay';
24
+ overlay.style.cssText = `
25
+ position: fixed;
26
+ top: 0;
27
+ left: 0;
28
+ width: 100%;
29
+ height: 100%;
30
+ background: rgba(0, 0, 0, 0.8);
31
+ display: flex;
32
+ align-items: center;
33
+ justify-content: center;
34
+ z-index: 1000;
35
+ opacity: 0;
36
+ transition: opacity 0.3s ease;
37
+ `;
38
+
39
+ const modal = document.createElement('div');
40
+ modal.style.cssText = `
41
+ background: white;
42
+ border-radius: 12px;
43
+ padding: 32px;
44
+ max-width: 500px;
45
+ margin: 20px;
46
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
47
+ text-align: center;
48
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
49
+ `;
50
+
51
+ modal.innerHTML = `
52
+ <div style="font-size: 48px; margin-bottom: 16px;">πŸ“š</div>
53
+ <h1 style="margin: 0 0 24px 0; color: #1a1a1a; font-size: 28px; font-weight: 600;">
54
+ Cloze Reader
55
+ </h1>
56
+
57
+ <div style="text-align: left; color: #4a4a4a; line-height: 1.6; margin-bottom: 32px;">
58
+ <p style="margin: 0 0 16px 0;">
59
+ <strong>Practice reading comprehension</strong> by filling in missing words from classic literature passages.
60
+ </p>
61
+
62
+ <p style="margin: 0 0 16px 0;">
63
+ <strong>How to play:</strong> Read the passage, fill in the blanks, and use hints or chat help (πŸ’¬) if needed. Progress through levels as you improve.
64
+ </p>
65
+
66
+ <p style="margin: 0 0 16px 0;">
67
+ <strong>Data source:</strong> Passages from Project Gutenberg's public domain collection, processed via Hugging Face Datasets.
68
+ </p>
69
+
70
+ <p style="margin: 0 0 0 0;">
71
+ <strong>AI assistance:</strong> Powered by Google's Gemma 3 model via OpenRouter for intelligent word selection and contextual hints.
72
+ </p>
73
+ </div>
74
+
75
+ <button id="welcome-start-btn" style="
76
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
77
+ color: white;
78
+ border: none;
79
+ padding: 12px 32px;
80
+ border-radius: 8px;
81
+ font-size: 16px;
82
+ font-weight: 600;
83
+ cursor: pointer;
84
+ transition: transform 0.2s ease;
85
+ " onmouseover="this.style.transform='scale(1.05)'" onmouseout="this.style.transform='scale(1)'">
86
+ Start Reading
87
+ </button>
88
+ `;
89
+
90
+ overlay.appendChild(modal);
91
+
92
+ // Add click handler
93
+ const startBtn = modal.querySelector('#welcome-start-btn');
94
+ startBtn.addEventListener('click', () => this.hide());
95
+
96
+ // Allow clicking outside to close
97
+ overlay.addEventListener('click', (e) => {
98
+ if (e.target === overlay) this.hide();
99
+ });
100
+
101
+ return overlay;
102
+ }
103
+
104
+ hide() {
105
+ const overlay = document.querySelector('.welcome-overlay');
106
+ if (!overlay) return;
107
+
108
+ overlay.style.opacity = '0';
109
+ setTimeout(() => {
110
+ overlay.remove();
111
+ this.isVisible = false;
112
+
113
+ // Remember that user has seen welcome
114
+ localStorage.setItem('cloze-reader-welcomed', 'true');
115
+ this.hasBeenShown = true;
116
+ }, 300);
117
+ }
118
+
119
+ // Method to reset welcome (for testing or new features)
120
+ reset() {
121
+ localStorage.removeItem('cloze-reader-welcomed');
122
+ this.hasBeenShown = false;
123
+ }
124
+ }
125
+
126
+ export default WelcomeOverlay;