The Utils module provides pure, stateless utility functions used throughout Estudo Organizado.
ID Generation
uid
Generate a unique identifier.
import { uid } from './utils.js';
const eventId = 'ev_' + uid();
const discId = 'disc_' + uid();
// Example: 'ev_l7k2m3n4p5q6r7s'
Unique string combining timestamp and random characters
The ID format is: timestamp_base36 + random_base36. While not guaranteed to be globally unique, collision probability is extremely low for typical use cases.
String Utilities
esc
Escape HTML entities for safe rendering.
import { esc } from './utils.js';
const userInput = '<script>alert("xss")</script>';
const safe = esc(userInput);
// Returns: '<script>alert("xss")</script>'
el.innerHTML = `<div>${esc(evento.titulo)}</div>`;
String to escape (or any value that can be converted to string)
HTML-safe string with escaped entities
Escapes these characters:
& → &
< → <
> → >
" → "
' → '
Always use esc() when inserting user-generated content into innerHTML to prevent XSS attacks.
Date Utilities
getLocalDateStr
Convert a Date object to local date string in ISO format.
import { getLocalDateStr } from './utils.js';
const today = getLocalDateStr();
// Returns: '2026-03-03'
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const tomorrowStr = getLocalDateStr(tomorrow);
// Returns: '2026-03-04'
Date object to convert (defaults to current date/time)
Date string in ‘YYYY-MM-DD’ format, adjusted for local timezone
This function accounts for timezone offset, ensuring dates are consistent with the user’s local time rather than UTC.
todayStr
Get today’s date string (cached for performance).
import { todayStr } from './utils.js';
const today = todayStr();
// Returns: '2026-03-03'
if (evento.data === todayStr()) {
console.log('Event is today!');
}
Today’s date in ‘YYYY-MM-DD’ format
The result is cached in _todayCache. Call invalidateTodayCache() if the app runs across midnight (rare in single-session usage).
invalidateTodayCache
Clear the today date cache.
import { invalidateTodayCache } from './utils.js';
// Typically called on app resume or after long idle:
invalidateTodayCache();
Format a date string for display in Brazilian Portuguese.
import { formatDate } from './utils.js';
const formatted = formatDate('2026-03-03');
// Returns: '03/03/2026'
const display = formatDate(evento.data);
Date string in ‘YYYY-MM-DD’ format
Formatted date in ‘DD/MM/YYYY’ format
cutoffDateStr
Calculate a date N days in the past.
import { cutoffDateStr } from './utils.js';
const sevenDaysAgo = cutoffDateStr(7);
const thirtyDaysAgo = cutoffDateStr(30);
// Filter recent events:
const recentEvents = state.eventos.filter(e =>
e.data >= cutoffDateStr(7)
);
Number of days to go back from today
Date string in ‘YYYY-MM-DD’ format
Time Utilities
Format seconds as HH:MM:SS or MM:SS.
import { formatTime } from './utils.js';
formatTime(45); // Returns: '00:45'
formatTime(3665); // Returns: '01:01:05'
formatTime(0); // Returns: '00:00'
Formatted time string (MM:SS if less than 1 hour, HH:MM:SS otherwise)
pad
Pad a number with leading zero.
import { pad } from './utils.js';
pad(5); // Returns: '05'
pad(12); // Returns: '12'
pad(0); // Returns: '00'
Two-character string with leading zero if needed
Event Utilities
getEventStatus
Determine the status of an event based on its date and status field.
import { getEventStatus } from './utils.js';
const evento = {
data: '2026-03-01',
status: 'agendado'
};
const status = getEventStatus(evento);
// Returns: 'atrasado' (because date is before today)
Event object with status and data fields
Event status: 'estudei', 'atrasado', or 'agendado'
Logic:
- If
evento.status === 'estudei' → return 'estudei'
- If
evento.data < todayStr() → return 'atrasado'
- Otherwise → return
'agendado'
Habit Types
HABIT_TYPES
Array of study habit definitions.
import { HABIT_TYPES } from './utils.js';
HABIT_TYPES.forEach(habit => {
console.log(habit.label, habit.icon, habit.color);
});
Array of habit type objects
Each habit object contains:
Unique identifier (e.g., ‘questoes’, ‘revisao’)
Display name (e.g., ‘Questões’, ‘Revisão’)
Emoji icon (e.g., ’📝’, ’🔄’)
Hex color code (e.g., ‘#3b82f6’)
Available Habit Types
| Key | Label | Icon | Color |
|---|
questoes | Questões | 📝 | #3b82f6 (blue) |
revisao | Revisão | 🔄 | #10b981 (green) |
discursiva | Discursiva | ✍️ | #f59e0b (amber) |
simulado | Simulado | 🎯 | #ef4444 (red) |
leitura | Leitura Seca | 📖 | #8b5cf6 (purple) |
informativo | Informativos | 📰 | #06b6d4 (cyan) |
sumula | Súmulas | ⚖️ | #6366f1 (indigo) |
videoaula | Videoaula | 📺 | #ec4899 (pink) |
getHabitType
Get a habit type definition by key.
import { getHabitType } from './utils.js';
const questoes = getHabitType('questoes');
console.log(questoes.label); // 'Questões'
console.log(questoes.icon); // '📝'
console.log(questoes.color); // '#3b82f6'
const unknown = getHabitType('invalid');
// Returns: undefined
Habit type object or undefined if not found
Usage Examples
Date Range Filtering
import { todayStr, cutoffDateStr } from './utils.js';
import { state } from './store.js';
const today = todayStr();
const weekAgo = cutoffDateStr(7);
const thisWeekEvents = state.eventos.filter(e =>
e.data >= weekAgo && e.data <= today
);
Safe HTML Rendering
import { esc } from './utils.js';
function renderEventTitle(evento) {
return `
<div class="event-title">
${esc(evento.titulo)}
</div>
`;
}
Time Display
import { formatTime, getElapsedSeconds } from './utils.js';
import { state } from './store.js';
const evento = state.eventos[0];
const elapsed = getElapsedSeconds(evento);
const display = formatTime(elapsed);
console.log(`Studied for ${display}`);
// Output: 'Studied for 01:23:45'
Habit Icon Display
import { getHabitType } from './utils.js';
function renderHabitBadge(habitKey) {
const habit = getHabitType(habitKey);
if (!habit) return '';
return `
<span style="color: ${habit.color}">
${habit.icon} ${habit.label}
</span>
`;
}
renderHabitBadge('questoes');
// Returns: '<span style="color: #3b82f6">📝 Questões</span>'
Unique ID Generation
import { uid } from './utils.js';
import { state, scheduleSave } from './store.js';
const newEvent = {
id: 'ev_' + uid(),
titulo: 'Study Session',
data: todayStr(),
duracao: 60,
status: 'agendado',
tempoAcumulado: 0,
criadoEm: new Date().toISOString()
};
state.eventos.push(newEvent);
scheduleSave();
todayStr() is cached and only computed once per session for performance
esc() is called frequently, so it’s kept minimal (no regex, just string replacement)
getHabitType() uses Array.find() which is fast for small arrays (8 items)
formatTime() uses simple math operations (no Date object instantiation)
Type Safety
While this is JavaScript, the utils are designed to be defensive:
// esc() handles non-string inputs:
esc(null); // Returns: ''
esc(undefined); // Returns: ''
esc(42); // Returns: '42'
esc('<b>Hi</b>'); // Returns: '<b>Hi</b>'
// formatDate() returns empty string for invalid input:
formatDate(null); // Returns: ''
formatDate(undefined); // Returns: ''