Skip to content

Commit d935765

Browse files
feat: Revamp Pomodoro Timer with enhanced UI and task management features
- Updated main.js to improve state management and UI rendering. - Refactored timer logic to include toggle and reset functionalities. - Enhanced task management with add, delete, and toggle completion features. - Redesigned HTML structure for better accessibility and user experience. - Updated CSS for a modern look with glass effect and improved color themes. - Removed deprecated pomodoro.js file and consolidated functionality. - Added workshop guide for live coding session.
1 parent 3750a0f commit d935765

5 files changed

Lines changed: 839 additions & 440 deletions

File tree

src/js/WORKSHOP_GUIDE.md

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
# 🎓 GDG Pomodoro: JavaScript Live Coding Script
2+
**Duration:** 1h - 1h 30m
3+
**Goal:** Build a working Pomodoro timer from scratch (excluding Task CRUD).
4+
5+
---
6+
7+
## 🏁 Phase 0: Setup (5 mins)
8+
* **Goal:** Ensure everyone has the HTML/CSS ready and connected.
9+
* **Action:** Open `main.js` (empty) and `index.html`.
10+
* **Talking Point:** "HTML is the skeleton, CSS is the skin, and JavaScript is the brain. Today we are building the brain."
11+
12+
---
13+
14+
## 🏗️ Phase 1: The "Memory" (State & Config) (10 mins)
15+
* **Goal:** Define the data our app needs to remember.
16+
* **Concept:** specific specific variables vs. objects.
17+
18+
### Step 1.1: Configuration
19+
```javascript
20+
// 1. CONFIGURATION
21+
const DURATIONS = {
22+
focus: 25 * 60,
23+
"short-break": 5 * 60,
24+
"long-break": 15 * 60,
25+
};
26+
```
27+
* *Explain:* specialized objects (Dictionaries) map keys to values. `25 * 60` is easier to read than `1500`.
28+
29+
### Step 1.2: State
30+
```javascript
31+
// 2. STATE
32+
let state = {
33+
mode: "focus",
34+
timeLeft: DURATIONS.focus,
35+
isRunning: false,
36+
timerInterval: null,
37+
};
38+
```
39+
* *Explain:* `state` is the "single source of truth". If the variable changes, the screen *should* change.
40+
41+
---
42+
43+
## 🔌 Phase 2: Connecting the Wires (DOM Selection) (10 mins)
44+
* **Goal:** Get references to HTML elements so we can control them.
45+
* **Concept:** `document.getElementById` and `querySelector`.
46+
47+
```javascript
48+
// 3. DOM ELEMENTS
49+
const elements = {
50+
timerDisplay: document.getElementById("timer-display"),
51+
toggleBtn: document.getElementById("toggle-btn"),
52+
toggleIcon: document.getElementById("toggle-icon"), // The play/pause icon
53+
resetBtn: document.getElementById("reset-btn"),
54+
modeButtons: document.querySelectorAll("[data-mode]"), // Selects all 3 buttons
55+
};
56+
```
57+
* *Tip:* Log `elements` to the console to show that they are real HTML nodes.
58+
59+
---
60+
61+
## 🎨 Phase 3: The "Render" Loop (15 mins)
62+
* **Goal:** Make the screen reflect the `state`. **(Crucial Step)**
63+
* **Concept:** Data Driven UI.
64+
65+
```javascript
66+
// 4. FUNCTIONS
67+
68+
function updateUI() {
69+
// Calculated minutes and seconds
70+
const minutes = Math.floor(state.timeLeft / 60);
71+
const seconds = state.timeLeft % 60;
72+
73+
// Format string: "25:00" using padStart
74+
elements.timerDisplay.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
75+
76+
// Update Button Icon
77+
elements.toggleIcon.textContent = state.isRunning ? "pause" : "play_arrow";
78+
}
79+
80+
// Call it once to test!
81+
updateUI();
82+
```
83+
* *Demo:* Manually change `state.timeLeft = 100` in the code and refresh. See the UI update? That's the power of the render function.
84+
85+
---
86+
87+
## ⏱️ Phase 4: Making it Tick (The Timer) (20 mins)
88+
* **Goal:** Start reducing `timeLeft` every second.
89+
* **Concept:** `setInterval` and `clearInterval`.
90+
91+
### Step 4.1: Toggle Logic
92+
```javascript
93+
function toggleTimer() {
94+
if (state.isRunning) {
95+
// STOP LOGIC
96+
state.isRunning = false;
97+
clearInterval(state.timerInterval);
98+
} else {
99+
// START LOGIC
100+
state.isRunning = true;
101+
102+
state.timerInterval = setInterval(() => {
103+
if (state.timeLeft > 0) {
104+
state.timeLeft--;
105+
updateUI(); // Don't forget to update the screen!
106+
} else {
107+
// Time's up!
108+
clearInterval(state.timerInterval);
109+
state.isRunning = false;
110+
alert("Time is up!");
111+
updateUI();
112+
}
113+
}, 1000); // 1000ms = 1 second
114+
}
115+
updateUI();
116+
}
117+
```
118+
119+
### Step 4.2: Hook up the Event Listener
120+
```javascript
121+
// 5. EVENTS
122+
elements.toggleBtn.addEventListener("click", toggleTimer);
123+
```
124+
* *Test:* Click the play button. Is it counting down? Click it again. Does it pause?
125+
126+
---
127+
128+
## 🎛️ Phase 5: Controls (Modes & Reset) (15 mins)
129+
* **Goal:** Allow switching between Focus and Breaks.
130+
* **Concept:** Reusing logic.
131+
132+
### Step 5.1: Reset
133+
```javascript
134+
function resetTimer() {
135+
state.isRunning = false;
136+
clearInterval(state.timerInterval);
137+
state.timeLeft = DURATIONS[state.mode]; // Reset to current mode's max time
138+
updateUI();
139+
}
140+
141+
elements.resetBtn.addEventListener("click", resetTimer);
142+
```
143+
144+
### Step 5.2: Switching Modes
145+
```javascript
146+
function switchMode(newMode) {
147+
state.mode = newMode;
148+
state.timeLeft = DURATIONS[newMode];
149+
// Reuse reset logic effectively
150+
resetTimer();
151+
152+
// OPTIONAL: Update active button visual
153+
elements.modeButtons.forEach(btn => {
154+
btn.classList.toggle("active", btn.dataset.mode === newMode);
155+
});
156+
}
157+
158+
// Add listeners to chips
159+
elements.modeButtons.forEach(btn => {
160+
btn.addEventListener("click", () => {
161+
const mode = btn.dataset.mode; // Read from HTML data-mode="..."
162+
switchMode(mode);
163+
});
164+
});
165+
```
166+
167+
---
168+
169+
## 🚀 Phase 6: Wrap up & Q/A (10 mins)
170+
* Recap: We separated State (Data) from UI (View).
171+
* Challenge for students: "Can you change the colors when the mode changes?" (Hint: It's just adding a class or setting a CSS variable in `switchMode`).

0 commit comments

Comments
 (0)