Documentation Index
Fetch the complete documentation index at: https://mintlify.com/chrisdzasc/Time-Tracking-Dashboard/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The JavaScript file (app.js) handles data fetching, DOM manipulation, and user interactions. It uses the Fetch API to load JSON data and updates the UI based on the selected time period (daily, weekly, or monthly).
Application Flow
Global Variables
The application starts by declaring a global array to store the fetched data:
Reference: app.js:1
Data Fetching
The Fetch API loads data immediately when the page loads:
fetch('./js/data.json')
.then(response => {
return response.json()
})
.then(data => {
dashboardData = data;
weeklyActivity();
});
The fetch chain:
- Requests
data.json
- Converts the response to JSON
- Stores the data in
dashboardData
- Calls
weeklyActivity() to display the default weekly view
Reference: app.js:3-11
DOM Element Selection
Button Array
The buttons are grouped into an array for easier iteration:
const buttons = [daily, weekly, monthly];
Reference: app.js:30
Utility Functions
removeActiveClasses()
This function removes the active styling from all time period buttons:
function removeActiveClasses() {
buttons.forEach(button => {
button.classList.remove("profile-card__option--active");
});
}
It iterates through the buttons array and removes the profile-card__option--active class from each one. This is called at the start of each activity function to reset the button states.
Reference: app.js:32-36
Main Activity Functions
All three activity functions follow the same pattern:
- Call
removeActiveClasses() to clear button states
- Add active class to the clicked button
- Update all activity card spans with data from the corresponding timeframe
dailyActivity()
weeklyActivity()
monthlyActivity()
function dailyActivity() {
removeActiveClasses();
daily.classList.add("profile-card__option--active");
workCurrent.innerText = dashboardData[0].timeframes.daily.current;
workPrevious.innerText = dashboardData[0].timeframes.daily.previous;
playCurrent.innerText = dashboardData[1].timeframes.daily.current;
playPrevious.innerText = dashboardData[1].timeframes.daily.previous;
studyCurrent.innerText = dashboardData[2].timeframes.daily.current;
studyPrevious.innerText = dashboardData[2].timeframes.daily.previous;
exerciseCurrent.innerText = dashboardData[3].timeframes.daily.current;
exercisePrevious.innerText = dashboardData[3].timeframes.daily.previous;
socialCurrent.innerText = dashboardData[4].timeframes.daily.current;
socialPrevious.innerText = dashboardData[4].timeframes.daily.previous;
selfCareCurrent.innerText = dashboardData[5].timeframes.daily.current;
selfCarePrevious.innerText = dashboardData[5].timeframes.daily.previous;
}
Displays daily time tracking data. Accesses dashboardData[index].timeframes.daily.current and .previous for each activity.Reference: app.js:38-60function weeklyActivity() {
removeActiveClasses();
weekly.classList.add("profile-card__option--active");
workCurrent.innerText = dashboardData[0].timeframes.weekly.current;
workPrevious.innerText = dashboardData[0].timeframes.weekly.previous;
playCurrent.innerText = dashboardData[1].timeframes.weekly.current;
playPrevious.innerText = dashboardData[1].timeframes.weekly.previous;
studyCurrent.innerText = dashboardData[2].timeframes.weekly.current;
studyPrevious.innerText = dashboardData[2].timeframes.weekly.previous;
exerciseCurrent.innerText = dashboardData[3].timeframes.weekly.current;
exercisePrevious.innerText = dashboardData[3].timeframes.weekly.previous;
socialCurrent.innerText = dashboardData[4].timeframes.weekly.current;
socialPrevious.innerText = dashboardData[4].timeframes.weekly.previous;
selfCareCurrent.innerText = dashboardData[5].timeframes.weekly.current;
selfCarePrevious.innerText = dashboardData[5].timeframes.weekly.previous;
}
Displays weekly time tracking data (default view). Called automatically after data loads.Reference: app.js:62-83function monthlyActivity() {
removeActiveClasses();
monthly.classList.add("profile-card__option--active");
workCurrent.innerText = dashboardData[0].timeframes.monthly.current;
workPrevious.innerText = dashboardData[0].timeframes.monthly.previous;
playCurrent.innerText = dashboardData[1].timeframes.monthly.current;
playPrevious.innerText = dashboardData[1].timeframes.monthly.previous;
studyCurrent.innerText = dashboardData[2].timeframes.monthly.current;
studyPrevious.innerText = dashboardData[2].timeframes.monthly.previous;
exerciseCurrent.innerText = dashboardData[3].timeframes.monthly.current;
exercisePrevious.innerText = dashboardData[3].timeframes.monthly.previous;
socialCurrent.innerText = dashboardData[4].timeframes.monthly.current;
socialPrevious.innerText = dashboardData[4].timeframes.monthly.previous;
selfCareCurrent.innerText = dashboardData[5].timeframes.monthly.current;
selfCarePrevious.innerText = dashboardData[5].timeframes.monthly.previous;
}
Displays monthly time tracking data. Accesses dashboardData[index].timeframes.monthly.current and .previous.Reference: app.js:85-106
Data Structure Mapping
The dashboard data array has a specific structure that maps to activity categories:
| Array Index | Activity | Variable Names |
|---|
| 0 | Work | workCurrent, workPrevious |
| 1 | Play | playCurrent, playPrevious |
| 2 | Study | studyCurrent, studyPrevious |
| 3 | Exercise | exerciseCurrent, exercisePrevious |
| 4 | Social | socialCurrent, socialPrevious |
| 5 | Self Care | selfCareCurrent, selfCarePrevious |
Example data access:
dashboardData[0].timeframes.weekly.current // Work current hours (weekly)
dashboardData[2].timeframes.daily.previous // Study previous hours (daily)
Event Listeners
Three click event listeners connect the buttons to their respective functions:
daily.addEventListener("click", dailyActivity);
weekly.addEventListener("click", weeklyActivity);
monthly.addEventListener("click", monthlyActivity);
Reference: app.js:109-113
Complete Execution Flow
-
Initialization (app.js:1)
- Declare
dashboardData array
-
Data Loading (app.js:3-11)
- Fetch JSON data
- Parse response
- Store in
dashboardData
- Call
weeklyActivity() to show initial state
-
DOM Selection (app.js:13-30)
- Select all button elements
- Select all current/previous span elements
- Create buttons array
-
Function Definitions (app.js:32-106)
- Define
removeActiveClasses()
- Define
dailyActivity()
- Define
weeklyActivity()
- Define
monthlyActivity()
-
Event Binding (app.js:109-113)
- Attach click listeners to all buttons
Updating the DOM
All DOM updates use the innerText property to set text content:
workCurrent.innerText = dashboardData[0].timeframes.daily.current;
This approach:
- Updates only the text within the
<span> element
- Preserves surrounding HTML structure
- Avoids XSS vulnerabilities (unlike
innerHTML)
Error Handling
The current implementation does not include error handling for the fetch request. In a production environment, you would add error handling:
fetch('./js/data.json')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
dashboardData = data;
weeklyActivity();
})
.catch(error => {
console.error('Error fetching data:', error);
});
Performance Considerations
Pros
- Direct DOM element references (cached after initial selection)
- No unnecessary re-queries of the DOM
- Simple, straightforward logic
Potential Improvements
- Could reduce code duplication by creating a generic update function
- Could use a data structure to map activity names to DOM elements
- Could implement loading states during data fetch
Code Refactoring Example
The three activity functions could be consolidated into a single function:
function updateActivity(timeframe, button) {
removeActiveClasses();
button.classList.add("profile-card__option--active");
const activities = [
{ current: workCurrent, previous: workPrevious },
{ current: playCurrent, previous: playPrevious },
{ current: studyCurrent, previous: studyPrevious },
{ current: exerciseCurrent, previous: exercisePrevious },
{ current: socialCurrent, previous: socialPrevious },
{ current: selfCareCurrent, previous: selfCarePrevious }
];
activities.forEach((activity, index) => {
activity.current.innerText = dashboardData[index].timeframes[timeframe].current;
activity.previous.innerText = dashboardData[index].timeframes[timeframe].previous;
});
}
// Event listeners would then call:
daily.addEventListener("click", () => updateActivity('daily', daily));
weekly.addEventListener("click", () => updateActivity('weekly', weekly));
monthly.addEventListener("click", () => updateActivity('monthly', monthly));
This refactored approach reduces code duplication while maintaining the same functionality.