191 lines
7.6 KiB
JavaScript
191 lines
7.6 KiB
JavaScript
/**
|
|
* api.js - API communication module
|
|
*
|
|
* This module handles all communication with the server API endpoints.
|
|
*/
|
|
|
|
import AppState from './state.js';
|
|
import { showLogMessage } from './uiHelpers.js';
|
|
import * as DateUtils from './dateUtils.js'; // Import all of DateUtils
|
|
|
|
/**
|
|
* Load report data from the server (now fetches real_work_hours)
|
|
* @param {boolean} isAutoRefresh - Whether this is an auto-refresh call
|
|
* @returns {Promise<Array>} - Promise resolving to report data
|
|
*/
|
|
export async function loadReportData(isAutoRefresh = false) {
|
|
const currentPeriod = AppState.getCurrentPeriod();
|
|
const user = AppState.getUserFilterText();
|
|
let apiUrl = '/api/reports/real_work_hours'; // New endpoint
|
|
const params = new URLSearchParams();
|
|
|
|
if (user) {
|
|
params.append('username', user);
|
|
}
|
|
|
|
// Add date parameters based on the current period
|
|
let startDate, endDate;
|
|
|
|
if (currentPeriod === 'daily') {
|
|
startDate = AppState.getSelectedDate();
|
|
endDate = startDate; // For daily, start and end date are the same
|
|
params.append('start_date', startDate);
|
|
params.append('end_date', endDate);
|
|
} else if (currentPeriod === 'weekly') {
|
|
if (AppState.getSelectedWeekDay()) {
|
|
startDate = AppState.getSelectedWeekDay();
|
|
endDate = startDate; // If a specific day in week is chosen, treat as daily
|
|
} else {
|
|
// Get current week's start (Monday) and end (Sunday)
|
|
// Assuming AppState.getSelectedDate() gives a date within the desired week if not today
|
|
const refDate = AppState.getSelectedDate() ? new Date(AppState.getSelectedDate()) : new Date();
|
|
startDate = DateUtils.getFirstDayOfWeek(refDate);
|
|
endDate = DateUtils.getLastDayOfWeek(refDate);
|
|
}
|
|
params.append('start_date', startDate);
|
|
params.append('end_date', endDate);
|
|
} else if (currentPeriod === 'monthly') {
|
|
// Get current month's start and end dates
|
|
// Assuming AppState.getSelectedDate() is not used for month context, so always current month
|
|
startDate = DateUtils.getFirstDayOfCurrentMonth();
|
|
endDate = DateUtils.getLastDayOfCurrentMonth();
|
|
params.append('start_date', startDate);
|
|
params.append('end_date', endDate);
|
|
}
|
|
// If no specific period logic matched or for a general overview (if API supports it without dates)
|
|
// we might not append dates, or the API endpoint could have defaults.
|
|
// For this implementation, daily, weekly, monthly will always have date params.
|
|
|
|
if (params.toString()) {
|
|
apiUrl += `?${params.toString()}`;
|
|
}
|
|
|
|
try {
|
|
const response = await fetch(apiUrl);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const result = await response.json();
|
|
|
|
if (result.success && result.data) {
|
|
// Store the data in app state
|
|
AppState.setReportData(result.data);
|
|
|
|
if (isAutoRefresh) {
|
|
showLogMessage('Report data refreshed automatically');
|
|
}
|
|
|
|
return result.data;
|
|
} else {
|
|
throw new Error(result.message || 'Failed to load data.');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching report data:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch current user states from the server
|
|
* @param {boolean} forceRefresh - Whether to force a refresh even if the cache is valid
|
|
* @returns {Promise<Object>} - Promise resolving to user states object
|
|
*/
|
|
export async function fetchUserStates(forceRefresh = false) {
|
|
// Only update user states if cache expired or force refresh
|
|
const now = Date.now();
|
|
if (!forceRefresh &&
|
|
now - AppState.getUserStatesLastUpdate() < AppState.getStateCacheDuration() &&
|
|
Object.keys(AppState.getUserStates()).length > 0) {
|
|
return AppState.getUserStates();
|
|
}
|
|
|
|
try {
|
|
const response = await fetch('/api/user-states');
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const result = await response.json();
|
|
if (result.success && result.data) {
|
|
const prevStates = {...AppState.getUserStates()};
|
|
AppState.setUserStates(result.data);
|
|
|
|
// If forcing a refresh, log the change statistics
|
|
if (forceRefresh) {
|
|
const totalUsers = Object.keys(result.data).length;
|
|
const workingUsers = Object.values(result.data).filter(state => state === 'working').length;
|
|
const changedStates = countChangedStates(prevStates, result.data);
|
|
|
|
// Only show message if it's a manual refresh or if there were changes
|
|
// Also check if AppState.isAutoRefreshEnabled is a function before calling
|
|
const autoRefreshEnabled = (AppState && typeof AppState.isAutoRefreshEnabled === 'function') ? AppState.isAutoRefreshEnabled() : true;
|
|
if (!autoRefreshEnabled || changedStates > 0) {
|
|
showLogMessage(`States refreshed: ${totalUsers} users (${workingUsers} working). ${changedStates} state changes detected.`);
|
|
}
|
|
}
|
|
|
|
return result.data;
|
|
} else {
|
|
// If result.success is false, throw an error with the message from the API
|
|
throw new Error(result.message || 'Failed to fetch user states: API indicated failure.');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching user states:', error);
|
|
// Optionally, clear cached states on error or handle more gracefully
|
|
// For now, re-throw to let the caller handle it or display a general error.
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load user activity data for a specific user
|
|
* @param {string} username - Username to fetch activity for
|
|
* @param {string} startDate - Start date in YYYY-MM-DD format
|
|
* @param {string} endDate - End date in YYYY-MM-DD format
|
|
* @returns {Promise<Array>} - Promise resolving to user activity data
|
|
*/
|
|
export async function loadUserActivityData(username, startDate, endDate) {
|
|
try {
|
|
const response = await fetch(`/api/user-activity/${encodeURIComponent(username)}?start_date=${startDate}&end_date=${endDate}`);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const result = await response.json();
|
|
if (result.success && result.data) {
|
|
return result.data.activities;
|
|
} else {
|
|
throw new Error(result.message || 'Failed to load activity data');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching user activity data:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to count changed states between refreshes
|
|
* @param {Object} prevStates - Previous state object
|
|
* @param {Object} newStates - New state object
|
|
* @returns {number} - Number of state changes
|
|
*/
|
|
function countChangedStates(prevStates, newStates) {
|
|
let count = 0;
|
|
|
|
// Check for changes in existing users
|
|
Object.keys(newStates).forEach(user => {
|
|
if (prevStates[user] && prevStates[user] !== newStates[user]) {
|
|
count++;
|
|
console.log(`State change detected: ${user} changed from ${prevStates[user]} to ${newStates[user]}`);
|
|
}
|
|
});
|
|
|
|
// Check for new users
|
|
const newUsers = Object.keys(newStates).filter(user => !prevStates[user]);
|
|
if (newUsers.length > 0) {
|
|
count += newUsers.length;
|
|
console.log(`New users detected: ${newUsers.join(', ')}`);
|
|
}
|
|
|
|
return count;
|
|
}
|