Skip to main content

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:
let dashboardData = [];
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:
  1. Requests data.json
  2. Converts the response to JSON
  3. Stores the data in dashboardData
  4. Calls weeklyActivity() to display the default weekly view
Reference: app.js:3-11

DOM Element Selection

const daily = document.querySelector('#daily');
const weekly = document.querySelector('#weekly');
const monthly = document.querySelector('#monthly');
These select the three time period buttons from the profile card.Reference: app.js:13-15

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:
  1. Call removeActiveClasses() to clear button states
  2. Add active class to the clicked button
  3. Update all activity card spans with data from the corresponding timeframe
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-60

Data Structure Mapping

The dashboard data array has a specific structure that maps to activity categories:
Array IndexActivityVariable Names
0WorkworkCurrent, workPrevious
1PlayplayCurrent, playPrevious
2StudystudyCurrent, studyPrevious
3ExerciseexerciseCurrent, exercisePrevious
4SocialsocialCurrent, socialPrevious
5Self CareselfCareCurrent, 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

  1. Initialization (app.js:1)
    • Declare dashboardData array
  2. Data Loading (app.js:3-11)
    • Fetch JSON data
    • Parse response
    • Store in dashboardData
    • Call weeklyActivity() to show initial state
  3. DOM Selection (app.js:13-30)
    • Select all button elements
    • Select all current/previous span elements
    • Create buttons array
  4. Function Definitions (app.js:32-106)
    • Define removeActiveClasses()
    • Define dailyActivity()
    • Define weeklyActivity()
    • Define monthlyActivity()
  5. 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.

Build docs developers (and LLMs) love